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