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