NCEPLIBS-g2c  1.8.0
aecpack.c
Go to the documentation of this file.
1 
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <math.h>
16 #include <libaec.h>
17 #include "grib2_int.h"
18 
52 static int
53 aecpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl,
54  unsigned char *cpack, g2int *lcpack, int verbose)
55 {
56  g2int ctemplen;
57  g2int *ifld = NULL;
58  g2int j;
59  g2int imin, imax;
60  g2int maxdif, nbits, ndpts, nbytes;
61  g2int ccsds_flags, ccsds_block_size, ccsds_rsi;
62  float bscale, dscale, rmax, rmin, temp;
63  double rmaxd, rmind;
64  static float alog2 = ALOG2; /* ln(2.0) */
65  unsigned char *ctemp;
66  float *ffld = fld;
67  double *dfld = fld;
68  int ret = G2C_NOERROR;
69 
70  LOG((2, "aecpack_int() fld_is_double %d width %ld height %ld idrstmpl[1] %d *lcpack %ld",
71  fld_is_double, width, height, idrstmpl[1], *lcpack));
72  LOG((3, "idrstmpl: %ld %ld %ld %ld %ld %ld %ld %ld", idrstmpl[0], idrstmpl[1], idrstmpl[2],
73  idrstmpl[3], idrstmpl[4], idrstmpl[5], idrstmpl[6], idrstmpl[7]));
74 
75  ctemplen = 0;
76  ccsds_flags = 0;
77  ccsds_block_size = 0;
78  ccsds_rsi = 0;
79  nbits = 0;
80 
81  ndpts = width * height;
82  bscale = int_power(2.0, -idrstmpl[1]);
83  dscale = int_power(10.0, idrstmpl[2]);
84  LOG((3, "ndpts %ld bscale %g dscale %g", ndpts, bscale, dscale));
85 
86  /* Find max and min values in the data. */
87  rmaxd = dfld[0];
88  rmind = dfld[0];
89  rmax = ffld[0];
90  rmin = ffld[0];
91  if (fld_is_double)
92  {
93  for (j = 1; j < ndpts; j++)
94  {
95  if (dfld[j] > rmaxd)
96  rmaxd = dfld[j];
97  if (dfld[j] < rmind)
98  rmind = dfld[j];
99  }
100  if (idrstmpl[1] == 0)
101  maxdif = (g2int)(rint(rmaxd * dscale) - rint(rmind * dscale));
102  else
103  maxdif = (g2int)rint((rmaxd - rmind) * dscale * bscale);
104  }
105  else
106  {
107  for (j = 1; j < ndpts; j++)
108  {
109  if (ffld[j] > rmax)
110  rmax = ffld[j];
111  if (ffld[j] < rmin)
112  rmin = ffld[j];
113  }
114  if (idrstmpl[1] == 0)
115  maxdif = (g2int)(rint(rmax * dscale) - rint(rmin * dscale));
116  else
117  maxdif = (g2int)rint((rmax - rmin) * dscale * bscale);
118  }
119  LOG((3, "rmax %g rmaxd %g rmin %g rmind %g", rmax, rmaxd, rmin, rmind));
120 
121  /* If max and min values are not equal, pack up field. If they are
122  * equal, we have a constant field, and the reference value (rmin)
123  * is the value for each point in the field and set nbits to 0. */
124  if (((fld_is_double && rmind != rmaxd) || (!fld_is_double && rmin != rmax)) && maxdif != 0)
125  {
126  /* Allocate memory for scaled data. */
127  ifld = malloc(ndpts * sizeof(g2int));
128 
129  /* Determine which algorithm to use based on user-supplied
130  * binary scale factor and number of bits. */
131  if (idrstmpl[1] == 0)
132  {
133  /* No binary scaling and calculate minumum number of bits
134  * in which the data will fit. */
135  imin = (g2int)rint((fld_is_double ? rmind : rmin) * dscale);
136  imax = (g2int)rint((fld_is_double ? rmaxd : rmax) * dscale);
137  maxdif = imax - imin;
138  temp = log((double)(maxdif + 1)) / alog2;
139  nbits = (g2int)ceil(temp);
140  /* scale data */
141  if (fld_is_double)
142  {
143  rmind = (float)imin;
144  for(j = 0; j < ndpts; j++)
145  ifld[j] = (g2int)rint(dfld[j] * dscale) - imin;
146  }
147  else
148  {
149  rmin = (float)imin;
150  for(j = 0; j < ndpts; j++)
151  ifld[j] = (g2int)rint(ffld[j] * dscale) - imin;
152  }
153  }
154  else
155  {
156  /* Use binary scaling factor and calculate minumum number
157  * of bits in which the data will fit. */
158  if (fld_is_double)
159  {
160  rmind = rmind * dscale;
161  rmaxd = rmaxd * dscale;
162  maxdif = (g2int)rint((rmaxd - rmind) * bscale);
163  }
164  else
165  {
166  rmin = rmin * dscale;
167  rmax = rmax * dscale;
168  maxdif = (g2int)rint((rmax - rmin) * bscale);
169  }
170  temp = log((double)(maxdif + 1)) / alog2;
171  nbits = (g2int)ceil(temp);
172  /* scale data */
173  if (fld_is_double)
174  {
175  for (j = 0; j < ndpts; j++)
176  ifld[j] = (g2int)rint(((dfld[j] * dscale) - rmind) * bscale);
177  }
178  else
179  {
180  for (j = 0; j < ndpts; j++)
181  ifld[j] = (g2int)rint(((ffld[j] * dscale) - rmin) * bscale);
182  }
183  }
184 
185  /* Define AEC compression options */
186  if (idrstmpl[3] <= 0)
187  {
188  nbits = pow(2, ceil(log(nbits)/log(2))); // Round to nearest base 2 int
189  }
190  else
191  {
192  nbits = idrstmpl[3];
193  nbits = pow(2, ceil(log(nbits)/log(2))); // Round to nearest base 2 int
194  }
195  nbits = nbits < 8 ? 8 : nbits;
196 
197  if (idrstmpl[5] == 0)
198  {
199  ccsds_flags = AEC_DATA_SIGNED | AEC_DATA_PREPROCESS | AEC_DATA_MSB;
200  }
201  else
202  {
203  ccsds_flags = idrstmpl[5];
204  }
205  if (idrstmpl[6] == 0)
206  {
207  ccsds_block_size = 16;
208  }
209  else
210  {
211  ccsds_block_size = idrstmpl[6];
212  }
213  if (idrstmpl[7] == 0)
214  {
215  ccsds_rsi = 128;
216  }
217  else
218  {
219  ccsds_rsi = idrstmpl[7];
220  }
221 
222  /* Pack data into full octets, then do AEC encode and
223  * calculate the length of the packed data in bytes. */
224  nbytes = (nbits + 7) / 8;
225  ctemp = calloc(ndpts, nbytes);
226  ctemplen = ndpts*nbytes;
227  sbits(ctemp, ifld, 0, nbytes*8, 0, ndpts);
228 
229  ret = enc_aec(ctemp, ctemplen, nbits, ccsds_flags, ccsds_block_size, ccsds_rsi, cpack, lcpack);
230  if (ret < 0)
231  {
232  if (verbose) printf("aecpack: ERROR Packing AEC = %d\n",ret);
233  nbits = 0;
234  *lcpack = 0;
235  }
236 
237  *lcpack = ret;
238  free(ctemp);
239  }
240  else
241  {
242  nbits = 0;
243  *lcpack = 0;
244  }
245 
246  /* Fill in values for template 5.42. */
247  if (fld_is_double)
248  rmin = (float)rmind;
249  mkieee(&rmin, idrstmpl, 1); /* ensure reference value is IEEE format. */
250  idrstmpl[3] = nbits;
251  idrstmpl[5] = ccsds_flags;
252  idrstmpl[6] = ccsds_block_size;
253  idrstmpl[7] = ccsds_rsi;
254  if (ifld)
255  free(ifld);
256 
257  return ret;
258 }
259 
296 void
297 aecpack(float *fld, g2int width, g2int height, g2int *idrstmpl,
298  unsigned char *cpack, g2int *lcpack)
299 {
300  aecpack_int(fld, 0, width, height, idrstmpl, cpack, lcpack, 1);
301 }
302 
345 int
346 g2c_aecpackf(float *fld, size_t width, size_t height, int *idrstmpl,
347  unsigned char *cpack, size_t *lcpack)
348 {
349  g2int width8 = width, height8 = height, lcpack8 = *lcpack;
350  g2int idrstmpl8[G2C_AEC_DRS_TEMPLATE_LEN];
351  int i, ret;
352 
353  for (i = 0; i < G2C_AEC_DRS_TEMPLATE_LEN; i++)
354  idrstmpl8[i] = idrstmpl[i];
355 
356  ret = aecpack_int(fld, 0, width8, height8, idrstmpl8, cpack, &lcpack8, 0);
357 
358  if (!ret)
359  {
360  for (i = 0; i < G2C_AEC_DRS_TEMPLATE_LEN; i++)
361  idrstmpl[i] = (int)idrstmpl8[i];
362  *lcpack = (g2int)lcpack8;
363  }
364  return ret;
365 }
366 
409 int
410 g2c_aecpackd(double *fld, size_t width, size_t height, int *idrstmpl,
411  unsigned char *cpack, size_t *lcpack)
412 {
413  g2int width8 = width, height8 = height, lcpack8 = *lcpack;
414  g2int idrstmpl8[G2C_AEC_DRS_TEMPLATE_LEN];
415  int i, ret;
416 
417  for (i = 0; i < G2C_AEC_DRS_TEMPLATE_LEN; i++)
418  idrstmpl8[i] = idrstmpl[i];
419 
420  ret = aecpack_int(fld, 1, width8, height8, idrstmpl8, cpack, &lcpack8, 0);
421 
422  if (!ret)
423  {
424  for (i = 0; i < G2C_AEC_DRS_TEMPLATE_LEN; i++)
425  idrstmpl[i] = (int)idrstmpl8[i];
426  *lcpack = (g2int)lcpack8;
427  }
428  return ret;
429 }
int g2c_aecpackf(float *fld, size_t width, size_t height, int *idrstmpl, unsigned char *cpack, size_t *lcpack)
This function packs up a float array into a AEC code stream.
Definition: aecpack.c:346
static int aecpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack, int verbose)
This internal function packs up a float or double array into a AEC/CCSDS code stream.
Definition: aecpack.c:53
int g2c_aecpackd(double *fld, size_t width, size_t height, int *idrstmpl, unsigned char *cpack, size_t *lcpack)
This function packs up a double array into a AEC code stream.
Definition: aecpack.c:410
void aecpack(float *fld, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This function packs up a float array into a AEC code stream.
Definition: aecpack.c:297
int enc_aec(unsigned char *data, g2int ctemplen, g2int nbits, g2int flags, g2int block_size, g2int rsi, unsigned char *aecbuf, g2int *aecbuflen)
This Function encodes data into an AEC code stream specified in the CCSDS 121.0-B-3 Blue Book.
Definition: decenc_aec.c:111
void sbits(unsigned char *out, g2int *in, g2int iskip, g2int nbits, g2int nskip, g2int n)
Store bits - put arbitrary size values into a packed bit string, taking the low order bits from each ...
Definition: gbits.c:180
#define G2C_AEC_DRS_TEMPLATE_LEN
Length of the idrstmpl array for AEC packing.
Definition: grib2.h:422
int64_t g2int
Long integer type.
Definition: grib2.h:33
#define G2C_NOERROR
No error.
Definition: grib2.h:491
Header file with internal function prototypes NCEPLIBS-g2c library.
void mkieee(float *a, g2int *rieee, g2int num)
This subroutine stores a list of real values in 32-bit IEEE floating point format.
Definition: mkieee.c:22
double int_power(double x, g2int y)
Function similar to C pow() power function.
Definition: int_power.c:18
#define LOG(e)
Ignore logging to stdout.
Definition: grib2_int.h:426
#define ALOG2
ln(2.0)
Definition: grib2_int.h:30