NCEPLIBS-g2c 1.9.0
Loading...
Searching...
No Matches
g2_addfield.c
Go to the documentation of this file.
1
7#include <stdio.h>
8#include <stdlib.h>
9#include "grib2_int.h"
10
100g2_addfield(unsigned char *cgrib, g2int ipdsnum, g2int *ipdstmpl,
101 float *coordlist, g2int numcoord, g2int idrsnum, g2int *idrstmpl,
102 float *fld, g2int ngrdpts, g2int ibmap, g2int *bmap)
103{
104 unsigned char *cpack;
105 static g2int zero = 0, one = 1, four = 4, five = 5, six = 6, seven = 7;
106 const g2int minsize = 50000;
107 g2int iofst, ibeg, lencurr, len, nsize;
108 g2int ilen, isecnum, i, nbits, temp, left;
109 g2int ibmprev, j, lcpack, ioctet, newlen, ndpts;
110 g2int lensec4, lensec5, lensec6, lensec7;
111 g2int issec3 = 0, isprevbmap = 0, lpos3 = 0, JJ, KK, MM;
112 g2int *coordieee;
113 float *pfld;
114 gtemplate *mappds, *mapdrs;
115#if defined USE_PNG || defined USE_JPEG2000 || defined USE_OPENJPEG || defined USE_AEC
116 unsigned int allones = 4294967295u;
117 g2int width, height, iscan, itemp;
118#endif
119 int ret;
120
121 /* Check for GRIB header and terminator. Translate the error codes
122 * to the legacy G2 error codes. */
123 if ((ret = g2c_check_msg(cgrib, &lencurr, 1)))
124 {
125 if (ret == G2C_ENOTGRIB)
126 return G2_ADD_MSG_INIT;
127 if (ret == G2C_EMSGCOMPLETE)
128 return G2_ADD_MSG_COMPLETE;
129 }
130
131 /* Loop through all current sections of the GRIB message to find
132 * the last section number. */
133 len = 16; /* length of Section 0 */
134 for (;;)
135 {
136 /* Get number and length of next section. */
137 iofst = len * 8;
138 gbit(cgrib, &ilen, iofst, 32);
139 iofst = iofst + 32;
140 gbit(cgrib, &isecnum, iofst, 8);
141 iofst = iofst + 8;
142
143 /* Check if previous Section 3 exists. */
144 if (isecnum == 3)
145 {
146 issec3 = 1;
147 lpos3 = len;
148 }
149 /* Check if a previous defined bitmap exists. */
150 if (isecnum == 6)
151 {
152 gbit(cgrib, &ibmprev, iofst, 8);
153 iofst = iofst + 8;
154 if (ibmprev >= 0 && ibmprev <= 253)
155 isprevbmap = 1;
156 }
157 len = len + ilen;
158
159 /* Exit loop if last section reached. */
160 if (len == lencurr)
161 break;
162
163 /* If byte count for each section doesn't match current */
164 /* total length, then there is a problem. */
165 if (len > lencurr)
166 {
167 printf("g2_addfield: Section byte counts don''t add to total.\n");
168 printf("g2_addfield: Sum of section byte counts = %ld\n", len);
169 printf("g2_addfield: Total byte count in Section 0 = %ld\n", lencurr);
170 return G2_BAD_SEC_COUNTS;
171 }
172 }
173
174 /* Sections 4 through 7 can only be added after section 3 or 7. */
175 if (isecnum != 3 && isecnum != 7)
176 {
177 printf("g2_addfield: Sections 4-7 can only be added after Section 3 or 7.\n");
178 printf("g2_addfield: Section %ld was the last found in given GRIB message.\n",
179 isecnum);
180 return G2_BAD_SEC;
181 }
182 else if (!issec3)
183 {
184 /* Sections 4 through 7 can only be added if section 3 was previously defined. */
185 printf("g2_addfield: Sections 4-7 can only be added if Section 3 was previously included.\n");
186 printf("g2_addfield: Section 3 was not found in given GRIB message.\n");
187 printf("g2_addfield: Call to routine addgrid required to specify Grid definition.\n");
188 return G2_ADDFIELD_BAD_GDS;
189 }
190
191 /* Add Section 4 - Product Definition Section. */
192 ibeg = lencurr * 8; /* Calculate offset for beginning of section 4 */
193 iofst = ibeg + 32; /* leave space for length of section */
194 sbit(cgrib, &four, iofst, 8); /* Store section number (4) */
195 iofst = iofst + 8;
196 sbit(cgrib, &numcoord, iofst, 16); /* Store num of coordinate values */
197 iofst = iofst + 16;
198 sbit(cgrib, &ipdsnum, iofst, 16); /* Store Prod Def Template num. */
199 iofst = iofst + 16;
200
201 /* Get Product Definition Template. */
202 if (!(mappds = getpdstemplate(ipdsnum)))
203 return G2_ADDFIELD_BAD_PDT;
204
205 /* Extend the Product Definition Template, if necessary. The */
206 /* number of values in a specific template may vary depending on */
207 /* data specified in the "static" part of the template. */
208 if (mappds->needext)
209 {
210 free(mappds);
211 mappds = extpdstemplate(ipdsnum, ipdstmpl);
212 }
213
214 /* Pack up each input value in array ipdstmpl into the the */
215 /* appropriate number of octets, which are specified in */
216 /* corresponding entries in array mappds. */
217 for (i = 0; i < mappds->maplen; i++)
218 {
219 nbits = abs(mappds->map[i]) * 8;
220 if ((mappds->map[i] >= 0) || (ipdstmpl[i] >= 0))
221 sbit(cgrib, ipdstmpl + i, iofst, nbits);
222 else
223 {
224 sbit(cgrib, &one, iofst, 1);
225 temp = abs(ipdstmpl[i]);
226 sbit(cgrib, &temp, iofst + 1, nbits-1);
227 }
228 iofst = iofst + nbits;
229 }
230
231 /* Pack template extension, if appropriate. */
232 j = mappds->maplen;
233 if (mappds->needext && (mappds->extlen > 0))
234 {
235 for (i = 0; i < mappds->extlen; i++)
236 {
237 nbits = abs(mappds->ext[i]) * 8;
238 if (mappds->ext[i] >= 0 || ipdstmpl[j] >= 0)
239 sbit(cgrib, ipdstmpl + j, iofst, nbits);
240 else
241 {
242 sbit(cgrib, &one, iofst, 1);
243 temp = abs(ipdstmpl[j]);
244 sbit(cgrib, &temp, iofst + 1, nbits - 1);
245 }
246 iofst = iofst + nbits;
247 j++;
248 }
249 }
250 if (mappds->ext)
251 free(mappds->ext);
252 free(mappds);
253
254 /* Add Optional list of vertical coordinate values after the */
255 /* Product Definition Template, if necessary. */
256 if (numcoord != 0)
257 {
258 coordieee = calloc(numcoord, sizeof(g2int));
259 mkieee(coordlist, coordieee, numcoord);
260 sbits(cgrib, coordieee, iofst, 32, 0, numcoord);
261 iofst = iofst + (32 * numcoord);
262 free(coordieee);
263 }
264
265 /* Calculate length of section 4 and store it in octets 1-4 of */
266 /* section 4. */
267 lensec4 = (iofst - ibeg) / 8;
268 sbit(cgrib, &lensec4, ibeg, 32);
269
270 /* Pack Data using appropriate algorithm Get Data Representation */
271 /* Template */
272 if (!(mapdrs = getdrstemplate(idrsnum)))
273 return G2_ADDFIELD_BAD_PDT;
274
275 /* Contract data field, removing data at invalid grid points, if */
276 /* bit-map is provided with field. */
277 if (ibmap == 0 || ibmap == 254)
278 {
279 pfld = malloc(ngrdpts * sizeof(float));
280 ndpts = 0;
281 for (j = 0; j < ngrdpts; j++)
282 {
283 if (bmap[j] == 1)
284 pfld[ndpts++] = fld[j];
285 }
286 }
287 else
288 {
289 ndpts = ngrdpts;
290 pfld = fld;
291 }
292
293 /* Allocate storage for the packed data. */
294 nsize = ndpts * 4;
295 if (nsize < minsize)
296 nsize = minsize;
297 cpack = malloc(nsize);
298
299 /* Call packing function based on idrsnum. */
300 if (idrsnum == 0) /* Simple Packing */
301 simpack(pfld, ndpts, idrstmpl, cpack, &lcpack);
302 else if (idrsnum == 2 || idrsnum == 3) /* Complex Packing */
303 cmplxpack(pfld, ndpts, idrsnum, idrstmpl, cpack, &lcpack);
304 else if (idrsnum == 50) /* Sperical Harmonic Simple Packing */
305 {
306 simpack(pfld + 1, ndpts - 1, idrstmpl, cpack, &lcpack);
307 mkieee(pfld, idrstmpl + 4, 1); /* ensure RE(0, 0) value is IEEE format */
308 }
309 else if (idrsnum == 51) /* Sperical Harmonic Complex Packing */
310 {
311 getpoly(cgrib + lpos3, &JJ, &KK, &MM);
312 if (JJ != 0 && KK != 0 && MM != 0)
313 specpack(pfld, ndpts, JJ, KK, MM, idrstmpl, cpack, &lcpack);
314 else
315 {
316 printf("g2_addfield: Cannot pack DRT 5.51.\n");
317 return G2_ADDFIELD_BAD_GDT;
318 }
319 }
320#if defined USE_JPEG2000 || defined USE_OPENJPEG
321 else if (idrsnum == 40 || idrsnum == 40000)
322 { /* JPEG2000 encoding */
323 if (ibmap == 255)
324 {
325 getdim(cgrib + lpos3, &width, &height, &iscan);
326 if (width == 0 || height == 0)
327 {
328 width = ndpts;
329 height = 1;
330 }
331 else if (width == allones || height == allones)
332 {
333 width = ndpts;
334 height = 1;
335 }
336 else if ((iscan & 32) == 32)
337 { /* Scanning mode: bit 3 */
338 itemp = width;
339 width = height;
340 height = itemp;
341 }
342 }
343 else
344 {
345 width = ndpts;
346 height = 1;
347 }
348 lcpack = nsize;
349 jpcpack(pfld, width, height, idrstmpl, cpack, &lcpack);
350 }
351#endif /* USE_JPEG2000 */
352#ifdef USE_PNG
353 else if (idrsnum == 41 || idrsnum == 40010)
354 { /* PNG encoding */
355 if (ibmap == 255)
356 {
357 getdim(cgrib + lpos3, &width, &height, &iscan);
358 if (width == 0 || height == 0)
359 {
360 width = ndpts;
361 height = 1;
362 }
363 else if (width == allones || height == allones)
364 {
365 width = ndpts;
366 height = 1;
367 }
368 else if ((iscan & 32) == 32)
369 { /* Scanning mode: bit 3 */
370 itemp = width;
371 width = height;
372 height = itemp;
373 }
374 }
375 else
376 {
377 width = ndpts;
378 height = 1;
379 }
380 pngpack(pfld, width, height, idrstmpl, cpack, &lcpack);
381 }
382#endif /* USE_PNG */
383#ifdef USE_AEC
384 else if (idrsnum == 42)
385 { /* AEC Encoding */
386 if (ibmap == 255)
387 {
388 getdim(cgrib + lpos3, &width, &height, &iscan);
389 if (width == 0 || height == 0)
390 {
391 width = ndpts;
392 height = 1;
393 }
394 else if (width == allones || height == allones)
395 {
396 width = ndpts;
397 height = 1;
398 }
399 else if ((iscan & 32) == 32)
400 { /* Scanning mode: bit 3 */
401 itemp = width;
402 width = height;
403 height = itemp;
404 }
405 }
406 else
407 {
408 width = ndpts;
409 height = 1;
410 }
411 //printf("IN G2C, in g2_addfield, using AEC compression...\n");
412 lcpack = nsize;
413 aecpack(pfld, width, height, idrstmpl, cpack, &lcpack);
414 }
415#endif /* USE_AEC */
416 else
417 {
418 printf("g2_addfield: Data Representation Template 5.%ld not yet implemented.\n", idrsnum);
419 return G2_ADDFIELD_BAD_DRT;
420 }
421
422 /* Free temp space. */
423 if (ibmap == 0 || ibmap == 254)
424 {
425 if (fld != pfld)
426 free(pfld);
427 }
428
429 /* The packing functions return an lcpack of -1 if there was an
430 * error packing. */
431 if (lcpack < 0)
432 {
433 if (cpack)
434 free(cpack);
435 return G2_ADDFIELD_ERR;
436 }
437
438 /* Add Section 5 - Data Representation Section */
439 ibeg = iofst; /* Calculate offset for beginning of section 5 */
440 iofst = ibeg + 32; /* leave space for length of section */
441 sbit(cgrib, &five, iofst, 8); /* Store section number (5) */
442 iofst = iofst + 8;
443 sbit(cgrib, &ndpts, iofst, 32); /* Store num of actual data points */
444 iofst = iofst + 32;
445 sbit(cgrib, &idrsnum, iofst, 16); /* Store Data Repr. Template num. */
446 iofst = iofst + 16;
447
448 /* Pack up each input value in array idrstmpl into the */
449 /* the appropriate number of octets, which are specified in */
450 /* corresponding entries in array mapdrs. */
451 for (i = 0; i < mapdrs->maplen; i++)
452 {
453 nbits = abs(mapdrs->map[i]) * 8;
454 if (mapdrs->map[i] >= 0 || idrstmpl[i] >= 0)
455 sbit(cgrib, idrstmpl + i, iofst, nbits);
456 else
457 {
458 sbit(cgrib, &one, iofst, 1);
459 temp = abs(idrstmpl[i]);
460 sbit(cgrib, &temp, iofst + 1, nbits - 1);
461 }
462 iofst = iofst + nbits;
463 }
464 free(mapdrs);
465
466 /* Calculate length of section 5 and store it in octets */
467 /* 1-4 of section 5. */
468 lensec5 = (iofst - ibeg) / 8;
469 sbit(cgrib, &lensec5, ibeg, 32);
470
471 /* Add Section 6 - Bit-Map Section */
472 ibeg = iofst; /* Calculate offset for beginning of section 6 */
473 iofst = ibeg + 32; /* leave space for length of section */
474 sbit(cgrib, &six, iofst, 8); /* Store section number (6) */
475 iofst = iofst + 8;
476 sbit(cgrib, &ibmap, iofst, 8); /* Store Bit Map indicator */
477 iofst = iofst + 8;
478
479 /* Store bitmap, if supplied */
480 if (ibmap == 0)
481 {
482 sbits(cgrib, bmap, iofst, 1, 0, ngrdpts); /* Store BitMap */
483 iofst = iofst + ngrdpts;
484 }
485
486 /* If specifying a previously defined bit-map, make sure */
487 /* one already exists in the current GRIB message. */
488 if (ibmap == 254 && !isprevbmap)
489 {
490 printf("g2_addfield: Requested previously defined bitmap,");
491 printf(" but one does not exist in the current GRIB message.\n");
493 }
494
495 /* Calculate length of section 6 and store it in octets */
496 /* 1-4 of section 6. Pad to end of octect, if necessary. */
497 left = 8 - (iofst % 8);
498 if (left != 8)
499 {
500 sbit(cgrib, &zero, iofst, left); /* Pad with zeros to fill Octet */
501 iofst = iofst + left;
502 }
503 lensec6 = (iofst - ibeg) / 8;
504 sbit(cgrib, &lensec6, ibeg, 32);
505
506 /* Add Section 7 - Data Section */
507 ibeg = iofst; /* Calculate offset for beginning of section 7 */
508 iofst = ibeg + 32; /* leave space for length of section */
509 sbit(cgrib, &seven, iofst, 8); /* Store section number (7) */
510 iofst = iofst + 8;
511
512 /* Store Packed Binary Data values, if non-constant field. */
513 if (lcpack != 0)
514 {
515 ioctet = iofst / 8;
516 /*cgrib(ioctet + 1:ioctet + lcpack)=cpack(1:lcpack) */
517 for (j = 0; j < lcpack; j++)
518 cgrib[ioctet + j] = cpack[j];
519 iofst = iofst + (8 * lcpack);
520 }
521
522 /* Calculate length of section 7 and store it in octets */
523 /* 1-4 of section 7. */
524 lensec7 = (iofst - ibeg) / 8;
525 sbit(cgrib, &lensec7, ibeg, 32);
526
527 if (cpack)
528 free(cpack);
529
530 /* Update current byte total of message in Section 0 */
531 newlen = lencurr + lensec4 + lensec5 + lensec6 + lensec7;
532 sbit(cgrib, &newlen, 96, 32);
533
534 return newlen;
535}
void aecpack(float *fld, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This function packs up a float array into a AEC code stream.
Definition aecpack.c:296
void cmplxpack(float *fld, g2int ndpts, g2int idrsnum, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
Pack up a data field using a complex packing algorithm.
Definition cmplxpack.c:37
gtemplate * getdrstemplate(g2int number)
This subroutine returns DRS template information for a specified Data Representation Template.
g2int g2_addfield(unsigned char *cgrib, g2int ipdsnum, g2int *ipdstmpl, float *coordlist, g2int numcoord, g2int idrsnum, g2int *idrstmpl, float *fld, g2int ngrdpts, g2int ibmap, g2int *bmap)
Pack sections 4 through 7 and adds them to a GRIB2 message.
void gbit(unsigned char *in, g2int *iout, g2int iskip, g2int nbits)
Get arbitrary size values from a packed bit string, right justifying each value in the unpacked iout ...
Definition gbits.c:20
void sbits(unsigned char *out, g2int *in, g2int iskip, g2int nbits, g2int nskip, g2int n)
Store arbitrary size values into a packed bit string, taking the low order bits from each value in th...
Definition gbits.c:178
void sbit(unsigned char *out, g2int *in, g2int iskip, g2int nbits)
Store arbitrary size values into a packed bit string, taking the low order bits from each value in th...
Definition gbits.c:38
g2int getdim(unsigned char *csec3, g2int *width, g2int *height, g2int *iscan)
Return the dimensions and scanning mode of a grid definition.
Definition getdim.c:27
g2int getpoly(unsigned char *csec3, g2int *jj, g2int *kk, g2int *mm)
This subroutine returns the J, K, and M pentagonal resolution parameters specified in a GRIB Grid Def...
Definition getpoly.c:40
#define G2_BAD_SEC_COUNTS
Sum of Section byte counts doesn't add to total byte count.
Definition grib2.h:475
#define G2_ADDFIELD_BAD_GDS
In g2_addfield() section 3 (GDS) not previously defined in message.
Definition grib2.h:477
#define G2_BAD_SEC
Previous Section was unexpected.
Definition grib2.h:463
#define G2_ADDFIELD_BAD_BITMAP
In g2_addfield() no bitmap in the GRIB message.
Definition grib2.h:479
#define G2_ADDFIELD_BAD_DRT
In g2_addfield() unsupported Data Representationi Template.
Definition grib2.h:478
#define G2_ADD_MSG_COMPLETE
GRIB message already complete.
Definition grib2.h:474
#define G2_ADDFIELD_BAD_PDT
In g2_addfield() could not find requested Product Definition Template.
Definition grib2.h:476
#define G2_ADD_MSG_INIT
GRIB message was not initialized - call g2_create() first.
Definition grib2.h:473
#define G2C_ENOTGRIB
GRIB header not found.
Definition grib2.h:493
#define G2_ADDFIELD_BAD_GDT
In g2_addfield() GDT of one of 5.50 through 5.53 required when using DRT 5.51.
Definition grib2.h:480
#define G2C_EMSGCOMPLETE
GRIB message already complete.
Definition grib2.h:494
#define G2_ADDFIELD_ERR
In g2_addfield() error packing data field.
Definition grib2.h:481
int64_t g2int
Long integer type.
Definition grib2.h:32
Header file with internal function prototypes NCEPLIBS-g2c library.
void pngpack(float *fld, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This subroutine packs up a float data field into PNG image format.
Definition pngpack.c:242
void mkieee(float *a, g2int *rieee, g2int num)
Store a list of real values in 32-bit IEEE floating point format.
Definition mkieee.c:22
g2int * ext
Number of octets of each entry in the extension part of the template.
Definition grib2_int.h:300
int g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose)
Check for 'GRIB' at the beginning of a GRIB message, and check to see if the message is already termi...
Definition util.c:26
g2int extlen
Number of entries in the template extension.
Definition grib2_int.h:296
g2int * map
Number of octets of each entry in the static part of the template.
Definition grib2_int.h:290
g2int needext
Indicates whether or not the template needs to be extended.
Definition grib2_int.h:293
void specpack(float *fld, g2int ndpts, g2int JJ, g2int KK, g2int MM, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
Pack a spectral data field using the complex packing algorithm for spherical harmonic data as defined...
Definition specpack.c:33
gtemplate * extpdstemplate(g2int number, g2int *list)
This subroutine generates the remaining octet map for a given Product Definition Template,...
void simpack(float *fld, g2int ndpts, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
Packs a data field using the simple packing algorithm.
Definition simpack.c:36
void jpcpack(float *fld, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This function packs up a float array into a JPEG2000 code stream.
Definition jpcpack.c:269
gtemplate * getpdstemplate(g2int number)
This subroutine returns PDS template information for a specified Product Definition Template.
g2int maplen
Number of entries in the static part of the template.
Definition grib2_int.h:286
Struct for GRIB template, returned by getgridtemplate().
Definition grib2_int.h:276