1 | /*-------------------------------------␍␊ |
2 | * PNGFILE.C -- Image File Functions␍␊ |
3 | *-------------------------------------␍␊ |
4 | *␍␊ |
5 | * Copyright 2000, Willem van Schaik.␍␊ |
6 | *␍␊ |
7 | * This code is released under the libpng license.␍␊ |
8 | * For conditions of distribution and use, see the disclaimer␍␊ |
9 | * and license in png.h␍␊ |
10 | */␍␊ |
11 | ␍␊ |
12 | #include <stdio.h>␍␊ |
13 | #include <stdbool.h>␍␊ |
14 | #include <png.h>␍␊ |
15 | #include "pngfile.h"␍␊ |
16 | #include <pexpert/i386/modules.h>␍␊ |
17 | #include <CException.h>␍␊ |
18 | ␍␊ |
19 | extern int openmem(char *buf, int len);␍␊ |
20 | ␍␊ |
21 | png_const_charp msg;␍␊ |
22 | ␍␊ |
23 | static png_structp png_ptr = NULL;␍␊ |
24 | static png_infop info_ptr = NULL;␍␊ |
25 | ␍␊ |
26 | static bool PngHandleFile (FILE *pfFile , unsigned char **ppbImageData,␍␊ |
27 | int *piWidth, int *piHeight, int *piChannels, void *BkgColor);␍␊ |
28 | /* cexcept interface */␍␊ |
29 | ␍␊ |
30 | static void␍␊ |
31 | png_cexcept_error(png_structp png_ptr, png_const_charp msg)␍␊ |
32 | {␍␊ |
33 | (void)png_ptr;␍␊ |
34 | ␉␍␊ |
35 | printf("libpng error: %s\n", msg);␍␊ |
36 | {␍␊ |
37 | Throw (-1);␍␊ |
38 | }␍␊ |
39 | }␍␊ |
40 | ␍␊ |
41 | #ifndef PNG_STDIO_SUPPORTED␍␊ |
42 | typedef FILE * png_FILE_p;␍␊ |
43 | static void PNGCBAPI␍␊ |
44 | png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)␍␊ |
45 | {␍␊ |
46 | ␉png_size_t check = 0;␍␊ |
47 | ␉png_voidp io_ptr;␍␊ |
48 | ␉␍␊ |
49 | ␉/* fread() returns 0 on error, so it is OK to store this in a png_size_t␍␊ |
50 | ␉ * instead of an int, which is what fread() actually returns.␍␊ |
51 | ␉ */␍␊ |
52 | ␉io_ptr = png_get_io_ptr(png_ptr);␍␊ |
53 | ␉if (io_ptr != NULL)␍␊ |
54 | ␉{␍␊ |
55 | ␉␉check = fread(data, 1, length, (png_FILE_p)io_ptr);␍␊ |
56 | ␉}␍␊ |
57 | ␉␍␊ |
58 | ␉if (check != length)␍␊ |
59 | ␉{␍␊ |
60 | ␉␉png_error(png_ptr, "Read Error");␍␊ |
61 | ␉}␍␊ |
62 | ␍␊ |
63 | }␍␊ |
64 | ␍␊ |
65 | #endif␍␊ |
66 | ␍␊ |
67 | /* PNG image handler functions */␍␊ |
68 | ␍␊ |
69 | static bool PngHandleFile (FILE *pfFile , unsigned char **ppbImageData,␍␊ |
70 | int *piWidth, int *piHeight, int *piChannels, void *BkgColor)␍␊ |
71 | {␍␊ |
72 | png_byte pbSig[8];␍␊ |
73 | int iBitDepth;␍␊ |
74 | int iColorType;␍␊ |
75 | #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED␍␊ |
76 | #ifdef PNG_FLOATING_POINT_SUPPORTED ␍␊ |
77 | double dGamma;␍␊ |
78 | png_color_16 *pBackground;␍␊ |
79 | png_color *pBkgColor = (png_color *)BkgColor;␍␊ |
80 | #endif␍␊ |
81 | #endif␍␊ |
82 | png_uint_32 ulChannels;␍␊ |
83 | png_uint_32 ulRowBytes;␍␊ |
84 | png_byte *pbImageData = *ppbImageData;␍␊ |
85 | static png_byte **ppbRowPointers = NULL;␍␊ |
86 | int i;␍␊ |
87 | ␍␊ |
88 | /* first check the eight byte PNG signature */␍␊ |
89 | ␍␊ |
90 | fread(pbSig, 1, 8, pfFile);␍␊ |
91 | ␍␊ |
92 | if (png_sig_cmp(pbSig, 0, 8))␍␊ |
93 | {␍␊ |
94 | *ppbImageData = pbImageData = NULL;␍␊ |
95 | return false;␍␊ |
96 | }␍␊ |
97 | ␍␊ |
98 | /* create the two png(-info) structures */␍␊ |
99 | ␍␊ |
100 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,␍␊ |
101 | (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);␍␊ |
102 | if (!png_ptr)␍␊ |
103 | {␍␊ |
104 | *ppbImageData = pbImageData = NULL;␍␊ |
105 | return false;␍␊ |
106 | }␍␊ |
107 | ␍␊ |
108 | info_ptr = png_create_info_struct(png_ptr);␍␊ |
109 | if (!info_ptr)␍␊ |
110 | {␍␊ |
111 | png_destroy_read_struct(&png_ptr, NULL, NULL);␍␊ |
112 | *ppbImageData = pbImageData = NULL;␍␊ |
113 | return false;␍␊ |
114 | }␍␊ |
115 | ␍␊ |
116 | CEXCEPTION_T e = CEXCEPTION_NONE;␍␊ |
117 | ␍␊ |
118 | Try␍␊ |
119 | {␍␊ |
120 | ␍␊ |
121 | /* initialize the png structure */␍␊ |
122 | ␍␊ |
123 | #ifdef PNG_STDIO_SUPPORTED␍␊ |
124 | png_init_io(png_ptr, pfFile);␍␊ |
125 | #else␍␊ |
126 | png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);␍␊ |
127 | #endif␍␊ |
128 | ␍␊ |
129 | png_set_sig_bytes(png_ptr, 8);␍␊ |
130 | ␍␊ |
131 | /* read all PNG info up to image data */␍␊ |
132 | ␍␊ |
133 | png_read_info(png_ptr, info_ptr);␍␊ |
134 | ␍␊ |
135 | /* get width, height, bit-depth and color-type */␍␊ |
136 | ␍␊ |
137 | png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)piWidth, (png_uint_32*)piHeight, &iBitDepth,␍␊ |
138 | &iColorType, NULL, NULL, NULL);␍␊ |
139 | ␍␊ |
140 | /* expand images of all color-type and bit-depth to 3x8-bit RGB */␍␊ |
141 | /* let the library process alpha, transparency, background, etc. */␍␊ |
142 | ␍␊ |
143 | #ifdef PNG_READ_16_TO_8_SUPPORTED␍␊ |
144 | if (iBitDepth == 16)␍␊ |
145 | # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED␍␊ |
146 | png_set_scale_16(png_ptr);␍␊ |
147 | # else␍␊ |
148 | png_set_strip_16(png_ptr);␍␊ |
149 | # endif␍␊ |
150 | #endif␍␊ |
151 | if (iColorType == PNG_COLOR_TYPE_PALETTE)␍␊ |
152 | png_set_expand(png_ptr);␍␊ |
153 | if (iBitDepth < 8)␍␊ |
154 | png_set_expand(png_ptr);␍␊ |
155 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))␍␊ |
156 | png_set_expand(png_ptr);␍␊ |
157 | if (iColorType == PNG_COLOR_TYPE_GRAY ||␍␊ |
158 | iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)␍␊ |
159 | png_set_gray_to_rgb(png_ptr);␍␊ |
160 | #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED␍␊ |
161 | #ifdef PNG_FLOATING_POINT_SUPPORTED␍␊ |
162 | /* set the background color to draw transparent and alpha images over */␍␊ |
163 | if (png_get_bKGD(png_ptr, info_ptr, &pBackground))␍␊ |
164 | {␍␊ |
165 | png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);␍␊ |
166 | pBkgColor->red = (png_byte) pBackground->red;␍␊ |
167 | pBkgColor->green = (png_byte) pBackground->green;␍␊ |
168 | pBkgColor->blue = (png_byte) pBackground->blue;␍␊ |
169 | }␍␊ |
170 | else␍␊ |
171 | {␍␊ |
172 | pBkgColor = NULL;␍␊ |
173 | }␍␊ |
174 | ␍␊ |
175 | /* if required set gamma conversion */␍␊ |
176 | if (png_get_gAMA(png_ptr, info_ptr, &dGamma))␍␊ |
177 | png_set_gamma(png_ptr, (double) 2.2, dGamma);␍␊ |
178 | #endif␍␊ |
179 | #endif␍␊ |
180 | ␍␊ |
181 | /* after the transformations are registered, update info_ptr data */␍␊ |
182 | ␍␊ |
183 | png_read_update_info(png_ptr, info_ptr);␍␊ |
184 | ␍␊ |
185 | /* get again width, height and the new bit-depth and color-type */␍␊ |
186 | ␍␊ |
187 | png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)piWidth, (png_uint_32*)piHeight, &iBitDepth,␍␊ |
188 | &iColorType, NULL, NULL, NULL);␍␊ |
189 | ␍␊ |
190 | ␍␊ |
191 | /* row_bytes is the width x number of channels */␍␊ |
192 | ␍␊ |
193 | ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);␍␊ |
194 | ulChannels = png_get_channels(png_ptr, info_ptr);␍␊ |
195 | ␍␊ |
196 | *piChannels = ulChannels;␍␊ |
197 | ␍␊ |
198 | /* now we can allocate memory to store the image */␍␊ |
199 | ␍␊ |
200 | if (pbImageData)␍␊ |
201 | {␍␊ |
202 | free (pbImageData);␍␊ |
203 | pbImageData = NULL;␍␊ |
204 | }␍␊ |
205 | if ((pbImageData = (png_byte *) calloc(ulRowBytes * (*piHeight)␍␊ |
206 | , sizeof(png_byte))) == NULL)␍␊ |
207 | {␍␊ |
208 | png_error(png_ptr, "Visual PNG: out of memory");␍␊ |
209 | }␉␉␍␊ |
210 | ␍␊ |
211 | *ppbImageData = pbImageData;␍␊ |
212 | ␍␊ |
213 | /* and allocate memory for an array of row-pointers */␍␊ |
214 | ␍␊ |
215 | //if ((ppbRowPointers = (png_bytepp) malloc((*piHeight)␍␊ |
216 | // * sizeof(png_bytep))) == NULL)␍␊ |
217 | if ((ppbRowPointers = (png_bytepp)calloc((*piHeight)␍␊ |
218 | ␉␉␉␉␉␉␉␉␉␉␉␉ , sizeof(png_bytep))) == NULL)␍␊ |
219 | ␉␉{␍␊ |
220 | png_error(png_ptr, "Visual PNG: out of memory");␍␊ |
221 | }␍␊ |
222 | ␍␊ |
223 | /* set the individual row-pointers to point at the correct offsets */␍␊ |
224 | ␍␊ |
225 | for (i = 0; i < (*piHeight); i++)␍␊ |
226 | ppbRowPointers[i] = pbImageData + i * ulRowBytes;␍␊ |
227 | ␍␊ |
228 | /* now we can go ahead and just read the whole image */␍␊ |
229 | ␍␊ |
230 | png_read_image(png_ptr, ppbRowPointers);␍␊ |
231 | ␍␊ |
232 | /* read the additional chunks in the PNG file (not really needed) */␍␊ |
233 | ␍␊ |
234 | png_read_end(png_ptr, NULL);␍␊ |
235 | ␍␊ |
236 | /* and we're done */␍␊ |
237 | ␍␊ |
238 | free (ppbRowPointers);␍␊ |
239 | ppbRowPointers = NULL;␍␊ |
240 | ␍␊ |
241 | /* yepp, done */␍␊ |
242 | } ␍␊ |
243 | Catch (e)␍␊ |
244 | {␍␊ |
245 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL);␍␊ |
246 | ␍␊ |
247 | *ppbImageData = pbImageData = NULL;␍␊ |
248 | ␍␊ |
249 | if(ppbRowPointers)␍␊ |
250 | free (ppbRowPointers);␍␊ |
251 | ␍␊ |
252 | ␍␊ |
253 | return false;␍␊ |
254 | }␍␊ |
255 | ␍␊ |
256 | ␍␊ |
257 | return true;␍␊ |
258 | }␍␊ |
259 | ␍␊ |
260 | bool PngLoadImage (const char* pstrFileName, unsigned char **ppbImageData,␍␊ |
261 | int *piWidth, int *piHeight, int *piChannels, void *BkgColor)␍␊ |
262 | {␍␊ |
263 | static FILE *pfFile; ␍␊ |
264 | //png_byte *pbImageData = *ppbImageData;␍␊ |
265 | bool ret;␍␊ |
266 | /* open the PNG input file */␍␊ |
267 | ␍␊ |
268 | if (!pstrFileName)␍␊ |
269 | {␍␊ |
270 | *ppbImageData =/* pbImageData =*/ NULL;␍␊ |
271 | return false;␍␊ |
272 | }␍␊ |
273 | ␍␊ |
274 | if (!(pfFile = fopen(pstrFileName, "rb")))␍␊ |
275 | {␍␊ |
276 | *ppbImageData = /*pbImageData =*/ NULL;␍␊ |
277 | return false;␍␊ |
278 | }␍␊ |
279 | ret = PngHandleFile(pfFile, ppbImageData,␍␊ |
280 | piWidth, piHeight, piChannels, BkgColor);␍␊ |
281 | ␍␊ |
282 | fclose (pfFile);␍␊ |
283 | ␍␊ |
284 | return ret;␍␊ |
285 | }␍␊ |
286 | ␍␊ |
287 | bool PngLoadData(unsigned char *pngData, int pngSize, int *piWidth,␍␊ |
288 | int *piHeight, unsigned char **ppbImageData, int *piChannels, void *BkgColor)␍␊ |
289 | {␍␊ |
290 | ␍␊ |
291 | static FILE *pfFile;␍␊ |
292 | //png_byte *pbImageData = *ppbImageData;␍␊ |
293 | bool ret;␍␊ |
294 | int fd ;␍␊ |
295 | /* open the PNG input file */␍␊ |
296 | ␍␊ |
297 | if (!pngData)␍␊ |
298 | {␍␊ |
299 | *ppbImageData = /*pbImageData =*/ NULL;␍␊ |
300 | return false;␍␊ |
301 | }␍␊ |
302 | ␍␊ |
303 | if ((fd = openmem((char*)pngData, pngSize)) < 0)␍␊ |
304 | {␍␊ |
305 | *ppbImageData = /*pbImageData =*/ NULL;␍␊ |
306 | return false;␍␊ |
307 | }␍␊ |
308 | ␍␊ |
309 | if (!(pfFile = fdopen(fd, "rb")))␍␊ |
310 | {␍␊ |
311 | *ppbImageData = /*pbImageData =*/ NULL;␍␊ |
312 | return false;␍␊ |
313 | }␍␊ |
314 | ret = PngHandleFile(pfFile, ppbImageData,␍␊ |
315 | piWidth, piHeight, piChannels, BkgColor);␍␊ |
316 | ␍␊ |
317 | fclose (pfFile);␍␊ |
318 | ␉␍␊ |
319 | return ret;␍␊ |
320 | }␍␊ |
321 | ␍␊ |
322 | #if 0␍␊ |
323 | void PngLoadImage_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)␍␊ |
324 | {␍␊ |
325 | void *BkgColor = NULL;␍␊ |
326 | const char*pstrFileName = (const char*)arg1;␍␊ |
327 | int *piWidth = (int *)arg3;␍␊ |
328 | int *piHeight = (int *)arg4;␍␊ |
329 | unsigned char **ppbImageData = (unsigned char **)arg5;␍␊ |
330 | int *piChannels = (int *)arg6;␍␊ |
331 | bool ret ;␍␊ |
332 | ret = PngLoadImage (pstrFileName, ppbImageData,␍␊ |
333 | piWidth, piHeight, piChannels, BkgColor);␍␊ |
334 | ␍␊ |
335 | if (ret == false) {␍␊ |
336 | *piHeight =0;␍␊ |
337 | *piWidth = 0;␍␊ |
338 | *ppbImageData = NULL;␍␊ |
339 | *piChannels = 0;␍␊ |
340 | }␍␊ |
341 | }␍␊ |
342 | ␍␊ |
343 | void PngLoadData_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)␍␊ |
344 | {␍␊ |
345 | void *BkgColor = NULL;␍␊ |
346 | unsigned char *pngData = (unsigned char *)arg1;␍␊ |
347 | int pngSize = *(int*)arg2;␍␊ |
348 | int *piWidth = (int *)arg3;␍␊ |
349 | int *piHeight = (int *)arg4;␍␊ |
350 | unsigned char **ppbImageData = (unsigned char **)arg5;␍␊ |
351 | int *piChannels = (int *)arg6;␍␊ |
352 | bool ret ;␍␊ |
353 | ␍␊ |
354 | ␍␊ |
355 | ret = PngLoadData(pngData, pngSize, piWidth,␍␊ |
356 | piHeight, ppbImageData, piChannels, BkgColor);␍␊ |
357 | ␍␊ |
358 | if (ret == false) {␍␊ |
359 | *piHeight =0;␍␊ |
360 | *piWidth = 0;␍␊ |
361 | *ppbImageData = NULL;␍␊ |
362 | *piChannels = 0;␍␊ |
363 | }␍␊ |
364 | }␍␊ |
365 | #endif␍␊ |
366 | /*-----------------␍␊ |
367 | * end of source␍␊ |
368 | *-----------------␍␊ |
369 | */␍␊ |
370 | |