void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl, unsigned char *cpack, g2int *lcpack) /*$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: misspack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2000-06-21 // // ABSTRACT: This subroutine packs up a data field using a complex // packing algorithm as defined in the GRIB2 documention. It // supports GRIB2 complex packing templates with or without // spatial differences (i.e. DRTs 5.2 and 5.3). // It also fills in GRIB2 Data Representation Template 5.2 or 5.3 // with the appropriate values. // This version assumes that Missing Value Management is being used and that // 1 or 2 missing values appear in the data. // // PROGRAM HISTORY LOG: // 2000-06-21 Gilbert // // USAGE: misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl, // unsigned char *cpack, g2int *lcpack) // INPUT ARGUMENT LIST: // fld[] - Contains the data values to pack // ndpts - The number of data values in array fld[] // idrsnum - Data Representation Template number 5.N // Must equal 2 or 3. // idrstmpl - Contains the array of values for Data Representation // Template 5.2 or 5.3 // [0] = Reference value - ignored on input // [1] = Binary Scale Factor // [2] = Decimal Scale Factor // . // . // [6] = Missing value management // [7] = Primary missing value // [8] = Secondary missing value // . // . // [16] = Order of Spatial Differencing ( 1 or 2 ) // . // . // // OUTPUT ARGUMENT LIST: // idrstmpl - Contains the array of values for Data Representation // Template 5.3 // [0] = Reference value - set by misspack routine. // [1] = Binary Scale Factor - unchanged from input // [2] = Decimal Scale Factor - unchanged from input // . // . // cpack - The packed data field (character*1 array) // *lcpack - length of packed field cpack(). // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$*/ { g2int *ifld, *ifldmiss, *jfld; g2int *jmin, *jmax, *lbit; static g2int zero=0; g2int *gref, *gwidth, *glen; g2int glength, grpwidth; g2int i, n, iofst, imin, ival1, ival2, isd, minsd, nbitsd; g2int nbitsgref, left, iwmax, ngwidthref, nbitsgwidth, ilmax; g2int nglenref, nglenlast, nbitsglen, ij; g2int j, missopt, nonmiss, itemp, maxorig, nbitorig, miss1, miss2; g2int ngroups, ng, num0, num1, num2; g2int imax, lg, mtemp, ier, igmax; g2int kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref; g2float rmissp, rmisss, bscale, dscale, rmin, temp; static g2int simple_alg = 0; static g2float alog2=0.69314718; /* ln(2.0) */ static g2int one=1; bscale=int_power(2.0,-idrstmpl[1]); dscale=int_power(10.0,idrstmpl[2]); missopt=idrstmpl[6]; if ( missopt != 1 && missopt != 2 ) { printf("misspack: Unrecognized option.\n"); *lcpack=-1; return; } else { /* Get missing values */ g2_rdieee(idrstmpl+7,&rmissp,1); if (missopt == 2) g2_rdieee(idrstmpl+8,&rmisss,1); } /* // Find min value of non-missing values in the data, // AND set up missing value mapping of the field. */ ifldmiss = calloc(ndpts,sizeof(g2int)); rmin=1E+37; if ( missopt == 1 ) { /* Primary missing value only */ for ( j=0; j<ndpts; j++) { if (fld[j] == rmissp) { ifldmiss[j]=1; } else { ifldmiss[j]=0; if (fld[j] < rmin) rmin=fld[j]; } } } if ( missopt == 2 ) { /* Primary and secondary missing values */ for ( j=0; j<ndpts; j++ ) { if (fld[j] == rmissp) { ifldmiss[j]=1; } else if (fld[j] == rmisss) { ifldmiss[j]=2; } else { ifldmiss[j]=0; if (fld[j] < rmin) rmin=fld[j]; } } } /* // Allocate work arrays: // Note: -ifldmiss[j],j=0,ndpts-1 is a map of original field indicating // which of the original data values // are primary missing (1), sencondary missing (2) or non-missing (0). // -jfld[j],j=0,nonmiss-1 is a subarray of just the non-missing values // from the original field. */ /*if (rmin != rmax) { */ iofst=0; ifld = calloc(ndpts,sizeof(g2int)); jfld = calloc(ndpts,sizeof(g2int)); gref = calloc(ndpts,sizeof(g2int)); gwidth = calloc(ndpts,sizeof(g2int)); glen = calloc(ndpts,sizeof(g2int)); /* // Scale original data */ nonmiss=0; if (idrstmpl[1] == 0) { /* No binary scaling */ imin=(g2int)rint(rmin*dscale); /*imax=(g2int)rint(rmax*dscale); */ rmin=(g2float)imin; for ( j=0; j<ndpts; j++) { if (ifldmiss[j] == 0) { jfld[nonmiss]=(g2int)rint(fld[j]*dscale)-imin; nonmiss++; } } } else { /* Use binary scaling factor */ rmin=rmin*dscale; /*rmax=rmax*dscale; */ for ( j=0; j<ndpts; j++ ) { if (ifldmiss[j] == 0) { jfld[nonmiss]=(g2int)rint(((fld[j]*dscale)-rmin)*bscale); nonmiss++; } } } /* // Calculate Spatial differences, if using DRS Template 5.3 */ if (idrsnum == 3) { /* spatial differences */ if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=2; if (idrstmpl[16] == 1) { /* first order */ ival1=jfld[0]; for ( j=nonmiss-1; j>0; j--) jfld[j]=jfld[j]-jfld[j-1]; jfld[0]=0; } else if (idrstmpl[16] == 2) { /* second order */ ival1=jfld[0]; ival2=jfld[1]; for ( j=nonmiss-1; j>1; j--) jfld[j]=jfld[j]-(2*jfld[j-1])+jfld[j-2]; jfld[0]=0; jfld[1]=0; } /* // subtract min value from spatial diff field */ isd=idrstmpl[16]; minsd=jfld[isd]; for ( j=isd; j<nonmiss; j++ ) if ( jfld[j] < minsd ) minsd=jfld[j]; for ( j=isd; j<nonmiss; j++ ) jfld[j]=jfld[j]-minsd; /* // find num of bits need to store minsd and add 1 extra bit // to indicate sign */ temp=log((double)(abs(minsd)+1))/alog2; nbitsd=(g2int)ceil(temp)+1; /* // find num of bits need to store ifld[0] ( and ifld[1] // if using 2nd order differencing ) */ maxorig=ival1; if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2; temp=log((double)(maxorig+1))/alog2; nbitorig=(g2int)ceil(temp)+1; if (nbitorig > nbitsd) nbitsd=nbitorig; /* increase number of bits to even multiple of 8 ( octet ) */ if ( (nbitsd%8) != 0) nbitsd=nbitsd+(8-(nbitsd%8)); /* // Store extra spatial differencing info into the packed // data section. */ if (nbitsd != 0) { /* pack first original value */ if (ival1 >= 0) { sbit(cpack,&ival1,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(ival1); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } if (idrstmpl[16] == 2) { /* pack second original value */ if (ival2 >= 0) { sbit(cpack,&ival2,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(ival2); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } } /* pack overall min of spatial differences */ if (minsd >= 0) { sbit(cpack,&minsd,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(minsd); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } } /*print *,'SDp ',ival1,ival2,minsd,nbitsd*/ } /* end of spatial diff section */ /* // Expand non-missing data values to original grid. */ miss1=jfld[0]; for ( j=0; j<nonmiss; j++) if (jfld[j] < miss1) miss1 = jfld[j]; miss1--; miss2=miss1-1; n=0; for ( j=0; j<ndpts; j++) { if ( ifldmiss[j] == 0 ) { ifld[j]=jfld[n]; n++; } else if ( ifldmiss[j] == 1 ) { ifld[j]=miss1; } else if ( ifldmiss[j] == 2 ) { ifld[j]=miss2; } } /* // Determine Groups to be used. */ if ( simple_alg == 1 ) { /* set group length to 10 : calculate number of groups */ /* and length of last group */ ngroups=ndpts/10; for (j=0;j<ngroups;j++) glen[j]=10; itemp=ndpts%10; if (itemp != 0) { ngroups++; glen[ngroups-1]=itemp; } } else { /* Use Dr. Glahn's algorithm for determining grouping. */ kfildo=6; minpk=10; inc=1; maxgrps=(ndpts/minpk)+1; jmin = calloc(maxgrps,sizeof(g2int)); jmax = calloc(maxgrps,sizeof(g2int)); lbit = calloc(maxgrps,sizeof(g2int)); g2_pack_gp(&kfildo,ifld,&ndpts,&missopt,&minpk,&inc,&miss1,&miss2, jmin,jmax,lbit,glen,&maxgrps,&ngroups,&ibit,&jbit, &kbit,&novref,&lbitref,&ier); /*printf("SAGier = %d %d %d %d %d %d\n",ier,ibit,jbit,kbit,novref,lbitref);*/ for ( ng=0; ng<ngroups; ng++) glen[ng]=glen[ng]+novref; free(jmin); free(jmax); free(lbit); } /* // For each group, find the group's reference value (min) // and the number of bits needed to hold the remaining values */ n=0; for ( ng=0; ng<ngroups; ng++) { /* how many of each type? */ num0=num1=num2=0; for (j=n; j<n+glen[ng]; j++) { if (ifldmiss[j] == 0 ) num0++; if (ifldmiss[j] == 1 ) num1++; if (ifldmiss[j] == 2 ) num2++; } if ( num0 == 0 ) { /* all missing values */ if ( num1 == 0 ) { /* all secondary missing */ gref[ng]=-2; gwidth[ng]=0; } else if ( num2 == 0 ) { /* all primary missing */ gref[ng]=-1; gwidth[ng]=0; } else { /* both primary and secondary */ gref[ng]=0; gwidth[ng]=1; } } else { /* contains some non-missing data */ /* find max and min values of group */ gref[ng]=2147483647; imax=-2147483647; j=n; for ( lg=0; lg<glen[ng]; lg++ ) { if ( ifldmiss[j] == 0 ) { if (ifld[j] < gref[ng]) gref[ng]=ifld[j]; if (ifld[j] > imax) imax=ifld[j]; } j++; } if (missopt == 1) imax=imax+1; if (missopt == 2) imax=imax+2; /* calc num of bits needed to hold data */ if ( gref[ng] != imax ) { temp=log((double)(imax-gref[ng]+1))/alog2; gwidth[ng]=(g2int)ceil(temp); } else { gwidth[ng]=0; } } /* Subtract min from data */ j=n; mtemp=(g2int)int_power(2.,gwidth[ng]); for ( lg=0; lg<glen[ng]; lg++ ) { if (ifldmiss[j] == 0) /* non-missing */ ifld[j]=ifld[j]-gref[ng]; else if (ifldmiss[j] == 1) /* primary missing */ ifld[j]=mtemp-1; else if (ifldmiss[j] == 2) /* secondary missing */ ifld[j]=mtemp-2; j++; } /* increment fld array counter */ n=n+glen[ng]; } /* // Find max of the group references and calc num of bits needed // to pack each groups reference value, then // pack up group reference values */ /*printf(" GREFS: "); */ /*for (j=0;j<ngroups;j++) printf(" %d",gref[j]); printf("\n"); */ igmax=gref[0]; for (j=1;j<ngroups;j++) if (gref[j] > igmax) igmax=gref[j]; if (missopt == 1) igmax=igmax+1; if (missopt == 2) igmax=igmax+2; if (igmax != 0) { temp=log((double)(igmax+1))/alog2; nbitsgref=(g2int)ceil(temp); /* reset the ref values of any "missing only" groups. */ mtemp=(g2int)int_power(2.,nbitsgref); for ( j=0; j<ngroups; j++ ) { if (gref[j] == -1) gref[j]=mtemp-1; if (gref[j] == -2) gref[j]=mtemp-2; } sbits(cpack,gref,iofst,nbitsgref,0,ngroups); itemp=nbitsgref*ngroups; iofst=iofst+itemp; /* Pad last octet with Zeros, if necessary, */ if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsgref=0; } /* // Find max/min of the group widths and calc num of bits needed // to pack each groups width value, then // pack up group width values */ /*write(77,*)'GWIDTHS: ',(gwidth(j),j=1,ngroups)*/ iwmax=gwidth[0]; ngwidthref=gwidth[0]; for (j=1;j<ngroups;j++) { if (gwidth[j] > iwmax) iwmax=gwidth[j]; if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j]; } if (iwmax != ngwidthref) { temp=log((double)(iwmax-ngwidthref+1))/alog2; nbitsgwidth=(g2int)ceil(temp); for ( i=0; i<ngroups; i++) gwidth[i]=gwidth[i]-ngwidthref; sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups); itemp=nbitsgwidth*ngroups; iofst=iofst+itemp; /* Pad last octet with Zeros, if necessary,*/ if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsgwidth=0; for (i=0;i<ngroups;i++) gwidth[i]=0; } /* // Find max/min of the group lengths and calc num of bits needed // to pack each groups length value, then // pack up group length values */ /*printf(" GLENS: ");*/ /*for (j=0;j<ngroups;j++) printf(" %d",glen[j]); printf("\n");*/ ilmax=glen[0]; nglenref=glen[0]; for (j=1;j<ngroups-1;j++) { if (glen[j] > ilmax) ilmax=glen[j]; if (glen[j] < nglenref) nglenref=glen[j]; } nglenlast=glen[ngroups-1]; if (ilmax != nglenref) { temp=log((double)(ilmax-nglenref+1))/alog2; nbitsglen=(g2int)ceil(temp); for ( i=0; i<ngroups-1; i++) glen[i]=glen[i]-nglenref; sbits(cpack,glen,iofst,nbitsglen,0,ngroups); itemp=nbitsglen*ngroups; iofst=iofst+itemp; /* Pad last octet with Zeros, if necessary,*/ if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsglen=0; for (i=0;i<ngroups;i++) glen[i]=0; } /* // For each group, pack data values */ /*write(77,*)'IFLDS: ',(ifld(j),j=1,ndpts)*/ n=0; ij=0; for ( ng=0; ng<ngroups; ng++) { glength=glen[ng]+nglenref; if (ng == (ngroups-1) ) glength=nglenlast; grpwidth=gwidth[ng]+ngwidthref; /*write(77,*)'NGP ',ng,grpwidth,glength,gref(ng)*/ if ( grpwidth != 0 ) { sbits(cpack,ifld+n,iofst,grpwidth,0,glength); iofst=iofst+(grpwidth*glength); } /* do kk=1,glength*/ /* ij=ij+1*/ /*write(77,*)'SAG ',ij,fld(ij),ifld(ij),gref(ng),bscale,rmin,dscale*/ /* enddo*/ n=n+glength; } /* Pad last octet with Zeros, if necessary,*/ if ( (iofst%8) != 0) { left=8-(iofst%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } *lcpack=iofst/8; if ( ifld != 0 ) free(ifld); free(jfld); if ( ifldmiss != 0 ) free(ifldmiss); free(gref); free(gwidth); free(glen); /*} //else { // Constant field ( max = min ) // nbits=0; // *lcpack=0; // nbitsgref=0; // ngroups=0; }*/ /* // Fill in ref value and number of bits in Template 5.2 */ mkieee(&rmin,idrstmpl+0,1); /* ensure reference value is IEEE format*/ idrstmpl[3]=nbitsgref; idrstmpl[4]=0; /* original data were reals*/ idrstmpl[5]=1; /* general group splitting*/ idrstmpl[9]=ngroups; /* Number of groups*/ idrstmpl[10]=ngwidthref; /* reference for group widths*/ idrstmpl[11]=nbitsgwidth; /* num bits used for group widths*/ idrstmpl[12]=nglenref; /* Reference for group lengths*/ idrstmpl[13]=1; /* length increment for group lengths*/ idrstmpl[14]=nglenlast; /* True length of last group*/ idrstmpl[15]=nbitsglen; /* num bits used for group lengths*/ if (idrsnum == 3) { idrstmpl[17]=nbitsd/8; /* num bits used for extra spatial*/ /* differencing values*/ } }
g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld) ////$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: simunpack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-29 // // ABSTRACT: This subroutine unpacks a data field that was packed using a // simple packing algorithm as defined in the GRIB2 documention, // using info from the GRIB2 Data Representation Template 5.0. // // PROGRAM HISTORY LOG: // 2002-10-29 Gilbert // // USAGE: int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts, // g2float *fld) // INPUT ARGUMENT LIST: // cpack - pointer to the packed data field. // idrstmpl - pointer to the array of values for Data Representation // Template 5.0 // ndpts - The number of data values to unpack // // OUTPUT ARGUMENT LIST: // fld - Contains the unpacked data values. fld must be allocated // with at least ndpts*sizeof(g2float) bytes before // calling this routine. // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$// { g2int *ifld; g2int j,nbits; g2float ref,bscale,dscale; // g2int itype; g2_rdieee(idrstmpl+0,&ref,1); bscale = int_power(2.0,idrstmpl[1]); dscale = int_power(10.0,-idrstmpl[2]); nbits = idrstmpl[3]; /* itype = idrstmpl[4]; NOT used */ ifld=(g2int *)calloc(ndpts,sizeof(g2int)); if ( ifld == 0 ) { fprintf(stderr,"Could not allocate space in simunpack.\n Data field NOT upacked.\n"); return(1); } // // if nbits equals 0, we have a constant field where the reference value // is the data value at each gridpoint // if (nbits != 0) { gbits(cpack,ifld,0,nbits,0,ndpts); for (j=0;j<ndpts;j++) { fld[j]=(((g2float)ifld[j]*bscale)+ref)*dscale; } } else { for (j=0;j<ndpts;j++) { fld[j]=ref; } } free(ifld); return(0); }
g2int g2_unpack4(unsigned char *cgrib,size_t sz,g2int *iofst,g2int *ipdsnum, g2int **ipdstmpl, g2int *mappdslen,g2float **coordlist,g2int *numcoord) /*//$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: g2_unpack4 // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-31 // // ABSTRACT: This subroutine unpacks Section 4 (Product Definition Section) // as defined in GRIB Edition 2. // // PROGRAM HISTORY LOG: // 2002-10-31 Gilbert // 2009-01-14 Vuong Changed structure name template to gtemplate // 2014-02-25 Steve Emmerson (UCAR/Unidata) Add length-checking of "cgrib" // array // // USAGE: int g2_unpack4(unsigned char *cgrib,size_t sz,g2int *iofst, // g2int *ipdsnum, // g2int **ipdstmpl,g2int *mappdslen, // g2float **coordlist,g2int *numcoord) // INPUT ARGUMENTS: // cgrib - Char array containing Section 4 of the GRIB2 message // sz - Size of "cgrib" array in bytes // iofst - Bit offset of the beginning of Section 4 in cgrib. // // OUTPUT ARGUMENTS: // iofst - Bit offset of the end of Section 4, returned. // ipdsnum - Product Definition Template Number ( see Code Table 4.0) // ipdstmpl - Pointer to integer array containing the data values for // the specified Product Definition // Template ( N=ipdsnum ). Each element of this integer // array contains an entry (in the order specified) of Product // Defintion Template 4.N // mappdslen- Number of elements in ipdstmpl[]. i.e. number of entries // in Product Defintion Template 4.N ( N=ipdsnum ). // coordlist- Pointer to real array containing floating point values // intended to document // the vertical discretisation associated to model data // on hybrid coordinate vertical levels. (part of Section 4) // numcoord - number of values in array coordlist. // // RETURN VALUES: // ierr - Error return code. // 0 = no error // 2 = Not section 4 // 5 = "GRIB" message contains an undefined Product Definition // Template. // 6 = memory allocation error // // REMARKS: // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$//*/ { g2int ierr,needext,i,j,nbits,isecnum; g2int lensec,isign,newlen; g2int *coordieee; g2int *lipdstmpl=0; g2float *lcoordlist; gtemplate *mappds; size_t bitsz = sz * 8; ierr=0; *ipdstmpl=0; /* NULL*/ *coordlist=0; /* NULL*/ if (*iofst + 40 > bitsz) return 2; gbit(cgrib,&lensec,*iofst,32); /* Get Length of Section*/ *iofst=*iofst+32; gbit(cgrib,&isecnum,*iofst,8); /* Get Section Number*/ *iofst=*iofst+8; if ( isecnum != 4 ) { ierr=2; *numcoord=0; *mappdslen=0; /* fprintf(stderr,"g2_unpack4: Not Section 4 data.\n");*/ return(ierr); } if (*iofst + 32 > bitsz) return 2; gbit(cgrib,numcoord,*iofst,16); /* Get num of coordinate values*/ *iofst=*iofst+16; gbit(cgrib,ipdsnum,*iofst,16); /* Get Prod. Def Template num.*/ *iofst=*iofst+16; /* Get Product Definition Template*/ mappds=getpdstemplate(*ipdsnum); if (mappds == 0) { /* undefine template*/ ierr=5; *mappdslen=0; return(ierr); } *mappdslen=mappds->maplen; needext=mappds->needext; /* // Unpack each value into array ipdstmpl from the // the appropriate number of octets, which are specified in // corresponding entries in array mappds. */ if (*mappdslen > 0) lipdstmpl=(g2int *)calloc(*mappdslen,sizeof(g2int)); if (lipdstmpl == 0) { ierr=6; *mappdslen=0; *ipdstmpl=0; /*NULL*/ if ( mappds != 0 ) free(mappds); return(ierr); } else { *ipdstmpl=lipdstmpl; } for (i=0;i<mappds->maplen;i++) { nbits=abs(mappds->map[i])*8; if ( mappds->map[i] >= 0 ) { if (*iofst + nbits > bitsz) { free(mappds); return 2; } gbit(cgrib,lipdstmpl+i,*iofst,nbits); } else { if (*iofst + nbits > bitsz) { free(mappds); return 2; } gbit(cgrib,&isign,*iofst,1); gbit(cgrib,lipdstmpl+i,*iofst+1,nbits-1); if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i]; } *iofst=*iofst+nbits; } /* // Check to see if the Product Definition Template needs to be // extended. // The number of values in a specific template may vary // depending on data specified in the "static" part of the // gtemplate. */ if ( needext ==1 ) { free(mappds); mappds=extpdstemplate(*ipdsnum,lipdstmpl); newlen=mappds->maplen+mappds->extlen; lipdstmpl=(g2int *)realloc(lipdstmpl,newlen*sizeof(g2int)); *ipdstmpl=lipdstmpl; /* Unpack the rest of the Product Definition Template*/ j=0; for (i=*mappdslen;i<newlen;i++) { nbits=abs(mappds->ext[j])*8; if ( mappds->ext[j] >= 0 ) { if (*iofst + nbits > bitsz) { free(mappds); return 2; } gbit(cgrib,lipdstmpl+i,*iofst,nbits); } else { if (*iofst + nbits > bitsz) { free(mappds); return 2; } gbit(cgrib,&isign,*iofst,1); gbit(cgrib,lipdstmpl+i,*iofst+1,nbits-1); if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i]; } *iofst=*iofst+nbits; j++; } *mappdslen=newlen; } if( mappds->ext != 0 ) free(mappds->ext); free(mappds); /* // Get Optional list of vertical coordinate values // after the Product Definition Template, if necessary. */ *coordlist=0; /* NULL*/ if ( *numcoord != 0 ) { coordieee=(g2int *)calloc(*numcoord,sizeof(g2int)); lcoordlist=(g2float *)calloc(*numcoord,sizeof(g2float)); if (coordieee == 0 || lcoordlist == 0) { ierr=6; *numcoord=0; *coordlist=0; /* NULL*/ if( coordieee != 0 ) free(coordieee); if( lcoordlist != 0 ) free(lcoordlist); return(ierr); } else { *coordlist=lcoordlist; } if (*iofst + 32**numcoord > bitsz) { free(coordieee); return 2; } gbits(cgrib,coordieee,*iofst,32,0,*numcoord); g2_rdieee(coordieee,*coordlist,*numcoord); free(coordieee); *iofst=*iofst+(32*(*numcoord)); } return(ierr); /* End of Section 4 processing*/ }
int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float *fld) /*//$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: comunpack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-29 // // ABSTRACT: This subroutine unpacks a data field that was packed using a // complex packing algorithm as defined in the GRIB2 documention, // using info from the GRIB2 Data Representation Template 5.2 or 5.3. // Supports GRIB2 complex packing templates with or without // spatial differences (i.e. DRTs 5.2 and 5.3). // // PROGRAM HISTORY LOG: // 2002-10-29 Gilbert // 2004-12-16 Gilbert - Added test ( provided by Arthur Taylor/MDL ) // to verify that group widths and lengths are // consistent with section length. // // USAGE: int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum, // g2int *idrstmpl, g2int ndpts,g2float *fld) // INPUT ARGUMENT LIST: // cpack - pointer to the packed data field. // lensec - length of section 7 (used for error checking). // idrsnum - Data Representation Template number 5.N // Must equal 2 or 3. // idrstmpl - pointer to the array of values for Data Representation // Template 5.2 or 5.3 // ndpts - The number of data values to unpack // // OUTPUT ARGUMENT LIST: // fld - Contains the unpacked data values. fld must be allocated // with at least ndpts*sizeof(g2float) bytes before // calling this routine. // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$*/ { g2int nbitsd=0,isign; g2int j,iofst,ival1,ival2,minsd,itemp,l,k,n,non=0; g2int *ifld,*ifldmiss=0; g2int *gref,*gwidth,*glen; g2int itype,ngroups,nbitsgref,nbitsgwidth,nbitsglen; g2int msng1,msng2; g2float ref,bscale,dscale,rmiss1,rmiss2; g2int totBit, totLen; /*printf('IDRSTMPL: ',(idrstmpl(j),j=1,16)*/ g2_rdieee(idrstmpl+0,&ref,1); /* printf("SAGTref: %f\n",ref);*/ bscale = (g2float)int_power(2.0,idrstmpl[1]); dscale = (g2float)int_power(10.0,-idrstmpl[2]); nbitsgref = idrstmpl[3]; itype = idrstmpl[4]; ngroups = idrstmpl[9]; nbitsgwidth = idrstmpl[11]; nbitsglen = idrstmpl[15]; if (idrsnum == 3) nbitsd=idrstmpl[17]*8; /* Constant field*/ if (ngroups == 0) { for (j=0;j<ndpts;j++) fld[j]=ref; return(0); } iofst=0; ifld=(g2int *)calloc(ndpts,sizeof(g2int)); /*printf("ALLOC ifld: %d %x\n",(int)ndpts,ifld);*/ gref=(g2int *)calloc(ngroups,sizeof(g2int)); /*printf("ALLOC gref: %d %x\n",(int)ngroups,gref);*/ gwidth=(g2int *)calloc(ngroups,sizeof(g2int)); /*printf("ALLOC gwidth: %d %x\n",(int)ngroups,gwidth);*/ /* // Get missing values, if supplied */ if ( idrstmpl[6] == 1 ) { if (itype == 0) g2_rdieee(idrstmpl+7,&rmiss1,1); else rmiss1=(g2float)idrstmpl[7]; } if ( idrstmpl[6] == 2 ) { if (itype == 0) { g2_rdieee(idrstmpl+7,&rmiss1,1); g2_rdieee(idrstmpl+8,&rmiss2,1); } else { rmiss1=(g2float)idrstmpl[7]; rmiss2=(g2float)idrstmpl[8]; } } /*printf("RMISSs: %f %f %f \n",rmiss1,rmiss2,ref);*/ /* // Extract Spatial differencing values, if using DRS Template 5.3 */ if (idrsnum == 3) { if (nbitsd != 0) { gbit(cpack,&isign,iofst,1); iofst=iofst+1; gbit(cpack,&ival1,iofst,nbitsd-1); iofst=iofst+nbitsd-1; if (isign == 1) ival1=-ival1; if (idrstmpl[16] == 2) { gbit(cpack,&isign,iofst,1); iofst=iofst+1; gbit(cpack,&ival2,iofst,nbitsd-1); iofst=iofst+nbitsd-1; if (isign == 1) ival2=-ival2; } gbit(cpack,&isign,iofst,1); iofst=iofst+1; gbit(cpack,&minsd,iofst,nbitsd-1); iofst=iofst+nbitsd-1; if (isign == 1) minsd=-minsd; } else { ival1=0; ival2=0; minsd=0; } /*printf("SDu %ld %ld %ld %ld \n",ival1,ival2,minsd,nbitsd);*/ } /* // Extract Each Group's reference value */ /*printf("SAG1: %ld %ld %ld \n",nbitsgref,ngroups,iofst);*/ if (nbitsgref != 0) { gbits(cpack,gref+0,iofst,nbitsgref,0,ngroups); itemp=nbitsgref*ngroups; iofst=iofst+itemp; if (itemp%8 != 0) iofst=iofst+(8-(itemp%8)); } else { for (j=0;j<ngroups;j++) gref[j]=0; } /* // Extract Each Group's bit width */ /*printf("SAG2: %ld %ld %ld %ld \n",nbitsgwidth,ngroups,iofst,idrstmpl[10]);*/ if (nbitsgwidth != 0) { gbits(cpack,gwidth+0,iofst,nbitsgwidth,0,ngroups); itemp=nbitsgwidth*ngroups; iofst=iofst+itemp; if (itemp%8 != 0) iofst=iofst+(8-(itemp%8)); } else { for (j=0;j<ngroups;j++) gwidth[j]=0; } for (j=0;j<ngroups;j++) gwidth[j]=gwidth[j]+idrstmpl[10]; /* // Extract Each Group's length (number of values in each group) */ glen=(g2int *)calloc(ngroups,sizeof(g2int)); /*printf("ALLOC glen: %d %x\n",(int)ngroups,glen);*/ /*printf("SAG3: %ld %ld %ld %ld %ld \n",nbitsglen,ngroups,iofst,idrstmpl[13],idrstmpl[12]);*/ if (nbitsglen != 0) { gbits(cpack,glen,iofst,nbitsglen,0,ngroups); itemp=nbitsglen*ngroups; iofst=iofst+itemp; if (itemp%8 != 0) iofst=iofst+(8-(itemp%8)); } else { for (j=0;j<ngroups;j++) glen[j]=0; } for (j=0;j<ngroups;j++) glen[j]=(glen[j]*idrstmpl[13])+idrstmpl[12]; glen[ngroups-1]=idrstmpl[14]; /* // Test to see if the group widths and lengths are consistent with number of // values, and length of section 7. */ totBit = 0; totLen = 0; for (j=0;j<ngroups;j++) { totBit += (gwidth[j]*glen[j]); totLen += glen[j]; } if (totLen != ndpts) { return 1; } if (totBit / 8. > lensec) { return 1; } /* // For each group, unpack data values */ if ( idrstmpl[6] == 0 ) { /* no missing values*/ n=0; for (j=0;j<ngroups;j++) { if (gwidth[j] != 0) { gbits(cpack,ifld+n,iofst,gwidth[j],0,glen[j]); for (k=0;k<glen[j];k++) { ifld[n]=ifld[n]+gref[j]; n=n+1; } } else { for (l=n;l<n+glen[j];l++) ifld[l]=gref[j]; n=n+glen[j]; } iofst=iofst+(gwidth[j]*glen[j]); } } else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) { /* missing values included*/ ifldmiss=(g2int *)malloc(ndpts*sizeof(g2int)); /*printf("ALLOC ifldmiss: %d %x\n",(int)ndpts,ifldmiss);*/ /*for (j=0;j<ndpts;j++) ifldmiss[j]=0;*/ n=0; non=0; for (j=0;j<ngroups;j++) { /*printf(" SAGNGP %d %d %d %d\n",j,gwidth[j],glen[j],gref[j]);*/ if (gwidth[j] != 0) { msng1=(g2int)int_power(2.0,gwidth[j])-1; msng2=msng1-1; gbits(cpack,ifld+n,iofst,gwidth[j],0,glen[j]); iofst=iofst+(gwidth[j]*glen[j]); for (k=0;k<glen[j];k++) { if (ifld[n] == msng1) { ifldmiss[n]=1; /*ifld[n]=0;*/ } else if (idrstmpl[6]==2 && ifld[n]==msng2) { ifldmiss[n]=2; /*ifld[n]=0;*/ } else { ifldmiss[n]=0; ifld[non++]=ifld[n]+gref[j]; } n++; } } else { msng1=(g2int)int_power(2.0,nbitsgref)-1; msng2=msng1-1; if (gref[j] == msng1) { for (l=n;l<n+glen[j];l++) ifldmiss[l]=1; } else if (idrstmpl[6]==2 && gref[j]==msng2) { for (l=n;l<n+glen[j];l++) ifldmiss[l]=2; } else { for (l=n;l<n+glen[j];l++) ifldmiss[l]=0; for (l=non;l<non+glen[j];l++) ifld[l]=gref[j]; non += glen[j]; } n=n+glen[j]; } } } if ( gref != 0 ) free(gref); if ( gwidth != 0 ) free(gwidth); if ( glen != 0 ) free(glen); /* // If using spatial differences, add overall min value, and // sum up recursively */ /*printf("SAGod: %ld %ld\n",idrsnum,idrstmpl[16]);*/ if (idrsnum == 3) { /* spatial differencing*/ if (idrstmpl[16] == 1) { /* first order*/ ifld[0]=ival1; if ( idrstmpl[6] == 0 ) itemp=ndpts; /* no missing values*/ else itemp=non; for (n=1;n<itemp;n++) { ifld[n]=ifld[n]+minsd; ifld[n]=ifld[n]+ifld[n-1]; } } else if (idrstmpl[16] == 2) { /* second order*/ ifld[0]=ival1; ifld[1]=ival2; if ( idrstmpl[6] == 0 ) itemp=ndpts; /* no missing values*/ else itemp=non; for (n=2;n<itemp;n++) { ifld[n]=ifld[n]+minsd; ifld[n]=ifld[n]+(2*ifld[n-1])-ifld[n-2]; } } } /* // Scale data back to original form */ /*printf("SAGT: %f %f %f\n",ref,bscale,dscale);*/ if ( idrstmpl[6] == 0 ) { /* no missing values*/ for (n=0;n<ndpts;n++) { fld[n]=(((g2float)ifld[n]*bscale)+ref)*dscale; } } else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) { /* missing values included*/ non=0; for (n=0;n<ndpts;n++) { if ( ifldmiss[n] == 0 ) { fld[n]=(((g2float)ifld[non++]*bscale)+ref)*dscale; /*printf(" SAG %d %f %d %f %f %f\n",n,fld[n],ifld[non-1],bscale,ref,dscale);*/ } else if ( ifldmiss[n] == 1 ) fld[n]=rmiss1; else if ( ifldmiss[n] == 2 ) fld[n]=rmiss2; } if ( ifldmiss != 0 ) free(ifldmiss); } if ( ifld != 0 ) free(ifld); return(0); }
g2int pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts, g2float *fld) /*$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: pngunpack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2003-08-27 // // ABSTRACT: This subroutine unpacks a data field that was packed into a // PNG image format // using info from the GRIB2 Data Representation Template 5.41 or 5.40010. // // PROGRAM HISTORY LOG: // 2003-08-27 Gilbert // // USAGE: pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts, // g2float *fld) // INPUT ARGUMENT LIST: // cpack - The packed data field (character*1 array) // len - length of packed field cpack(). // idrstmpl - Pointer to array of values for Data Representation // Template 5.41 or 5.40010 // ndpts - The number of data values to unpack // // OUTPUT ARGUMENT LIST: // fld[] - Contains the unpacked data values // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: IBM SP // //$$$*/ { g2int *ifld; g2int j,nbits,iret,width,height; g2float ref,bscale,dscale; unsigned char *ctemp; g2_rdieee(idrstmpl+0,&ref,1); bscale = int_power(2.0,idrstmpl[1]); dscale = int_power(10.0,-idrstmpl[2]); nbits = idrstmpl[3]; /* // if nbits equals 0, we have a constant field where the reference value // is the data value at each gridpoint */ if (nbits != 0) { ifld=(g2int *)calloc(ndpts,sizeof(g2int)); ctemp=(unsigned char *)calloc(ndpts*4,1); if ( ifld == 0 || ctemp == 0) { fprintf(stderr,"Could not allocate space in jpcunpack.\n Data field NOT upacked.\n"); if (ifld) free(ifld); if (ctemp) free(ctemp); return(1); } iret=(g2int)dec_png(cpack,&width,&height,ctemp); gbits(ctemp,ifld,0,nbits,0,ndpts); for (j=0;j<ndpts;j++) { fld[j]=(((g2float)ifld[j]*bscale)+ref)*dscale; } free(ctemp); free(ifld); } else { for (j=0;j<ndpts;j++) fld[j]=ref; } return(0); }