Line data Source code
1 : #include "grib2.h"
2 : #ifndef USE_PNG
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 :
19 129 : 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 129 : mem=(png_stream *)png_get_io_ptr(png_ptr);
30 129 : if( (g2int)length + mem->stream_len > mem->stream_total_len )
31 : {
32 0 : jmp_buf* psSetJmpContext = (jmp_buf *)png_get_error_ptr( png_ptr );
33 0 : if (psSetJmpContext)
34 0 : longjmp( *psSetJmpContext, 1 );
35 : }
36 : else
37 : {
38 129 : ptr=(void *)mem->stream_ptr;
39 129 : offset=mem->stream_len;
40 : /* printf("SAGrd %ld %ld %x\n",offset,length,ptr); */
41 129 : memcpy(data,ptr+offset,length);
42 129 : mem->stream_len += (g2int)length;
43 : }
44 129 : }
45 :
46 :
47 :
48 14 : 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 14 : if ( len < 8 || png_sig_cmp(pngbuf,0,8) != 0)
62 0 : return (-3);
63 :
64 : /* create and initialize png_structs */
65 :
66 14 : png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
67 : NULL, NULL);
68 14 : if (!png_ptr)
69 0 : return (-1);
70 :
71 14 : info_ptr = png_create_info_struct(png_ptr);
72 14 : if (!info_ptr)
73 : {
74 0 : png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);
75 0 : return (-2);
76 : }
77 :
78 14 : end_info = png_create_info_struct(png_ptr);
79 14 : if (!end_info)
80 : {
81 0 : png_destroy_read_struct(&png_ptr,(png_infopp)info_ptr,(png_infopp)NULL);
82 0 : return (-2);
83 : }
84 :
85 : /* Set Error callback */
86 :
87 14 : if (setjmp(png_jmpbuf(png_ptr)))
88 : {
89 0 : png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
90 0 : return (-3);
91 : }
92 :
93 : /* Initialize info for reading PNG stream from memory */
94 :
95 14 : read_io_ptr.stream_ptr=(png_voidp)pngbuf;
96 14 : read_io_ptr.stream_len=0;
97 14 : read_io_ptr.stream_total_len = len;
98 :
99 : /* Set new custom read function */
100 :
101 14 : 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 14 : png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
107 :
108 : /* Get pointer to each row of image data */
109 :
110 14 : 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 14 : if( !png_get_IHDR(png_ptr, info_ptr, &u_width, &u_height,
116 : &bit_depth, &color, &interlace, &l_compress, &filter) )
117 : {
118 0 : fprintf(stderr, "png_get_IHDR() failed\n");
119 0 : png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
120 0 : return( -4 );
121 : }
122 14 : if( u_width > (unsigned)INT_MAX || u_height > (unsigned)INT_MAX )
123 : {
124 0 : fprintf(stderr, "invalid width/height\n");
125 0 : png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
126 0 : return( -5 );
127 : }
128 14 : *width = (g2int) u_width;
129 14 : *height = (g2int) u_height;
130 14 : if( (*width) * (*height) != ndpts )
131 : {
132 0 : fprintf(stderr, "invalid width/height\n");
133 0 : png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
134 0 : 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 14 : if ( color == PNG_COLOR_TYPE_RGB ) {
145 0 : bit_depth=24;
146 : }
147 14 : else if ( color == PNG_COLOR_TYPE_RGB_ALPHA ) {
148 0 : bit_depth=32;
149 : }
150 14 : if( bit_depth != nbits )
151 : {
152 0 : fprintf(stderr, "inconsistent PNG bit depth\n");
153 0 : png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
154 0 : return( -7 );
155 : }
156 : /* Copy image data to output string */
157 :
158 14 : n=0;
159 14 : bytes=bit_depth/8;
160 14 : clen=(*width)*bytes;
161 1738 : for (j=0;j<*height;j++) {
162 9004940 : for (k=0;k<clen;k++) {
163 9003210 : cout[n]=*(row_pointers[j]+k);
164 9003210 : n++;
165 : }
166 : }
167 :
168 : /* Clean up */
169 :
170 14 : png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
171 14 : return 0;
172 :
173 : }
174 :
175 : #endif /* USE_PNG */
|