39#define __STDC_LIMIT_MACROS
52#include <jasper/jasper.h>
55const double GRIB_MISSING_VALUE = GRIB_NOTDEF;
70 stat_proc.t =
nullptr;
87 earth_sphere_scale_factor;
88 int earth_sphere_scale_value;
90 unsigned char earth_major_scale_factor;
92 int earth_major_scale_value;
95 unsigned char earth_minor_scale_factor;
97 int earth_minor_scale_value;
101 double slat, slon, latin1, latin2, splat, splon;
119 int rescomp, scan_mode, proj_flag;
121 int param_cat, param_num, gen_proc, time_unit, fcst_time;
122 int ens_type, perturb_num, derived_fcst_code, nfcst_in_ensemble;
123 int lvl1_type, lvl2_type;
126 int eyr, emo, edy, etime;
127 int num_ranges, nmiss;
131 int stat_proc, type, num_points;
134 int split_method, miss_val_mgmt;
135 unsigned int num_groups;
136 float primary_miss_sub, secondary_miss_sub;
141 unsigned int ref, incr, last, pack_width;
144 unsigned int order, order_vals_width;
150 int E, D, num_packed, pack_width, orig_val_type;
152 unsigned char *bitmap;
170 unsigned char *buffer;
172 int total_len, disc, ed_num;
173 int center_id, sub_center_id, table_ver, local_table_ver, ref_time_type;
174 int yr, mo, dy, time;
175 int prod_status, data_type;
182static int dec_jpeg2000(
char *injpc,
int bufsize,
int *outfld)
226 jas_image_t *image =
nullptr;
227 jas_stream_t *jpcstream;
228 jas_image_cmpt_t *pcmpt;
229 char *opts =
nullptr;
239 jpcstream = jas_stream_memopen(injpc, bufsize);
240 if (jpcstream ==
nullptr) {
241 printf(
" dec_jpeg2000: no memory\n");
247 image = jpc_decode(jpcstream, opts);
248 if (image ==
nullptr) {
249 printf(
" jpc_decode return = %d \n", ier);
253 pcmpt = image->cmpts_[0];
258 if (image->numcmpts_ != 1) {
259 printf(
"dec_jpeg2000: Found color image. Grayscale expected.\n");
267 data = jas_matrix_create(jas_image_height(image), jas_image_width(image));
268 jas_image_readcmpt(image, 0, 0, 0, jas_image_width(image),
269 jas_image_height(image), data);
274 for (i = 0; i < pcmpt->height_; i++)
275 for (j = 0; j < pcmpt->width_; j++) outfld[k++] = data->rows_[i][j];
279 jas_matrix_destroy(data);
280 ier = jas_stream_close(jpcstream);
281 jas_image_destroy(image);
287static unsigned int uint2(
unsigned char const *p) {
return (p[0] << 8) + p[1]; }
289static unsigned int uint4(
unsigned const char *p) {
290 return ((p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]);
293static int int2(
unsigned const char *p) {
296 i = -(((p[0] & 0x7f) << 8) + p[1]);
298 i = (p[0] << 8) + p[1];
303static int int4(
unsigned const char *p) {
306 i = -(((p[0] & 0x7f) << 24) + (p[1] << 16) + (p[2] << 8) + p[3]);
308 i = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
313static float ieee2flt(
unsigned const char *ieee) {
317 if ((ieee[0] & 127) == 0 && ieee[1] == 0 && ieee[2] == 0 && ieee[3] == 0)
320 exp = ((ieee[0] & 127) << 1) + (ieee[1] >> 7);
321 fmant = (double)((
int)ieee[3] + (int)(ieee[2] << 8) +
322 (int)((ieee[1] | 128) << 16));
323 if (ieee[0] & 128) fmant = -fmant;
325 return (
float)(ldexp(fmant, (
int)(exp - 128 - 22)));
328static inline void getBits(
unsigned const char *buf,
int *loc,
size_t first,
336 zuint oct = first / 8;
337 zuint bit = first % 8;
339 zuint val = (buf[oct] << 24) + (buf[oct + 1] << 16) + (buf[oct + 2] << 8) +
342 val = val >> (32 - nbBits);
352 size_t ofs = grib_msg->offset / 8;
353 unsigned char *b = grib_msg->buffer + ofs;
357 grib_msg->center_id = uint2(b + 5);
358 grib_msg->sub_center_id = uint2(b + 7);
359 grib_msg->table_ver = b[9];
360 grib_msg->local_table_ver = b[10];
361 grib_msg->ref_time_type = b[11];
362 grib_msg->yr = uint2(b + 12);
363 grib_msg->mo = b[14];
364 grib_msg->dy = b[15];
368 grib_msg->time = hh * 10000 + mm * 100 + ss;
369 grib_msg->prod_status = b[19];
370 grib_msg->data_type = b[20];
371 grib_msg->offset += length * 8;
374static bool unpackLUS(
GRIBMessage *grib_msg) {
return true; }
377 size_t ofs = grib_msg->offset / 8;
378 unsigned char *b = grib_msg->buffer + ofs;
380 grib_msg->md.earth_shape = b[14];
382 grib_msg->md.earth_sphere_scale_factor =
384 grib_msg->md.earth_sphere_scale_value =
387 grib_msg->md.earth_major_scale_factor =
389 grib_msg->md.earth_major_scale_value =
392 grib_msg->md.earth_minor_scale_factor =
394 grib_msg->md.earth_minor_scale_value =
399 int src, num_in_list;
400 size_t ofs = grib_msg->offset / 8;
401 unsigned char *b = grib_msg->buffer + ofs;
405 fprintf(stderr,
"Don't recognize predetermined grid definitions");
410 if (num_in_list > 0) {
411 fprintf(stderr,
"Unable to unpack quasi-regular grids");
416 grib_msg->md.gds_templ_num = uint2(b + 12);
417 switch (grib_msg->md.gds_templ_num) {
421 parse_earth(grib_msg);
423 grib_msg->md.nx = uint4(b + 30);
424 grib_msg->md.ny = uint4(b + 34);
427 int4(b + 46) / 1000000.;
429 int4(b + 50) / 1000000.;
431 grib_msg->md.rescomp = b[54];
433 grib_msg->md.lats.elat =
434 int4(b + 55) / 1000000.;
435 grib_msg->md.lons.elon =
436 int4(b + 59) / 1000000.;
438 grib_msg->md.xinc.loinc =
439 uint4(b + 63) / 1000000.;
441 if (grib_msg->md.gds_templ_num == 0)
442 grib_msg->md.yinc.lainc =
443 uint4(b + 67) / 1000000.;
445 grib_msg->md.scan_mode = b[71];
448 parse_earth(grib_msg);
450 grib_msg->md.nx = uint4(b + 30);
451 grib_msg->md.ny = uint4(b + 34);
454 int4(b + 38) / 1000000.;
456 int4(b + 42) / 1000000.;
458 grib_msg->md.rescomp = b[46];
464 grib_msg->md.lats.elat =
465 int4(b + 51) / 1000000.;
466 grib_msg->md.lons.elon =
467 int4(b + 55) / 1000000.;
469 grib_msg->md.scan_mode = b[59];
471 grib_msg->md.xinc.loinc = uint4(b + 64) / 1000.;
472 grib_msg->md.yinc.lainc = uint4(b + 68) / 1000.;
475 parse_earth(grib_msg);
477 grib_msg->md.nx = uint4(b + 30);
478 grib_msg->md.ny = uint4(b + 34);
481 int4(b + 38) / 1000000.;
483 int4(b + 42) / 1000000.;
485 grib_msg->md.rescomp = b[46];
487 grib_msg->md.lats.lad = int4(b + 47) / 1000000.;
488 grib_msg->md.lons.lov = int4(b + 51) / 1000000.;
490 grib_msg->md.xinc.dxinc =
491 int4(b + 55) / 1000.;
492 grib_msg->md.yinc.dyinc =
493 int4(b + 59) / 1000.;
495 grib_msg->md.proj_flag = b[63];
496 grib_msg->md.scan_mode = b[64];
498 grib_msg->md.latin1 = int4(b + 65) / 1000000.;
499 grib_msg->md.latin2 = int4(b + 69) / 1000000.;
502 int4(b + 73) / 1000000.;
508 fprintf(stderr,
"Grid template %d is not understood\n",
509 grib_msg->md.gds_templ_num);
515static void unpack_stat_proc(
GRIBMessage *grib_msg,
unsigned const char *b) {
519 grib_msg->md.stat_proc.eyr = uint2(b);
520 grib_msg->md.stat_proc.emo = b[2];
521 grib_msg->md.stat_proc.edy = b[3];
525 grib_msg->md.stat_proc.etime = hh * 10000 + mm * 100 + ss;
527 grib_msg->md.stat_proc.num_ranges =
529 grib_msg->md.stat_proc.nmiss =
532 if (grib_msg->md.stat_proc.t != 0) {
533 delete[] grib_msg->md.stat_proc.t;
535 grib_msg->md.stat_proc.t =
538 for (n = 0; n < (size_t)grib_msg->md.stat_proc.num_ranges; n++) {
539 grib_msg->md.stat_proc.t[n].proc_code = b[off];
540 grib_msg->md.stat_proc.t[n].incr_type = b[off + 1];
541 grib_msg->md.stat_proc.t[n].time_unit = b[off + 2];
542 grib_msg->md.stat_proc.t[n].time_length = uint4(b + off + 3);
543 grib_msg->md.stat_proc.t[n].incr_unit = b[off + 7];
544 grib_msg->md.stat_proc.t[n].incr_length = uint4(b + off + 8);
551 int num_coords, factor;
552 size_t ofs = grib_msg->offset / 8;
553 unsigned char *b = grib_msg->buffer + ofs;
555 num_coords = uint2(b + 5);
556 if (num_coords > 0) {
557 fprintf(stderr,
"Unable to decode hybrid coordinates");
561 grib_msg->md.pds_templ_num =
563 grib_msg->md.stat_proc.num_ranges = 0;
564 switch (grib_msg->md.pds_templ_num) {
572 grib_msg->md.ens_type = -1;
573 grib_msg->md.derived_fcst_code = -1;
574 grib_msg->md.spatial_proc.type = -1;
575 grib_msg->md.param_cat = b[9];
576 grib_msg->md.param_num = b[10];
577 grib_msg->md.gen_proc = b[11];
579 grib_msg->md.time_unit = b[17];
580 grib_msg->md.fcst_time = uint4(b + 18);
582 grib_msg->md.lvl1_type = b[22];
584 grib_msg->md.lvl1 = int4(b + 24) / pow(10., (
double)factor);
586 grib_msg->md.lvl2_type = b[28];
588 grib_msg->md.lvl2 = int4(b + 30) / pow(10., (
double)factor);
590 switch (grib_msg->md.pds_templ_num) {
593 grib_msg->md.ens_type = b[34];
594 grib_msg->md.perturb_num = b[35];
595 grib_msg->md.nfcst_in_ensemble = b[36];
597 switch (grib_msg->md.pds_templ_num) {
599 unpack_stat_proc(grib_msg, b + 37);
605 grib_msg->md.derived_fcst_code = b[34];
606 grib_msg->md.nfcst_in_ensemble = b[35];
608 switch (grib_msg->md.pds_templ_num) {
610 unpack_stat_proc(grib_msg, b + 36);
615 unpack_stat_proc(grib_msg, b + 34);
618 grib_msg->md.spatial_proc.stat_proc = b[34];
619 grib_msg->md.spatial_proc.type = b[35];
620 grib_msg->md.spatial_proc.num_points = b[36];
625 fprintf(stderr,
"Product Definition Template %d is not understood\n",
626 grib_msg->md.pds_templ_num);
634 size_t ofs = grib_msg->offset / 8;
635 unsigned char *b = grib_msg->buffer + ofs;
637 grib_msg->md.num_packed = uint4(b + 5);
638 grib_msg->md.drs_templ_num =
641 switch (grib_msg->md.drs_templ_num) {
643 grib_msg->md.precision = b[11];
655 grib_msg->md.R = ieee2flt(b + 11);
656 grib_msg->md.E = int2(b + 15);
657 grib_msg->md.D = int2(b + 17);
658 grib_msg->md.R /= pow(10., grib_msg->md.D);
660 grib_msg->md.pack_width = b[19];
661 grib_msg->md.orig_val_type = b[20];
663 if (grib_msg->md.drs_templ_num == 3 || grib_msg->md.drs_templ_num == 2) {
664 grib_msg->md.complex_pack.split_method = b[21];
665 grib_msg->md.complex_pack.miss_val_mgmt = b[22];
666 if (grib_msg->md.orig_val_type == 0) {
667 grib_msg->md.complex_pack.primary_miss_sub = ieee2flt(b + 23);
668 grib_msg->md.complex_pack.secondary_miss_sub = ieee2flt(b + 27);
669 }
else if (grib_msg->md.orig_val_type == 1) {
670 grib_msg->md.complex_pack.primary_miss_sub = uint4(b + 23);
671 grib_msg->md.complex_pack.secondary_miss_sub = uint4(b + 27);
674 "Unable to decode missing value substitutes for original "
676 grib_msg->md.orig_val_type);
679 grib_msg->md.complex_pack.num_groups = uint4(b + 31);
681 grib_msg->md.complex_pack.width.ref = b[35];
682 grib_msg->md.complex_pack.width.pack_width = b[36];
684 grib_msg->md.complex_pack.length.ref = uint4(b + 37);
685 grib_msg->md.complex_pack.length.incr = b[41];
686 grib_msg->md.complex_pack.length.last = uint4(b + 42);
687 grib_msg->md.complex_pack.length.pack_width = b[46];
689 if (grib_msg->md.drs_templ_num == 3) {
690 grib_msg->md.complex_pack.spatial_diff.order = b[47];
691 grib_msg->md.complex_pack.spatial_diff.order_vals_width = b[48];
693 grib_msg->md.complex_pack.spatial_diff.order = 0;
694 grib_msg->md.complex_pack.spatial_diff.order_vals_width = 0;
698 fprintf(stderr,
"Data template %d is not understood\n",
699 grib_msg->md.drs_templ_num);
707 int ind, len, n, bit;
708 size_t ofs = grib_msg->offset / 8;
709 unsigned char *b = grib_msg->buffer + ofs;
716 if (len < 7)
return false;
718 grib_msg->md.bmssize = len;
720 delete[] grib_msg->md.bitmap;
721 delete[] grib_msg->md.bms;
722 grib_msg->md.bitmap =
new unsigned char[len];
723 grib_msg->md.bms =
new zuchar[grib_msg->md.bmssize];
724 memcpy(grib_msg->md.bms, b + 6, grib_msg->md.bmssize);
725 for (n = 0; n < len; n++) {
726 getBits(grib_msg->buffer, &bit, grib_msg->offset + 48 + n, 1);
727 grib_msg->md.bitmap[n] = bit;
734 delete[] grib_msg->md.bitmap;
735 grib_msg->md.bitmap =
nullptr;
736 delete[] grib_msg->md.bms;
737 grib_msg->md.bms =
nullptr;
738 grib_msg->md.bmssize = 0;
742 "This code is not currently set up to deal with predefined "
755 int *ref_vals, *widths;
757 int *first_vals = 0, sign, omin;
758 long long miss_val, group_miss_val;
761 float lastgp, D = pow(10., grib_msg->md.D), E = pow(2., grib_msg->md.E);
764 groups.first_vals =
nullptr;
766 off = grib_msg->offset + 40;
767 int npoints = grib_msg->md.ny * grib_msg->md.nx;
768 switch (grib_msg->md.drs_templ_num) {
770 grib_msg->grids.gridpoints =
new double[npoints];
771 for (l = 0; l < npoints; l++) {
772 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
773 getBits(grib_msg->buffer, &pval, off, grib_msg->md.pack_width);
774 grib_msg->grids.gridpoints[l] = grib_msg->md.R + pval * E / D;
775 off += grib_msg->md.pack_width;
777 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
781 if (grib_msg->md.complex_pack.num_groups > 0) {
782 if (grib_msg->md.complex_pack.spatial_diff.order) {
784 new int[grib_msg->md.complex_pack.spatial_diff.order];
785 for (n = 0; n < grib_msg->md.complex_pack.spatial_diff.order; ++n) {
787 grib_msg->buffer, &groups.first_vals[n], off,
788 grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8);
789 off += grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8;
792 getBits(grib_msg->buffer, &groups.sign, off, 1);
794 grib_msg->buffer, &groups.omin, off + 1,
795 grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8 - 1);
796 if (groups.sign == 1) {
797 groups.omin = -groups.omin;
799 off += grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8;
803 grib_msg->grids.gridpoints =
new double[npoints];
804 if (grib_msg->md.complex_pack.num_groups == 0) {
805 for (l = 0; l < npoints; ++l) {
806 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
810 if (grib_msg->md.complex_pack.miss_val_mgmt > 0) {
811 groups.miss_val = pow(2., grib_msg->md.pack_width) - 1;
813 groups.miss_val = GRIB_MISSING_VALUE;
816 groups.ref_vals =
new int[grib_msg->md.complex_pack.num_groups];
817 groups.widths =
new int[grib_msg->md.complex_pack.num_groups];
818 groups.lengths =
new int[grib_msg->md.complex_pack.num_groups];
820 for (n = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
821 getBits(grib_msg->buffer, &groups.ref_vals[n], off,
822 grib_msg->md.pack_width);
823 off += grib_msg->md.pack_width;
825 off = (off + 7) & ~7;
827 for (n = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
828 getBits(grib_msg->buffer, &groups.widths[n], off,
829 grib_msg->md.complex_pack.width.pack_width);
830 groups.widths[n] += grib_msg->md.complex_pack.width.ref;
831 off += grib_msg->md.complex_pack.width.pack_width;
833 off = (off + 7) & ~7;
835 for (n = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
836 getBits(grib_msg->buffer, &groups.lengths[n], off,
837 grib_msg->md.complex_pack.length.pack_width);
838 off += grib_msg->md.complex_pack.length.pack_width;
840 off = (off + 7) & ~7;
842 groups.max_length = 0;
843 for (n = 0; n < grib_msg->md.complex_pack.num_groups - 1; ++n) {
845 grib_msg->md.complex_pack.length.ref +
846 groups.lengths[n] * grib_msg->md.complex_pack.length.incr;
847 if (groups.lengths[n] > groups.max_length) {
848 groups.max_length = groups.lengths[n];
851 groups.lengths[n] = grib_msg->md.complex_pack.length.last;
852 if (groups.lengths[n] > groups.max_length) {
853 groups.max_length = groups.lengths[n];
856 for (n = 0, l = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
857 if (groups.widths[n] > 0) {
858 if (grib_msg->md.complex_pack.miss_val_mgmt > 0) {
859 groups.group_miss_val = pow(2., groups.widths[n]) - 1;
861 groups.group_miss_val = GRIB_MISSING_VALUE;
863 for (
int i = 0; i < groups.lengths[n];) {
864 if (grib_msg->md.bitmap !=
nullptr && grib_msg->md.bitmap[l] == 0) {
865 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
867 getBits(grib_msg->buffer, &pval, off, groups.widths[n]);
868 off += groups.widths[n];
869 if (pval == groups.group_miss_val) {
870 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
872 grib_msg->grids.gridpoints[l] =
873 pval + groups.ref_vals[n] + groups.omin;
880 for (
int i = 0; i < groups.lengths[n];) {
881 if (grib_msg->md.bitmap !=
nullptr && grib_msg->md.bitmap[l] == 0) {
882 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
884 if (groups.ref_vals[n] == groups.miss_val) {
885 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
887 grib_msg->grids.gridpoints[l] =
888 groups.ref_vals[n] + groups.omin;
897 for (; l < npoints; ++l) {
898 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
901 if (grib_msg->md.drs_templ_num == 3) {
902 if (groups.first_vals !=
nullptr) {
903 for (n = grib_msg->md.complex_pack.spatial_diff.order - 1; n > 0;
905 lastgp = groups.first_vals[n] - groups.first_vals[n - 1];
906 for (l = 0, m = 0; l < grib_msg->md.nx * grib_msg->md.ny; ++l) {
907 if (grib_msg->grids.gridpoints[l] != GRIB_MISSING_VALUE) {
908 if (m >= grib_msg->md.complex_pack.spatial_diff.order) {
909 grib_msg->grids.gridpoints[l] += lastgp;
910 lastgp = grib_msg->grids.gridpoints[l];
917 for (l = 0, m = 0, lastgp = 0; l < npoints; ++l) {
918 if (grib_msg->grids.gridpoints[l] != GRIB_MISSING_VALUE) {
919 if (m < grib_msg->md.complex_pack.spatial_diff.order) {
920 grib_msg->grids.gridpoints[l] =
921 grib_msg->md.R + groups.first_vals[m] * E / D;
922 lastgp = grib_msg->md.R * D / E + groups.first_vals[m];
924 lastgp += grib_msg->grids.gridpoints[l];
925 grib_msg->grids.gridpoints[l] = lastgp * E / D;
930 delete[] groups.first_vals;
932 for (l = 0; l < npoints; ++l) {
933 if (grib_msg->grids.gridpoints[l] != GRIB_MISSING_VALUE) {
934 grib_msg->grids.gridpoints[l] =
935 grib_msg->md.R + grib_msg->grids.gridpoints[l] * E / D;
938 delete[] groups.ref_vals;
939 delete[] groups.widths;
940 delete[] groups.lengths;
944 if (grib_msg->md.precision == 1) {
945 grib_msg->grids.gridpoints =
new double[npoints];
946 for (
int ll = 0; ll < npoints; ll++) {
947 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[ll] == 1) {
948 grib_msg->grids.gridpoints[ll] =
949 ieee2flt(grib_msg->buffer + off / 8);
952 grib_msg->grids.gridpoints[ll] = GRIB_MISSING_VALUE;
954 }
else if (grib_msg->md.precision == 2) {
955 static const int one = 1;
956 bool const is_lsb = *((
char *)&one) == 1;
957 grib_msg->grids.gridpoints =
new double[npoints];
958 for (l = 0; l < npoints; l++) {
959 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
962 unsigned char temp[8];
963 for (
int j = 0; j < 8; j++) {
964 temp[j] = grib_msg->buffer[off / 8 + 7 - j];
968 memcpy(&d, grib_msg->buffer + off / 8, 8);
970 grib_msg->grids.gridpoints[l] = d;
973 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
977 "g2_unpack7: Invalid precision=%d for Data Section 5.4.\n",
978 grib_msg->md.precision);
985 int len, *jvals, cnt;
986 getBits(grib_msg->buffer, &len, grib_msg->offset, 32);
987 if (len < 5)
return false;
989 jvals =
new int[npoints];
990 grib_msg->grids.gridpoints =
new double[npoints];
992 dec_jpeg2000((
char *)&grib_msg->buffer[grib_msg->offset / 8 + 5], len,
995 for (l = 0; l < npoints; l++) {
996 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
997 if (len == 0) jvals[cnt] = 0;
998 grib_msg->grids.gridpoints[l] = grib_msg->md.R + jvals[cnt++] * E / D;
1000 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
1006 erreur(
"Unknown packing %d", grib_msg->md.drs_templ_num);
1012static zuchar GRBV2_TO_DATA(
int productDiscipline,
int dataCat,
int dataNum) {
1015 switch (productDiscipline) {
1044 ret = GRB_HUMID_SPEC;
1047 ret = GRB_HUMID_REL;
1050 ret = GRB_PRECIP_RATE;
1055 ret = GRB_PRECIP_TOT;
1058 ret = GRB_SNOW_DEPTH;
1061 ret = GRB_FRZRAIN_CATEG;
1065 ret = GRB_SNOW_CATEG;
1075 ret = GRB_WIND_SPEED;
1084 ret = GRB_WIND_GUST;
1098 ret = GRB_GEOPOT_HGT;
1109 ret = GRB_CLOUD_TOT;
1125 ret = GRB_COMP_REFL;
1136 case 3: ret= GRB_WVHGT;
break;
1137 DATA_TO_GRBV2[DATA_WAVES_WND_DIR] = grb2DataType(10,0,4);
1138 DATA_TO_GRBV2[DATA_WAVES_WND_HGT] = grb2DataType(10,0,5);
1139 DATA_TO_GRBV2[DATA_WAVES_WND_PERIOD] = grb2DataType(10,0,6);
1140 DATA_TO_GRBV2[DATA_WAVES_SWL_DIR] = grb2DataType(10,0,7);
1141 DATA_TO_GRBV2[DATA_WAVES_SWL_HGT] = grb2DataType(10,0,8);
1142 DATA_TO_GRBV2[DATA_WAVES_SWL_PERIOD] = grb2DataType(10,0,9);
1143 DATA_TO_GRBV2[DATA_WAVES_PRIM_DIR] = grb2DataType(10,0,10);
1144 DATA_TO_GRBV2[DATA_WAVES_PRIM_PERIOD] = grb2DataType(10,0,11);
1145 DATA_TO_GRBV2[DATA_WAVES_SEC_DIR] = grb2DataType(10,0,12);
1146 DATA_TO_GRBV2[DATA_WAVES_SEC_PERIOD] = grb2DataType(10,0,13);
1178 ret = GRB_CUR_SPEED;
1200 erreur(
"unknown Discipline %d dataCat %d dataNum %d", productDiscipline,
1208static int mapStatisticalEndTime(
GRIBMessage *grid) {
1212 if (grid->md.time_unit == grid->md.stat_proc.t[0].time_unit)
1213 switch (grid->md.time_unit) {
1217 return grid->md.fcst_time + grid->md.stat_proc.t[0].time_length;
1220 return (grid->md.stat_proc.edy - grid->dy);
1222 return (grid->md.stat_proc.emo - grid->mo);
1224 return (grid->md.stat_proc.eyr - grid->yr);
1226 fprintf(stderr,
"Unable to map end time with units %d to GRIB1\n",
1227 grid->md.time_unit);
1231 if (grid->md.time_unit == 0 && grid->md.stat_proc.t[0].time_unit == 1) {
1233 return grid->md.fcst_time + grid->md.stat_proc.t[0].time_length * 60;
1236 if (grid->md.time_unit == 1 && grid->md.stat_proc.t[0].time_unit == 0 &&
1237 (grid->md.stat_proc.t[0].time_unit % 60) != 0) {
1239 return grid->md.fcst_time + grid->md.stat_proc.t[0].time_length / 60;
1242 fprintf(stderr,
"Unable to map end time %d %d %d %d \n", grid->md.time_unit,
1243 grid->md.stat_proc.t[0].time_unit, grid->md.fcst_time,
1244 grid->md.stat_proc.t[0].time_length);
1249static bool mapTimeRange(
GRIBMessage *grid, zuint *p1, zuint *p2,
1250 zuchar *t_range,
int *n_avg,
int *n_missing,
1252 switch (grid->md.pds_templ_num) {
1258 *p1 = grid->md.fcst_time;
1260 *n_avg = *n_missing = 0;
1265 if (grid->md.stat_proc.num_ranges > 1) {
1266 if (center == 7 && grid->md.stat_proc.num_ranges == 2) {
1268 *p2 = grid->md.stat_proc.t[0].incr_length;
1269 *p1 = *p2 - grid->md.stat_proc.t[1].time_length;
1270 *n_avg = grid->md.stat_proc.t[0].time_length;
1271 switch (grid->md.stat_proc.t[0].proc_code) {
1320 "Unable to map NCEP statistical process code %d to GRIB1\n",
1321 grid->md.stat_proc.t[0].proc_code);
1326 "Unable to map multiple statistical processes to GRIB1\n");
1330 switch (grid->md.stat_proc.t[0].proc_code) {
1334 switch (grid->md.stat_proc.t[0].proc_code) {
1345 *p1 = grid->md.fcst_time;
1346 *p2 = mapStatisticalEndTime(grid);
1347 if (*p2 == UINT_MAX) {
1350 if (grid->md.stat_proc.t[0].incr_length == 0)
1353 fprintf(stderr,
"Unable to map discrete processing to GRIB1\n");
1361 *p1 = grid->md.fcst_time;
1362 *p2 = mapStatisticalEndTime(grid);
1363 if (*p2 == UINT_MAX) {
1366 if (grid->md.stat_proc.t[0].incr_length == 0)
1369 fprintf(stderr,
"Unable to map discrete processing to GRIB1\n");
1375 if (grid->md.stat_proc.t[0].proc_code == 255 && center == 7) {
1376 if (grid->disc == 0) {
1377 if (grid->md.param_cat == 0) {
1378 switch (grid->md.param_num) {
1382 *p1 = grid->md.fcst_time;
1383 *p2 = mapStatisticalEndTime(grid);
1384 if (*p2 == UINT_MAX) {
1387 if (grid->md.stat_proc.t[0].incr_length == 0)
1391 "Unable to map discrete processing to GRIB1\n");
1399 fprintf(stderr,
"Unable to map statistical process %d to GRIB1\n",
1400 grid->md.stat_proc.t[0].proc_code);
1405 *n_missing = grid->md.stat_proc.nmiss;
1409 "Unable to map time range for Product Definition Template %d "
1411 grid->md.pds_templ_num);
1420void GribV2Record::translateDataType() {
1427 multiplyAllData(3600.0);
1545void GribV2Record::readDataSet(
ZUFILE *file) {
1556 while (strncmp(&((
char *)grib_msg->buffer)[grib_msg->offset / 8],
"7777",
1559 getBits(grib_msg->buffer, &len, grib_msg->offset, 32);
1560 getBits(grib_msg->buffer, &sec_num, grib_msg->offset + 4 * 8, 8);
1563 if (skip ==
true)
break;
1564 ok = unpackLUS(grib_msg);
1567 if (skip ==
true)
break;
1568 ok = unpackGDS(grib_msg);
1570 Ni = grib_msg->md.nx;
1571 Nj = grib_msg->md.ny;
1572 La1 = grib_msg->md.slat;
1573 Lo1 = grib_msg->md.slon;
1574 La2 = grib_msg->md.lats.elat;
1575 Lo2 = grib_msg->md.lons.elon;
1576 Di = grib_msg->md.xinc.loinc;
1577 Dj = grib_msg->md.yinc.lainc;
1578 scan_flags = grib_msg->md.scan_mode;
1579 is_scan_i_positive = (scan_flags & 0x80) == 0;
1580 is_scan_j_positive = (scan_flags & 0x40) != 0;
1581 is_adjacent_i = (scan_flags & 0x20) == 0;
1586 if (is_scan_i_positive)
1604 if (Ni <= 1 || Nj <= 1) {
1605 erreur(
"Record %d: Ni=%d Nj=%d",
id, Ni, Nj);
1608 Di = (
Lo2 -
Lo1) / (Ni - 1);
1609 Dj = (La2 - La1) / (Nj - 1);
1614 if (skip ==
true)
break;
1615 ok = unpackPDS(grib_msg);
1620 productTemplate = grib_msg->md.pds_templ_num;
1621 dataCat = grib_msg->md.param_cat;
1622 dataNum = grib_msg->md.param_num;
1623 data_type = GRBV2_TO_DATA(productDiscipline, dataCat, dataNum);
1632 if (grib_msg->md.lvl2_type == 8 && grib_msg->md.lvl1_type == 1) {
1637 int n_avg, n_missing;
1646 SetRecordCurrentDate(MakeDate(
refyear, refmonth, refday, refhour,
1655 if (skip ==
true)
break;
1656 ok = unpackDRS(grib_msg);
1659 if (skip ==
true)
break;
1660 ok = unpackBMS(grib_msg);
1662 if (grib_msg->md.bmssize != 0) {
1664 bms_size = grib_msg->md.bmssize;
1665 bms_bits =
new zuchar[grib_msg->md.bmssize];
1666 memcpy(bms_bits, grib_msg->md.bms, grib_msg->md.bmssize);
1671 if (skip ==
false) {
1672 ok = unpackDS(grib_msg);
1674 data = grib_msg->grids.gridpoints;
1675 grib_msg->grids.gridpoints = 0;
1678 if (grib_msg->num_grids != 1) DS =
true;
1681 grib_msg->offset += len * 8;
1682 if (
ok ==
false || DS ==
true)
break;
1688 printf(
"==== GV2 %d\n",
ok);
1689 printf(
"Lo1=%f Lo2=%f La1=%f La2=%f\n",
Lo1,
Lo2, La1, La2);
1690 printf(
"Lo1=%f Lo2=%f La1=%f La2=%f\n", grib_msg->md.slon,
1691 grib_msg->md.lons.elon, grib_msg->md.slat, grib_msg->md.lats.elat);
1692 printf(
"Ni=%d Nj=%d\n", Ni, Nj);
1693 printf(
"has_di_dj=%d Di,Dj=(%f %f)\n", has_di_dj, Di, Dj);
1694 printf(
"is_scan_i_positive=%d is_scan_j_positive=%d is_adjacent_i=%d\n",
1695 is_scan_i_positive, is_scan_j_positive, is_adjacent_i);
1696 printf(
"hasBMS=%d\n",
hasBMS);
1700 translateDataType();
1705 strncmp(&((
char *)grib_msg->buffer)[grib_msg->offset / 8],
"7777", 4) ==
1713GribV2Record::GribV2Record(
ZUFILE *file,
int id_) {
1715 seekStart = zu_tell(file);
1723 long start = seekStart;
1730 if (zu_read(file, strgrib, 4) != 4) {
1736 bool b_haveReadGRIB =
false;
1738 if (strncmp(strgrib,
"GRIB", 4) != 0)
1741 b_len_add_8 =
false;
1742 b_haveReadGRIB =
true;
1746 if ((strgrib[0] == 0) && (strgrib[1] == 0) && (strgrib[2] == 0) &&
1747 (strgrib[3] == 0)) {
1748 b_len_add_8 =
false;
1749 b_haveReadGRIB =
false;
1751 ok = readGribSection0_IS(file,
1756 unpackIDS(grib_msg);
1759 off = grib_msg->offset / 8;
1760 while (strncmp(&((
char *)grib_msg->buffer)[off],
"7777", 4) != 0) {
1761 len = uint4(grib_msg->buffer + off);
1762 sec_num = grib_msg->buffer[off + 4];
1763 if (sec_num == 7) grib_msg->num_grids++;
1768 (void)zu_seek(file, start, SEEK_SET);
1772 refmonth = grib_msg->mo;
1773 refday = grib_msg->dy;
1774 refhour = grib_msg->time / 10000;
1775 refminute = (grib_msg->time / 100) % 100;
1776 ref_date = MakeDate(
refyear, refmonth, refday, refhour, refminute, 0);
1777 sprintf(str_ref_date,
"%04d-%02d-%02d %02d:%02d",
refyear, refmonth, refday,
1778 refhour, refminute);
1782 productDiscipline = grib_msg->disc;
1787bool GribV2Record::hasMoreDataSet()
const {
1788 return grib_msg && grib_msg->num_grids != 1 ? true :
false;
1795 delete[] rec1->data;
1796 delete[] rec1->bms_bits;
1800 rec1->readDataSet(file);
1807#pragma warning(disable : 4717)
1810#pragma warning(default : 4717)
1813GribV2Record::~GribV2Record() {
delete grib_msg; }
1822 unsigned char temp[16];
1826 if (grib_msg->buffer !=
nullptr) {
1827 delete[] grib_msg->buffer;
1828 grib_msg->buffer =
nullptr;
1830 grib_msg->num_grids = 0;
1832 if ((status = zu_read(fp, &temp[4], 12)) != 12) {
1835 grib_msg->disc = temp[6];
1836 grib_msg->ed_num = temp[7];
1839 if (grib_msg->ed_num != 2)
return false;
1841 getBits(temp, &grib_msg->total_len, 96, 32);
1843 if (grib_msg->total_len < 16 || grib_msg->total_len > (INT_MAX - 4))
1846 grib_msg->md.nx = grib_msg->md.ny = 0;
1847 grib_msg->buffer =
new unsigned char[grib_msg->total_len + 4];
1848 memcpy(grib_msg->buffer, temp, 16);
1849 num = grib_msg->total_len - 16;
1851 status = zu_read(fp, &grib_msg->buffer[16], num);
1852 if (status != (
int)num)
return false;
1854 if (strncmp(&((
char *)grib_msg->buffer)[grib_msg->total_len - 4],
"7777",
1856 fprintf(stderr,
"Warning: no end section found\n");
1858 grib_msg->offset = 128;
1862bool GribV2Record::readGribSection0_IS(
ZUFILE *file,
bool b_skip_initial_GRIB) {
1864 fileOffset0 = zu_tell(file);
1866 if (!b_skip_initial_GRIB) {
1868 while ((zu_read(file, strgrib, 1) == 1) && (strgrib[0] !=
'G')) {
1871 if (strgrib[0] !=
'G') {
1876 if (zu_read(file, strgrib + 1, 3) != 3) {
1881 if (strncmp(strgrib,
"GRIB", 4) != 0) {
1882 printf(
"readGribSection0_IS(): Unknown file header : %c%c%c%c\n",
1883 strgrib[0], strgrib[1], strgrib[2], strgrib[3]);
1890 seekStart = zu_tell(file) - 4;
1892 if (unpackIS(file, grib_msg) ==
false) {
1911zuint GribV2Record::periodSeconds(zuchar
unit, zuint P1, zuint P2,
1943 erreur(
"id=%d: unknown time unit in PDS b18=%d",
id,
unit);
1947 grib_debug(
"id=%d: PDS unit %d (time range) b21=%d %d P1=%d P2=%d\n",
id,
1948 unit, range, res, P1, P2);
1970 dur = ((zuint)P1 << 8) + (zuint)P2;
1973 erreur(
"id=%d: unknown time range in PDS b21=%d",
id, range);
A meteorological data grid from a GRIB (Gridded Binary) file.
bool eof
Signals when the end of the GRIB file has been reached during parsing.
zuint periodsec
Forecast period in seconds.
bool is_duplicated
Indicates if this record was created through copying rather than direct reading.
double Lo2
Grid end coordinates.
zuint period_p1
Time range indicators for this forecast step.
double Lo1
Grid origin coordinates.
zuchar id_model
Model identifier within the originating center.
zuchar GetDataType() const
Returns the type of meteorological parameter stored in this grid.
zuchar id_grid
Grid identifier used by the originating center.
bool ok
Indicates record validity.
int id
Unique identifier for this record.
bool hasBMS
Indicates presence of a bitmap section.
zuint level_value
Numeric value associated with level_type.
zuint GetLevelValue() const
Returns the numeric value associated with the level type.
zuint refyear
Components of the reference time for this forecast.
zuchar data_type
Parameter identifier as defined by GRIB tables.
time_t ref_date
Unix timestamp of model initialization time.
zuchar level_type
Vertical level type indicator.
bool known_data
Indicates whether the data type in this record is recognized by the parser.
int data_center_model
Identifies the numerical weather model that produced this data.
zuchar id_center
Originating center ID as defined by WMO common table C-1.
zuchar edition_number
GRIB edition number, indicating the version of the GRIB specification used.
zuchar time_range
Statistical processing indicator.
zuchar GetLevelType() const
Returns the type of vertical level for this grid's data.
GRIB Version 2 Record Implementation.