36#define __STDC_LIMIT_MACROS
49#include <jasper/jasper.h>
52const double GRIB_MISSING_VALUE = GRIB_NOTDEF;
84 earth_sphere_scale_factor;
85 int earth_sphere_scale_value;
87 unsigned char earth_major_scale_factor;
89 int earth_major_scale_value;
92 unsigned char earth_minor_scale_factor;
94 int earth_minor_scale_value;
98 double slat, slon, latin1, latin2, splat, splon;
116 int rescomp, scan_mode, proj_flag;
118 int param_cat, param_num, gen_proc, time_unit, fcst_time;
119 int ens_type, perturb_num, derived_fcst_code, nfcst_in_ensemble;
120 int lvl1_type, lvl2_type;
123 int eyr, emo, edy, etime;
124 int num_ranges, nmiss;
128 int stat_proc, type, num_points;
131 int split_method, miss_val_mgmt;
132 unsigned int num_groups;
133 float primary_miss_sub, secondary_miss_sub;
138 unsigned int ref, incr, last, pack_width;
141 unsigned int order, order_vals_width;
147 int E, D, num_packed, pack_width, orig_val_type;
149 unsigned char *bitmap;
167 unsigned char *buffer;
169 int total_len, disc, ed_num;
170 int center_id, sub_center_id, table_ver, local_table_ver, ref_time_type;
171 int yr, mo, dy, time;
172 int prod_status, data_type;
179static int dec_jpeg2000(
char *injpc,
int bufsize,
int *outfld)
223 jas_image_t *image =
nullptr;
224 jas_stream_t *jpcstream;
225 jas_image_cmpt_t *pcmpt;
236 jpcstream = jas_stream_memopen(injpc, bufsize);
237 if (jpcstream ==
nullptr) {
238 printf(
" dec_jpeg2000: no memory\n");
244 image = jpc_decode(jpcstream, opts);
245 if (image ==
nullptr) {
246 printf(
" jpc_decode return = %d \n", ier);
250 pcmpt = image->cmpts_[0];
255 if (image->numcmpts_ != 1) {
256 printf(
"dec_jpeg2000: Found color image. Grayscale expected.\n");
264 data = jas_matrix_create(jas_image_height(image), jas_image_width(image));
265 jas_image_readcmpt(image, 0, 0, 0, jas_image_width(image),
266 jas_image_height(image), data);
271 for (i = 0; i < pcmpt->height_; i++)
272 for (j = 0; j < pcmpt->width_; j++) outfld[k++] = data->rows_[i][j];
276 jas_matrix_destroy(data);
277 ier = jas_stream_close(jpcstream);
278 jas_image_destroy(image);
284static unsigned int uint2(
unsigned char const *p) {
return (p[0] << 8) + p[1]; }
286static unsigned int uint4(
unsigned const char *p) {
287 return ((p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]);
290static int int2(
unsigned const char *p) {
293 i = -(((p[0] & 0x7f) << 8) + p[1]);
295 i = (p[0] << 8) + p[1];
300static int int4(
unsigned const char *p) {
303 i = -(((p[0] & 0x7f) << 24) + (p[1] << 16) + (p[2] << 8) + p[3]);
305 i = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
310static float ieee2flt(
unsigned const char *ieee) {
314 if ((ieee[0] & 127) == 0 && ieee[1] == 0 && ieee[2] == 0 && ieee[3] == 0)
317 exp = ((ieee[0] & 127) << 1) + (ieee[1] >> 7);
318 fmant = (double)((
int)ieee[3] + (int)(ieee[2] << 8) +
319 (int)((ieee[1] | 128) << 16));
320 if (ieee[0] & 128) fmant = -fmant;
322 return (
float)(ldexp(fmant, (
int)(exp - 128 - 22)));
325static inline void getBits(
unsigned const char *buf,
int *loc,
size_t first,
333 zuint oct = first / 8;
334 zuint bit = first % 8;
336 zuint val = (buf[oct] << 24) + (buf[oct + 1] << 16) + (buf[oct + 2] << 8) +
339 val = val >> (32 - nbBits);
349 size_t ofs = grib_msg->offset / 8;
350 unsigned char *b = grib_msg->buffer + ofs;
354 grib_msg->center_id = uint2(b + 5);
355 grib_msg->sub_center_id = uint2(b + 7);
356 grib_msg->table_ver = b[9];
357 grib_msg->local_table_ver = b[10];
358 grib_msg->ref_time_type = b[11];
359 grib_msg->yr = uint2(b + 12);
360 grib_msg->mo = b[14];
361 grib_msg->dy = b[15];
365 grib_msg->time = hh * 10000 + mm * 100 + ss;
366 grib_msg->prod_status = b[19];
367 grib_msg->data_type = b[20];
368 grib_msg->offset += length * 8;
371static bool unpackLUS(
GRIBMessage *grib_msg) {
return true; }
374 size_t ofs = grib_msg->offset / 8;
375 unsigned char *b = grib_msg->buffer + ofs;
377 grib_msg->md.earth_shape = b[14];
379 grib_msg->md.earth_sphere_scale_factor =
381 grib_msg->md.earth_sphere_scale_value =
384 grib_msg->md.earth_major_scale_factor =
386 grib_msg->md.earth_major_scale_value =
389 grib_msg->md.earth_minor_scale_factor =
391 grib_msg->md.earth_minor_scale_value =
396 int src, num_in_list;
397 size_t ofs = grib_msg->offset / 8;
398 unsigned char *b = grib_msg->buffer + ofs;
402 fprintf(stderr,
"Don't recognize predetermined grid definitions");
407 if (num_in_list > 0) {
408 fprintf(stderr,
"Unable to unpack quasi-regular grids");
413 grib_msg->md.gds_templ_num = uint2(b + 12);
414 switch (grib_msg->md.gds_templ_num) {
418 parse_earth(grib_msg);
420 grib_msg->md.nx = uint4(b + 30);
421 grib_msg->md.ny = uint4(b + 34);
424 int4(b + 46) / 1000000.;
426 int4(b + 50) / 1000000.;
428 grib_msg->md.rescomp = b[54];
430 grib_msg->md.lats.elat =
431 int4(b + 55) / 1000000.;
432 grib_msg->md.lons.elon =
433 int4(b + 59) / 1000000.;
435 grib_msg->md.xinc.loinc =
436 uint4(b + 63) / 1000000.;
438 if (grib_msg->md.gds_templ_num == 0)
439 grib_msg->md.yinc.lainc =
440 uint4(b + 67) / 1000000.;
442 grib_msg->md.scan_mode = b[71];
445 parse_earth(grib_msg);
447 grib_msg->md.nx = uint4(b + 30);
448 grib_msg->md.ny = uint4(b + 34);
451 int4(b + 38) / 1000000.;
453 int4(b + 42) / 1000000.;
455 grib_msg->md.rescomp = b[46];
461 grib_msg->md.lats.elat =
462 int4(b + 51) / 1000000.;
463 grib_msg->md.lons.elon =
464 int4(b + 55) / 1000000.;
466 grib_msg->md.scan_mode = b[59];
468 grib_msg->md.xinc.loinc = uint4(b + 64) / 1000.;
469 grib_msg->md.yinc.lainc = uint4(b + 68) / 1000.;
472 parse_earth(grib_msg);
474 grib_msg->md.nx = uint4(b + 30);
475 grib_msg->md.ny = uint4(b + 34);
478 int4(b + 38) / 1000000.;
480 int4(b + 42) / 1000000.;
482 grib_msg->md.rescomp = b[46];
484 grib_msg->md.lats.lad = int4(b + 47) / 1000000.;
485 grib_msg->md.lons.lov = int4(b + 51) / 1000000.;
487 grib_msg->md.xinc.dxinc =
488 int4(b + 55) / 1000.;
489 grib_msg->md.yinc.dyinc =
490 int4(b + 59) / 1000.;
492 grib_msg->md.proj_flag = b[63];
493 grib_msg->md.scan_mode = b[64];
495 grib_msg->md.latin1 = int4(b + 65) / 1000000.;
496 grib_msg->md.latin2 = int4(b + 69) / 1000000.;
499 int4(b + 73) / 1000000.;
505 fprintf(stderr,
"Grid template %d is not understood\n",
506 grib_msg->md.gds_templ_num);
512static void unpack_stat_proc(
GRIBMessage *grib_msg,
unsigned const char *b) {
516 grib_msg->md.stat_proc.eyr = uint2(b);
517 grib_msg->md.stat_proc.emo = b[2];
518 grib_msg->md.stat_proc.edy = b[3];
522 grib_msg->md.stat_proc.etime = hh * 10000 + mm * 100 + ss;
524 grib_msg->md.stat_proc.num_ranges =
526 grib_msg->md.stat_proc.nmiss =
529 if (grib_msg->md.stat_proc.t != 0) {
530 delete[] grib_msg->md.stat_proc.t;
532 grib_msg->md.stat_proc.t =
535 for (n = 0; n < (size_t)grib_msg->md.stat_proc.num_ranges; n++) {
536 grib_msg->md.stat_proc.t[n].proc_code = b[off];
537 grib_msg->md.stat_proc.t[n].incr_type = b[off + 1];
538 grib_msg->md.stat_proc.t[n].time_unit = b[off + 2];
539 grib_msg->md.stat_proc.t[n].time_length = uint4(b + off + 3);
540 grib_msg->md.stat_proc.t[n].incr_unit = b[off + 7];
541 grib_msg->md.stat_proc.t[n].incr_length = uint4(b + off + 8);
548 int num_coords, factor;
549 size_t ofs = grib_msg->offset / 8;
550 unsigned char *b = grib_msg->buffer + ofs;
552 num_coords = uint2(b + 5);
553 if (num_coords > 0) {
554 fprintf(stderr,
"Unable to decode hybrid coordinates");
558 grib_msg->md.pds_templ_num =
560 grib_msg->md.stat_proc.num_ranges = 0;
561 switch (grib_msg->md.pds_templ_num) {
569 grib_msg->md.ens_type = -1;
570 grib_msg->md.derived_fcst_code = -1;
571 grib_msg->md.spatial_proc.type = -1;
572 grib_msg->md.param_cat = b[9];
573 grib_msg->md.param_num = b[10];
574 grib_msg->md.gen_proc = b[11];
576 grib_msg->md.time_unit = b[17];
577 grib_msg->md.fcst_time = uint4(b + 18);
579 grib_msg->md.lvl1_type = b[22];
581 grib_msg->md.lvl1 = int4(b + 24) / pow(10., (
double)factor);
583 grib_msg->md.lvl2_type = b[28];
585 grib_msg->md.lvl2 = int4(b + 30) / pow(10., (
double)factor);
587 switch (grib_msg->md.pds_templ_num) {
590 grib_msg->md.ens_type = b[34];
591 grib_msg->md.perturb_num = b[35];
592 grib_msg->md.nfcst_in_ensemble = b[36];
594 switch (grib_msg->md.pds_templ_num) {
596 unpack_stat_proc(grib_msg, b + 37);
602 grib_msg->md.derived_fcst_code = b[34];
603 grib_msg->md.nfcst_in_ensemble = b[35];
605 switch (grib_msg->md.pds_templ_num) {
607 unpack_stat_proc(grib_msg, b + 36);
612 unpack_stat_proc(grib_msg, b + 34);
615 grib_msg->md.spatial_proc.stat_proc = b[34];
616 grib_msg->md.spatial_proc.type = b[35];
617 grib_msg->md.spatial_proc.num_points = b[36];
622 fprintf(stderr,
"Product Definition Template %d is not understood\n",
623 grib_msg->md.pds_templ_num);
631 size_t ofs = grib_msg->offset / 8;
632 unsigned char *b = grib_msg->buffer + ofs;
634 grib_msg->md.num_packed = uint4(b + 5);
635 grib_msg->md.drs_templ_num =
638 switch (grib_msg->md.drs_templ_num) {
640 grib_msg->md.precision = b[11];
652 grib_msg->md.R = ieee2flt(b + 11);
653 grib_msg->md.E = int2(b + 15);
654 grib_msg->md.D = int2(b + 17);
655 grib_msg->md.R /= pow(10., grib_msg->md.D);
657 grib_msg->md.pack_width = b[19];
658 grib_msg->md.orig_val_type = b[20];
660 if (grib_msg->md.drs_templ_num == 3 || grib_msg->md.drs_templ_num == 2) {
661 grib_msg->md.complex_pack.split_method = b[21];
662 grib_msg->md.complex_pack.miss_val_mgmt = b[22];
663 if (grib_msg->md.orig_val_type == 0) {
664 grib_msg->md.complex_pack.primary_miss_sub = ieee2flt(b + 23);
665 grib_msg->md.complex_pack.secondary_miss_sub = ieee2flt(b + 27);
666 }
else if (grib_msg->md.orig_val_type == 1) {
667 grib_msg->md.complex_pack.primary_miss_sub = uint4(b + 23);
668 grib_msg->md.complex_pack.secondary_miss_sub = uint4(b + 27);
671 "Unable to decode missing value substitutes for original "
673 grib_msg->md.orig_val_type);
676 grib_msg->md.complex_pack.num_groups = uint4(b + 31);
678 grib_msg->md.complex_pack.width.ref = b[35];
679 grib_msg->md.complex_pack.width.pack_width = b[36];
681 grib_msg->md.complex_pack.length.ref = uint4(b + 37);
682 grib_msg->md.complex_pack.length.incr = b[41];
683 grib_msg->md.complex_pack.length.last = uint4(b + 42);
684 grib_msg->md.complex_pack.length.pack_width = b[46];
686 if (grib_msg->md.drs_templ_num == 3) {
687 grib_msg->md.complex_pack.spatial_diff.order = b[47];
688 grib_msg->md.complex_pack.spatial_diff.order_vals_width = b[48];
690 grib_msg->md.complex_pack.spatial_diff.order = 0;
691 grib_msg->md.complex_pack.spatial_diff.order_vals_width = 0;
695 fprintf(stderr,
"Data template %d is not understood\n",
696 grib_msg->md.drs_templ_num);
704 int ind, len, n, bit;
705 size_t ofs = grib_msg->offset / 8;
706 unsigned char *b = grib_msg->buffer + ofs;
713 if (len < 7)
return false;
715 grib_msg->md.bmssize = len;
717 delete[] grib_msg->md.bitmap;
718 delete[] grib_msg->md.bms;
719 grib_msg->md.bitmap =
new unsigned char[len];
720 grib_msg->md.bms =
new zuchar[grib_msg->md.bmssize];
721 memcpy(grib_msg->md.bms, b + 6, grib_msg->md.bmssize);
722 for (n = 0; n < len; n++) {
723 getBits(grib_msg->buffer, &bit, grib_msg->offset + 48 + n, 1);
724 grib_msg->md.bitmap[n] = bit;
731 delete[] grib_msg->md.bitmap;
732 grib_msg->md.bitmap =
nullptr;
733 delete[] grib_msg->md.bms;
734 grib_msg->md.bms =
nullptr;
735 grib_msg->md.bmssize = 0;
739 "This code is not currently set up to deal with predefined "
752 int *ref_vals, *widths;
754 int *first_vals = 0, sign, omin;
755 long long miss_val, group_miss_val;
758 float lastgp, D = pow(10., grib_msg->md.D), E = pow(2., grib_msg->md.E);
761 groups.first_vals =
nullptr;
763 off = grib_msg->offset + 40;
764 int npoints = grib_msg->md.ny * grib_msg->md.nx;
765 switch (grib_msg->md.drs_templ_num) {
767 grib_msg->grids.gridpoints =
new double[npoints];
768 for (l = 0; l < npoints; l++) {
769 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
770 getBits(grib_msg->buffer, &pval, off, grib_msg->md.pack_width);
771 grib_msg->grids.gridpoints[l] = grib_msg->md.R + pval * E / D;
772 off += grib_msg->md.pack_width;
774 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
778 if (grib_msg->md.complex_pack.num_groups > 0) {
779 if (grib_msg->md.complex_pack.spatial_diff.order) {
781 new int[grib_msg->md.complex_pack.spatial_diff.order];
782 for (n = 0; n < grib_msg->md.complex_pack.spatial_diff.order; ++n) {
784 grib_msg->buffer, &groups.first_vals[n], off,
785 grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8);
786 off += grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8;
789 getBits(grib_msg->buffer, &groups.sign, off, 1);
791 grib_msg->buffer, &groups.omin, off + 1,
792 grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8 - 1);
793 if (groups.sign == 1) {
794 groups.omin = -groups.omin;
796 off += grib_msg->md.complex_pack.spatial_diff.order_vals_width * 8;
800 grib_msg->grids.gridpoints =
new double[npoints];
801 if (grib_msg->md.complex_pack.num_groups == 0) {
802 for (l = 0; l < npoints; ++l) {
803 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
807 if (grib_msg->md.complex_pack.miss_val_mgmt > 0) {
808 groups.miss_val = pow(2., grib_msg->md.pack_width) - 1;
810 groups.miss_val = GRIB_MISSING_VALUE;
813 groups.ref_vals =
new int[grib_msg->md.complex_pack.num_groups];
814 groups.widths =
new int[grib_msg->md.complex_pack.num_groups];
815 groups.lengths =
new int[grib_msg->md.complex_pack.num_groups];
817 for (n = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
818 getBits(grib_msg->buffer, &groups.ref_vals[n], off,
819 grib_msg->md.pack_width);
820 off += grib_msg->md.pack_width;
822 off = (off + 7) & ~7;
824 for (n = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
825 getBits(grib_msg->buffer, &groups.widths[n], off,
826 grib_msg->md.complex_pack.width.pack_width);
827 groups.widths[n] += grib_msg->md.complex_pack.width.ref;
828 off += grib_msg->md.complex_pack.width.pack_width;
830 off = (off + 7) & ~7;
832 for (n = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
833 getBits(grib_msg->buffer, &groups.lengths[n], off,
834 grib_msg->md.complex_pack.length.pack_width);
835 off += grib_msg->md.complex_pack.length.pack_width;
837 off = (off + 7) & ~7;
839 groups.max_length = 0;
840 for (n = 0; n < grib_msg->md.complex_pack.num_groups - 1; ++n) {
842 grib_msg->md.complex_pack.length.ref +
843 groups.lengths[n] * grib_msg->md.complex_pack.length.incr;
844 if (groups.lengths[n] > groups.max_length) {
845 groups.max_length = groups.lengths[n];
848 groups.lengths[n] = grib_msg->md.complex_pack.length.last;
849 if (groups.lengths[n] > groups.max_length) {
850 groups.max_length = groups.lengths[n];
853 for (n = 0, l = 0; n < grib_msg->md.complex_pack.num_groups; ++n) {
854 if (groups.widths[n] > 0) {
855 if (grib_msg->md.complex_pack.miss_val_mgmt > 0) {
856 groups.group_miss_val = pow(2., groups.widths[n]) - 1;
858 groups.group_miss_val = GRIB_MISSING_VALUE;
860 for (
int i = 0; i < groups.lengths[n];) {
861 if (grib_msg->md.bitmap !=
nullptr && grib_msg->md.bitmap[l] == 0) {
862 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
864 getBits(grib_msg->buffer, &pval, off, groups.widths[n]);
865 off += groups.widths[n];
866 if (pval == groups.group_miss_val) {
867 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
869 grib_msg->grids.gridpoints[l] =
870 pval + groups.ref_vals[n] + groups.omin;
877 for (
int i = 0; i < groups.lengths[n];) {
878 if (grib_msg->md.bitmap !=
nullptr && grib_msg->md.bitmap[l] == 0) {
879 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
881 if (groups.ref_vals[n] == groups.miss_val) {
882 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
884 grib_msg->grids.gridpoints[l] =
885 groups.ref_vals[n] + groups.omin;
894 for (; l < npoints; ++l) {
895 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
898 if (grib_msg->md.drs_templ_num == 3) {
899 if (groups.first_vals !=
nullptr) {
900 for (n = grib_msg->md.complex_pack.spatial_diff.order - 1; n > 0;
902 lastgp = groups.first_vals[n] - groups.first_vals[n - 1];
903 for (l = 0, m = 0; l < grib_msg->md.nx * grib_msg->md.ny; ++l) {
904 if (grib_msg->grids.gridpoints[l] != GRIB_MISSING_VALUE) {
905 if (m >= grib_msg->md.complex_pack.spatial_diff.order) {
906 grib_msg->grids.gridpoints[l] += lastgp;
907 lastgp = grib_msg->grids.gridpoints[l];
914 for (l = 0, m = 0, lastgp = 0; l < npoints; ++l) {
915 if (grib_msg->grids.gridpoints[l] != GRIB_MISSING_VALUE) {
916 if (m < grib_msg->md.complex_pack.spatial_diff.order) {
917 grib_msg->grids.gridpoints[l] =
918 grib_msg->md.R + groups.first_vals[m] * E / D;
919 lastgp = grib_msg->md.R * D / E + groups.first_vals[m];
921 lastgp += grib_msg->grids.gridpoints[l];
922 grib_msg->grids.gridpoints[l] = lastgp * E / D;
927 delete[] groups.first_vals;
929 for (l = 0; l < npoints; ++l) {
930 if (grib_msg->grids.gridpoints[l] != GRIB_MISSING_VALUE) {
931 grib_msg->grids.gridpoints[l] =
932 grib_msg->md.R + grib_msg->grids.gridpoints[l] * E / D;
935 delete[] groups.ref_vals;
936 delete[] groups.widths;
937 delete[] groups.lengths;
941 if (grib_msg->md.precision == 1) {
942 grib_msg->grids.gridpoints =
new double[npoints];
943 for (
int l = 0; l < npoints; l++) {
944 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
945 grib_msg->grids.gridpoints[l] =
946 ieee2flt(grib_msg->buffer + off / 8);
949 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
951 }
else if (grib_msg->md.precision == 2) {
952 static const int one = 1;
953 bool const is_lsb = *((
char *)&one) == 1;
954 grib_msg->grids.gridpoints =
new double[npoints];
955 for (l = 0; l < npoints; l++) {
956 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
959 unsigned char temp[8];
960 for (
int j = 0; j < 8; j++) {
961 temp[j] = grib_msg->buffer[off / 8 + 7 - j];
965 memcpy(&d, grib_msg->buffer + off / 8, 8);
967 grib_msg->grids.gridpoints[l] = d;
970 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
974 "g2_unpack7: Invalid precision=%d for Data Section 5.4.\n",
975 grib_msg->md.precision);
982 int len, *jvals, cnt;
983 getBits(grib_msg->buffer, &len, grib_msg->offset, 32);
984 if (len < 5)
return false;
986 jvals =
new int[npoints];
987 grib_msg->grids.gridpoints =
new double[npoints];
989 dec_jpeg2000((
char *)&grib_msg->buffer[grib_msg->offset / 8 + 5], len,
992 for (l = 0; l < npoints; l++) {
993 if (grib_msg->md.bitmap ==
nullptr || grib_msg->md.bitmap[l] == 1) {
994 if (len == 0) jvals[cnt] = 0;
995 grib_msg->grids.gridpoints[l] = grib_msg->md.R + jvals[cnt++] * E / D;
997 grib_msg->grids.gridpoints[l] = GRIB_MISSING_VALUE;
1003 erreur(
"Unknown packing %d", grib_msg->md.drs_templ_num);
1009static zuchar GRBV2_TO_DATA(
int productDiscipline,
int dataCat,
int dataNum) {
1012 switch (productDiscipline) {
1041 ret = GRB_HUMID_SPEC;
1044 ret = GRB_HUMID_REL;
1047 ret = GRB_PRECIP_RATE;
1052 ret = GRB_PRECIP_TOT;
1055 ret = GRB_SNOW_DEPTH;
1058 ret = GRB_FRZRAIN_CATEG;
1062 ret = GRB_SNOW_CATEG;
1072 ret = GRB_WIND_SPEED;
1081 ret = GRB_WIND_GUST;
1095 ret = GRB_GEOPOT_HGT;
1106 ret = GRB_CLOUD_TOT;
1122 ret = GRB_COMP_REFL;
1133 case 3: ret= GRB_WVHGT;
break;
1134 DATA_TO_GRBV2[DATA_WAVES_WND_DIR] = grb2DataType(10,0,4);
1135 DATA_TO_GRBV2[DATA_WAVES_WND_HGT] = grb2DataType(10,0,5);
1136 DATA_TO_GRBV2[DATA_WAVES_WND_PERIOD] = grb2DataType(10,0,6);
1137 DATA_TO_GRBV2[DATA_WAVES_SWL_DIR] = grb2DataType(10,0,7);
1138 DATA_TO_GRBV2[DATA_WAVES_SWL_HGT] = grb2DataType(10,0,8);
1139 DATA_TO_GRBV2[DATA_WAVES_SWL_PERIOD] = grb2DataType(10,0,9);
1140 DATA_TO_GRBV2[DATA_WAVES_PRIM_DIR] = grb2DataType(10,0,10);
1141 DATA_TO_GRBV2[DATA_WAVES_PRIM_PERIOD] = grb2DataType(10,0,11);
1142 DATA_TO_GRBV2[DATA_WAVES_SEC_DIR] = grb2DataType(10,0,12);
1143 DATA_TO_GRBV2[DATA_WAVES_SEC_PERIOD] = grb2DataType(10,0,13);
1175 ret = GRB_CUR_SPEED;
1197 erreur(
"unknown Discipline %d dataCat %d dataNum %d", productDiscipline,
1205static int mapStatisticalEndTime(
GRIBMessage *grid) {
1209 if (grid->md.time_unit == grid->md.stat_proc.t[0].time_unit)
1210 switch (grid->md.time_unit) {
1214 return grid->md.fcst_time + grid->md.stat_proc.t[0].time_length;
1217 return (grid->md.stat_proc.edy - grid->dy);
1219 return (grid->md.stat_proc.emo - grid->mo);
1221 return (grid->md.stat_proc.eyr - grid->yr);
1223 fprintf(stderr,
"Unable to map end time with units %d to GRIB1\n",
1224 grid->md.time_unit);
1228 if (grid->md.time_unit == 0 && grid->md.stat_proc.t[0].time_unit == 1) {
1230 return grid->md.fcst_time + grid->md.stat_proc.t[0].time_length * 60;
1233 if (grid->md.time_unit == 1 && grid->md.stat_proc.t[0].time_unit == 0 &&
1234 (grid->md.stat_proc.t[0].time_unit % 60) != 0) {
1236 return grid->md.fcst_time + grid->md.stat_proc.t[0].time_length / 60;
1239 fprintf(stderr,
"Unable to map end time %d %d %d %d \n", grid->md.time_unit,
1240 grid->md.stat_proc.t[0].time_unit, grid->md.fcst_time,
1241 grid->md.stat_proc.t[0].time_length);
1246static bool mapTimeRange(
GRIBMessage *grid, zuint *p1, zuint *p2,
1247 zuchar *t_range,
int *n_avg,
int *n_missing,
1249 switch (grid->md.pds_templ_num) {
1255 *p1 = grid->md.fcst_time;
1257 *n_avg = *n_missing = 0;
1262 if (grid->md.stat_proc.num_ranges > 1) {
1263 if (center == 7 && grid->md.stat_proc.num_ranges == 2) {
1265 *p2 = grid->md.stat_proc.t[0].incr_length;
1266 *p1 = *p2 - grid->md.stat_proc.t[1].time_length;
1267 *n_avg = grid->md.stat_proc.t[0].time_length;
1268 switch (grid->md.stat_proc.t[0].proc_code) {
1317 "Unable to map NCEP statistical process code %d to GRIB1\n",
1318 grid->md.stat_proc.t[0].proc_code);
1323 "Unable to map multiple statistical processes to GRIB1\n");
1327 switch (grid->md.stat_proc.t[0].proc_code) {
1331 switch (grid->md.stat_proc.t[0].proc_code) {
1342 *p1 = grid->md.fcst_time;
1343 *p2 = mapStatisticalEndTime(grid);
1344 if (*p2 == UINT_MAX) {
1347 if (grid->md.stat_proc.t[0].incr_length == 0)
1350 fprintf(stderr,
"Unable to map discrete processing to GRIB1\n");
1358 *p1 = grid->md.fcst_time;
1359 *p2 = mapStatisticalEndTime(grid);
1360 if (*p2 == UINT_MAX) {
1363 if (grid->md.stat_proc.t[0].incr_length == 0)
1366 fprintf(stderr,
"Unable to map discrete processing to GRIB1\n");
1372 if (grid->md.stat_proc.t[0].proc_code == 255 && center == 7) {
1373 if (grid->disc == 0) {
1374 if (grid->md.param_cat == 0) {
1375 switch (grid->md.param_num) {
1379 *p1 = grid->md.fcst_time;
1380 *p2 = mapStatisticalEndTime(grid);
1381 if (*p2 == UINT_MAX) {
1384 if (grid->md.stat_proc.t[0].incr_length == 0)
1388 "Unable to map discrete processing to GRIB1\n");
1396 fprintf(stderr,
"Unable to map statistical process %d to GRIB1\n",
1397 grid->md.stat_proc.t[0].proc_code);
1402 *n_missing = grid->md.stat_proc.nmiss;
1406 "Unable to map time range for Product Definition Template %d "
1408 grid->md.pds_templ_num);
1417void GribV2Record::translateDataType() {
1424 multiplyAllData(3600.0);
1542void GribV2Record::readDataSet(
ZUFILE *file) {
1553 while (strncmp(&((
char *)grib_msg->buffer)[grib_msg->offset / 8],
"7777",
1556 getBits(grib_msg->buffer, &len, grib_msg->offset, 32);
1557 getBits(grib_msg->buffer, &sec_num, grib_msg->offset + 4 * 8, 8);
1560 if (skip ==
true)
break;
1561 ok = unpackLUS(grib_msg);
1564 if (skip ==
true)
break;
1565 ok = unpackGDS(grib_msg);
1567 Ni = grib_msg->md.nx;
1568 Nj = grib_msg->md.ny;
1569 La1 = grib_msg->md.slat;
1570 Lo1 = grib_msg->md.slon;
1571 La2 = grib_msg->md.lats.elat;
1572 Lo2 = grib_msg->md.lons.elon;
1573 Di = grib_msg->md.xinc.loinc;
1574 Dj = grib_msg->md.yinc.lainc;
1575 scanFlags = grib_msg->md.scan_mode;
1576 isScanIpositive = (scanFlags & 0x80) == 0;
1577 isScanJpositive = (scanFlags & 0x40) != 0;
1578 isAdjacentI = (scanFlags & 0x20) == 0;
1583 if (isScanIpositive)
1601 if (Ni <= 1 || Nj <= 1) {
1602 erreur(
"Record %d: Ni=%d Nj=%d",
id, Ni, Nj);
1605 Di = (
Lo2 -
Lo1) / (Ni - 1);
1606 Dj = (La2 - La1) / (Nj - 1);
1611 if (skip ==
true)
break;
1612 ok = unpackPDS(grib_msg);
1617 productTemplate = grib_msg->md.pds_templ_num;
1618 dataCat = grib_msg->md.param_cat;
1619 dataNum = grib_msg->md.param_num;
1620 dataType = GRBV2_TO_DATA(productDiscipline, dataCat, dataNum);
1629 if (grib_msg->md.lvl2_type == 8 && grib_msg->md.lvl1_type == 1) {
1634 int n_avg, n_missing;
1643 setRecordCurrentDate(makeDate(
refyear, refmonth, refday, refhour,
1652 if (skip ==
true)
break;
1653 ok = unpackDRS(grib_msg);
1656 if (skip ==
true)
break;
1657 ok = unpackBMS(grib_msg);
1659 if (grib_msg->md.bmssize != 0) {
1661 BMSsize = grib_msg->md.bmssize;
1662 BMSbits =
new zuchar[grib_msg->md.bmssize];
1663 memcpy(BMSbits, grib_msg->md.bms, grib_msg->md.bmssize);
1668 if (skip ==
false) {
1669 ok = unpackDS(grib_msg);
1671 data = grib_msg->grids.gridpoints;
1672 grib_msg->grids.gridpoints = 0;
1675 if (grib_msg->num_grids != 1) DS =
true;
1678 grib_msg->offset += len * 8;
1679 if (
ok ==
false || DS ==
true)
break;
1685 printf(
"==== GV2 %d\n",
ok);
1686 printf(
"Lo1=%f Lo2=%f La1=%f La2=%f\n",
Lo1,
Lo2, La1, La2);
1687 printf(
"Lo1=%f Lo2=%f La1=%f La2=%f\n", grib_msg->md.slon,
1688 grib_msg->md.lons.elon, grib_msg->md.slat, grib_msg->md.lats.elat);
1689 printf(
"Ni=%d Nj=%d\n", Ni, Nj);
1690 printf(
"hasDiDj=%d Di,Dj=(%f %f)\n", hasDiDj, Di, Dj);
1691 printf(
"isScanIpositive=%d isScanJpositive=%d isAdjacentI=%d\n",
1692 isScanIpositive, isScanJpositive, isAdjacentI);
1693 printf(
"hasBMS=%d\n",
hasBMS);
1697 translateDataType();
1702 strncmp(&((
char *)grib_msg->buffer)[grib_msg->offset / 8],
"7777", 4) ==
1710GribV2Record::GribV2Record(
ZUFILE *file,
int id_) {
1712 seekStart = zu_tell(file);
1720 long start = seekStart;
1727 if (zu_read(file, strgrib, 4) != 4) {
1733 bool b_haveReadGRIB =
false;
1735 if (strncmp(strgrib,
"GRIB", 4) != 0)
1738 b_len_add_8 =
false;
1739 b_haveReadGRIB =
true;
1743 if ((strgrib[0] == 0) && (strgrib[1] == 0) && (strgrib[2] == 0) &&
1744 (strgrib[3] == 0)) {
1745 b_len_add_8 =
false;
1746 b_haveReadGRIB =
false;
1748 ok = readGribSection0_IS(file,
1753 unpackIDS(grib_msg);
1756 off = grib_msg->offset / 8;
1757 while (strncmp(&((
char *)grib_msg->buffer)[off],
"7777", 4) != 0) {
1758 len = uint4(grib_msg->buffer + off);
1759 sec_num = grib_msg->buffer[off + 4];
1760 if (sec_num == 7) grib_msg->num_grids++;
1765 (void)zu_seek(file, start, SEEK_SET);
1769 refmonth = grib_msg->mo;
1770 refday = grib_msg->dy;
1771 refhour = grib_msg->time / 10000;
1772 refminute = (grib_msg->time / 100) % 100;
1773 refDate = makeDate(
refyear, refmonth, refday, refhour, refminute, 0);
1774 sprintf(strRefDate,
"%04d-%02d-%02d %02d:%02d",
refyear, refmonth, refday,
1775 refhour, refminute);
1777 idModel = grib_msg->table_ver;
1779 productDiscipline = grib_msg->disc;
1784bool GribV2Record::hasMoreDataSet()
const {
1785 return grib_msg && grib_msg->num_grids != 1 ? true :
false;
1792 delete[] rec1->data;
1793 delete[] rec1->BMSbits;
1797 rec1->readDataSet(file);
1804#pragma warning(disable : 4717)
1807#pragma warning(default : 4717)
1810GribV2Record::~GribV2Record() {
delete grib_msg; }
1819 unsigned char temp[16];
1823 if (grib_msg->buffer !=
nullptr) {
1824 delete[] grib_msg->buffer;
1825 grib_msg->buffer =
nullptr;
1827 grib_msg->num_grids = 0;
1829 if ((status = zu_read(fp, &temp[4], 12)) != 12) {
1832 grib_msg->disc = temp[6];
1833 grib_msg->ed_num = temp[7];
1836 if (grib_msg->ed_num != 2)
return false;
1838 getBits(temp, &grib_msg->total_len, 96, 32);
1840 if (grib_msg->total_len < 16 || grib_msg->total_len > (INT_MAX - 4))
1843 grib_msg->md.nx = grib_msg->md.ny = 0;
1844 grib_msg->buffer =
new unsigned char[grib_msg->total_len + 4];
1845 memcpy(grib_msg->buffer, temp, 16);
1846 num = grib_msg->total_len - 16;
1848 status = zu_read(fp, &grib_msg->buffer[16], num);
1849 if (status != (
int)num)
return false;
1851 if (strncmp(&((
char *)grib_msg->buffer)[grib_msg->total_len - 4],
"7777",
1853 fprintf(stderr,
"Warning: no end section found\n");
1855 grib_msg->offset = 128;
1859bool GribV2Record::readGribSection0_IS(
ZUFILE *file,
bool b_skip_initial_GRIB) {
1861 fileOffset0 = zu_tell(file);
1863 if (!b_skip_initial_GRIB) {
1865 while ((zu_read(file, strgrib, 1) == 1) && (strgrib[0] !=
'G')) {
1868 if (strgrib[0] !=
'G') {
1873 if (zu_read(file, strgrib + 1, 3) != 3) {
1878 if (strncmp(strgrib,
"GRIB", 4) != 0) {
1879 printf(
"readGribSection0_IS(): Unknown file header : %c%c%c%c\n",
1880 strgrib[0], strgrib[1], strgrib[2], strgrib[3]);
1887 seekStart = zu_tell(file) - 4;
1889 if (unpackIS(file, grib_msg) ==
false) {
1908zuint GribV2Record::periodSeconds(zuchar
unit, zuint P1, zuint P2,
1940 erreur(
"id=%d: unknown time unit in PDS b18=%d",
id,
unit);
1944 grib_debug(
"id=%d: PDS unit %d (time range) b21=%d %d P1=%d P2=%d\n",
id,
1945 unit, range, res, P1, P2);
1967 dur = ((zuint)P1 << 8) + (zuint)P2;
1970 erreur(
"id=%d: unknown time range in PDS b21=%d",
id, range);
GRIB Version 2 Record Implementation.
Represents 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.
zuchar dataType
Parameter identifier as defined by GRIB tables.
zuchar editionNumber
GRIB edition number, indicating the version of the GRIB specification used.
bool knownData
Indicates whether the data type in this record is recognized by the parser.
zuchar levelType
Vertical level type indicator.
double Lo2
Grid end coordinates.
double Lo1
Grid origin coordinates.
zuchar timeRange
Statistical processing indicator.
bool IsDuplicated
Indicates if this record was created through copying rather than direct reading.
zuchar idCenter
Originating center ID as defined by WMO common table C-1.
bool ok
Indicates record validity.
zuchar idGrid
Grid identifier used by the originating center.
zuint periodP1
Time range indicators for this forecast step.
time_t refDate
Unix timestamp of model initialization time.
int id
Unique identifier for this record.
bool hasBMS
Indicates presence of a bitmap section.
int dataCenterModel
Identifies the numerical weather model that produced this data.
zuint refyear
Components of the reference time for this forecast.
zuint levelValue
Numeric value associated with levelType.
zuint getLevelValue() const
Returns the numeric value associated with the level type.
zuchar getLevelType() const
Returns the type of vertical level for this grid's data.
zuchar idModel
Model identifier within the originating center.
zuchar getDataType() const
Returns the type of meteorological parameter stored in this grid.