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