1 | #include <stdio.h> |
---|
2 | #include <stdlib.h> |
---|
3 | #include <math.h> |
---|
4 | #include "dprints.h" /* for dprints */ |
---|
5 | #include "gribfuncs.h" /* prototypes */ |
---|
6 | /* |
---|
7 | REVISION/MODIFICATION HISTORY: |
---|
8 | 03/07/94 written by Mugur Georgescu CSC, Monterey CA |
---|
9 | 02/01/96 modified by Steve Lowe SAIC, Monterey CA |
---|
10 | 04/17/96 modified by Alice Nakajima SAIC, Monterey CA |
---|
11 | 06/19/96 add hdrprint;/nakajima |
---|
12 | * |
---|
13 | * ******************************************************************** |
---|
14 | * A. FUNCTION: gribgetbds |
---|
15 | * decodes the Binary Data Section of the GRIB message |
---|
16 | * and filling grib_data float array. |
---|
17 | * |
---|
18 | * INTERFACE: |
---|
19 | * int gribgetbds (curr_ptr, deci_scale, bms, gds, |
---|
20 | * ppgrib_data, bds_head, errmsg) |
---|
21 | * |
---|
22 | * ARGUMENTS (I=input, O=output, I&O=input and output): |
---|
23 | * (I) char *curr_ptr; |
---|
24 | * points to first Octet of the BDS to be decoded; |
---|
25 | * (I) short deci_scale; |
---|
26 | * decimal scaling factor to be applied to data; |
---|
27 | * (I) BMS_INPUT *bms; |
---|
28 | * points to the decoded internal Bit Map Section Struct |
---|
29 | * (I/O) grid_desc_sec *gds |
---|
30 | * points to decoded internal grid definition struct |
---|
31 | * (O) float **ppgrib_data; |
---|
32 | * double pointer to array of float, null upon entry; |
---|
33 | * upon successful exit, holds the unpacked and restored float data |
---|
34 | * in a newly malloced array; |
---|
35 | * (O) BDS_HEAD_INPUT *bds_head; |
---|
36 | * points to Binary Data Sect hdr struct, empty upon entry; |
---|
37 | * to be filled with decoded BDS info; |
---|
38 | * (O) char *errmsg; |
---|
39 | * Only returned filled when error occurred; |
---|
40 | * |
---|
41 | * RETURN CODE: |
---|
42 | * 0> no errors |
---|
43 | * 1> unrecognized packing algorithm |
---|
44 | * 2> number of points does not match bitmap |
---|
45 | * 3> number of points does not match grid size in GDS |
---|
46 | * 4> malloc error |
---|
47 | * ******************************************************************** |
---|
48 | */ |
---|
49 | |
---|
50 | #if PROTOTYPE_NEEDED |
---|
51 | int gribgetbds ( char *curr_ptr, short deci_scale, BMS_INPUT *bms, |
---|
52 | grid_desc_sec *gds, float **ppgrib_data, |
---|
53 | BDS_HEAD_INPUT *bds_head, char *errmsg) |
---|
54 | #else |
---|
55 | int gribgetbds (curr_ptr, deci_scale, bms, gds, ppgrib_data, |
---|
56 | bds_head, errmsg) |
---|
57 | char *curr_ptr; |
---|
58 | short deci_scale; |
---|
59 | BMS_INPUT *bms; |
---|
60 | grid_desc_sec *gds; |
---|
61 | float **ppgrib_data; |
---|
62 | BDS_HEAD_INPUT *bds_head; |
---|
63 | char *errmsg; |
---|
64 | #endif |
---|
65 | { |
---|
66 | char *func="gribgetbds"; |
---|
67 | char *in = curr_ptr; /* pointer to beginning of BDS */ |
---|
68 | long length; /* size of the Binary Data Section */ |
---|
69 | long scale; /* scaling factor */ |
---|
70 | float ref_val; /* reference value (minimum value) */ |
---|
71 | unsigned long something; /* generic value from message */ |
---|
72 | long data_width; /* number of bits that data occupies */ |
---|
73 | int halfBYTE4; /* the first 4 bits in 4-th byte */ |
---|
74 | int status=0; |
---|
75 | int sign; /* sign + or - */ |
---|
76 | float dscale; /* 10 to the decimal scaling power */ |
---|
77 | float bscale; /* 2 to the binary scaling power */ |
---|
78 | unsigned long skip=0; /* number of bits to be skipped */ |
---|
79 | long c_ristic; /* characteristic for float representation */ |
---|
80 | long mantissa; /* mantissa for float representation */ |
---|
81 | long numpts; /* number of bits left at end of bitstream */ |
---|
82 | unsigned long data_pts; /* number of data points in bitstream */ |
---|
83 | unsigned long num_calc; /* temp work var */ |
---|
84 | float *grib_data=0; /* local work array for grid data */ |
---|
85 | float fdata=0; /* data value stored in reference */ |
---|
86 | int i,j; /* array counter */ |
---|
87 | int xsize, ysize; |
---|
88 | float *outdata; |
---|
89 | |
---|
90 | DPRINT1 ("Entering %s()\n", func); |
---|
91 | /* |
---|
92 | * |
---|
93 | * A.1 FUNCTION gbyte !get bds length |
---|
94 | */ |
---|
95 | |
---|
96 | gbyte(in,(unsigned long *) &length,&skip,24); |
---|
97 | DPRINT0 ("bds_head->length\n"); |
---|
98 | bds_head->length = (unsigned long) length; |
---|
99 | |
---|
100 | /* |
---|
101 | * |
---|
102 | * A.2 FUNCTION gbyte !get BDS flag |
---|
103 | */ |
---|
104 | gbyte(in, (unsigned long *) &halfBYTE4, &skip, 4); |
---|
105 | DPRINT0 ("bds_head->usBDS_flag\n"); |
---|
106 | bds_head->usBDS_flag = (short) halfBYTE4; /* get BDS Flag (Table 11) */ |
---|
107 | |
---|
108 | /* |
---|
109 | * |
---|
110 | * A.3 IF (unsupported packing algorithm) THEN |
---|
111 | * RETURN 1 |
---|
112 | * ENDIF |
---|
113 | */ |
---|
114 | /* need to check on packing algorithm */ |
---|
115 | if (halfBYTE4) /* unrecognized packing algorithm */ |
---|
116 | { |
---|
117 | DPRINT1 ("%s: error, unrecognized packing algorithm\n", func); |
---|
118 | sprintf(errmsg, "%s: unrecognized packing algorithm\n", func); |
---|
119 | status= (1); |
---|
120 | goto BYE; |
---|
121 | } |
---|
122 | |
---|
123 | /* |
---|
124 | * |
---|
125 | * A.4 FUNCTION gbyte !get number of unused bits |
---|
126 | */ |
---|
127 | gbyte(in,(unsigned long *) &numpts,&skip,4); /* get #bits at end of BDS */ |
---|
128 | DPRINT0 ("numpts\n"); |
---|
129 | |
---|
130 | /* |
---|
131 | * |
---|
132 | * A.5 FUNCTION gbyte !get Binary Scale Factor |
---|
133 | */ |
---|
134 | gbyte(in,&something,&skip,16); |
---|
135 | DPRINT0 ("Sign & bds_head->Bin_sc_fctr\n"); |
---|
136 | sign = (int)(something >> 15) & 1; /* get sign for scale */ |
---|
137 | scale = (int)(something) & 32767; /* get scale */ |
---|
138 | if(sign) /* scale negative */ |
---|
139 | scale = -scale; /* multiply scale by -1 */ |
---|
140 | bds_head->Bin_sc_fctr = (int) scale; /* get binary scale factor */ |
---|
141 | DPRINT1 ("Binary Scale Factor = %d\n", scale); |
---|
142 | |
---|
143 | /* |
---|
144 | * |
---|
145 | * A.6 CALCULATE Reference value from IBM representation |
---|
146 | * !FUNCTION gbyte !get the sign of reference |
---|
147 | * !FUNCTION gbyte !get charateristic |
---|
148 | * !FUNCTION gbyte !get the mantissa |
---|
149 | */ |
---|
150 | gbyte(in,&something,&skip,8); |
---|
151 | DPRINT0 ("Sign & Reference)\n"); |
---|
152 | sign = (int)(something >> 7) & 1; /* get the sign for reference value */ |
---|
153 | |
---|
154 | skip -= 7; |
---|
155 | gbyte(in,(unsigned long *)&c_ristic,&skip,7); /*characteristic for the float*/ |
---|
156 | DPRINT0 ("c_ristic\n"); |
---|
157 | |
---|
158 | gbyte(in,(unsigned long*)&mantissa,&skip,24); /*mantissa for the float */ |
---|
159 | DPRINT0 ("mantissa\n"); |
---|
160 | c_ristic -= 64; /* subtract 64 from characteristic */ |
---|
161 | ref_val = (float) mantissa * (float)(pow(16.0,(double)c_ristic)) * |
---|
162 | (pow(2.0,-24.0)); |
---|
163 | if(sign) /* negative reference value */ |
---|
164 | ref_val = -ref_val; /* multiply ref_val by -1 */ |
---|
165 | bds_head->fReference = (float)ref_val; |
---|
166 | DPRINT1 ("Reference = %f\n", ref_val); |
---|
167 | |
---|
168 | /* |
---|
169 | * |
---|
170 | * A.7 FUNCTION gbyte !get data width |
---|
171 | */ |
---|
172 | gbyte(in, (unsigned long*) &data_width,&skip,8); /* get data width */ |
---|
173 | DPRINT0 ("bds_head->usBit_pack_num\n"); |
---|
174 | bds_head->usBit_pack_num = (short)data_width; |
---|
175 | |
---|
176 | /* |
---|
177 | * |
---|
178 | * A.8 SET Binary and Decimal Scale Factors |
---|
179 | */ |
---|
180 | /* set binary scale */ |
---|
181 | bscale = (float)pow (2.0,(double) scale); |
---|
182 | |
---|
183 | /* set decimal scale */ |
---|
184 | dscale = (float)pow (10.0, (double) deci_scale); |
---|
185 | |
---|
186 | DPRINT2 ("Scaled-up BSF= (2**%d) = %f\n", scale, bscale); |
---|
187 | DPRINT2 ("Scaled-up DSF= (10**%d) = %f\n", deci_scale,dscale); |
---|
188 | |
---|
189 | /* |
---|
190 | * |
---|
191 | * A.9 IF (data_width is zero) THEN |
---|
192 | * ! grid contains a constant value |
---|
193 | * IF expected grid size is invalid THEN |
---|
194 | * FORCE grid size of 1 |
---|
195 | * ENDIF |
---|
196 | * ALLOCATE array for grid of expected grid size |
---|
197 | * FILL grid with the constant value |
---|
198 | * RETURN 0 !success |
---|
199 | * ENDIF |
---|
200 | */ |
---|
201 | if (!data_width) /* grid contains constant value, success, all done */ |
---|
202 | { |
---|
203 | /* Used to send back array of 1 element: |
---|
204 | # bds_head->ulGrid_size = 1; |
---|
205 | # fdata = (float) (ref_val / dscale); |
---|
206 | # *ppgrib_data = (float *) malloc(sizeof(float)); |
---|
207 | # **ppgrib_data = fdata; |
---|
208 | */ |
---|
209 | |
---|
210 | fdata = (float) (ref_val / dscale); |
---|
211 | if (bds_head->ulGrid_size <= 0) { |
---|
212 | fprintf(stdout, |
---|
213 | "WARNING: gribgetbds detects bad ulGrid_size (%ld); "\ |
---|
214 | "Set to 1 to hold constant value %lf\n", bds_head->ulGrid_size, fdata); |
---|
215 | bds_head->ulGrid_size = 1; |
---|
216 | } |
---|
217 | |
---|
218 | grib_data =(float *) malloc(bds_head->ulGrid_size * sizeof(float)); |
---|
219 | if (!grib_data) { |
---|
220 | sprintf(errmsg, |
---|
221 | "%s: failed to create array[%d] for grid to hold Constant data", |
---|
222 | func, bds_head->ulGrid_size); |
---|
223 | goto BYE; |
---|
224 | } |
---|
225 | |
---|
226 | *ppgrib_data = grib_data; /* store address */ |
---|
227 | for (i=0; i < bds_head->ulGrid_size ; ) |
---|
228 | grib_data[i++] = fdata; /* fill grid with constant val */ |
---|
229 | |
---|
230 | DPRINT3("%s: grid[%ld] contains convant value %lf\n", |
---|
231 | func, bds_head->ulGrid_size, fdata); |
---|
232 | |
---|
233 | status = (0); /* no errors */ |
---|
234 | goto BYE; |
---|
235 | } |
---|
236 | |
---|
237 | /* fill the data array with values from message */ |
---|
238 | /* - Assume that GDS may not be included so that |
---|
239 | * the number of grid points may not be defined. |
---|
240 | * - Compute space to malloc based on BDS length, |
---|
241 | * data_width, and numpts. |
---|
242 | * - if grid_size from GDS is zero, use |
---|
243 | * computed number of points. |
---|
244 | */ |
---|
245 | |
---|
246 | /* |
---|
247 | * |
---|
248 | * A.10 CALCULATE number of data points actually in BDS |
---|
249 | */ |
---|
250 | num_calc = ((length - 11)*8 - numpts) / data_width; |
---|
251 | |
---|
252 | /* Check the number of points computed against info in the BMS |
---|
253 | or GDS, if they are available */ |
---|
254 | |
---|
255 | /* |
---|
256 | * |
---|
257 | * A.11 IF (BMS is present and has included bitmap) THEN |
---|
258 | * IF (#calculated not same as #bits set in BMS) THEN |
---|
259 | * RETURN 2 |
---|
260 | * ENDIF |
---|
261 | */ |
---|
262 | |
---|
263 | if (bms->uslength > 6) |
---|
264 | { |
---|
265 | if (bms->ulbits_set != num_calc) { |
---|
266 | DPRINT3 ("%s: BMS present, #datapts calculated (%d) " \ |
---|
267 | "not same as BMS's set bits (%d)\n",func, num_calc, bms->ulbits_set); |
---|
268 | |
---|
269 | sprintf(errmsg,"%s: BMS present, #datapts calculated (%d) " \ |
---|
270 | "not same as BMS's set bits (%d)\n",func, num_calc, bms->ulbits_set); |
---|
271 | status= (2); goto BYE; |
---|
272 | } |
---|
273 | } |
---|
274 | /* |
---|
275 | * A.11.1 ELSE !no bms |
---|
276 | * IF (GDS is present AND |
---|
277 | * #calculated not same as GDS's grid size) |
---|
278 | * THEN |
---|
279 | * RETURN 3 |
---|
280 | * ENDIF |
---|
281 | */ |
---|
282 | |
---|
283 | else |
---|
284 | |
---|
285 | { |
---|
286 | if (bds_head->ulGrid_size && bds_head->ulGrid_size != num_calc) { |
---|
287 | DPRINT0("Averting failure of grid size test\n"); |
---|
288 | /* |
---|
289 | DPRINT3 ( "%s: GDS present, #datapts calculated (%d) " \ |
---|
290 | "not same as GDS's grid size (%d)\n", |
---|
291 | func,num_calc,bds_head->ulGrid_size); |
---|
292 | |
---|
293 | sprintf(errmsg,"%s: GDS present, #datapts calculated (%d) " \ |
---|
294 | "not same as GDS's grid size (%d)\n", |
---|
295 | func,num_calc,bds_head->ulGrid_size); |
---|
296 | status=(3); goto BYE; |
---|
297 | */ |
---|
298 | } |
---|
299 | } |
---|
300 | |
---|
301 | |
---|
302 | /* |
---|
303 | * A.11 ENDIF (BMS present) |
---|
304 | */ |
---|
305 | |
---|
306 | /* Only reach this point if number of points in BDS matches info |
---|
307 | in BMS or GDS. This number is unchecked if no BMS or GDS. */ |
---|
308 | |
---|
309 | /* Make sure number of points in BDS is value used for extracting */ |
---|
310 | /* |
---|
311 | * |
---|
312 | * A.12 SET #datapoints |
---|
313 | */ |
---|
314 | bds_head->ulGrid_size = num_calc; |
---|
315 | data_pts= num_calc; |
---|
316 | |
---|
317 | /* |
---|
318 | * |
---|
319 | * A.13 ALLOCATE storage for float array size |
---|
320 | * IF (error) THEN |
---|
321 | * RETURN 4 |
---|
322 | * ENDIF |
---|
323 | */ |
---|
324 | grib_data =(float *) malloc(data_pts * sizeof(float)); |
---|
325 | if (grib_data==NULL) { |
---|
326 | DPRINT1 ("%s: failed to malloc Grib_Data\n",func); |
---|
327 | sprintf(errmsg,"%s: failed to malloc Grib_Data\n",func); |
---|
328 | status=(4); goto BYE; } |
---|
329 | |
---|
330 | /* |
---|
331 | * |
---|
332 | * A.14 SET data array pointer to local data array |
---|
333 | */ |
---|
334 | *ppgrib_data = grib_data; |
---|
335 | |
---|
336 | /* |
---|
337 | * |
---|
338 | * A.15 FOR (each data point) DO |
---|
339 | * FUNCTION gbyte_quiet !get data_width bits |
---|
340 | * INCREMENT skip by data_width |
---|
341 | * COMPUTE and STORE value in float array |
---|
342 | * ENDDO |
---|
343 | */ |
---|
344 | |
---|
345 | DPRINT3 ( "Restore float data by = (float)(%f + X * %f)) / %f;\n", |
---|
346 | ref_val, bscale, dscale); |
---|
347 | |
---|
348 | for(i=0;i < data_pts ;i++) |
---|
349 | { |
---|
350 | gbyte_quiet(in,&something,&skip,data_width); |
---|
351 | grib_data[i]= (float)(ref_val + (something * bscale))/dscale; |
---|
352 | } |
---|
353 | |
---|
354 | /* |
---|
355 | * Unthin grid if it is thinned |
---|
356 | */ |
---|
357 | if (gds->head.thin != NULL) { |
---|
358 | if ((gds->head.usData_type == LATLON_PRJ) || |
---|
359 | (gds->head.usData_type == GAUSS_PRJ) || |
---|
360 | (gds->head.usData_type == ROT_LATLON_PRJ) || |
---|
361 | (gds->head.usData_type == ROT_GAUSS_PRJ) || |
---|
362 | (gds->head.usData_type == STR_LATLON_PRJ) || |
---|
363 | (gds->head.usData_type == STR_GAUSS_PRJ) || |
---|
364 | (gds->head.usData_type == STR_ROT_LATLON_PRJ) || |
---|
365 | (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) { |
---|
366 | ysize = gds->llg.usNj; |
---|
367 | } else if (gds->head.usData_type == MERC_PRJ) { |
---|
368 | ysize = gds->merc.rows; |
---|
369 | } else if (gds->head.usData_type == POLAR_PRJ) { |
---|
370 | ysize = gds->pol.usNy; |
---|
371 | } else if ((gds->head.usData_type == LAMB_PRJ) || |
---|
372 | (gds->head.usData_type == ALBERS_PRJ) || |
---|
373 | (gds->head.usData_type == OBLIQ_LAMB_PRJ)) { |
---|
374 | ysize = gds->lam.iNy; |
---|
375 | } else { |
---|
376 | DPRINT2 ("%s: unknown datatype=%d\n",func, gds->head.usData_type); |
---|
377 | sprintf(errmsg,"%s: unknown datatype=%d\n",func, gds->head.usData_type); |
---|
378 | status=1; /* set status to failure */ |
---|
379 | } |
---|
380 | |
---|
381 | xsize = 0; |
---|
382 | for (j = 0; j<ysize; j++) { |
---|
383 | if (gds->head.thin[j] > xsize) { |
---|
384 | xsize = gds->head.thin[j]; |
---|
385 | } |
---|
386 | } |
---|
387 | outdata = (float *)malloc(ysize*xsize*sizeof(float)); |
---|
388 | grib_unthin(grib_data,outdata,gds->head.thin,ysize, |
---|
389 | &xsize); |
---|
390 | free(grib_data); |
---|
391 | grib_data = (float *)malloc(sizeof(float)*ysize*xsize); |
---|
392 | *ppgrib_data = grib_data; |
---|
393 | memcpy(grib_data,outdata,sizeof(float)*ysize*xsize); |
---|
394 | free(outdata); |
---|
395 | free(gds->head.thin); |
---|
396 | gds->head.thin = NULL; |
---|
397 | if ((gds->head.usData_type == LATLON_PRJ) || |
---|
398 | (gds->head.usData_type == GAUSS_PRJ) || |
---|
399 | (gds->head.usData_type == ROT_LATLON_PRJ) || |
---|
400 | (gds->head.usData_type == ROT_GAUSS_PRJ) || |
---|
401 | (gds->head.usData_type == STR_LATLON_PRJ) || |
---|
402 | (gds->head.usData_type == STR_GAUSS_PRJ) || |
---|
403 | (gds->head.usData_type == STR_ROT_LATLON_PRJ) || |
---|
404 | (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) { |
---|
405 | gds->llg.usNi = xsize; |
---|
406 | gds->llg.iDi = abs(gds->llg.lLat2 - gds->llg.lLat1)/(xsize-1); |
---|
407 | } else if (gds->head.usData_type == MERC_PRJ) { |
---|
408 | gds->merc.cols = xsize; |
---|
409 | } else if (gds->head.usData_type == POLAR_PRJ) { |
---|
410 | gds->pol.usNx = xsize; |
---|
411 | } else if ((gds->head.usData_type == LAMB_PRJ) || |
---|
412 | (gds->head.usData_type == ALBERS_PRJ) || |
---|
413 | (gds->head.usData_type == OBLIQ_LAMB_PRJ)) { |
---|
414 | gds->lam.iNx = xsize; |
---|
415 | } else { |
---|
416 | DPRINT2 ("%s: unknown datatype=%d\n",func, gds->head.usData_type); |
---|
417 | sprintf(errmsg,"%s: unknown datatype=%d\n",func, gds->head.usData_type); |
---|
418 | status=1; /* set status to failure */ |
---|
419 | } |
---|
420 | } |
---|
421 | |
---|
422 | DPRINT0 ("Sample of first 30 unpacked & restored datapoints=\n"); |
---|
423 | for (i=0; i < 30; i+=5) |
---|
424 | DPRINT6 ("%03d: %f %f %f %f %f\n", |
---|
425 | i, grib_data[i], grib_data[i+1],grib_data[i+2], |
---|
426 | grib_data[i+3], grib_data[i+4] ); |
---|
427 | |
---|
428 | BYE: |
---|
429 | /* |
---|
430 | * |
---|
431 | * A.16 RETURN Status; |
---|
432 | */ |
---|
433 | DPRINT2 ("Exiting %s, status=%d\n", func, status); |
---|
434 | return(status); |
---|
435 | /* |
---|
436 | * END OF FUNCTION |
---|
437 | * |
---|
438 | */ |
---|
439 | } |
---|