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