1 #include "grib2.h"
2 #ifndef USE_PNG
dec_png(unsigned char * pngbuf,g2int len,g2int * width,g2int * height,unsigned char * cout,g2int ndpts,g2int nbits)3 int dec_png(unsigned char *pngbuf,g2int len,g2int *width,g2int *height,unsigned char *cout, g2int ndpts, g2int nbits){return 0;}
4 #else /* USE_PNG */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <limits.h>
9 #include <png.h>
10
11
12 struct png_stream {
13 unsigned char *stream_ptr; /* location to write PNG stream */
14 g2int stream_len; /* number of bytes written */
15 g2int stream_total_len;
16 };
17 typedef struct png_stream png_stream;
18
user_read_data(png_structp png_ptr,png_bytep data,png_size_t length)19 static void user_read_data(png_structp png_ptr,png_bytep data, png_size_t length)
20 /*
21 Custom read function used so that libpng will read a PNG stream
22 from memory instead of a file on disk.
23 */
24 {
25 char *ptr;
26 g2int offset;
27 png_stream *mem;
28
29 mem=(png_stream *)png_get_io_ptr(png_ptr);
30 if( (g2int)length + mem->stream_len > mem->stream_total_len )
31 {
32 jmp_buf* psSetJmpContext = (jmp_buf *)png_get_error_ptr( png_ptr );
33 if (psSetJmpContext)
34 longjmp( *psSetJmpContext, 1 );
35 }
36 else
37 {
38 ptr=(void *)mem->stream_ptr;
39 offset=mem->stream_len;
40 /* printf("SAGrd %ld %ld %x\n",offset,length,ptr); */
41 memcpy(data,ptr+offset,length);
42 mem->stream_len += (g2int)length;
43 }
44 }
45
46
47
dec_png(unsigned char * pngbuf,g2int len,g2int * width,g2int * height,unsigned char * cout,g2int ndpts,g2int nbits)48 int dec_png(unsigned char *pngbuf,g2int len,g2int *width,g2int *height,unsigned char *cout, g2int ndpts, g2int nbits)
49 {
50 int interlace,color,l_compress,filter,bit_depth;
51 g2int j,k,n,bytes,clen;
52 png_structp png_ptr;
53 png_infop info_ptr,end_info;
54 png_bytepp row_pointers;
55 png_stream read_io_ptr;
56 png_uint_32 u_width;
57 png_uint_32 u_height;
58
59 /* check if stream is a valid PNG format */
60
61 if ( len < 8 || png_sig_cmp(pngbuf,0,8) != 0)
62 return (-3);
63
64 /* create and initialize png_structs */
65
66 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
67 NULL, NULL);
68 if (!png_ptr)
69 return (-1);
70
71 info_ptr = png_create_info_struct(png_ptr);
72 if (!info_ptr)
73 {
74 png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);
75 return (-2);
76 }
77
78 end_info = png_create_info_struct(png_ptr);
79 if (!end_info)
80 {
81 png_destroy_read_struct(&png_ptr,(png_infopp)info_ptr,(png_infopp)NULL);
82 return (-2);
83 }
84
85 /* Set Error callback */
86
87 if (setjmp(png_jmpbuf(png_ptr)))
88 {
89 png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
90 return (-3);
91 }
92
93 /* Initialize info for reading PNG stream from memory */
94
95 read_io_ptr.stream_ptr=(png_voidp)pngbuf;
96 read_io_ptr.stream_len=0;
97 read_io_ptr.stream_total_len = len;
98
99 /* Set new custom read function */
100
101 png_set_read_fn(png_ptr,(png_voidp)&read_io_ptr,(png_rw_ptr)user_read_data);
102 /* png_init_io(png_ptr, fptr); */
103
104 /* Read and decode PNG stream */
105
106 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
107
108 /* Get pointer to each row of image data */
109
110 row_pointers = png_get_rows(png_ptr, info_ptr);
111
112 /* Get image info, such as size, depth, colortype, etc... */
113
114 /*printf("SAGT:png %d %d %d\n",info_ptr->width,info_ptr->height,info_ptr->bit_depth);*/
115 if( !png_get_IHDR(png_ptr, info_ptr, &u_width, &u_height,
116 &bit_depth, &color, &interlace, &l_compress, &filter) )
117 {
118 fprintf(stderr, "png_get_IHDR() failed\n");
119 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
120 return( -4 );
121 }
122 if( u_width > (unsigned)INT_MAX || u_height > (unsigned)INT_MAX )
123 {
124 fprintf(stderr, "invalid width/height\n");
125 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
126 return( -5 );
127 }
128 *width = (g2int) u_width;
129 *height = (g2int) u_height;
130 if( (*width) * (*height) != ndpts )
131 {
132 fprintf(stderr, "invalid width/height\n");
133 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
134 return( -6 );
135 }
136
137 /* Check if image was grayscale */
138
139 /*
140 if (color != PNG_COLOR_TYPE_GRAY ) {
141 fprintf(stderr,"dec_png: Grayscale image was expected. \n");
142 }
143 */
144 if ( color == PNG_COLOR_TYPE_RGB ) {
145 bit_depth=24;
146 }
147 else if ( color == PNG_COLOR_TYPE_RGB_ALPHA ) {
148 bit_depth=32;
149 }
150 if( bit_depth != nbits )
151 {
152 fprintf(stderr, "inconsistent PNG bit depth\n");
153 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
154 return( -7 );
155 }
156 /* Copy image data to output string */
157
158 n=0;
159 bytes=bit_depth/8;
160 clen=(*width)*bytes;
161 for (j=0;j<*height;j++) {
162 for (k=0;k<clen;k++) {
163 cout[n]=*(row_pointers[j]+k);
164 n++;
165 }
166 }
167
168 /* Clean up */
169
170 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
171 return 0;
172
173 }
174
175 #endif /* USE_PNG */
176