g2int jpcunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts, g2float *fld) //$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: jpcunpack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2003-08-27 // // ABSTRACT: This subroutine unpacks a data field that was packed into a // JPEG2000 code stream // using info from the GRIB2 Data Representation Template 5.40 or 5.40000. // // PROGRAM HISTORY LOG: // 2003-08-27 Gilbert // // USAGE: jpcunpack(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.40 or 5.40000 // 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; g2float ref,bscale,dscale; 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)); if ( ifld == 0 ) { // fprintf(stderr,"Could not allocate space in jpcunpack.\n Data field NOT upacked.\n"); return(1); } iret=(g2int)dec_jpeg2000(cpack,len,ifld); for (j=0;j<ndpts;j++) { fld[j]=(((g2float)ifld[j]*bscale)+ref)*dscale; } free(ifld); } else { for (j=0;j<ndpts;j++) fld[j]=ref; } return(0); }
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 documentation, // 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 /* ,itype */; g2float ref,bscale,dscale; rdieee(idrstmpl+0,&ref,1); bscale = (float)int_power(2.0,idrstmpl[1]); dscale = (float)int_power(10.0,-idrstmpl[2]); nbits = idrstmpl[3]; /* itype = idrstmpl[4]; */ ifld=(g2int *)calloc(ndpts,sizeof(g2int)); if ( ifld == 0 ) { fprintf(stderr,"Could not allocate space in simunpack.\n" "Data field NOT unpacked.\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); }
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 rdieee(idrstmpl+7,&rmissp,1); if (missopt == 2) 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)); 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); if ( jfld != 0 ) free(jfld); if ( ifldmiss != 0 ) free(ifldmiss); if ( gref != 0 ) free(gref); if ( gwidth != 0 ) free(gwidth); if ( glen != 0 ) 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 } }
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) 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) rdieee(idrstmpl+7,&rmiss1,1); else rmiss1=(g2float)idrstmpl[7]; } if ( idrstmpl[6] == 2 ) { if (itype == 0) { rdieee(idrstmpl+7,&rmiss1,1); 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 g2_unpack4(unsigned char *cgrib,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 // // USAGE: int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum, // g2int **ipdstmpl,g2int *mappdslen, // g2float **coordlist,g2int *numcoord) // INPUT ARGUMENTS: // cgrib - Char array containing Section 4 of the GRIB2 message // 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; xxtemplate *mappds; ierr=0; *ipdstmpl=0; // NULL *coordlist=0; // NULL 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); } 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 ) { gbit(cgrib,lipdstmpl+i,*iofst,nbits); } else { 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 // template. // 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 ) { gbit(cgrib,lipdstmpl+i,*iofst,nbits); } else { 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); if( mappds != 0 ) 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; } gbits(cgrib,coordieee,*iofst,32,0,*numcoord); rdieee(coordieee,*coordlist,*numcoord); free(coordieee); *iofst=*iofst+(32*(*numcoord)); } return(ierr); // End of Section 4 processing }
g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl, g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float **fld) //$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: g2_unpack7 // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-31 // // ABSTRACT: This subroutine unpacks Section 7 (Data Section) // as defined in GRIB Edition 2. // // PROGRAM HISTORY LOG: // 2002-10-31 Gilbert // 2002-12-20 Gilbert - Added GDT info to arguments // and added 5.51 processing. // 2003-08-29 Gilbert - Added support for new templates using // PNG and JPEG2000 algorithms/templates. // 2004-11-29 Gilbert - JPEG2000 now allowed to use WMO Template no. 5.40 // PNG now allowed to use WMO Template no. 5.41 // 2004-12-16 Taylor - Added check on comunpack return code. // 2008-12-23 Wesley - Initialize Number of data points unpacked // // USAGE: int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum, // g2int *igdstmpl, g2int idrsnum, // g2int *idrstmpl, g2int ndpts,g2float **fld) // INPUT ARGUMENTS: // cgrib - char array containing Section 7 of the GRIB2 message // iofst - Bit offset of the beginning of Section 7 in cgrib. // igdsnum - Grid Definition Template Number ( see Code Table 3.0) // ( Only used for DRS Template 5.51 ) // igdstmpl - Pointer to an integer array containing the data values for // the specified Grid Definition // Template ( N=igdsnum ). Each element of this integer // array contains an entry (in the order specified) of Grid // Definition Template 3.N // ( Only used for DRS Template 5.51 ) // idrsnum - Data Representation Template Number ( see Code Table 5.0) // idrstmpl - Pointer to an integer array containing the data values for // the specified Data Representation // Template ( N=idrsnum ). Each element of this integer // array contains an entry (in the order specified) of Data // Representation Template 5.N // ndpts - Number of data points unpacked and returned. // // OUTPUT ARGUMENTS: // iofst - Bit offset at the end of Section 7, returned. // fld - Pointer to a float array containing the unpacked data field. // // RETURN VALUES: // ierr - Error return code. // 0 = no error // 2 = Not section 7 // 4 = Unrecognized Data Representation Template // 5 = need one of GDT 3.50 through 3.53 to decode DRT 5.51 // 6 = memory allocation error // 7 = corrupt section 7. // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$// { g2int ierr,isecnum; g2int ipos,lensec; g2float *lfld; ierr=0; *fld=0; //NULL 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 != 7 ) { ierr=2; //fprintf(stderr,"g2_unpack7: Not Section 7 data.\n"); return(ierr); } ipos=(*iofst/8); lfld=(g2float *)calloc(ndpts ? ndpts : 1,sizeof(g2float)); if (lfld == 0) { ierr=6; return(ierr); } *fld=lfld; if (idrsnum == 0) simunpack(cgrib+ipos,idrstmpl,ndpts,lfld); else if (idrsnum == 2 || idrsnum == 3) { if (comunpack(cgrib+ipos,lensec,idrsnum,idrstmpl,ndpts,lfld) != 0) { return 7; } } else if( idrsnum == 4 ) { // Grid point data - IEEE Floating Point Data static const int one = 1; int is_lsb = *((char*)&one) == 1; if (idrstmpl[0] == 1) { // IEEE754 single precision memcpy(lfld, cgrib+ipos, 4 * ndpts ); if( is_lsb ) { int i; unsigned char* ch_fld = (unsigned char*) lfld; for(i=0;i<ndpts;i++) { unsigned char temp = ch_fld[i*4]; ch_fld[i*4] = ch_fld[i*4+3]; ch_fld[i*4+3] = temp; temp = ch_fld[i*4+1]; ch_fld[i*4+1] = ch_fld[i*4+2]; ch_fld[i*4+2] = temp; } } } else if( idrstmpl[0] == 2) { // IEEE754 double precision // FIXME? due to the interface: we downgrade it to float int i; unsigned char* src = cgrib+ipos; if( is_lsb ) { for(i=0;i<ndpts;i++) { unsigned char temp[8]; double d; { int j; for(j = 0; j < 8; j++ ) temp[j] = src[i * 8 + 7 - j]; } memcpy(&d, temp, 8); lfld[i] = DoubleToFloatClamp(d); } } else { for(i=0;i<ndpts;i++) { double d; memcpy(&d, src + i * 8, 8); lfld[i] = DoubleToFloatClamp(d); } } } else { fprintf(stderr,"g2_unpack7: Invalid precision=%ld for Data Section 5.4.\n", idrstmpl[0]); ierr=5; free(lfld); *fld=0; //NULL return(ierr); } } else if (idrsnum == 50) { // Spectral Simple simunpack(cgrib+ipos,idrstmpl,ndpts-1,lfld+1); rdieee(idrstmpl+4,lfld+0,1); } else if (idrsnum == 51) // Spectral complex if ( igdsnum>=50 && igdsnum <=53 ) specunpack(cgrib+ipos,idrstmpl,ndpts,igdstmpl[0],igdstmpl[2],igdstmpl[2],lfld); else { fprintf(stderr,"g2_unpack7: Cannot use GDT 3.%d to unpack Data Section 5.51.\n",(int)igdsnum); ierr=5; free(lfld); *fld=0; //NULL return(ierr); } #ifdef USE_JPEG2000 else if (idrsnum == 40 || idrsnum == 40000) { jpcunpack(cgrib+ipos,lensec-5,idrstmpl,ndpts,lfld); } #endif /* USE_JPEG2000 */ #ifdef USE_PNG else if (idrsnum == 41 || idrsnum == 40010) { pngunpack(cgrib+ipos,lensec-5,idrstmpl,ndpts,lfld); } #endif /* USE_PNG */ else { fprintf(stderr,"g2_unpack7: Data Representation Template 5.%d not yet implemented.\n",(int)idrsnum); ierr=4; free(lfld); *fld=0; //NULL return(ierr); } *iofst=*iofst+(8*lensec); return(ierr); // End of Section 7 processing }