Example #1
0
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);
}
Example #2
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);
}
Example #3
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
      }

}
Example #4
0
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);
      
}
Example #5
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

}
Example #6
0
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

}