NCEPLIBS-g2c  1.7.0
pngpack.c
Go to the documentation of this file.
1 
5 #include <stdlib.h>
6 #include <math.h>
7 #include "grib2_int.h"
8 
40 static void
41 pngpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl,
42  unsigned char *cpack, g2int *lcpack)
43 {
44  g2int *ifld = NULL;
45  static float alog2 = ALOG2; /* ln(2.0) */
46  g2int j, nbits, imin, imax, maxdif;
47  g2int ndpts, nbytes;
48  float bscale, dscale, rmax, rmin, temp;
49  double rmaxd, rmind;
50  unsigned char *ctemp;
51  float *ffld = fld;
52  double *dfld = fld;
53 
54  LOG((2, "pngpack_int fld_is_double %d width %ld height %ld idrstmpl[1] %d",
55  fld_is_double, width, height, idrstmpl[1]));
56 
57  ndpts = width * height;
58  bscale = int_power(2.0, -idrstmpl[1]);
59  dscale = int_power(10.0, idrstmpl[2]);
60  LOG((3, "ndpts %d bscale %g dscale %g", ndpts, bscale, dscale));
61 
62  /* Find max and min values in the data. Either rmax and rmin will
63  * be used (if fld_is_double is not true), or rmaxd and rmind will
64  * be used (if fld_is_double is true). */
65  rmaxd = dfld[0];
66  rmind = dfld[0];
67  rmax = ffld[0];
68  rmin = ffld[0];
69  if (fld_is_double)
70  {
71  for (j = 1; j < ndpts; j++)
72  {
73  if (dfld[j] > rmaxd)
74  rmaxd = dfld[j];
75  if (dfld[j] < rmind)
76  rmind = dfld[j];
77  }
78  maxdif = (g2int)rint((rmaxd - rmind) * dscale * bscale);
79  }
80  else
81  {
82  for (j = 1; j < ndpts; j++)
83  {
84  if (ffld[j] > rmax)
85  rmax = ffld[j];
86  if (ffld[j] < rmin)
87  rmin = ffld[j];
88  }
89  maxdif = (g2int)rint((rmax - rmin) * dscale * bscale);
90  }
91  LOG((3, "rmax %g rmaxd %g rmin %g rmind %g", rmax, rmaxd, rmin, rmind));
92 
93  /* If max and min values are not equal, pack up field. If they are
94  * equal, we have a constant field, and the reference value (rmin)
95  * is the value for each point in the field and set nbits to 0. */
96  if (((fld_is_double && rmind != rmaxd) || (!fld_is_double && rmin != rmax)) && maxdif != 0)
97  {
98  ifld = malloc(ndpts * sizeof(g2int));
99 
100  /* Determine which algorithm to use based on user-supplied
101  * binary scale factor and number of bits. */
102  if (idrstmpl[1] == 0)
103  {
104  /* No binary scaling and calculate minumum number of bits
105  * in which the data will fit. */
106  imin = (g2int)rint((fld_is_double ? rmind : rmin) * dscale);
107  imax = (g2int)rint((fld_is_double ? rmaxd : rmax) * dscale);
108  maxdif = imax - imin;
109  temp = log((double)(maxdif + 1)) / alog2;
110  nbits = (g2int)ceil(temp);
111  /* scale data */
112  if (fld_is_double)
113  {
114  rmind = (float)imin;
115  for(j = 0; j < ndpts; j++)
116  ifld[j] = (g2int)rint(dfld[j] * dscale) - imin;
117  }
118  else
119  {
120  rmin = (float)imin;
121  for(j = 0; j < ndpts; j++)
122  ifld[j] = (g2int)rint(ffld[j] * dscale) - imin;
123  }
124  }
125  else
126  {
127  /* Use binary scaling factor and calculate minumum number
128  * of bits in which the data will fit. */
129  if (fld_is_double)
130  {
131  rmind = rmind * dscale;
132  rmaxd = rmaxd * dscale;
133  maxdif = (g2int)rint((rmaxd - rmind) * bscale);
134  }
135  else
136  {
137  rmin = rmin * dscale;
138  rmax = rmax * dscale;
139  maxdif = (g2int)rint((rmax - rmin) * bscale);
140  }
141  temp = log((double)(maxdif + 1)) / alog2;
142  nbits = (g2int)ceil(temp);
143  /* scale data */
144  if (fld_is_double)
145  {
146  for (j = 0; j < ndpts; j++)
147  ifld[j] = (g2int)rint(((dfld[j] * dscale) - rmind) * bscale);
148  }
149  else
150  {
151  for (j = 0; j < ndpts; j++)
152  ifld[j] = (g2int)rint(((ffld[j] * dscale) - rmin) * bscale);
153  }
154  }
155 
156  /* Pack data into full octets, then do PNG encode and
157  * calculate the length of the packed data in bytes. */
158  if (nbits <= 8)
159  nbits = 8;
160  else if (nbits <= 16)
161  nbits = 16;
162  else if (nbits <= 24)
163  nbits = 24;
164  else
165  nbits = 32;
166 
167  nbytes = (nbits / 8) * ndpts;
168  ctemp = calloc(nbytes, 1);
169  sbits(ctemp, ifld, 0, nbits, 0, ndpts);
170 
171  /* Encode data into PNG Format. */
172  if ((*lcpack = (g2int)enc_png(ctemp, width, height, nbits, cpack)) <= 0)
173  printf("pngpack: ERROR Packing PNG = %d\n", (int)*lcpack);
174 
175  free(ctemp);
176  }
177  else
178  {
179  nbits = 0;
180  *lcpack = 0;
181  }
182 
183  /* Fill in ref value and number of bits in Template 5.0. */
184  if (fld_is_double)
185  rmin = (float)rmind;
186  mkieee(&rmin, idrstmpl, 1); /* ensure reference value is IEEE format */
187  idrstmpl[3] = nbits;
188  idrstmpl[4] = 0; /* original data were reals */
189 
190  if (ifld)
191  free(ifld);
192 }
193 
223 void
224 pngpack(float *fld, g2int width, g2int height, g2int *idrstmpl,
225  unsigned char *cpack, g2int *lcpack)
226 {
227  pngpack_int(fld, 0, width, height, idrstmpl, cpack, lcpack);
228 }
229 
258 void
259 pngpackd(double *fld, g2int width, g2int height, g2int *idrstmpl,
260  unsigned char *cpack, g2int *lcpack)
261 {
262  pngpack_int(fld, 1, width, height, idrstmpl, cpack, lcpack);
263 }
264 
enc_png
int enc_png(unsigned char *data, g2int width, g2int height, g2int nbits, unsigned char *pngbuf)
Encode PNG.
Definition: enc_png.c:75
pngpackd
void pngpackd(double *fld, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This subroutine packs up a double data field into PNG image format.
Definition: pngpack.c:259
pngpack_int
static void pngpack_int(void *fld, int fld_is_double, g2int width, g2int height, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This internal function packs up float or double data into PNG image format.
Definition: pngpack.c:41
int_power
double int_power(double x, g2int y)
Function similar to C pow() power function.
Definition: int_power.c:18
LOG
#define LOG(e)
Ignore logging to stdout.
Definition: grib2_int.h:138
grib2_int.h
Header file with internal function prototypes NCEPLIBS-g2c library.
sbits
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:114
mkieee
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
g2int
int64_t g2int
Long integer type.
Definition: grib2.h:28
pngpack
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:224
ALOG2
#define ALOG2
ln(2.0)
Definition: grib2_int.h:21