/src/gdal/frmts/grib/degrib/g2clib/compack.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <stdlib.h> |
2 | | #include <math.h> |
3 | | #include "grib2.h" |
4 | | |
5 | | |
6 | | void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl, |
7 | | unsigned char *cpack,g2int *lcpack) |
8 | | //$$$ SUBPROGRAM DOCUMENTATION BLOCK |
9 | | // . . . . |
10 | | // SUBPROGRAM: compack |
11 | | // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-07 |
12 | | // |
13 | | // ABSTRACT: This subroutine packs up a data field using a complex |
14 | | // packing algorithm as defined in the GRIB2 documentation. It |
15 | | // supports GRIB2 complex packing templates with or without |
16 | | // spatial differences (i.e. DRTs 5.2 and 5.3). |
17 | | // It also fills in GRIB2 Data Representation Template 5.2 or 5.3 |
18 | | // with the appropriate values. |
19 | | // |
20 | | // PROGRAM HISTORY LOG: |
21 | | // 2002-11-07 Gilbert |
22 | | // |
23 | | // USAGE: void compack(g2float *fld,g2int ndpts,g2int idrsnum, |
24 | | // g2int *idrstmpl,unsigned char *cpack,g2int *lcpack) |
25 | | // |
26 | | // INPUT ARGUMENTS: |
27 | | // fld[] - Contains the data values to pack |
28 | | // ndpts - The number of data values in array fld[] |
29 | | // idrsnum - Data Representation Template number 5.N |
30 | | // Must equal 2 or 3. |
31 | | // idrstmpl - Contains the array of values for Data Representation |
32 | | // Template 5.2 or 5.3 |
33 | | // [0] = Reference value - ignored on input |
34 | | // [1] = Binary Scale Factor |
35 | | // [2] = Decimal Scale Factor |
36 | | // . |
37 | | // . |
38 | | // [6] = Missing value management |
39 | | // [7] = Primary missing value |
40 | | // [8] = Secondary missing value |
41 | | // . |
42 | | // . |
43 | | // [16] = Order of Spatial Differencing ( 1 or 2 ) |
44 | | // . |
45 | | // . |
46 | | // |
47 | | // OUTPUT ARGUMENTS: |
48 | | // idrstmpl - Contains the array of values for Data Representation |
49 | | // Template 5.3 |
50 | | // [0] = Reference value - set by compack routine. |
51 | | // [1] = Binary Scale Factor - unchanged from input |
52 | | // [2] = Decimal Scale Factor - unchanged from input |
53 | | // . |
54 | | // . |
55 | | // cpack - The packed data field |
56 | | // lcpack - length of packed field cpack (or -1 in case of error) |
57 | | // |
58 | | // REMARKS: None |
59 | | // |
60 | | // ATTRIBUTES: |
61 | | // LANGUAGE: C |
62 | | // MACHINE: |
63 | | // |
64 | | //$$$ |
65 | 0 | { |
66 | |
|
67 | 0 | const g2int zero=0; |
68 | 0 | g2int *ifld,*gref,*glen,*gwidth; |
69 | 0 | g2int *jmin, *jmax, *lbit; |
70 | 0 | g2int i,j,n, /* nbits, */ imin,imax,left; |
71 | 0 | g2int isd,itemp,ilmax,ngwidthref=0,nbitsgwidth=0; |
72 | 0 | g2int nglenref=0,nglenlast=0,iofst,ival1,ival2=0; |
73 | 0 | g2int minsd,nbitsd=0,maxorig,nbitorig,ngroups; |
74 | 0 | g2int lg,ng,igmax,iwmax,nbitsgref; |
75 | 0 | g2int glength,grpwidth,nbitsglen=0; |
76 | 0 | g2int kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref; |
77 | 0 | g2int missopt, miss1, miss2, ier = 0; |
78 | 0 | g2float bscale,dscale,rmax,rmin,temp; |
79 | 0 | const g2int simple_alg = 0; |
80 | 0 | const g2float alog2=0.69314718f; // ln(2.0) |
81 | 0 | const g2int one=1; |
82 | |
|
83 | 0 | bscale=(float)int_power(2.0,-idrstmpl[1]); |
84 | 0 | dscale=(float)int_power(10.0,idrstmpl[2]); |
85 | | // |
86 | | // Find max and min values in the data |
87 | | // |
88 | 0 | rmax=fld[0]; |
89 | 0 | rmin=fld[0]; |
90 | 0 | for (j=1;j<ndpts;j++) { |
91 | 0 | if (fld[j] > rmax) rmax=fld[j]; |
92 | 0 | if (fld[j] < rmin) rmin=fld[j]; |
93 | 0 | } |
94 | | |
95 | | // |
96 | | // If max and min values are not equal, pack up field. |
97 | | // If they are equal, we have a constant field, and the reference |
98 | | // value (rmin) is the value for each point in the field and |
99 | | // set nbits to 0. |
100 | | // |
101 | 0 | if (rmin != rmax) { |
102 | 0 | iofst=0; |
103 | 0 | ifld=calloc(ndpts,sizeof(g2int)); |
104 | 0 | gref=calloc(ndpts,sizeof(g2int)); |
105 | 0 | gwidth=calloc(ndpts,sizeof(g2int)); |
106 | 0 | glen=calloc(ndpts,sizeof(g2int)); |
107 | 0 | if( ifld == NULL || gref == NULL || gwidth == NULL || glen == NULL ) |
108 | 0 | { |
109 | 0 | free(ifld); |
110 | 0 | free(gref); |
111 | 0 | free(gwidth); |
112 | 0 | free(glen); |
113 | 0 | *lcpack = -1; |
114 | 0 | return; |
115 | 0 | } |
116 | | // |
117 | | // Scale original data |
118 | | // |
119 | 0 | if (idrstmpl[1] == 0) { // No binary scaling |
120 | 0 | imin=(g2int)RINT(rmin*dscale); |
121 | | //imax=(g2int)rint(rmax*dscale); |
122 | 0 | rmin=(g2float)imin; |
123 | 0 | for (j=0;j<ndpts;j++) |
124 | 0 | ifld[j]=(g2int)RINT(fld[j]*dscale)-imin; |
125 | 0 | } |
126 | 0 | else { // Use binary scaling factor |
127 | 0 | rmin=rmin*dscale; |
128 | | //rmax=rmax*dscale; |
129 | 0 | for (j=0;j<ndpts;j++) |
130 | 0 | ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale); |
131 | 0 | } |
132 | | // |
133 | | // Calculate spatial differences, if using DRS Template 5.3. |
134 | | // |
135 | 0 | if (idrsnum == 3) { // spatial differences |
136 | 0 | if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=1; |
137 | 0 | if (idrstmpl[16] == 1) { // first order |
138 | 0 | ival1=ifld[0]; |
139 | 0 | for (j=ndpts-1;j>0;j--) |
140 | 0 | ifld[j]=ifld[j]-ifld[j-1]; |
141 | 0 | ifld[0]=0; |
142 | 0 | } |
143 | 0 | else if (idrstmpl[16] == 2) { // second order |
144 | 0 | ival1=ifld[0]; |
145 | 0 | ival2=ifld[1]; |
146 | 0 | for (j=ndpts-1;j>1;j--) |
147 | 0 | ifld[j]=ifld[j]-(2*ifld[j-1])+ifld[j-2]; |
148 | 0 | ifld[0]=0; |
149 | 0 | ifld[1]=0; |
150 | 0 | } |
151 | | // |
152 | | // subtract min value from spatial diff field |
153 | | // |
154 | 0 | isd=idrstmpl[16]; |
155 | 0 | minsd=ifld[isd]; |
156 | 0 | for (j=isd;j<ndpts;j++) if ( ifld[j] < minsd ) minsd=ifld[j]; |
157 | 0 | for (j=isd;j<ndpts;j++) ifld[j]=ifld[j]-minsd; |
158 | | // |
159 | | // find num of bits need to store minsd and add 1 extra bit |
160 | | // to indicate sign |
161 | | // |
162 | 0 | temp=(float)(log((double)(abs(minsd)+1))/alog2); |
163 | 0 | nbitsd=(g2int)ceil(temp)+1; |
164 | | // |
165 | | // find num of bits need to store ifld[0] ( and ifld[1] |
166 | | // if using 2nd order differencing ) |
167 | | // |
168 | 0 | maxorig=ival1; |
169 | 0 | if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2; |
170 | 0 | temp=(float)(log((double)(maxorig+1))/alog2); |
171 | 0 | nbitorig=(g2int)ceil(temp)+1; |
172 | 0 | if (nbitorig > nbitsd) nbitsd=nbitorig; |
173 | | // increase number of bits to even multiple of 8 ( octet ) |
174 | 0 | if ( (nbitsd%8) != 0) nbitsd=nbitsd+(8-(nbitsd%8)); |
175 | | // |
176 | | // Store extra spatial differencing info into the packed |
177 | | // data section. |
178 | | // |
179 | 0 | if (nbitsd != 0) { |
180 | | // pack first original value |
181 | 0 | if (ival1 >= 0) { |
182 | 0 | sbit(cpack,&ival1,iofst,nbitsd); |
183 | 0 | iofst=iofst+nbitsd; |
184 | 0 | } |
185 | 0 | else { |
186 | 0 | sbit(cpack,&one,iofst,1); |
187 | 0 | iofst=iofst+1; |
188 | 0 | itemp=abs(ival1); |
189 | 0 | sbit(cpack,&itemp,iofst,nbitsd-1); |
190 | 0 | iofst=iofst+nbitsd-1; |
191 | 0 | } |
192 | 0 | if (idrstmpl[16] == 2) { |
193 | | // pack second original value |
194 | 0 | if (ival2 >= 0) { |
195 | 0 | sbit(cpack,&ival2,iofst,nbitsd); |
196 | 0 | iofst=iofst+nbitsd; |
197 | 0 | } |
198 | 0 | else { |
199 | 0 | sbit(cpack,&one,iofst,1); |
200 | 0 | iofst=iofst+1; |
201 | 0 | itemp=abs(ival2); |
202 | 0 | sbit(cpack,&itemp,iofst,nbitsd-1); |
203 | 0 | iofst=iofst+nbitsd-1; |
204 | 0 | } |
205 | 0 | } |
206 | | // pack overall min of spatial differences |
207 | 0 | if (minsd >= 0) { |
208 | 0 | sbit(cpack,&minsd,iofst,nbitsd); |
209 | 0 | iofst=iofst+nbitsd; |
210 | 0 | } |
211 | 0 | else { |
212 | 0 | sbit(cpack,&one,iofst,1); |
213 | 0 | iofst=iofst+1; |
214 | 0 | itemp=abs(minsd); |
215 | 0 | sbit(cpack,&itemp,iofst,nbitsd-1); |
216 | 0 | iofst=iofst+nbitsd-1; |
217 | 0 | } |
218 | 0 | } |
219 | | //printf("SDp %ld %ld %ld %ld\n",ival1,ival2,minsd,nbitsd); |
220 | 0 | } // end of spatial diff section |
221 | | // |
222 | | // Determine Groups to be used. |
223 | | // |
224 | 0 | if ( simple_alg == 1 ) { |
225 | | // set group length to 10; calculate number of groups |
226 | | // and length of last group |
227 | 0 | ngroups=ndpts/10; |
228 | 0 | for (j=0;j<ngroups;j++) glen[j]=10; |
229 | 0 | itemp=ndpts%10; |
230 | 0 | if (itemp != 0) { |
231 | 0 | ngroups=ngroups+1; |
232 | 0 | glen[ngroups-1]=itemp; |
233 | 0 | } |
234 | 0 | } |
235 | 0 | else { |
236 | | // Use Dr. Glahn's algorithm for determining grouping. |
237 | | // |
238 | 0 | kfildo=6; |
239 | 0 | minpk=10; |
240 | 0 | inc=1; |
241 | 0 | maxgrps=(ndpts/minpk)+1; |
242 | 0 | jmin = calloc(maxgrps,sizeof(g2int)); |
243 | 0 | jmax = calloc(maxgrps,sizeof(g2int)); |
244 | 0 | lbit = calloc(maxgrps,sizeof(g2int)); |
245 | 0 | if( jmin == NULL || jmax == NULL || lbit == NULL ) |
246 | 0 | { |
247 | 0 | free(jmin); |
248 | 0 | free(jmax); |
249 | 0 | free(lbit); |
250 | |
|
251 | 0 | free(ifld); |
252 | 0 | free(gref); |
253 | 0 | free(gwidth); |
254 | 0 | free(glen); |
255 | 0 | *lcpack = -1; |
256 | 0 | return; |
257 | 0 | } |
258 | 0 | missopt=0; |
259 | 0 | pack_gp(&kfildo,ifld,&ndpts,&missopt,&minpk,&inc,&miss1,&miss2, |
260 | 0 | jmin,jmax,lbit,glen,&maxgrps,&ngroups,&ibit,&jbit, |
261 | 0 | &kbit,&novref,&lbitref,&ier); |
262 | | //print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref |
263 | 0 | for ( ng=0; ng<ngroups; ng++) glen[ng]=glen[ng]+novref; |
264 | 0 | free(jmin); |
265 | 0 | free(jmax); |
266 | 0 | free(lbit); |
267 | 0 | if( ier != 0 ) |
268 | 0 | { |
269 | 0 | free(ifld); |
270 | 0 | free(gref); |
271 | 0 | free(gwidth); |
272 | 0 | free(glen); |
273 | 0 | *lcpack = -1; |
274 | 0 | return; |
275 | 0 | } |
276 | 0 | } |
277 | | // |
278 | | // For each group, find the group's reference value |
279 | | // and the number of bits needed to hold the remaining values |
280 | | // |
281 | 0 | n=0; |
282 | 0 | for (ng=0;ng<ngroups;ng++) { |
283 | | // find max and min values of group |
284 | 0 | gref[ng]=ifld[n]; |
285 | 0 | imax=ifld[n]; |
286 | 0 | j=n+1; |
287 | 0 | for (lg=1;lg<glen[ng];lg++) { |
288 | 0 | if (ifld[j] < gref[ng]) gref[ng]=ifld[j]; |
289 | 0 | if (ifld[j] > imax) imax=ifld[j]; |
290 | 0 | j++; |
291 | 0 | } |
292 | | // calc num of bits needed to hold data |
293 | 0 | if ( gref[ng] != imax ) { |
294 | 0 | temp=(float)(log((double)(imax-gref[ng]+1))/alog2); |
295 | 0 | gwidth[ng]=(g2int)ceil(temp); |
296 | 0 | } |
297 | 0 | else |
298 | 0 | gwidth[ng]=0; |
299 | | // Subtract min from data |
300 | 0 | j=n; |
301 | 0 | for (lg=0;lg<glen[ng];lg++) { |
302 | 0 | ifld[j]=ifld[j]-gref[ng]; |
303 | 0 | j++; |
304 | 0 | } |
305 | | // increment fld array counter |
306 | 0 | n=n+glen[ng]; |
307 | 0 | } |
308 | | // |
309 | | // Find max of the group references and calc num of bits needed |
310 | | // to pack each groups reference value, then |
311 | | // pack up group reference values |
312 | | // |
313 | 0 | igmax=gref[0]; |
314 | 0 | for (j=1;j<ngroups;j++) if (gref[j] > igmax) igmax=gref[j]; |
315 | 0 | if (igmax != 0) { |
316 | 0 | temp=(float)(log((double)(igmax+1))/alog2); |
317 | 0 | nbitsgref=(g2int)ceil(temp); |
318 | 0 | sbits(cpack,gref,iofst,nbitsgref,0,ngroups); |
319 | 0 | itemp=nbitsgref*ngroups; |
320 | 0 | iofst=iofst+itemp; |
321 | | // Pad last octet with Zeros, if necessary, |
322 | 0 | if ( (itemp%8) != 0) { |
323 | 0 | left=8-(itemp%8); |
324 | 0 | sbit(cpack,&zero,iofst,left); |
325 | 0 | iofst=iofst+left; |
326 | 0 | } |
327 | 0 | } |
328 | 0 | else |
329 | 0 | nbitsgref=0; |
330 | | // |
331 | | // Find max/min of the group widths and calc num of bits needed |
332 | | // to pack each groups width value, then |
333 | | // pack up group width values |
334 | | // |
335 | 0 | iwmax=gwidth[0]; |
336 | 0 | ngwidthref=gwidth[0]; |
337 | 0 | for (j=1;j<ngroups;j++) { |
338 | 0 | if (gwidth[j] > iwmax) iwmax=gwidth[j]; |
339 | 0 | if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j]; |
340 | 0 | } |
341 | 0 | if (iwmax != ngwidthref) { |
342 | 0 | temp=(float)(log((double)(iwmax-ngwidthref+1))/alog2); |
343 | 0 | nbitsgwidth=(g2int)ceil(temp); |
344 | 0 | for (i=0;i<ngroups;i++) |
345 | 0 | gwidth[i]=gwidth[i]-ngwidthref; |
346 | 0 | sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups); |
347 | 0 | itemp=nbitsgwidth*ngroups; |
348 | 0 | iofst=iofst+itemp; |
349 | | // Pad last octet with Zeros, if necessary, |
350 | 0 | if ( (itemp%8) != 0) { |
351 | 0 | left=8-(itemp%8); |
352 | 0 | sbit(cpack,&zero,iofst,left); |
353 | 0 | iofst=iofst+left; |
354 | 0 | } |
355 | 0 | } |
356 | 0 | else { |
357 | 0 | nbitsgwidth=0; |
358 | 0 | for (i=0;i<ngroups;i++) gwidth[i]=0; |
359 | 0 | } |
360 | | // |
361 | | // Find max/min of the group lengths and calc num of bits needed |
362 | | // to pack each groups length value, then |
363 | | // pack up group length values |
364 | | // |
365 | | //write(77,*)'GLENS: ',(glen(j),j=1,ngroups) |
366 | 0 | ilmax=glen[0]; |
367 | 0 | nglenref=glen[0]; |
368 | 0 | for (j=1;j<ngroups-1;j++) { |
369 | 0 | if (glen[j] > ilmax) ilmax=glen[j]; |
370 | 0 | if (glen[j] < nglenref) nglenref=glen[j]; |
371 | 0 | } |
372 | 0 | nglenlast=glen[ngroups-1]; |
373 | 0 | if (ilmax != nglenref) { |
374 | 0 | temp=(float)(log((double)(ilmax-nglenref+1))/alog2); |
375 | 0 | nbitsglen=(g2int)ceil(temp); |
376 | 0 | for (i=0;i<ngroups-1;i++) glen[i]=glen[i]-nglenref; |
377 | 0 | sbits(cpack,glen,iofst,nbitsglen,0,ngroups); |
378 | 0 | itemp=nbitsglen*ngroups; |
379 | 0 | iofst=iofst+itemp; |
380 | | // Pad last octet with Zeros, if necessary, |
381 | 0 | if ( (itemp%8) != 0) { |
382 | 0 | left=8-(itemp%8); |
383 | 0 | sbit(cpack,&zero,iofst,left); |
384 | 0 | iofst=iofst+left; |
385 | 0 | } |
386 | 0 | } |
387 | 0 | else { |
388 | 0 | nbitsglen=0; |
389 | 0 | for (i=0;i<ngroups;i++) glen[i]=0; |
390 | 0 | } |
391 | | // |
392 | | // For each group, pack data values |
393 | | // |
394 | 0 | n=0; |
395 | 0 | for (ng=0;ng<ngroups;ng++) { |
396 | 0 | glength=glen[ng]+nglenref; |
397 | 0 | if (ng == (ngroups-1) ) glength=nglenlast; |
398 | 0 | grpwidth=gwidth[ng]+ngwidthref; |
399 | 0 | if ( grpwidth != 0 ) { |
400 | 0 | sbits(cpack,ifld+n,iofst,grpwidth,0,glength); |
401 | 0 | iofst=iofst+(grpwidth*glength); |
402 | 0 | } |
403 | 0 | n=n+glength; |
404 | 0 | } |
405 | | // Pad last octet with Zeros, if necessary, |
406 | 0 | if ( (iofst%8) != 0) { |
407 | 0 | left=8-(iofst%8); |
408 | 0 | sbit(cpack,&zero,iofst,left); |
409 | 0 | iofst=iofst+left; |
410 | 0 | } |
411 | 0 | *lcpack=iofst/8; |
412 | | // |
413 | 0 | free(ifld); |
414 | 0 | free(gref); |
415 | 0 | free(gwidth); |
416 | 0 | free(glen); |
417 | 0 | } |
418 | 0 | else { // Constant field ( max = min ) |
419 | | /* nbits=0; */ |
420 | 0 | *lcpack=0; |
421 | 0 | nbitsgref=0; |
422 | 0 | ngroups=0; |
423 | 0 | } |
424 | | |
425 | | // |
426 | | // Fill in ref value and number of bits in Template 5.2 |
427 | | // |
428 | 0 | mkieee(&rmin,idrstmpl+0,1); // ensure reference value is IEEE format |
429 | 0 | idrstmpl[3]=nbitsgref; |
430 | 0 | idrstmpl[4]=0; // original data were reals |
431 | 0 | idrstmpl[5]=1; // general group splitting |
432 | 0 | idrstmpl[6]=0; // No internal missing values |
433 | 0 | idrstmpl[7]=0; // Primary missing value |
434 | 0 | idrstmpl[8]=0; // secondary missing value |
435 | 0 | idrstmpl[9]=ngroups; // Number of groups |
436 | 0 | idrstmpl[10]=ngwidthref; // reference for group widths |
437 | 0 | idrstmpl[11]=nbitsgwidth; // num bits used for group widths |
438 | 0 | idrstmpl[12]=nglenref; // Reference for group lengths |
439 | 0 | idrstmpl[13]=1; // length increment for group lengths |
440 | 0 | idrstmpl[14]=nglenlast; // True length of last group |
441 | 0 | idrstmpl[15]=nbitsglen; // num bits used for group lengths |
442 | 0 | if (idrsnum == 3) { |
443 | 0 | idrstmpl[17]=nbitsd/8; // num bits used for extra spatial |
444 | | // differencing values |
445 | 0 | } |
446 | |
|
447 | 0 | } |