NCEPLIBS-g2c 2.2.0
Loading...
Searching...
No Matches
decenc_png.c
Go to the documentation of this file.
1
6#include "grib2_int.h"
7#include <png.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
15struct png_stream
16{
17 unsigned char *stream_ptr;
18 g2int stream_len;
19};
20
21typedef struct png_stream png_stream;
23void user_read_data(png_structp, png_bytep, png_uint_32);
24void user_write_data(png_structp, png_bytep, png_uint_32);
25void user_flush_data(png_structp);
26
37void
38user_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
39{
40 char *ptr;
41 g2int offset;
42 png_stream *mem;
43
44 mem = (png_stream *)png_get_io_ptr(png_ptr);
45 ptr = (void *)mem->stream_ptr;
46 offset = mem->stream_len;
47 memcpy(data, ptr + offset, length);
48 mem->stream_len += length;
49}
50
61void
62user_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
63{
64 unsigned char *ptr;
65 g2int offset;
66 png_stream *mem;
67
68 mem = (png_stream *)png_get_io_ptr(png_ptr);
69 ptr = mem->stream_ptr;
70 offset = mem->stream_len;
71 memcpy(ptr + offset, data, length);
72 mem->stream_len += length;
73}
74
82void
83user_flush_data(png_structp png_ptr)
84{
85}
86
99int
100g2c_dec_png(unsigned char *pngbuf, int *width, int *height,
101 unsigned char *cout)
102{
103 g2int width8 = *width, height8 = *height;
104 int ret;
105
106 ret = dec_png(pngbuf, &width8, &height8, cout);
107
108 *width = (g2int)width8;
109 *height = (g2int)height8;
110
111 return ret;
112}
113
126int
127dec_png(unsigned char *pngbuf, g2int *width, g2int *height,
128 unsigned char *cout)
129{
130 int interlace, color, compres, filter, bit_depth;
131 g2int j, k, n, bytes;
132 png_structp png_ptr;
133 png_infop info_ptr, end_info;
134 png_bytepp row_pointers;
135 png_stream read_io_ptr;
136 png_uint_32 h32, w32;
137
138 /* Check if stream is a valid PNG format. */
139 if (png_sig_cmp(pngbuf, 0, 8) != 0)
140 return -3;
141
142 /* Create and initialize png_structs. */
143 if (!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
144 NULL, NULL)))
145 return -1;
146
147 if (!(info_ptr = png_create_info_struct(png_ptr)))
148 {
149 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
150 return -2;
151 }
152
153 if (!(end_info = png_create_info_struct(png_ptr)))
154 {
155 png_destroy_read_struct(&png_ptr, (png_infopp)info_ptr, (png_infopp)NULL);
156 return -2;
157 }
158
159 /* Set Error callback. */
160 if (setjmp(png_jmpbuf(png_ptr)))
161 {
162 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
163 return -3;
164 }
165
166 /* Initialize info for reading PNG stream from memory. */
167 read_io_ptr.stream_ptr = (png_voidp)pngbuf;
168 read_io_ptr.stream_len = 0;
169
170 /* Set new custom read function. */
171 png_set_read_fn(png_ptr, (png_voidp)&read_io_ptr, (png_rw_ptr)user_read_data);
172
173 /* support for larger grids */
174 png_set_user_limits(png_ptr, G2C_PNG_WIDTH_MAX, G2C_PNG_HEIGHT_MAX);
175
176 /* Read and decode PNG stream. */
177 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
178
179 /* Get pointer to each row of image data. */
180 row_pointers = png_get_rows(png_ptr, info_ptr);
181
182 /* Get image info, such as size, depth, colortype, etc... */
183 /*printf("SAGT:png %d %d %d\n", info_ptr->width, info_ptr->height, info_ptr->bit_depth);*/
184 // (void)png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)width, (png_uint_32 *)height,
185 (void)png_get_IHDR(png_ptr, info_ptr, &w32, &h32,
186 &bit_depth, &color, &interlace, &compres, &filter);
187
188 *height = h32;
189 *width = w32;
190
191 /* Check if image was grayscale. */
192 /*
193 if (color != PNG_COLOR_TYPE_GRAY) {
194 fprintf(stderr, "dec_png: Grayscale image was expected. \n");
195 }
196 */
197 if (color == PNG_COLOR_TYPE_RGB)
198 bit_depth = 24;
199 else if (color == PNG_COLOR_TYPE_RGB_ALPHA)
200 bit_depth = 32;
201
202 /* Copy image data to output string */
203 n = 0;
204 bytes = (*width * bit_depth) / 8;
205 if ((*width * bit_depth) % 8 != 0)
206 {
207 bytes++;
208 }
209 for (j = 0; j < *height; j++)
210 {
211 for (k = 0; k < bytes; k++)
212 {
213 cout[n] = *(row_pointers[j] + k);
214 n++;
215 }
216 }
217
218 /* Clean up. */
219 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
220 return 0;
221}
222
236int
237g2c_enc_png(unsigned char *data, int width, int height, int nbits,
238 unsigned char *pngbuf)
239{
240 g2int width8 = width, height8 = height, nbits8 = nbits;
241
242 return enc_png(data, width8, height8, nbits8, pngbuf);
243}
244
258int
259enc_png(unsigned char *data, g2int width, g2int height, g2int nbits,
260 unsigned char *pngbuf)
261{
262 int color_type;
263 g2int j, bytes, pnglen, bit_depth;
264 png_structp png_ptr;
265 png_infop info_ptr;
266 png_bytep **row_pointers;
267 png_stream write_io_ptr;
268
269 /* Create and initialize png_structs. */
270 if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
271 return -1;
272
273 if (!(info_ptr = png_create_info_struct(png_ptr)))
274 {
275 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
276 return -2;
277 }
278
279 /* Set Error callback. */
280 if (setjmp(png_jmpbuf(png_ptr)))
281 {
282 png_destroy_write_struct(&png_ptr, &info_ptr);
283 return -3;
284 }
285
286 /* Initialize info for writing PNG stream to memory. */
287 write_io_ptr.stream_ptr = (png_voidp)pngbuf;
288 write_io_ptr.stream_len = 0;
289
290 /* Set new custom write functions. */
291 png_set_write_fn(png_ptr, (png_voidp)&write_io_ptr, (png_rw_ptr)user_write_data,
292 (png_flush_ptr)user_flush_data);
293
294 /* Set the image size, colortype, filter type, etc... */
295 bit_depth = nbits;
296 color_type = PNG_COLOR_TYPE_GRAY;
297 if (nbits == 24)
298 {
299 bit_depth = 8;
300 color_type = PNG_COLOR_TYPE_RGB;
301 }
302 else if (nbits == 32)
303 {
304 bit_depth = 8;
305 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
306 }
307 png_set_IHDR(png_ptr, info_ptr, width, height,
308 bit_depth, color_type, PNG_INTERLACE_NONE,
309 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
310
311 /* Put image data into the PNG info structure. */
312 bytes = (width * nbits) / 8;
313 if ((width * nbits) % 8 != 0)
314 {
315 bytes++;
316 }
317
318 row_pointers = malloc(height * sizeof(png_bytep));
319 for (j = 0; j < height; j++)
320 row_pointers[j] = (png_bytep *)(data + (j * bytes));
321
322 png_set_rows(png_ptr, info_ptr, (png_bytepp)row_pointers);
323
324 /* Do the PNG encoding, and write out PNG stream. */
325 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
326
327 /* Clean up. */
328 png_destroy_write_struct(&png_ptr, &info_ptr);
329 free(row_pointers);
330 pnglen = write_io_ptr.stream_len;
331 return pnglen;
332}
int enc_png(unsigned char *data, g2int width, g2int height, g2int nbits, unsigned char *pngbuf)
Encode PNG.
Definition decenc_png.c:259
int dec_png(unsigned char *pngbuf, g2int *width, g2int *height, unsigned char *cout)
Decode PNG.
Definition decenc_png.c:127
struct png_stream png_stream
Typedef for PNG stream.
Definition decenc_png.c:21
int g2c_enc_png(unsigned char *data, int width, int height, int nbits, unsigned char *pngbuf)
Encode PNG.
Definition decenc_png.c:237
void user_flush_data(png_structp)
Dummy Custom flush function.
Definition decenc_png.c:83
void user_read_data(png_structp, png_bytep, png_uint_32)
Custom read function used so that libpng will read a PNG stream from memory instead of a file on disk...
Definition decenc_png.c:38
void user_write_data(png_structp, png_bytep, png_uint_32)
Custom write function used to that libpng will write to memory location instead of a file on disk.
Definition decenc_png.c:62
int g2c_dec_png(unsigned char *pngbuf, int *width, int *height, unsigned char *cout)
Decode PNG.
Definition decenc_png.c:100
#define G2C_PNG_WIDTH_MAX
Maximum width of PNG grid.
Definition grib2.h:430
#define G2C_PNG_HEIGHT_MAX
Maximum height of PNG grid.
Definition grib2.h:431
int64_t g2int
Long integer type.
Definition grib2.h:32
Header file with internal function prototypes NCEPLIBS-g2c library.