1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "grib2.h"
4
5 g2int getdim(unsigned char *,g2int *,g2int *,g2int *);
6 g2int getpoly(unsigned char *,g2int *,g2int *,g2int *);
7 void simpack(g2float *, g2int, g2int *, unsigned char *, g2int *);
8 void cmplxpack(g2float *, g2int, g2int, g2int *, unsigned char *, g2int *);
9 void specpack(g2float *,g2int,g2int,g2int,g2int,g2int *,unsigned char *,
10 g2int *);
11 void jpcpack(g2float *,g2int,g2int,g2int *,unsigned char *,g2int *);
12 #ifdef USE_PNG
13 void pngpack(g2float *,g2int,g2int,g2int *,unsigned char *,g2int *);
14 #endif /* USE_PNG */
15
16
17
g2_addfield(unsigned char * cgrib,g2int ipdsnum,g2int * ipdstmpl,g2float * coordlist,g2int numcoord,g2int idrsnum,g2int * idrstmpl,g2float * fld,g2int ngrdpts,g2int ibmap,g2int * bmap)18 g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
19 g2float *coordlist,g2int numcoord,g2int idrsnum,g2int *idrstmpl,
20 g2float *fld,g2int ngrdpts,g2int ibmap,g2int *bmap)
21 //$$$ SUBPROGRAM DOCUMENTATION BLOCK
22 // . . . .
23 // SUBPROGRAM: g2_addfield
24 // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-05
25 //
26 // ABSTRACT: This routine packs up Sections 4 through 7 for a given field
27 // and adds them to a GRIB2 message. They are Product Definition Section,
28 // Data Representation Section, Bit-Map Section and Data Section,
29 // respectively.
30 // This routine is used with routines "g2_create", "g2_addlocal",
31 // "g2_addgrid", and "g2_gribend" to create a complete GRIB2 message.
32 // g2_create must be called first to initialize a new GRIB2 message.
33 // Also, routine g2_addgrid must be called after g2_create and
34 // before this routine to add the appropriate grid description to
35 // the GRIB2 message. Also, a call to g2_gribend is required to complete
36 // GRIB2 message after all fields have been added.
37 //
38 // PROGRAM HISTORY LOG:
39 // 2002-11-05 Gilbert
40 // 2002-12-23 Gilbert - Added complex spherical harmonic packing
41 // 2003-08-27 Gilbert - Added support for new templates using
42 // PNG and JPEG2000 algorithms/templates.
43 // 2004-11-29 Gilbert - JPEG2000 now allowed to use WMO Template no. 5.40
44 // PNG now allowed to use WMO Template no. 5.41
45 // - Added check to determine if packing algorithm failed.
46 // 2005-05-10 Gilbert - Imposed minimum size on cpack, used to hold encoded
47 // bit string.
48 // 2009-01-14 Vuong Changed structure name template to gtemplate
49 //
50 // USAGE: int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
51 // g2float *coordlist,g2int numcoord,g2int idrsnum,g2int *idrstmpl,
52 // g2float *fld,g2int ngrdpts,g2int ibmap,g2int *bmap)
53 // INPUT ARGUMENT LIST:
54 // cgrib - Char array that contains the GRIB2 message to which sections
55 // 4 through 7 should be added.
56 // ipdsnum - Product Definition Template Number ( see Code Table 4.0)
57 // ipdstmpl - Contains the data values for the specified Product Definition
58 // Template ( N=ipdsnum ). Each element of this integer
59 // array contains an entry (in the order specified) of Product
60 // Definition Template 4.N
61 // coordlist- Array containing floating point values intended to document
62 // the vertical discretisation associated to model data
63 // on hybrid coordinate vertical levels.
64 // numcoord - number of values in array coordlist.
65 // idrsnum - Data Representation Template Number ( see Code Table 5.0 )
66 // idrstmpl - Contains the data values for the specified Data Representation
67 // Template ( N=idrsnum ). Each element of this integer
68 // array contains an entry (in the order specified) of Data
69 // Representation Template 5.N
70 // Note that some values in this template (eg. reference
71 // values, number of bits, etc...) may be changed by the
72 // data packing algorithms.
73 // Use this to specify scaling factors and order of
74 // spatial differencing, if desired.
75 // fld[] - Array of data points to pack.
76 // ngrdpts - Number of data points in grid.
77 // i.e. size of fld and bmap.
78 // ibmap - Bitmap indicator ( see Code Table 6.0 )
79 // 0 = bitmap applies and is included in Section 6.
80 // 1-253 = Predefined bitmap applies
81 // 254 = Previously defined bitmap applies to this field
82 // 255 = Bit map does not apply to this product.
83 // bmap[] - Integer array containing bitmap to be added. ( if ibmap=0 )
84 //
85 // OUTPUT ARGUMENT LIST:
86 // cgrib - Character array to contain the updated GRIB2 message.
87 // Must be allocated large enough to store the entire
88 // GRIB2 message.
89 //
90 // RETURN VALUES:
91 // ierr - Return code.
92 // > 0 = Current size of updated GRIB2 message
93 // -1 = GRIB message was not initialized. Need to call
94 // routine g2_create first.
95 // -2 = GRIB message already complete. Cannot add new section.
96 // -3 = Sum of Section byte counts doesn't add to total byte count
97 // -4 = Previous Section was not 3 or 7.
98 // -5 = Could not find requested Product Definition Template.
99 // -6 = Section 3 (GDS) not previously defined in message
100 // -7 = Tried to use unsupported Data Representationi Template
101 // -8 = Specified use of a previously defined bitmap, but one
102 // does not exist in the GRIB message.
103 // -9 = GDT of one of 5.50 through 5.53 required to pack field
104 // using DRT 5.51.
105 // -10 = Error packing data field.
106 //
107 // REMARKS: Note that the Sections 4 through 7 can only follow
108 // Section 3 or Section 7 in a GRIB2 message.
109 //
110 // ATTRIBUTES:
111 // LANGUAGE: C
112 // MACHINE:
113 //
114 //$$$
115 {
116 g2int ierr;
117 const unsigned char G=0x47; // 'G'
118 const unsigned char R=0x52; // 'R'
119 const unsigned char I=0x49; // 'I'
120 const unsigned char B=0x42; // 'B'
121 const unsigned char s7=0x37; // '7'
122
123 unsigned char *cpack;
124 const g2int zero=0,one=1,four=4,five=5,six=6,seven=7;
125 const g2int minsize=50000;
126 g2int iofst,ibeg,lencurr,len,nsize;
127 g2int ilen,isecnum,i,nbits,temp,left;
128 g2int ibmprev,j,lcpack,ioctet,newlen,ndpts;
129 g2int lensec4,lensec5,lensec6,lensec7;
130 g2int issec3,isprevbmap,lpos3=0,JJ,KK,MM;
131 g2int *coordieee;
132 g2int width,height,iscan,itemp;
133 g2float *pfld;
134 gtemplate *mappds,*mapdrs;
135 const unsigned int allones=4294967295u;
136
137 ierr=0;
138 //
139 // Check to see if beginning of GRIB message exists
140 //
141 if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
142 printf("g2_addfield: GRIB not found in given message.\n");
143 printf("g2_addfield: Call to routine g2_create required to initialize GRIB message.\n");
144 ierr=-1;
145 return(ierr);
146 }
147 //
148 // Get current length of GRIB message
149 //
150 gbit(cgrib,&lencurr,96,32);
151 //
152 // Check to see if GRIB message is already complete
153 //
154 if ( cgrib[lencurr-4]==s7 && cgrib[lencurr-3]==s7 &&
155 cgrib[lencurr-2]==s7 && cgrib[lencurr-1]==s7 ) {
156 printf("g2_addfield: GRIB message already complete. Cannot add new section.\n");
157 ierr=-2;
158 return(ierr);
159 }
160 //
161 // Loop through all current sections of the GRIB message to
162 // find the last section number.
163 //
164 issec3=0;
165 isprevbmap=0;
166 len=16; // length of Section 0
167 for (;;) {
168 // Get number and length of next section
169 iofst=len*8;
170 gbit(cgrib,&ilen,iofst,32);
171 iofst=iofst+32;
172 gbit(cgrib,&isecnum,iofst,8);
173 iofst=iofst+8;
174 // Check if previous Section 3 exists
175 if (isecnum == 3) {
176 issec3=1;
177 lpos3=len;
178 }
179 // Check if a previous defined bitmap exists
180 if (isecnum == 6) {
181 gbit(cgrib,&ibmprev,iofst,8);
182 /*iofst=iofst+8;*/
183 if ((ibmprev >= 0) && (ibmprev <= 253)) isprevbmap=1;
184 }
185 len=len+ilen;
186 // Exit loop if last section reached
187 if ( len == lencurr ) break;
188 // If byte count for each section doesn't match current
189 // total length, then there is a problem.
190 if ( len > lencurr ) {
191 printf("g2_addfield: Section byte counts don''t add to total.\n");
192 printf("g2_addfield: Sum of section byte counts = %d\n",len);
193 printf("g2_addfield: Total byte count in Section 0 = %d\n",lencurr);
194 ierr=-3;
195 return(ierr);
196 }
197 }
198 //
199 // Sections 4 through 7 can only be added after section 3 or 7.
200 //
201 if ( (isecnum != 3) && (isecnum != 7) ) {
202 printf("g2_addfield: Sections 4-7 can only be added after Section 3 or 7.\n");
203 printf("g2_addfield: Section ',isecnum,' was the last found in given GRIB message.\n");
204 ierr=-4;
205 return(ierr);
206 //
207 // Sections 4 through 7 can only be added if section 3 was previously defined.
208 //
209 }
210 else if ( ! issec3) {
211 printf("g2_addfield: Sections 4-7 can only be added if Section 3 was previously included.\n");
212 printf("g2_addfield: Section 3 was not found in given GRIB message.\n");
213 printf("g2_addfield: Call to routine addgrid required to specify Grid definition.\n");
214 ierr=-6;
215 return(ierr);
216 }
217 //
218 // Add Section 4 - Product Definition Section
219 //
220 ibeg=lencurr*8; // Calculate offset for beginning of section 4
221 iofst=ibeg+32; // leave space for length of section
222 sbit(cgrib,&four,iofst,8); // Store section number ( 4 )
223 iofst=iofst+8;
224 sbit(cgrib,&numcoord,iofst,16); // Store num of coordinate values
225 iofst=iofst+16;
226 sbit(cgrib,&ipdsnum,iofst,16); // Store Prod Def Template num.
227 iofst=iofst+16;
228 //
229 // Get Product Definition Template
230 //
231 mappds=getpdstemplate(ipdsnum);
232 if (mappds == 0) { // undefined template
233 ierr=-5;
234 return(ierr);
235 }
236 //
237 // Extend the Product Definition Template, if necessary.
238 // The number of values in a specific template may vary
239 // depending on data specified in the "static" part of the
240 // template.
241 //
242 if ( mappds->needext ) {
243 free(mappds);
244 mappds=extpdstemplate(ipdsnum,ipdstmpl);
245 }
246 //
247 // Pack up each input value in array ipdstmpl into the
248 // the appropriate number of octets, which are specified in
249 // corresponding entries in array mappds.
250 //
251 for (i=0;i<mappds->maplen;i++) {
252 nbits=abs(mappds->map[i])*8;
253 if ( (mappds->map[i] >= 0) || (ipdstmpl[i] >= 0) )
254 sbit(cgrib,ipdstmpl+i,iofst,nbits);
255 else {
256 sbit(cgrib,&one,iofst,1);
257 temp=abs(ipdstmpl[i]);
258 sbit(cgrib,&temp,iofst+1,nbits-1);
259 }
260 iofst=iofst+nbits;
261 }
262 // Pack template extension, if appropriate
263 j=mappds->maplen;
264 if ( mappds->needext && (mappds->extlen > 0) ) {
265 for (i=0;i<mappds->extlen;i++) {
266 nbits=abs(mappds->ext[i])*8;
267 if ( (mappds->ext[i] >= 0) || (ipdstmpl[j] >= 0) )
268 sbit(cgrib,ipdstmpl+j,iofst,nbits);
269 else {
270 sbit(cgrib,&one,iofst,1);
271 temp=abs(ipdstmpl[j]);
272 sbit(cgrib,&temp,iofst+1,nbits-1);
273 }
274 iofst=iofst+nbits;
275 j++;
276 }
277 }
278 free(mappds);
279 //
280 // Add Optional list of vertical coordinate values
281 // after the Product Definition Template, if necessary.
282 //
283 if ( numcoord != 0 ) {
284 coordieee=(g2int *)calloc(numcoord,sizeof(g2int));
285 mkieee(coordlist,coordieee,numcoord);
286 sbits(cgrib,coordieee,iofst,32,0,numcoord);
287 iofst=iofst+(32*numcoord);
288 free(coordieee);
289 }
290 //
291 // Calculate length of section 4 and store it in octets
292 // 1-4 of section 4.
293 //
294 lensec4=(iofst-ibeg)/8;
295 sbit(cgrib,&lensec4,ibeg,32);
296 //
297 // Pack Data using appropriate algorithm
298 //
299 //
300 // Get Data Representation Template
301 //
302 mapdrs=getdrstemplate(idrsnum);
303 if (mapdrs == 0) {
304 ierr=-5;
305 return(ierr);
306 }
307 //
308 // contract data field, removing data at invalid grid points,
309 // if bit-map is provided with field.
310 //
311 if ( ibmap == 0 || ibmap==254 ) {
312 pfld=(g2float *)malloc(ngrdpts*sizeof(g2float));
313 ndpts=0;
314 for (j=0;j<ngrdpts;j++) {
315 if ( bmap[j]==1 ) pfld[ndpts++]=fld[j];
316 }
317 }
318 else {
319 ndpts=ngrdpts;
320 pfld=fld;
321 }
322 nsize=ndpts*4;
323 if ( nsize < minsize ) nsize=minsize;
324 cpack=malloc(nsize);
325 if (idrsnum == 0) // Simple Packing
326 simpack(pfld,ndpts,idrstmpl,cpack,&lcpack);
327 else if (idrsnum==2 || idrsnum==3) // Complex Packing
328 cmplxpack(pfld,ndpts,idrsnum,idrstmpl,cpack,&lcpack);
329 else if (idrsnum == 50) { // Sperical Harmonic Simple Packing
330 simpack(pfld+1,ndpts-1,idrstmpl,cpack,&lcpack);
331 mkieee(pfld+0,idrstmpl+4,1); // ensure RE(0,0) value is IEEE format
332 }
333 else if (idrsnum == 51) { // Sperical Harmonic Complex Packing
334 getpoly(cgrib+lpos3,&JJ,&KK,&MM);
335 if ( JJ!=0 && KK!=0 && MM!=0 )
336 specpack(pfld,ndpts,JJ,KK,MM,idrstmpl,cpack,&lcpack);
337 else {
338 printf("g2_addfield: Cannot pack DRT 5.51.\n");
339 return (-9);
340 }
341 }
342 else if (idrsnum == 40 || idrsnum == 40000) { /* JPEG2000 encoding */
343 if (ibmap == 255) {
344 getdim(cgrib+lpos3,&width,&height,&iscan);
345 if ( width==0 || height==0 ) {
346 width=ndpts;
347 height=1;
348 }
349 else if ( (unsigned int)width==allones || (unsigned int)height==allones ) {
350 width=ndpts;
351 height=1;
352 }
353 else if ( (iscan&32) == 32) { /* Scanning mode: bit 3 */
354 itemp=width;
355 width=height;
356 height=itemp;
357 }
358 }
359 else {
360 width=ndpts;
361 height=1;
362 }
363 lcpack=nsize;
364 jpcpack(pfld,width,height,idrstmpl,cpack,&lcpack);
365 }
366 #ifdef USE_PNG
367 else if (idrsnum == 41 || idrsnum == 40010) { /* PNG encoding */
368 if (ibmap == 255) {
369 getdim(cgrib+lpos3,&width,&height,&iscan);
370 if ( width==0 || height==0 ) {
371 width=ndpts;
372 height=1;
373 }
374 else if ( (unsigned int)width==allones || (unsigned int)height==allones ) {
375 width=ndpts;
376 height=1;
377 }
378 else if ( (iscan&32) == 32) { /* Scanning mode: bit 3 */
379 itemp=width;
380 width=height;
381 height=itemp;
382 }
383 }
384 else {
385 width=ndpts;
386 height=1;
387 }
388 pngpack(pfld,width,height,idrstmpl,cpack,&lcpack);
389 }
390 #endif /* USE_PNG */
391 else {
392 printf("g2_addfield: Data Representation Template 5.%d not yet implemented.\n",idrsnum);
393 ierr=-7;
394 return(ierr);
395 }
396 if ( ibmap == 0 || ibmap==254 ) { // free temp space
397 if (fld != pfld) free(pfld);
398 }
399 if ( lcpack < 0 ) {
400 if( cpack != 0 ) free(cpack);
401 ierr=-10;
402 return(ierr);
403 }
404
405 //
406 // Add Section 5 - Data Representation Section
407 //
408 ibeg=iofst; // Calculate offset for beginning of section 5
409 iofst=ibeg+32; // leave space for length of section
410 sbit(cgrib,&five,iofst,8); // Store section number ( 5 )
411 iofst=iofst+8;
412 sbit(cgrib,&ndpts,iofst,32); // Store num of actual data points
413 iofst=iofst+32;
414 sbit(cgrib,&idrsnum,iofst,16); // Store Data Repr. Template num.
415 iofst=iofst+16;
416 //
417 // Pack up each input value in array idrstmpl into the
418 // the appropriate number of octets, which are specified in
419 // corresponding entries in array mapdrs.
420 //
421 for (i=0;i<mapdrs->maplen;i++) {
422 nbits=abs(mapdrs->map[i])*8;
423 if ( (mapdrs->map[i] >= 0) || (idrstmpl[i] >= 0) )
424 sbit(cgrib,idrstmpl+i,iofst,nbits);
425 else {
426 sbit(cgrib,&one,iofst,1);
427 temp=abs(idrstmpl[i]);
428 sbit(cgrib,&temp,iofst+1,nbits-1);
429 }
430 iofst=iofst+nbits;
431 }
432 free(mapdrs);
433 //
434 // Calculate length of section 5 and store it in octets
435 // 1-4 of section 5.
436 //
437 lensec5=(iofst-ibeg)/8;
438 sbit(cgrib,&lensec5,ibeg,32);
439
440 //
441 // Add Section 6 - Bit-Map Section
442 //
443 ibeg=iofst; // Calculate offset for beginning of section 6
444 iofst=ibeg+32; // leave space for length of section
445 sbit(cgrib,&six,iofst,8); // Store section number ( 6 )
446 iofst=iofst+8;
447 sbit(cgrib,&ibmap,iofst,8); // Store Bit Map indicator
448 iofst=iofst+8;
449 //
450 // Store bitmap, if supplied
451 //
452 if (ibmap == 0) {
453 sbits(cgrib,bmap,iofst,1,0,ngrdpts); // Store BitMap
454 iofst=iofst+ngrdpts;
455 }
456 //
457 // If specifying a previously defined bit-map, make sure
458 // one already exists in the current GRIB message.
459 //
460 if ((ibmap==254) && ( ! isprevbmap)) {
461 printf("g2_addfield: Requested previously defined bitmap,");
462 printf(" but one does not exist in the current GRIB message.\n");
463 ierr=-8;
464 return(ierr);
465 }
466 //
467 // Calculate length of section 6 and store it in octets
468 // 1-4 of section 6. Pad to end of octet, if necessary.
469 //
470 left=8-(iofst%8);
471 if (left != 8) {
472 sbit(cgrib,&zero,iofst,left); // Pad with zeros to fill Octet
473 iofst=iofst+left;
474 }
475 lensec6=(iofst-ibeg)/8;
476 sbit(cgrib,&lensec6,ibeg,32);
477
478 //
479 // Add Section 7 - Data Section
480 //
481 ibeg=iofst; // Calculate offset for beginning of section 7
482 iofst=ibeg+32; // leave space for length of section
483 sbit(cgrib,&seven,iofst,8); // Store section number ( 7 )
484 iofst=iofst+8;
485 // Store Packed Binary Data values, if non-constant field
486 if (lcpack != 0) {
487 ioctet=iofst/8;
488 //cgrib(ioctet+1:ioctet+lcpack)=cpack(1:lcpack)
489 for (j=0;j<lcpack;j++) cgrib[ioctet+j]=cpack[j];
490 iofst=iofst+(8*lcpack);
491 }
492 //
493 // Calculate length of section 7 and store it in octets
494 // 1-4 of section 7.
495 //
496 lensec7=(iofst-ibeg)/8;
497 sbit(cgrib,&lensec7,ibeg,32);
498
499 if( cpack != 0 ) free(cpack);
500 //
501 // Update current byte total of message in Section 0
502 //
503 newlen=lencurr+lensec4+lensec5+lensec6+lensec7;
504 sbit(cgrib,&newlen,96,32);
505
506 return(newlen);
507
508 }
509