NCEPLIBS-g2c 2.0.0
Loading...
Searching...
No Matches
aecpack.c
Go to the documentation of this file.
1
13#include "grib2_int.h"
14#include <libaec.h>
15#include <math.h>
16#include <stdint.h>
17#include <stdlib.h>
18
51static int
52aecpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl,
53 unsigned char *cpack, g2int *lcpack, int verbose)
54{
55 g2int ctemplen;
56 g2int *ifld = NULL;
57 g2int j;
58 g2int imin, imax;
59 g2int maxdif, nbits, ndpts, nbytes;
60 g2int ccsds_flags, ccsds_block_size, ccsds_rsi;
61 float bscale, dscale, rmax, rmin, temp;
62 double rmaxd, rmind;
63 static float alog2 = ALOG2; /* ln(2.0) */
64 unsigned char *ctemp;
65 float *ffld = fld;
66 double *dfld = fld;
67 int ret = G2C_NOERROR;
68
69 LOG((2, "aecpack_int() fld_is_double %d width %ld height %ld idrstmpl[1] %d *lcpack %ld",
70 fld_is_double, width, height, idrstmpl[1], *lcpack));
71 LOG((3, "idrstmpl: %ld %ld %ld %ld %ld %ld %ld %ld", idrstmpl[0], idrstmpl[1], idrstmpl[2],
72 idrstmpl[3], idrstmpl[4], idrstmpl[5], idrstmpl[6], idrstmpl[7]));
73
74 ctemplen = 0;
75 ccsds_flags = 0;
76 ccsds_block_size = 0;
77 ccsds_rsi = 0;
78 nbits = 0;
79
80 ndpts = width * height;
81 bscale = int_power(2.0, -idrstmpl[1]);
82 dscale = int_power(10.0, idrstmpl[2]);
83 LOG((3, "ndpts %ld bscale %g dscale %g", ndpts, bscale, dscale));
84
85 /* Find max and min values in the data. */
86 rmaxd = dfld[0];
87 rmind = dfld[0];
88 rmax = ffld[0];
89 rmin = ffld[0];
90 if (fld_is_double)
91 {
92 for (j = 1; j < ndpts; j++)
93 {
94 if (dfld[j] > rmaxd)
95 rmaxd = dfld[j];
96 if (dfld[j] < rmind)
97 rmind = dfld[j];
98 }
99 if (idrstmpl[1] == 0)
100 maxdif = (g2int)(rint(rmaxd * dscale) - rint(rmind * dscale));
101 else
102 maxdif = (g2int)rint((rmaxd - rmind) * dscale * bscale);
103 }
104 else
105 {
106 for (j = 1; j < ndpts; j++)
107 {
108 if (ffld[j] > rmax)
109 rmax = ffld[j];
110 if (ffld[j] < rmin)
111 rmin = ffld[j];
112 }
113 if (idrstmpl[1] == 0)
114 maxdif = (g2int)(rint(rmax * dscale) - rint(rmin * dscale));
115 else
116 maxdif = (g2int)rint((rmax - rmin) * dscale * bscale);
117 }
118 LOG((3, "rmax %g rmaxd %g rmin %g rmind %g", rmax, rmaxd, rmin, rmind));
119
120 /* If max and min values are not equal, pack up field. If they are
121 * equal, we have a constant field, and the reference value (rmin)
122 * is the value for each point in the field and set nbits to 0. */
123 if (((fld_is_double && rmind != rmaxd) || (!fld_is_double && rmin != rmax)) && maxdif != 0)
124 {
125 /* Allocate memory for scaled data. */
126 ifld = malloc(ndpts * sizeof(g2int));
127
128 /* Determine which algorithm to use based on user-supplied
129 * binary scale factor and number of bits. */
130 if (idrstmpl[1] == 0)
131 {
132 /* No binary scaling and calculate minumum number of bits
133 * in which the data will fit. */
134 imin = (g2int)rint((fld_is_double ? rmind : rmin) * dscale);
135 imax = (g2int)rint((fld_is_double ? rmaxd : rmax) * dscale);
136 maxdif = imax - imin;
137 temp = log((double)(maxdif + 1)) / alog2;
138 nbits = (g2int)ceil(temp);
139 /* scale data */
140 if (fld_is_double)
141 {
142 rmind = (float)imin;
143 for (j = 0; j < ndpts; j++)
144 ifld[j] = (g2int)rint(dfld[j] * dscale) - imin;
145 }
146 else
147 {
148 rmin = (float)imin;
149 for (j = 0; j < ndpts; j++)
150 ifld[j] = (g2int)rint(ffld[j] * dscale) - imin;
151 }
152 }
153 else
154 {
155 /* Use binary scaling factor and calculate minumum number
156 * of bits in which the data will fit. */
157 if (fld_is_double)
158 {
159 rmind = rmind * dscale;
160 rmaxd = rmaxd * dscale;
161 maxdif = (g2int)rint((rmaxd - rmind) * bscale);
162 }
163 else
164 {
165 rmin = rmin * dscale;
166 rmax = rmax * dscale;
167 maxdif = (g2int)rint((rmax - rmin) * bscale);
168 }
169 temp = log((double)(maxdif + 1)) / alog2;
170 nbits = (g2int)ceil(temp);
171 /* scale data */
172 if (fld_is_double)
173 {
174 for (j = 0; j < ndpts; j++)
175 ifld[j] = (g2int)rint(((dfld[j] * dscale) - rmind) * bscale);
176 }
177 else
178 {
179 for (j = 0; j < ndpts; j++)
180 ifld[j] = (g2int)rint(((ffld[j] * dscale) - rmin) * bscale);
181 }
182 }
183
184 /* Define AEC compression options */
185 if (idrstmpl[3] <= 0)
186 {
187 nbits = pow(2, ceil(log(nbits) / log(2))); // Round to nearest base 2 int
188 }
189 else
190 {
191 nbits = idrstmpl[3];
192 nbits = pow(2, ceil(log(nbits) / log(2))); // Round to nearest base 2 int
193 }
194 nbits = nbits < 8 ? 8 : nbits;
195
196 if (idrstmpl[5] == 0)
197 {
198 ccsds_flags = AEC_DATA_SIGNED | AEC_DATA_PREPROCESS | AEC_DATA_MSB;
199 }
200 else
201 {
202 ccsds_flags = idrstmpl[5];
203 }
204 if (idrstmpl[6] == 0)
205 {
206 ccsds_block_size = 16;
207 }
208 else
209 {
210 ccsds_block_size = idrstmpl[6];
211 }
212 if (idrstmpl[7] == 0)
213 {
214 ccsds_rsi = 128;
215 }
216 else
217 {
218 ccsds_rsi = idrstmpl[7];
219 }
220
221 /* Pack data into full octets, then do AEC encode and
222 * calculate the length of the packed data in bytes. */
223 nbytes = (nbits + 7) / 8;
224 ctemp = calloc(ndpts, nbytes);
225 ctemplen = ndpts * nbytes;
226 sbits(ctemp, ifld, 0, nbytes * 8, 0, ndpts);
227
228 *lcpack = enc_aec(ctemp, ctemplen, nbits, ccsds_flags, ccsds_block_size, ccsds_rsi, cpack, lcpack);
229 if (*lcpack < 0)
230 {
231 if (verbose)
232 printf("aecpack: ERROR Packing AEC = %d\n", ret);
233 nbits = 0;
234 *lcpack = 0;
235 ret = G2C_EAEC;
236 }
237
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
296void
297aecpack(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
345int
346g2c_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;
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
409int
410g2c_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;
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)
Pack a float or double array into a AEC/CCSDS code stream.
Definition aecpack.c:52
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)
Encode data into an AEC code stream specified in the CCSDS 121.0-B-3 Blue Book.
Definition decenc_aec.c:108
void sbits(unsigned char *out, g2int *in, g2int iskip, g2int nbits, g2int nskip, g2int n)
Store arbitrary size values into a packed bit string, taking the low order bits from each value in th...
Definition gbits.c:178
#define G2C_EAEC
Error encoding/decoding AEC data.
Definition grib2.h:502
#define G2C_AEC_DRS_TEMPLATE_LEN
Length of the idrstmpl array for AEC packing.
Definition grib2.h:407
int64_t g2int
Long integer type.
Definition grib2.h:32
#define G2C_NOERROR
No error.
Definition grib2.h:476
Header file with internal function prototypes NCEPLIBS-g2c library.
void mkieee(float *a, g2int *rieee, g2int num)
Store 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:428
#define ALOG2
ln(2.0)
Definition grib2_int.h:30