| 1 | #include <stdio.h> /* standard I/O header file */ |
|---|
| 2 | #include <stdlib.h> |
|---|
| 3 | #include <string.h> |
|---|
| 4 | #include "dprints.h" /* for dprints & func prototype*/ |
|---|
| 5 | #include "gribfuncs.h" /* prototypes */ |
|---|
| 6 | |
|---|
| 7 | /* PROGRAMMER : Steve Lowe and Todd Kienitz, SAIC Monterey |
|---|
| 8 | DATE : February 7, 1996 |
|---|
| 9 | Oct. 1996 by Alice Nakajima, SAIC Monterey |
|---|
| 10 | * |
|---|
| 11 | ********************************************************************* |
|---|
| 12 | * A. FUNCTION: grib_dec |
|---|
| 13 | * decode a Gridded Binary (GRIB edition 1) format message |
|---|
| 14 | * |
|---|
| 15 | * INTERFACE: |
|---|
| 16 | * int grib_dec (curr_ptr, pds, gds, bds_head, bms, ppgrib_data, errmsg) |
|---|
| 17 | * |
|---|
| 18 | * ARGUMENTS (I=input, O=output, I&O=input and output): |
|---|
| 19 | * (I) char *curr_ptr; |
|---|
| 20 | * pointer to block containing GRIB message to decode; |
|---|
| 21 | * (O) PDS_INPUT *pds ; |
|---|
| 22 | * to be filled with decoded Product Defn Section info; |
|---|
| 23 | * (O) grid_desc_sec *gds; |
|---|
| 24 | * to be filled with decoded Binary Data Section info; |
|---|
| 25 | * (O) BDS_HEAD_INPUT *bds_head; |
|---|
| 26 | * to be filled with decoded Binary Data Section info; |
|---|
| 27 | * (O) BMS_INPUT *bms; |
|---|
| 28 | * to be filled with decoded Bitmap Section info; |
|---|
| 29 | * (O) float **ppgrib_data; |
|---|
| 30 | * points to NULL upon entry; upon successful exit, points to newly |
|---|
| 31 | * malloced Float array filled with unpacked and restored data; |
|---|
| 32 | * (O) char *errmsg; |
|---|
| 33 | * Empty array, Returned filled if error occurred; |
|---|
| 34 | * |
|---|
| 35 | * RETURN CODE: |
|---|
| 36 | * 0> Success, **ppgrib_data now points to a block containing |
|---|
| 37 | * the unpacked & restored data (float); |
|---|
| 38 | * 1> Fail: first 4 bytes of curr_ptr is not 'GRIB' |
|---|
| 39 | * 2> Fail: last 4 bytes of curr_ptr is not '7777' |
|---|
| 40 | * 3> Fail: not Grib Edition 1 |
|---|
| 41 | * 4> Fail: unknown projection type; |
|---|
| 42 | *********************************************************************** |
|---|
| 43 | */ |
|---|
| 44 | |
|---|
| 45 | #if PROTOTYPE_NEEDED |
|---|
| 46 | int grib_dec (char *curr_ptr, PDS_INPUT *pds, grid_desc_sec *gds, |
|---|
| 47 | BDS_HEAD_INPUT *bds_head, BMS_INPUT *bms, float **ppgrib_data, |
|---|
| 48 | char *errmsg) |
|---|
| 49 | #else |
|---|
| 50 | int grib_dec (curr_ptr, pds, gds, bds_head, bms, ppgrib_data, errmsg) |
|---|
| 51 | char *curr_ptr; /*input= ptr to 1st byte of GRIB message block*/ |
|---|
| 52 | PDS_INPUT *pds; /* output=ptr to Internal PDS struct*/ |
|---|
| 53 | grid_desc_sec *gds; /* output=ptr to Internal GDS struct*/ |
|---|
| 54 | BDS_HEAD_INPUT*bds_head; /*out=ptr to Internal BDS header struct*/ |
|---|
| 55 | BMS_INPUT *bms; /*output=ptr to Internal bitmap section struct*/ |
|---|
| 56 | float **ppgrib_data; /*outp=ptr to nothing upon entry; upon exit, */ |
|---|
| 57 | /* points to a newly malloced array of floats; */ |
|---|
| 58 | char *errmsg; /* output= empty unless Error happens */ |
|---|
| 59 | #endif |
|---|
| 60 | { |
|---|
| 61 | char *func="grib_dec"; |
|---|
| 62 | unsigned long lMessageSize; /* message and section size */ |
|---|
| 63 | long edition; /* GRIB edition number */ |
|---|
| 64 | int flag; /* tests if a condition has happened */ |
|---|
| 65 | int gds_flag; /* set if Gds present */ |
|---|
| 66 | int nReturn = 0; |
|---|
| 67 | unsigned long skip; |
|---|
| 68 | float *outdata; |
|---|
| 69 | int xsize; |
|---|
| 70 | int j; |
|---|
| 71 | |
|---|
| 72 | /* |
|---|
| 73 | * |
|---|
| 74 | * A.0 DEBUG printing |
|---|
| 75 | */ |
|---|
| 76 | DPRINT1 ("Entering %s\n", func); |
|---|
| 77 | DPRINT6 ( |
|---|
| 78 | "curr_ptr=%ld, pds=%ld, gds=%ld\nbds_head=%ld, bms=%ld, ppgrib_data=%ld\n", |
|---|
| 79 | curr_ptr, pds, gds, bds_head, bms, ppgrib_data); |
|---|
| 80 | /* |
|---|
| 81 | * |
|---|
| 82 | * A.1 IF (incoming pointer is not at 'GRIB') |
|---|
| 83 | * RETURN 1 !errmsg filled |
|---|
| 84 | * ENDIF |
|---|
| 85 | */ |
|---|
| 86 | if(strncmp(curr_ptr,"GRIB",4) != 0) { |
|---|
| 87 | sprintf (errmsg,"%s: no 'GRIB' at beg. of this msg\n", func); |
|---|
| 88 | nReturn= (1); /* GRIB not found */ |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | /* |
|---|
| 92 | * |
|---|
| 93 | * A.2 FUNCTION gbyte !get total message length from IDS |
|---|
| 94 | */ |
|---|
| 95 | skip=32; |
|---|
| 96 | gbyte(curr_ptr,&lMessageSize,&skip,24); |
|---|
| 97 | DPRINT0 ("lMessageSize\n"); |
|---|
| 98 | |
|---|
| 99 | /* |
|---|
| 100 | * |
|---|
| 101 | * A.3 IF (Message does not end with '7777') |
|---|
| 102 | * RETURN 2 !errmsg filled |
|---|
| 103 | * ENDIF |
|---|
| 104 | */ |
|---|
| 105 | if(strncmp((curr_ptr + lMessageSize - 4),"7777",4)!=0) { |
|---|
| 106 | DPRINT1 ("%s: no '7777' at end of this msg\n", func); |
|---|
| 107 | sprintf (errmsg,"%s: no '7777' at end of this msg\n", func); |
|---|
| 108 | nReturn= 2; goto BYE; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | /* |
|---|
| 112 | * |
|---|
| 113 | * A.4 EXTRACT the GRIB edition out of Section 0 |
|---|
| 114 | * IF (not GRIB edition 1) |
|---|
| 115 | * RETURN 3 !errmsg filled |
|---|
| 116 | * ENDIF |
|---|
| 117 | */ |
|---|
| 118 | edition = (long) curr_ptr[7]; /* get edition */ |
|---|
| 119 | pds->usEd_num = (unsigned short) edition; |
|---|
| 120 | if(edition != 1) { |
|---|
| 121 | DPRINT1 ("%s: error, not Grib Edition 1 \n", func); |
|---|
| 122 | sprintf (errmsg,"%s: not Grib Edition 1 \n", func); |
|---|
| 123 | nReturn=(3); goto BYE; |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | /* |
|---|
| 127 | * |
|---|
| 128 | * A.5 MOVE pointer to the Product Definition section |
|---|
| 129 | */ |
|---|
| 130 | curr_ptr = curr_ptr + 8; |
|---|
| 131 | |
|---|
| 132 | /* |
|---|
| 133 | * |
|---|
| 134 | * A.6 FUNCTION gribgetpds !decode the PDS |
|---|
| 135 | * RETURN error code if fails !errmsg filled |
|---|
| 136 | */ |
|---|
| 137 | if( nReturn= gribgetpds(curr_ptr, pds, errmsg)) { |
|---|
| 138 | DPRINT2 ("%s: error=%d in grib get pds;\n", func, nReturn); |
|---|
| 139 | upd_child_errmsg (func, errmsg); |
|---|
| 140 | goto BYE; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | /* |
|---|
| 144 | * |
|---|
| 145 | * A.7 MOVE pointer to the end of PDS |
|---|
| 146 | */ |
|---|
| 147 | curr_ptr += pds->uslength; |
|---|
| 148 | |
|---|
| 149 | /* |
|---|
| 150 | * |
|---|
| 151 | * A.8 IF (GDS is present) |
|---|
| 152 | */ |
|---|
| 153 | gds_flag = pds->usGds_bms_id >> 7 & 1; |
|---|
| 154 | if(gds_flag) /* grid description section present */ |
|---|
| 155 | { |
|---|
| 156 | /* |
|---|
| 157 | * A.8.1 FUNCTION gribgetgds !decode GDS |
|---|
| 158 | * RETURN error code if fails !errmsg filled |
|---|
| 159 | */ |
|---|
| 160 | if( nReturn=gribgetgds(curr_ptr, gds, errmsg)) { |
|---|
| 161 | DPRINT2 ("%s: error=%d in grib get GDS;\n", func, nReturn); |
|---|
| 162 | upd_child_errmsg (func, errmsg); |
|---|
| 163 | goto BYE; |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | /* |
|---|
| 167 | * A.8.2 MOVE the cursor to the next section (either BMS/BDS) |
|---|
| 168 | */ |
|---|
| 169 | curr_ptr += gds->head.uslength; |
|---|
| 170 | /* |
|---|
| 171 | * A.8.3 SET the number of data points depending on Projection |
|---|
| 172 | */ |
|---|
| 173 | switch(gds->head.usData_type) |
|---|
| 174 | { |
|---|
| 175 | case LATLON_PRJ: /* Lat/Lon Grid */ |
|---|
| 176 | case GAUSS_PRJ: /* Gaussian Latitude/Longitude grid */ |
|---|
| 177 | case ROT_LATLON_PRJ: /* Rotated Lat/Lon */ |
|---|
| 178 | case ROT_GAUSS_PRJ: /* Rotated Gaussian */ |
|---|
| 179 | case STR_LATLON_PRJ: /* Stretched Lat/Lon */ |
|---|
| 180 | case STR_GAUSS_PRJ : /* Stretched Gaussian */ |
|---|
| 181 | case STR_ROT_LATLON_PRJ : /* Stretched and Rotated Lat/Lon */ |
|---|
| 182 | case STR_ROT_GAUSS_PRJ : /* Stretched and Rotated Gaussian */ |
|---|
| 183 | bds_head->ulGrid_size = gds->llg.usNi * gds->llg.usNj; |
|---|
| 184 | break; |
|---|
| 185 | |
|---|
| 186 | case MERC_PRJ: /* Mercator Grid */ |
|---|
| 187 | bds_head->ulGrid_size = gds->merc.cols * gds->merc.rows; |
|---|
| 188 | break; |
|---|
| 189 | |
|---|
| 190 | case LAMB_PRJ: /* Lambert Conformal */ |
|---|
| 191 | case ALBERS_PRJ: /* Albers equal-area */ |
|---|
| 192 | case OBLIQ_LAMB_PRJ: /* Oblique Lambert Conformal */ |
|---|
| 193 | bds_head->ulGrid_size = gds->lam.iNx * gds->lam.iNy; |
|---|
| 194 | break; |
|---|
| 195 | |
|---|
| 196 | case POLAR_PRJ: /* Polar Stereographic */ |
|---|
| 197 | bds_head->ulGrid_size = gds->pol.usNx * gds->pol.usNy; |
|---|
| 198 | break; |
|---|
| 199 | |
|---|
| 200 | default: /* unknown */ |
|---|
| 201 | DPRINT2 ("%s: unknown usData_type=%d\n",func,gds->head.usData_type); |
|---|
| 202 | sprintf(errmsg,"%s: unknown usData_type=%d\n", |
|---|
| 203 | func, gds->head.usData_type); |
|---|
| 204 | nReturn= (4); goto BYE; |
|---|
| 205 | } |
|---|
| 206 | } |
|---|
| 207 | /* |
|---|
| 208 | * A.8 ENDIF (GDS is present) |
|---|
| 209 | */ |
|---|
| 210 | |
|---|
| 211 | /* |
|---|
| 212 | * |
|---|
| 213 | * A.9 IF (bitmap Section is present) |
|---|
| 214 | */ |
|---|
| 215 | flag = pds->usGds_bms_id >> 6 & 1; |
|---|
| 216 | if(flag) /* bit map section present */ |
|---|
| 217 | { |
|---|
| 218 | /* |
|---|
| 219 | * A.9.1 FUNCTION gribgetbms !decode BMS |
|---|
| 220 | * RETURN error code if fails !errmsg filled |
|---|
| 221 | */ |
|---|
| 222 | if( nReturn=gribgetbms(curr_ptr,bms,gds_flag, bds_head->ulGrid_size,errmsg)) |
|---|
| 223 | { |
|---|
| 224 | DPRINT2 ("%s: error=%d in grib get BMS;\n",func,nReturn); |
|---|
| 225 | upd_child_errmsg (func, errmsg); |
|---|
| 226 | goto BYE; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | /* |
|---|
| 230 | * A.9.2 MOVE the cursor to beginning of Binary Data Section |
|---|
| 231 | */ |
|---|
| 232 | curr_ptr += bms->uslength; |
|---|
| 233 | |
|---|
| 234 | } /* Bms present */ |
|---|
| 235 | /* |
|---|
| 236 | * A.9 ENDIF !bms present |
|---|
| 237 | */ |
|---|
| 238 | |
|---|
| 239 | |
|---|
| 240 | /* |
|---|
| 241 | * |
|---|
| 242 | * A.10 FUNCTION gribgetbds() |
|---|
| 243 | * RETURN error code if failed !errmsg filled |
|---|
| 244 | */ |
|---|
| 245 | if(nReturn=gribgetbds(curr_ptr, pds->sDec_sc_fctr, bms, gds, ppgrib_data, |
|---|
| 246 | bds_head, errmsg)) |
|---|
| 247 | { |
|---|
| 248 | DPRINT2 ("%s: error=%d in grib get BDS;\n",func,nReturn); |
|---|
| 249 | upd_child_errmsg (func, errmsg); |
|---|
| 250 | goto BYE; |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | /* |
|---|
| 254 | * |
|---|
| 255 | * A.11 SET return code to 0 !no errors |
|---|
| 256 | */ |
|---|
| 257 | nReturn = 0; |
|---|
| 258 | |
|---|
| 259 | /* |
|---|
| 260 | * |
|---|
| 261 | * A.12 RETURN return code; |
|---|
| 262 | */ |
|---|
| 263 | BYE: |
|---|
| 264 | DPRINT2 ("Exit %s, Stat=%d\n", func, nReturn); |
|---|
| 265 | return(nReturn); |
|---|
| 266 | /* |
|---|
| 267 | * |
|---|
| 268 | * END OF FUNCTION |
|---|
| 269 | * |
|---|
| 270 | * |
|---|
| 271 | */ |
|---|
| 272 | } |
|---|