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