NCEPLIBS-g2c 2.0.0
Loading...
Searching...
No Matches
pngpack.c
Go to the documentation of this file.
1
5#include "grib2_int.h"
6#include <math.h>
7#include <stdlib.h>
8
52static int
53pngpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl,
54 unsigned char *cpack, g2int *lcpack, int verbose)
55{
56 g2int *ifld = NULL;
57 static float alog2 = ALOG2; /* ln(2.0) */
58 g2int j, nbits, imin, imax, maxdif;
59 g2int ndpts, nbytes;
60 float bscale, dscale, rmax, rmin, temp;
61 double rmaxd, rmind;
62 unsigned char *ctemp;
63 float *ffld = fld;
64 double *dfld = fld;
65 int ret = G2C_NOERROR;
66
67 LOG((2, "pngpack_int fld_is_double %d width %ld height %ld idrstmpl[1] %d",
68 fld_is_double, width, height, idrstmpl[1]));
69
70 ndpts = width * height;
71 bscale = int_power(2.0, -idrstmpl[1]);
72 dscale = int_power(10.0, idrstmpl[2]);
73 LOG((3, "ndpts %d bscale %g dscale %g", ndpts, bscale, dscale));
74
75 /* Find max and min values in the data. Either rmax and rmin will
76 * be used (if fld_is_double is not true), or rmaxd and rmind will
77 * be used (if fld_is_double is true). */
78 rmaxd = dfld[0];
79 rmind = dfld[0];
80 rmax = ffld[0];
81 rmin = ffld[0];
82 if (fld_is_double)
83 {
84 for (j = 1; j < ndpts; j++)
85 {
86 if (dfld[j] > rmaxd)
87 rmaxd = dfld[j];
88 if (dfld[j] < rmind)
89 rmind = dfld[j];
90 }
91 maxdif = (g2int)rint((rmaxd - rmind) * dscale * bscale);
92 }
93 else
94 {
95 for (j = 1; j < ndpts; j++)
96 {
97 if (ffld[j] > rmax)
98 rmax = ffld[j];
99 if (ffld[j] < rmin)
100 rmin = ffld[j];
101 }
102 maxdif = (g2int)rint((rmax - rmin) * dscale * bscale);
103 }
104 LOG((3, "rmax %g rmaxd %g rmin %g rmind %g", rmax, rmaxd, rmin, rmind));
105
106 /* If max and min values are not equal, pack up field. If they are
107 * equal, we have a constant field, and the reference value (rmin)
108 * is the value for each point in the field and set nbits to 0. */
109 if (((fld_is_double && rmind != rmaxd) || (!fld_is_double && rmin != rmax)) && maxdif != 0)
110 {
111 ifld = malloc(ndpts * sizeof(g2int));
112
113 /* Determine which algorithm to use based on user-supplied
114 * binary scale factor and number of bits. */
115 if (idrstmpl[1] == 0)
116 {
117 /* No binary scaling and calculate minumum number of bits
118 * in which the data will fit. */
119 imin = (g2int)rint((fld_is_double ? rmind : rmin) * dscale);
120 imax = (g2int)rint((fld_is_double ? rmaxd : rmax) * dscale);
121 maxdif = imax - imin;
122 temp = log((double)(maxdif + 1)) / alog2;
123 nbits = (g2int)ceil(temp);
124 /* scale data */
125 if (fld_is_double)
126 {
127 rmind = (float)imin;
128 for (j = 0; j < ndpts; j++)
129 ifld[j] = (g2int)rint(dfld[j] * dscale) - imin;
130 }
131 else
132 {
133 rmin = (float)imin;
134 for (j = 0; j < ndpts; j++)
135 ifld[j] = (g2int)rint(ffld[j] * dscale) - imin;
136 }
137 }
138 else
139 {
140 /* Use binary scaling factor and calculate minumum number
141 * of bits in which the data will fit. */
142 if (fld_is_double)
143 {
144 rmind = rmind * dscale;
145 rmaxd = rmaxd * dscale;
146 maxdif = (g2int)rint((rmaxd - rmind) * bscale);
147 }
148 else
149 {
150 rmin = rmin * dscale;
151 rmax = rmax * dscale;
152 maxdif = (g2int)rint((rmax - rmin) * bscale);
153 }
154 temp = log((double)(maxdif + 1)) / alog2;
155 nbits = (g2int)ceil(temp);
156 /* scale data */
157 if (fld_is_double)
158 {
159 for (j = 0; j < ndpts; j++)
160 ifld[j] = (g2int)rint(((dfld[j] * dscale) - rmind) * bscale);
161 }
162 else
163 {
164 for (j = 0; j < ndpts; j++)
165 ifld[j] = (g2int)rint(((ffld[j] * dscale) - rmin) * bscale);
166 }
167 }
168
169 /* Pack data into full octets, then do PNG encode and
170 * calculate the length of the packed data in bytes. */
171 if (nbits <= 1)
172 nbits = 1;
173 else if (nbits <= 2)
174 nbits = 2;
175 else if (nbits <= 4)
176 nbits = 4;
177 else if (nbits <= 8)
178 nbits = 8;
179 else if (nbits <= 16)
180 nbits = 16;
181 else if (nbits <= 24)
182 nbits = 24;
183 else
184 nbits = 32;
185
186 int bytes_per_row = (nbits * width) / 8;
187 if ((width * nbits) % 8 != 0)
188 {
189 bytes_per_row++;
190 }
191 nbytes = bytes_per_row * height;
192 ctemp = calloc(nbytes, 1);
193 for (j = 0; j < height; j++)
194 sbits(ctemp + (j * bytes_per_row), ifld + (j * width), 0, nbits, 0, width);
195
196 /* Encode data into PNG Format. */
197 if ((*lcpack = (g2int)enc_png(ctemp, width, height, nbits, cpack)) <= 0)
198 {
199 if (verbose)
200 printf("pngpack: ERROR Packing PNG = %d\n", (int)*lcpack);
201 ret = G2C_EPNG;
202 }
203 free(ctemp);
204 }
205 else
206 {
207 nbits = 0;
208 *lcpack = 0;
209 }
210
211 /* Fill in ref value and number of bits in Template 5.0. */
212 if (fld_is_double)
213 rmin = (float)rmind;
214 mkieee(&rmin, idrstmpl, 1); /* ensure reference value is IEEE format */
215 idrstmpl[3] = nbits;
216 idrstmpl[4] = 0; /* original data were reals */
217
218 if (ifld)
219 free(ifld);
220
221 return ret;
222}
223
253void
254pngpack(float *fld, g2int width, g2int height, g2int *idrstmpl,
255 unsigned char *cpack, g2int *lcpack)
256{
257 /* Ignore the return value. */
258 pngpack_int(fld, 0, width, height, idrstmpl, cpack, lcpack, 1);
259}
260
293int
294g2c_pngpackf(float *fld, size_t width, size_t height, int *idrstmpl,
295 unsigned char *cpack, int *lcpack)
296{
297 g2int width8 = width, height8 = height, lcpack8 = *lcpack;
299 int i, ret;
300
301 for (i = 0; i < G2C_PNG_DRS_TEMPLATE_LEN; i++)
302 idrstmpl8[i] = idrstmpl[i];
303
304 ret = pngpack_int(fld, 0, width8, height8, idrstmpl8, cpack, &lcpack8, 0);
305
306 if (!ret)
307 {
308 for (i = 0; i < G2C_PNG_DRS_TEMPLATE_LEN; i++)
309 idrstmpl[i] = (int)idrstmpl8[i];
310 *lcpack = (g2int)lcpack8;
311 }
312 return ret;
313}
314
347int
348g2c_pngpackd(double *fld, size_t width, size_t height, int *idrstmpl,
349 unsigned char *cpack, int *lcpack)
350{
351 g2int width8 = width, height8 = height, lcpack8 = *lcpack;
353 int i, ret;
354
355 for (i = 0; i < G2C_PNG_DRS_TEMPLATE_LEN; i++)
356 idrstmpl8[i] = idrstmpl[i];
357
358 ret = pngpack_int(fld, 1, width8, height8, idrstmpl8, cpack, &lcpack8, 0);
359
360 if (!ret)
361 {
362 for (i = 0; i < G2C_PNG_DRS_TEMPLATE_LEN; i++)
363 idrstmpl[i] = (int)idrstmpl8[i];
364 *lcpack = (g2int)lcpack8;
365 }
366 return ret;
367}
int enc_png(unsigned char *data, g2int width, g2int height, g2int nbits, unsigned char *pngbuf)
Encode PNG.
Definition decenc_png.c:207
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_EPNG
Error encoding/decoding PNG data.
Definition grib2.h:496
#define G2C_PNG_DRS_TEMPLATE_LEN
Length of the idrstmpl array for PNG packing.
Definition grib2.h:406
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
void pngpack(float *fld, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This subroutine packs up a float data field into PNG image format.
Definition pngpack.c:254
int g2c_pngpackd(double *fld, size_t width, size_t height, int *idrstmpl, unsigned char *cpack, int *lcpack)
This subroutine packs up a double data field into PNG image format.
Definition pngpack.c:348
int g2c_pngpackf(float *fld, size_t width, size_t height, int *idrstmpl, unsigned char *cpack, int *lcpack)
This subroutine packs up a float data field into PNG image format.
Definition pngpack.c:294
static int pngpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack, int verbose)
Packs float or double data into PNG image format.
Definition pngpack.c:53