1 /* mcidas.c:
2 *
3 * McIDAS areafile support. contributed by Glenn P. Davis
4 * (davis@unidata.ucar.edu).
5 */
6
7 #include "xloadimage.h"
8 #include "mcidas.h"
9
10 char *mc_sensor();
11
12 static struct {
13 int days;
14 char *name;
15 } month_info[13] = {
16 { 0, "Pad" },
17 { 31, "Jan" },
18 { 29, "Feb" }, /* longest */
19 { 31, "Mar" },
20 { 30, "Apr" },
21 { 31, "May" },
22 { 30, "Jun" },
23 { 31, "Jul" },
24 { 31, "Aug" },
25 { 30, "Sep" },
26 { 31, "Oct" },
27 { 30, "Nov" },
28 { 31, "Dec" }
29 };
30
31 /* convert numeric dates to human-readable
32 */
convert_date(time,date)33 static char *convert_date(time, date)
34 int time, date;
35 { static char buf[30];
36 int hour;
37 int minute;
38 int second;
39 int year;
40 int month;
41 int day;
42
43 year = date / 1000;
44 if (year > 50) /* gives us a range from 1950 - 2050, probably good enough */
45 year += 1900;
46 else
47 year += 2000;
48 day = date % 1000;
49
50 /* adjust day for non-leap-years if necessary
51 */
52 if ((day > 31 + 28) && ((year % 4) || (year == 2000)))
53 day++;
54
55 /* find month in year that this day falls in
56 */
57 for (month= 1; day > month_info[month].days; day -= month_info[month].days)
58 month++;
59
60 /* break time-of-day up
61 */
62 hour = time / 10000;
63 minute = (time % 10000) / 100;
64 second = (time % 100);
65
66 snprintf(buf, 29, "%d:%2.2d:%2.2d %s %d, %d (day %d)",
67 hour, minute, second, month_info[month].name, day, year,
68 (date % 1000));
69 return(buf);
70 }
71
72 /*
73 * convert from little endian to big endian four byte object
74 */
75 static unsigned long
vhtonl(lend)76 vhtonl(lend)
77 unsigned long lend ;
78 {
79 unsigned long bend ;
80 unsigned char *lp, *bp ;
81
82 lp = ((unsigned char *)&lend) + 3 ;
83 bp = (unsigned char *) &bend ;
84
85 *bp++ = *lp-- ;
86 *bp++ = *lp-- ;
87 *bp++ = *lp-- ;
88 *bp = *lp ;
89
90 return(bend) ;
91 }
92
babble(name,dir)93 static void babble(name, dir)
94 char *name;
95 struct area_dir *dir;
96 {
97 printf("%s is a %ldx%ld McIDAS areafile from %s at %s (%ld, %ld) (%ld, %ld)\n",
98 name,
99 dir->esiz, dir->lsiz,
100 mc_sensor(dir->satid),
101 convert_date(dir->itime, dir->idate),
102 dir->lcor,
103 dir->ecor,
104 dir->lres,
105 dir->eres) ;
106 }
107
swap_bytes(dir)108 static void swap_bytes(dir)
109 struct area_dir *dir;
110 {
111 unsigned long *begin ;
112 unsigned long *ulp ;
113
114 begin = (unsigned long *)dir ;
115 for(ulp = begin ; ulp < &begin[AREA_COMMENTS] ; ulp++)
116 *ulp = vhtonl(*ulp) ;
117 for(ulp = &begin[AREA_CALKEY] ; ulp < &begin[AREA_STYPE] ; ulp++)
118 *ulp = vhtonl(*ulp) ;
119 }
120
121 /* ARGSUSED */
mcidasIdent(fullname,name)122 int mcidasIdent(fullname, name)
123 char *fullname, *name;
124 { ZFILE *zf;
125 struct area_dir dir ;
126 int r;
127
128 if (! (zf= zopen(fullname))) {
129 perror("mcidasIdent");
130 return(0);
131 }
132 switch (zread(zf, (byte *)&dir, sizeof(struct area_dir))) {
133 case -1:
134 perror("mcidasIdent");
135 r= 0;
136 break;
137
138 case sizeof(struct area_dir):
139 if (memToValLSB((char *)&dir.type, 4) != 4) {
140 r= 0;
141 break;
142 }
143 if (dir.type != 4)
144 swap_bytes(&dir);
145 babble(name, &dir);
146 r= 1;
147 break;
148
149 default:
150 r= 0;
151 break;
152 }
153 zclose(zf);
154 return(r);
155 }
156
157
mcidasLoad(fullname,name,verbose)158 Image *mcidasLoad(fullname, name, verbose)
159 char *fullname, *name;
160 unsigned int verbose;
161 { ZFILE *zf;
162 struct area_dir dir;
163 struct navigation nav;
164 Image *image;
165 unsigned int y;
166
167 if (! (zf= zopen(fullname))) {
168 perror("mcidasLoad");
169 return(NULL);
170 }
171 switch (zread(zf, (byte *)&dir, sizeof(struct area_dir))) {
172 case -1:
173 perror("mcidasLoad");
174 zclose(zf);
175 exit(1);
176
177 case sizeof(struct area_dir):
178 if (memToValLSB((char *)&dir.type, 4) != 4) {
179 zclose(zf);
180 return(NULL) ;
181 }
182 if (dir.type != 4)
183 swap_bytes(&dir);
184 break;
185
186 default:
187 zclose(zf);
188 return(NULL);
189 }
190
191 if (verbose)
192 babble(name, &dir);
193
194 znocache(zf);
195 /* skip the nav */
196 if( zread(zf, (byte *)&nav, sizeof(struct navigation)) !=
197 sizeof(struct navigation)) {
198 zclose(zf);
199 return(NULL) ;
200 }
201
202 /* get an image to put the data in
203 */
204 image= newRGBImage(dir.esiz, dir.lsiz, dir.zsiz * 8);
205
206 /* set up the colormap, linear grey scale
207 */
208 for (y= 0; y < image->rgb.size; y++) {
209 *(image->rgb.red + y)=
210 *(image->rgb.green + y)=
211 *(image->rgb.blue + y)= y * (65536 / image->rgb.size) ;
212 }
213 image->rgb.used= image->rgb.size ;
214
215 /* read the first band from the image and warn if there are other bands
216 * we can't read.
217 */
218 zread(zf, image->data, dir.esiz * dir.lsiz * dir.zsiz) ;
219 if (dir.bands > 1)
220 printf("Warning: Only showing first of %ld bands\n", dir.bands);
221
222 zclose(zf);
223 image->title= dupString(name);
224 return(image);
225 }
226