Mercurial > mm7
comparison lib/libpng/pngread.c @ 2296:6e178010fc29
libpng
author | Ritor1 |
---|---|
date | Mon, 17 Mar 2014 01:21:55 +0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2295:6fd03869f65c | 2296:6e178010fc29 |
---|---|
1 | |
2 /* pngread.c - read a PNG file | |
3 * | |
4 * Last changed in libpng 1.6.10 [March 6, 2014] | |
5 * Copyright (c) 1998-2014 Glenn Randers-Pehrson | |
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |
8 * | |
9 * This code is released under the libpng license. | |
10 * For conditions of distribution and use, see the disclaimer | |
11 * and license in png.h | |
12 * | |
13 * This file contains routines that an application calls directly to | |
14 * read a PNG file or stream. | |
15 */ | |
16 | |
17 #include "pngpriv.h" | |
18 #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) | |
19 # include <errno.h> | |
20 #endif | |
21 | |
22 #ifdef PNG_READ_SUPPORTED | |
23 | |
24 /* Create a PNG structure for reading, and allocate any memory needed. */ | |
25 PNG_FUNCTION(png_structp,PNGAPI | |
26 png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, | |
27 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) | |
28 { | |
29 #ifndef PNG_USER_MEM_SUPPORTED | |
30 png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, | |
31 error_fn, warn_fn, NULL, NULL, NULL); | |
32 #else | |
33 return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, | |
34 warn_fn, NULL, NULL, NULL); | |
35 } | |
36 | |
37 /* Alternate create PNG structure for reading, and allocate any memory | |
38 * needed. | |
39 */ | |
40 PNG_FUNCTION(png_structp,PNGAPI | |
41 png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, | |
42 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, | |
43 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) | |
44 { | |
45 png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, | |
46 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); | |
47 #endif /* PNG_USER_MEM_SUPPORTED */ | |
48 | |
49 if (png_ptr != NULL) | |
50 { | |
51 png_ptr->mode = PNG_IS_READ_STRUCT; | |
52 | |
53 /* Added in libpng-1.6.0; this can be used to detect a read structure if | |
54 * required (it will be zero in a write structure.) | |
55 */ | |
56 # ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
57 png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE; | |
58 # endif | |
59 | |
60 # ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED | |
61 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; | |
62 | |
63 /* In stable builds only warn if an application error can be completely | |
64 * handled. | |
65 */ | |
66 # if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC | |
67 png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; | |
68 # endif | |
69 # endif | |
70 | |
71 /* TODO: delay this, it can be done in png_init_io (if the app doesn't | |
72 * do it itself) avoiding setting the default function if it is not | |
73 * required. | |
74 */ | |
75 png_set_read_fn(png_ptr, NULL, NULL); | |
76 } | |
77 | |
78 return png_ptr; | |
79 } | |
80 | |
81 | |
82 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
83 /* Read the information before the actual image data. This has been | |
84 * changed in v0.90 to allow reading a file that already has the magic | |
85 * bytes read from the stream. You can tell libpng how many bytes have | |
86 * been read from the beginning of the stream (up to the maximum of 8) | |
87 * via png_set_sig_bytes(), and we will only check the remaining bytes | |
88 * here. The application can then have access to the signature bytes we | |
89 * read if it is determined that this isn't a valid PNG file. | |
90 */ | |
91 void PNGAPI | |
92 png_read_info(png_structrp png_ptr, png_inforp info_ptr) | |
93 { | |
94 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | |
95 int keep; | |
96 #endif | |
97 | |
98 png_debug(1, "in png_read_info"); | |
99 | |
100 if (png_ptr == NULL || info_ptr == NULL) | |
101 return; | |
102 | |
103 /* Read and check the PNG file signature. */ | |
104 png_read_sig(png_ptr, info_ptr); | |
105 | |
106 for (;;) | |
107 { | |
108 png_uint_32 length = png_read_chunk_header(png_ptr); | |
109 png_uint_32 chunk_name = png_ptr->chunk_name; | |
110 | |
111 /* IDAT logic needs to happen here to simplify getting the two flags | |
112 * right. | |
113 */ | |
114 if (chunk_name == png_IDAT) | |
115 { | |
116 if (!(png_ptr->mode & PNG_HAVE_IHDR)) | |
117 png_chunk_error(png_ptr, "Missing IHDR before IDAT"); | |
118 | |
119 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && | |
120 !(png_ptr->mode & PNG_HAVE_PLTE)) | |
121 png_chunk_error(png_ptr, "Missing PLTE before IDAT"); | |
122 | |
123 else if (png_ptr->mode & PNG_AFTER_IDAT) | |
124 png_chunk_benign_error(png_ptr, "Too many IDATs found"); | |
125 | |
126 png_ptr->mode |= PNG_HAVE_IDAT; | |
127 } | |
128 | |
129 else if (png_ptr->mode & PNG_HAVE_IDAT) | |
130 png_ptr->mode |= PNG_AFTER_IDAT; | |
131 | |
132 /* This should be a binary subdivision search or a hash for | |
133 * matching the chunk name rather than a linear search. | |
134 */ | |
135 if (chunk_name == png_IHDR) | |
136 png_handle_IHDR(png_ptr, info_ptr, length); | |
137 | |
138 else if (chunk_name == png_IEND) | |
139 png_handle_IEND(png_ptr, info_ptr, length); | |
140 | |
141 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | |
142 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) | |
143 { | |
144 png_handle_unknown(png_ptr, info_ptr, length, keep); | |
145 | |
146 if (chunk_name == png_PLTE) | |
147 png_ptr->mode |= PNG_HAVE_PLTE; | |
148 | |
149 else if (chunk_name == png_IDAT) | |
150 { | |
151 png_ptr->idat_size = 0; /* It has been consumed */ | |
152 break; | |
153 } | |
154 } | |
155 #endif | |
156 else if (chunk_name == png_PLTE) | |
157 png_handle_PLTE(png_ptr, info_ptr, length); | |
158 | |
159 else if (chunk_name == png_IDAT) | |
160 { | |
161 png_ptr->idat_size = length; | |
162 break; | |
163 } | |
164 | |
165 #ifdef PNG_READ_bKGD_SUPPORTED | |
166 else if (chunk_name == png_bKGD) | |
167 png_handle_bKGD(png_ptr, info_ptr, length); | |
168 #endif | |
169 | |
170 #ifdef PNG_READ_cHRM_SUPPORTED | |
171 else if (chunk_name == png_cHRM) | |
172 png_handle_cHRM(png_ptr, info_ptr, length); | |
173 #endif | |
174 | |
175 #ifdef PNG_READ_gAMA_SUPPORTED | |
176 else if (chunk_name == png_gAMA) | |
177 png_handle_gAMA(png_ptr, info_ptr, length); | |
178 #endif | |
179 | |
180 #ifdef PNG_READ_hIST_SUPPORTED | |
181 else if (chunk_name == png_hIST) | |
182 png_handle_hIST(png_ptr, info_ptr, length); | |
183 #endif | |
184 | |
185 #ifdef PNG_READ_oFFs_SUPPORTED | |
186 else if (chunk_name == png_oFFs) | |
187 png_handle_oFFs(png_ptr, info_ptr, length); | |
188 #endif | |
189 | |
190 #ifdef PNG_READ_pCAL_SUPPORTED | |
191 else if (chunk_name == png_pCAL) | |
192 png_handle_pCAL(png_ptr, info_ptr, length); | |
193 #endif | |
194 | |
195 #ifdef PNG_READ_sCAL_SUPPORTED | |
196 else if (chunk_name == png_sCAL) | |
197 png_handle_sCAL(png_ptr, info_ptr, length); | |
198 #endif | |
199 | |
200 #ifdef PNG_READ_pHYs_SUPPORTED | |
201 else if (chunk_name == png_pHYs) | |
202 png_handle_pHYs(png_ptr, info_ptr, length); | |
203 #endif | |
204 | |
205 #ifdef PNG_READ_sBIT_SUPPORTED | |
206 else if (chunk_name == png_sBIT) | |
207 png_handle_sBIT(png_ptr, info_ptr, length); | |
208 #endif | |
209 | |
210 #ifdef PNG_READ_sRGB_SUPPORTED | |
211 else if (chunk_name == png_sRGB) | |
212 png_handle_sRGB(png_ptr, info_ptr, length); | |
213 #endif | |
214 | |
215 #ifdef PNG_READ_iCCP_SUPPORTED | |
216 else if (chunk_name == png_iCCP) | |
217 png_handle_iCCP(png_ptr, info_ptr, length); | |
218 #endif | |
219 | |
220 #ifdef PNG_READ_sPLT_SUPPORTED | |
221 else if (chunk_name == png_sPLT) | |
222 png_handle_sPLT(png_ptr, info_ptr, length); | |
223 #endif | |
224 | |
225 #ifdef PNG_READ_tEXt_SUPPORTED | |
226 else if (chunk_name == png_tEXt) | |
227 png_handle_tEXt(png_ptr, info_ptr, length); | |
228 #endif | |
229 | |
230 #ifdef PNG_READ_tIME_SUPPORTED | |
231 else if (chunk_name == png_tIME) | |
232 png_handle_tIME(png_ptr, info_ptr, length); | |
233 #endif | |
234 | |
235 #ifdef PNG_READ_tRNS_SUPPORTED | |
236 else if (chunk_name == png_tRNS) | |
237 png_handle_tRNS(png_ptr, info_ptr, length); | |
238 #endif | |
239 | |
240 #ifdef PNG_READ_zTXt_SUPPORTED | |
241 else if (chunk_name == png_zTXt) | |
242 png_handle_zTXt(png_ptr, info_ptr, length); | |
243 #endif | |
244 | |
245 #ifdef PNG_READ_iTXt_SUPPORTED | |
246 else if (chunk_name == png_iTXt) | |
247 png_handle_iTXt(png_ptr, info_ptr, length); | |
248 #endif | |
249 | |
250 else | |
251 png_handle_unknown(png_ptr, info_ptr, length, | |
252 PNG_HANDLE_CHUNK_AS_DEFAULT); | |
253 } | |
254 } | |
255 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
256 | |
257 /* Optional call to update the users info_ptr structure */ | |
258 void PNGAPI | |
259 png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) | |
260 { | |
261 png_debug(1, "in png_read_update_info"); | |
262 | |
263 if (png_ptr != NULL) | |
264 { | |
265 if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) | |
266 { | |
267 png_read_start_row(png_ptr); | |
268 | |
269 # ifdef PNG_READ_TRANSFORMS_SUPPORTED | |
270 png_read_transform_info(png_ptr, info_ptr); | |
271 # else | |
272 PNG_UNUSED(info_ptr) | |
273 # endif | |
274 } | |
275 | |
276 /* New in 1.6.0 this avoids the bug of doing the initializations twice */ | |
277 else | |
278 png_app_error(png_ptr, | |
279 "png_read_update_info/png_start_read_image: duplicate call"); | |
280 } | |
281 } | |
282 | |
283 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
284 /* Initialize palette, background, etc, after transformations | |
285 * are set, but before any reading takes place. This allows | |
286 * the user to obtain a gamma-corrected palette, for example. | |
287 * If the user doesn't call this, we will do it ourselves. | |
288 */ | |
289 void PNGAPI | |
290 png_start_read_image(png_structrp png_ptr) | |
291 { | |
292 png_debug(1, "in png_start_read_image"); | |
293 | |
294 if (png_ptr != NULL) | |
295 { | |
296 if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) | |
297 png_read_start_row(png_ptr); | |
298 | |
299 /* New in 1.6.0 this avoids the bug of doing the initializations twice */ | |
300 else | |
301 png_app_error(png_ptr, | |
302 "png_start_read_image/png_read_update_info: duplicate call"); | |
303 } | |
304 } | |
305 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
306 | |
307 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
308 #ifdef PNG_MNG_FEATURES_SUPPORTED | |
309 /* Undoes intrapixel differencing, | |
310 * NOTE: this is apparently only supported in the 'sequential' reader. | |
311 */ | |
312 static void | |
313 png_do_read_intrapixel(png_row_infop row_info, png_bytep row) | |
314 { | |
315 png_debug(1, "in png_do_read_intrapixel"); | |
316 | |
317 if ( | |
318 (row_info->color_type & PNG_COLOR_MASK_COLOR)) | |
319 { | |
320 int bytes_per_pixel; | |
321 png_uint_32 row_width = row_info->width; | |
322 | |
323 if (row_info->bit_depth == 8) | |
324 { | |
325 png_bytep rp; | |
326 png_uint_32 i; | |
327 | |
328 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
329 bytes_per_pixel = 3; | |
330 | |
331 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
332 bytes_per_pixel = 4; | |
333 | |
334 else | |
335 return; | |
336 | |
337 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) | |
338 { | |
339 *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); | |
340 *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); | |
341 } | |
342 } | |
343 else if (row_info->bit_depth == 16) | |
344 { | |
345 png_bytep rp; | |
346 png_uint_32 i; | |
347 | |
348 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
349 bytes_per_pixel = 6; | |
350 | |
351 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
352 bytes_per_pixel = 8; | |
353 | |
354 else | |
355 return; | |
356 | |
357 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) | |
358 { | |
359 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); | |
360 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); | |
361 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); | |
362 png_uint_32 red = (s0 + s1 + 65536) & 0xffff; | |
363 png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; | |
364 *(rp ) = (png_byte)((red >> 8) & 0xff); | |
365 *(rp + 1) = (png_byte)(red & 0xff); | |
366 *(rp + 4) = (png_byte)((blue >> 8) & 0xff); | |
367 *(rp + 5) = (png_byte)(blue & 0xff); | |
368 } | |
369 } | |
370 } | |
371 } | |
372 #endif /* PNG_MNG_FEATURES_SUPPORTED */ | |
373 | |
374 void PNGAPI | |
375 png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) | |
376 { | |
377 png_row_info row_info; | |
378 | |
379 if (png_ptr == NULL) | |
380 return; | |
381 | |
382 png_debug2(1, "in png_read_row (row %lu, pass %d)", | |
383 (unsigned long)png_ptr->row_number, png_ptr->pass); | |
384 | |
385 /* png_read_start_row sets the information (in particular iwidth) for this | |
386 * interlace pass. | |
387 */ | |
388 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) | |
389 png_read_start_row(png_ptr); | |
390 | |
391 /* 1.5.6: row_info moved out of png_struct to a local here. */ | |
392 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ | |
393 row_info.color_type = png_ptr->color_type; | |
394 row_info.bit_depth = png_ptr->bit_depth; | |
395 row_info.channels = png_ptr->channels; | |
396 row_info.pixel_depth = png_ptr->pixel_depth; | |
397 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); | |
398 | |
399 if (png_ptr->row_number == 0 && png_ptr->pass == 0) | |
400 { | |
401 /* Check for transforms that have been set but were defined out */ | |
402 #if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) | |
403 if (png_ptr->transformations & PNG_INVERT_MONO) | |
404 png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); | |
405 #endif | |
406 | |
407 #if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) | |
408 if (png_ptr->transformations & PNG_FILLER) | |
409 png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); | |
410 #endif | |
411 | |
412 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ | |
413 !defined(PNG_READ_PACKSWAP_SUPPORTED) | |
414 if (png_ptr->transformations & PNG_PACKSWAP) | |
415 png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); | |
416 #endif | |
417 | |
418 #if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) | |
419 if (png_ptr->transformations & PNG_PACK) | |
420 png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); | |
421 #endif | |
422 | |
423 #if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) | |
424 if (png_ptr->transformations & PNG_SHIFT) | |
425 png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); | |
426 #endif | |
427 | |
428 #if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) | |
429 if (png_ptr->transformations & PNG_BGR) | |
430 png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); | |
431 #endif | |
432 | |
433 #if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) | |
434 if (png_ptr->transformations & PNG_SWAP_BYTES) | |
435 png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); | |
436 #endif | |
437 } | |
438 | |
439 #ifdef PNG_READ_INTERLACING_SUPPORTED | |
440 /* If interlaced and we do not need a new row, combine row and return. | |
441 * Notice that the pixels we have from previous rows have been transformed | |
442 * already; we can only combine like with like (transformed or | |
443 * untransformed) and, because of the libpng API for interlaced images, this | |
444 * means we must transform before de-interlacing. | |
445 */ | |
446 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) | |
447 { | |
448 switch (png_ptr->pass) | |
449 { | |
450 case 0: | |
451 if (png_ptr->row_number & 0x07) | |
452 { | |
453 if (dsp_row != NULL) | |
454 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
455 png_read_finish_row(png_ptr); | |
456 return; | |
457 } | |
458 break; | |
459 | |
460 case 1: | |
461 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) | |
462 { | |
463 if (dsp_row != NULL) | |
464 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
465 | |
466 png_read_finish_row(png_ptr); | |
467 return; | |
468 } | |
469 break; | |
470 | |
471 case 2: | |
472 if ((png_ptr->row_number & 0x07) != 4) | |
473 { | |
474 if (dsp_row != NULL && (png_ptr->row_number & 4)) | |
475 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
476 | |
477 png_read_finish_row(png_ptr); | |
478 return; | |
479 } | |
480 break; | |
481 | |
482 case 3: | |
483 if ((png_ptr->row_number & 3) || png_ptr->width < 3) | |
484 { | |
485 if (dsp_row != NULL) | |
486 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
487 | |
488 png_read_finish_row(png_ptr); | |
489 return; | |
490 } | |
491 break; | |
492 | |
493 case 4: | |
494 if ((png_ptr->row_number & 3) != 2) | |
495 { | |
496 if (dsp_row != NULL && (png_ptr->row_number & 2)) | |
497 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
498 | |
499 png_read_finish_row(png_ptr); | |
500 return; | |
501 } | |
502 break; | |
503 | |
504 case 5: | |
505 if ((png_ptr->row_number & 1) || png_ptr->width < 2) | |
506 { | |
507 if (dsp_row != NULL) | |
508 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
509 | |
510 png_read_finish_row(png_ptr); | |
511 return; | |
512 } | |
513 break; | |
514 | |
515 default: | |
516 case 6: | |
517 if (!(png_ptr->row_number & 1)) | |
518 { | |
519 png_read_finish_row(png_ptr); | |
520 return; | |
521 } | |
522 break; | |
523 } | |
524 } | |
525 #endif | |
526 | |
527 if (!(png_ptr->mode & PNG_HAVE_IDAT)) | |
528 png_error(png_ptr, "Invalid attempt to read row data"); | |
529 | |
530 /* Fill the row with IDAT data: */ | |
531 png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); | |
532 | |
533 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) | |
534 { | |
535 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) | |
536 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, | |
537 png_ptr->prev_row + 1, png_ptr->row_buf[0]); | |
538 else | |
539 png_error(png_ptr, "bad adaptive filter value"); | |
540 } | |
541 | |
542 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before | |
543 * 1.5.6, while the buffer really is this big in current versions of libpng | |
544 * it may not be in the future, so this was changed just to copy the | |
545 * interlaced count: | |
546 */ | |
547 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); | |
548 | |
549 #ifdef PNG_MNG_FEATURES_SUPPORTED | |
550 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && | |
551 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) | |
552 { | |
553 /* Intrapixel differencing */ | |
554 png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); | |
555 } | |
556 #endif | |
557 | |
558 #ifdef PNG_READ_TRANSFORMS_SUPPORTED | |
559 if (png_ptr->transformations) | |
560 png_do_read_transformations(png_ptr, &row_info); | |
561 #endif | |
562 | |
563 /* The transformed pixel depth should match the depth now in row_info. */ | |
564 if (png_ptr->transformed_pixel_depth == 0) | |
565 { | |
566 png_ptr->transformed_pixel_depth = row_info.pixel_depth; | |
567 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) | |
568 png_error(png_ptr, "sequential row overflow"); | |
569 } | |
570 | |
571 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) | |
572 png_error(png_ptr, "internal sequential row size calculation error"); | |
573 | |
574 #ifdef PNG_READ_INTERLACING_SUPPORTED | |
575 /* Blow up interlaced rows to full size */ | |
576 if (png_ptr->interlaced && | |
577 (png_ptr->transformations & PNG_INTERLACE)) | |
578 { | |
579 if (png_ptr->pass < 6) | |
580 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, | |
581 png_ptr->transformations); | |
582 | |
583 if (dsp_row != NULL) | |
584 png_combine_row(png_ptr, dsp_row, 1/*display*/); | |
585 | |
586 if (row != NULL) | |
587 png_combine_row(png_ptr, row, 0/*row*/); | |
588 } | |
589 | |
590 else | |
591 #endif | |
592 { | |
593 if (row != NULL) | |
594 png_combine_row(png_ptr, row, -1/*ignored*/); | |
595 | |
596 if (dsp_row != NULL) | |
597 png_combine_row(png_ptr, dsp_row, -1/*ignored*/); | |
598 } | |
599 png_read_finish_row(png_ptr); | |
600 | |
601 if (png_ptr->read_row_fn != NULL) | |
602 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); | |
603 | |
604 } | |
605 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
606 | |
607 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
608 /* Read one or more rows of image data. If the image is interlaced, | |
609 * and png_set_interlace_handling() has been called, the rows need to | |
610 * contain the contents of the rows from the previous pass. If the | |
611 * image has alpha or transparency, and png_handle_alpha()[*] has been | |
612 * called, the rows contents must be initialized to the contents of the | |
613 * screen. | |
614 * | |
615 * "row" holds the actual image, and pixels are placed in it | |
616 * as they arrive. If the image is displayed after each pass, it will | |
617 * appear to "sparkle" in. "display_row" can be used to display a | |
618 * "chunky" progressive image, with finer detail added as it becomes | |
619 * available. If you do not want this "chunky" display, you may pass | |
620 * NULL for display_row. If you do not want the sparkle display, and | |
621 * you have not called png_handle_alpha(), you may pass NULL for rows. | |
622 * If you have called png_handle_alpha(), and the image has either an | |
623 * alpha channel or a transparency chunk, you must provide a buffer for | |
624 * rows. In this case, you do not have to provide a display_row buffer | |
625 * also, but you may. If the image is not interlaced, or if you have | |
626 * not called png_set_interlace_handling(), the display_row buffer will | |
627 * be ignored, so pass NULL to it. | |
628 * | |
629 * [*] png_handle_alpha() does not exist yet, as of this version of libpng | |
630 */ | |
631 | |
632 void PNGAPI | |
633 png_read_rows(png_structrp png_ptr, png_bytepp row, | |
634 png_bytepp display_row, png_uint_32 num_rows) | |
635 { | |
636 png_uint_32 i; | |
637 png_bytepp rp; | |
638 png_bytepp dp; | |
639 | |
640 png_debug(1, "in png_read_rows"); | |
641 | |
642 if (png_ptr == NULL) | |
643 return; | |
644 | |
645 rp = row; | |
646 dp = display_row; | |
647 if (rp != NULL && dp != NULL) | |
648 for (i = 0; i < num_rows; i++) | |
649 { | |
650 png_bytep rptr = *rp++; | |
651 png_bytep dptr = *dp++; | |
652 | |
653 png_read_row(png_ptr, rptr, dptr); | |
654 } | |
655 | |
656 else if (rp != NULL) | |
657 for (i = 0; i < num_rows; i++) | |
658 { | |
659 png_bytep rptr = *rp; | |
660 png_read_row(png_ptr, rptr, NULL); | |
661 rp++; | |
662 } | |
663 | |
664 else if (dp != NULL) | |
665 for (i = 0; i < num_rows; i++) | |
666 { | |
667 png_bytep dptr = *dp; | |
668 png_read_row(png_ptr, NULL, dptr); | |
669 dp++; | |
670 } | |
671 } | |
672 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
673 | |
674 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
675 /* Read the entire image. If the image has an alpha channel or a tRNS | |
676 * chunk, and you have called png_handle_alpha()[*], you will need to | |
677 * initialize the image to the current image that PNG will be overlaying. | |
678 * We set the num_rows again here, in case it was incorrectly set in | |
679 * png_read_start_row() by a call to png_read_update_info() or | |
680 * png_start_read_image() if png_set_interlace_handling() wasn't called | |
681 * prior to either of these functions like it should have been. You can | |
682 * only call this function once. If you desire to have an image for | |
683 * each pass of a interlaced image, use png_read_rows() instead. | |
684 * | |
685 * [*] png_handle_alpha() does not exist yet, as of this version of libpng | |
686 */ | |
687 void PNGAPI | |
688 png_read_image(png_structrp png_ptr, png_bytepp image) | |
689 { | |
690 png_uint_32 i, image_height; | |
691 int pass, j; | |
692 png_bytepp rp; | |
693 | |
694 png_debug(1, "in png_read_image"); | |
695 | |
696 if (png_ptr == NULL) | |
697 return; | |
698 | |
699 #ifdef PNG_READ_INTERLACING_SUPPORTED | |
700 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) | |
701 { | |
702 pass = png_set_interlace_handling(png_ptr); | |
703 /* And make sure transforms are initialized. */ | |
704 png_start_read_image(png_ptr); | |
705 } | |
706 else | |
707 { | |
708 if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) | |
709 { | |
710 /* Caller called png_start_read_image or png_read_update_info without | |
711 * first turning on the PNG_INTERLACE transform. We can fix this here, | |
712 * but the caller should do it! | |
713 */ | |
714 png_warning(png_ptr, "Interlace handling should be turned on when " | |
715 "using png_read_image"); | |
716 /* Make sure this is set correctly */ | |
717 png_ptr->num_rows = png_ptr->height; | |
718 } | |
719 | |
720 /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in | |
721 * the above error case. | |
722 */ | |
723 pass = png_set_interlace_handling(png_ptr); | |
724 } | |
725 #else | |
726 if (png_ptr->interlaced) | |
727 png_error(png_ptr, | |
728 "Cannot read interlaced image -- interlace handler disabled"); | |
729 | |
730 pass = 1; | |
731 #endif | |
732 | |
733 image_height=png_ptr->height; | |
734 | |
735 for (j = 0; j < pass; j++) | |
736 { | |
737 rp = image; | |
738 for (i = 0; i < image_height; i++) | |
739 { | |
740 png_read_row(png_ptr, *rp, NULL); | |
741 rp++; | |
742 } | |
743 } | |
744 } | |
745 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
746 | |
747 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
748 /* Read the end of the PNG file. Will not read past the end of the | |
749 * file, will verify the end is accurate, and will read any comments | |
750 * or time information at the end of the file, if info is not NULL. | |
751 */ | |
752 void PNGAPI | |
753 png_read_end(png_structrp png_ptr, png_inforp info_ptr) | |
754 { | |
755 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | |
756 int keep; | |
757 #endif | |
758 | |
759 png_debug(1, "in png_read_end"); | |
760 | |
761 if (png_ptr == NULL) | |
762 return; | |
763 | |
764 /* If png_read_end is called in the middle of reading the rows there may | |
765 * still be pending IDAT data and an owned zstream. Deal with this here. | |
766 */ | |
767 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | |
768 if (!png_chunk_unknown_handling(png_ptr, png_IDAT)) | |
769 #endif | |
770 png_read_finish_IDAT(png_ptr); | |
771 | |
772 #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED | |
773 /* Report invalid palette index; added at libng-1.5.10 */ | |
774 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && | |
775 png_ptr->num_palette_max > png_ptr->num_palette) | |
776 png_benign_error(png_ptr, "Read palette index exceeding num_palette"); | |
777 #endif | |
778 | |
779 do | |
780 { | |
781 png_uint_32 length = png_read_chunk_header(png_ptr); | |
782 png_uint_32 chunk_name = png_ptr->chunk_name; | |
783 | |
784 if (chunk_name == png_IEND) | |
785 png_handle_IEND(png_ptr, info_ptr, length); | |
786 | |
787 else if (chunk_name == png_IHDR) | |
788 png_handle_IHDR(png_ptr, info_ptr, length); | |
789 | |
790 else if (info_ptr == NULL) | |
791 png_crc_finish(png_ptr, length); | |
792 | |
793 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | |
794 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) | |
795 { | |
796 if (chunk_name == png_IDAT) | |
797 { | |
798 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) | |
799 png_benign_error(png_ptr, "Too many IDATs found"); | |
800 } | |
801 png_handle_unknown(png_ptr, info_ptr, length, keep); | |
802 if (chunk_name == png_PLTE) | |
803 png_ptr->mode |= PNG_HAVE_PLTE; | |
804 } | |
805 #endif | |
806 | |
807 else if (chunk_name == png_IDAT) | |
808 { | |
809 /* Zero length IDATs are legal after the last IDAT has been | |
810 * read, but not after other chunks have been read. | |
811 */ | |
812 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) | |
813 png_benign_error(png_ptr, "Too many IDATs found"); | |
814 | |
815 png_crc_finish(png_ptr, length); | |
816 } | |
817 else if (chunk_name == png_PLTE) | |
818 png_handle_PLTE(png_ptr, info_ptr, length); | |
819 | |
820 #ifdef PNG_READ_bKGD_SUPPORTED | |
821 else if (chunk_name == png_bKGD) | |
822 png_handle_bKGD(png_ptr, info_ptr, length); | |
823 #endif | |
824 | |
825 #ifdef PNG_READ_cHRM_SUPPORTED | |
826 else if (chunk_name == png_cHRM) | |
827 png_handle_cHRM(png_ptr, info_ptr, length); | |
828 #endif | |
829 | |
830 #ifdef PNG_READ_gAMA_SUPPORTED | |
831 else if (chunk_name == png_gAMA) | |
832 png_handle_gAMA(png_ptr, info_ptr, length); | |
833 #endif | |
834 | |
835 #ifdef PNG_READ_hIST_SUPPORTED | |
836 else if (chunk_name == png_hIST) | |
837 png_handle_hIST(png_ptr, info_ptr, length); | |
838 #endif | |
839 | |
840 #ifdef PNG_READ_oFFs_SUPPORTED | |
841 else if (chunk_name == png_oFFs) | |
842 png_handle_oFFs(png_ptr, info_ptr, length); | |
843 #endif | |
844 | |
845 #ifdef PNG_READ_pCAL_SUPPORTED | |
846 else if (chunk_name == png_pCAL) | |
847 png_handle_pCAL(png_ptr, info_ptr, length); | |
848 #endif | |
849 | |
850 #ifdef PNG_READ_sCAL_SUPPORTED | |
851 else if (chunk_name == png_sCAL) | |
852 png_handle_sCAL(png_ptr, info_ptr, length); | |
853 #endif | |
854 | |
855 #ifdef PNG_READ_pHYs_SUPPORTED | |
856 else if (chunk_name == png_pHYs) | |
857 png_handle_pHYs(png_ptr, info_ptr, length); | |
858 #endif | |
859 | |
860 #ifdef PNG_READ_sBIT_SUPPORTED | |
861 else if (chunk_name == png_sBIT) | |
862 png_handle_sBIT(png_ptr, info_ptr, length); | |
863 #endif | |
864 | |
865 #ifdef PNG_READ_sRGB_SUPPORTED | |
866 else if (chunk_name == png_sRGB) | |
867 png_handle_sRGB(png_ptr, info_ptr, length); | |
868 #endif | |
869 | |
870 #ifdef PNG_READ_iCCP_SUPPORTED | |
871 else if (chunk_name == png_iCCP) | |
872 png_handle_iCCP(png_ptr, info_ptr, length); | |
873 #endif | |
874 | |
875 #ifdef PNG_READ_sPLT_SUPPORTED | |
876 else if (chunk_name == png_sPLT) | |
877 png_handle_sPLT(png_ptr, info_ptr, length); | |
878 #endif | |
879 | |
880 #ifdef PNG_READ_tEXt_SUPPORTED | |
881 else if (chunk_name == png_tEXt) | |
882 png_handle_tEXt(png_ptr, info_ptr, length); | |
883 #endif | |
884 | |
885 #ifdef PNG_READ_tIME_SUPPORTED | |
886 else if (chunk_name == png_tIME) | |
887 png_handle_tIME(png_ptr, info_ptr, length); | |
888 #endif | |
889 | |
890 #ifdef PNG_READ_tRNS_SUPPORTED | |
891 else if (chunk_name == png_tRNS) | |
892 png_handle_tRNS(png_ptr, info_ptr, length); | |
893 #endif | |
894 | |
895 #ifdef PNG_READ_zTXt_SUPPORTED | |
896 else if (chunk_name == png_zTXt) | |
897 png_handle_zTXt(png_ptr, info_ptr, length); | |
898 #endif | |
899 | |
900 #ifdef PNG_READ_iTXt_SUPPORTED | |
901 else if (chunk_name == png_iTXt) | |
902 png_handle_iTXt(png_ptr, info_ptr, length); | |
903 #endif | |
904 | |
905 else | |
906 png_handle_unknown(png_ptr, info_ptr, length, | |
907 PNG_HANDLE_CHUNK_AS_DEFAULT); | |
908 } while (!(png_ptr->mode & PNG_HAVE_IEND)); | |
909 } | |
910 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
911 | |
912 /* Free all memory used in the read struct */ | |
913 static void | |
914 png_read_destroy(png_structrp png_ptr) | |
915 { | |
916 png_debug(1, "in png_read_destroy"); | |
917 | |
918 #ifdef PNG_READ_GAMMA_SUPPORTED | |
919 png_destroy_gamma_table(png_ptr); | |
920 #endif | |
921 | |
922 png_free(png_ptr, png_ptr->big_row_buf); | |
923 png_free(png_ptr, png_ptr->big_prev_row); | |
924 png_free(png_ptr, png_ptr->read_buffer); | |
925 | |
926 #ifdef PNG_READ_QUANTIZE_SUPPORTED | |
927 png_free(png_ptr, png_ptr->palette_lookup); | |
928 png_free(png_ptr, png_ptr->quantize_index); | |
929 #endif | |
930 | |
931 if (png_ptr->free_me & PNG_FREE_PLTE) | |
932 png_zfree(png_ptr, png_ptr->palette); | |
933 png_ptr->free_me &= ~PNG_FREE_PLTE; | |
934 | |
935 #if defined(PNG_tRNS_SUPPORTED) || \ | |
936 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) | |
937 if (png_ptr->free_me & PNG_FREE_TRNS) | |
938 png_free(png_ptr, png_ptr->trans_alpha); | |
939 png_ptr->free_me &= ~PNG_FREE_TRNS; | |
940 #endif | |
941 | |
942 inflateEnd(&png_ptr->zstream); | |
943 | |
944 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED | |
945 png_free(png_ptr, png_ptr->save_buffer); | |
946 #endif | |
947 | |
948 #if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\ | |
949 defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) | |
950 png_free(png_ptr, png_ptr->unknown_chunk.data); | |
951 #endif | |
952 | |
953 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED | |
954 png_free(png_ptr, png_ptr->chunk_list); | |
955 #endif | |
956 | |
957 /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error | |
958 * callbacks are still set at this point. They are required to complete the | |
959 * destruction of the png_struct itself. | |
960 */ | |
961 } | |
962 | |
963 /* Free all memory used by the read */ | |
964 void PNGAPI | |
965 png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, | |
966 png_infopp end_info_ptr_ptr) | |
967 { | |
968 png_structrp png_ptr = NULL; | |
969 | |
970 png_debug(1, "in png_destroy_read_struct"); | |
971 | |
972 if (png_ptr_ptr != NULL) | |
973 png_ptr = *png_ptr_ptr; | |
974 | |
975 if (png_ptr == NULL) | |
976 return; | |
977 | |
978 /* libpng 1.6.0: use the API to destroy info structs to ensure consistent | |
979 * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API. | |
980 * The extra was, apparently, unnecessary yet this hides memory leak bugs. | |
981 */ | |
982 png_destroy_info_struct(png_ptr, end_info_ptr_ptr); | |
983 png_destroy_info_struct(png_ptr, info_ptr_ptr); | |
984 | |
985 *png_ptr_ptr = NULL; | |
986 png_read_destroy(png_ptr); | |
987 png_destroy_png_struct(png_ptr); | |
988 } | |
989 | |
990 void PNGAPI | |
991 png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) | |
992 { | |
993 if (png_ptr == NULL) | |
994 return; | |
995 | |
996 png_ptr->read_row_fn = read_row_fn; | |
997 } | |
998 | |
999 | |
1000 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED | |
1001 #ifdef PNG_INFO_IMAGE_SUPPORTED | |
1002 void PNGAPI | |
1003 png_read_png(png_structrp png_ptr, png_inforp info_ptr, | |
1004 int transforms, | |
1005 voidp params) | |
1006 { | |
1007 if (png_ptr == NULL || info_ptr == NULL) | |
1008 return; | |
1009 | |
1010 /* png_read_info() gives us all of the information from the | |
1011 * PNG file before the first IDAT (image data chunk). | |
1012 */ | |
1013 png_read_info(png_ptr, info_ptr); | |
1014 if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) | |
1015 png_error(png_ptr, "Image is too high to process with png_read_png()"); | |
1016 | |
1017 /* -------------- image transformations start here ------------------- */ | |
1018 /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM | |
1019 * is not implemented. This will only happen in de-configured (non-default) | |
1020 * libpng builds. The results can be unexpected - png_read_png may return | |
1021 * short or mal-formed rows because the transform is skipped. | |
1022 */ | |
1023 | |
1024 /* Tell libpng to strip 16-bit/color files down to 8 bits per color. | |
1025 */ | |
1026 if (transforms & PNG_TRANSFORM_SCALE_16) | |
1027 /* Added at libpng-1.5.4. "strip_16" produces the same result that it | |
1028 * did in earlier versions, while "scale_16" is now more accurate. | |
1029 */ | |
1030 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED | |
1031 png_set_scale_16(png_ptr); | |
1032 #else | |
1033 png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported"); | |
1034 #endif | |
1035 | |
1036 /* If both SCALE and STRIP are required pngrtran will effectively cancel the | |
1037 * latter by doing SCALE first. This is ok and allows apps not to check for | |
1038 * which is supported to get the right answer. | |
1039 */ | |
1040 if (transforms & PNG_TRANSFORM_STRIP_16) | |
1041 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED | |
1042 png_set_strip_16(png_ptr); | |
1043 #else | |
1044 png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported"); | |
1045 #endif | |
1046 | |
1047 /* Strip alpha bytes from the input data without combining with | |
1048 * the background (not recommended). | |
1049 */ | |
1050 if (transforms & PNG_TRANSFORM_STRIP_ALPHA) | |
1051 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED | |
1052 png_set_strip_alpha(png_ptr); | |
1053 #else | |
1054 png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported"); | |
1055 #endif | |
1056 | |
1057 /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single | |
1058 * byte into separate bytes (useful for paletted and grayscale images). | |
1059 */ | |
1060 if (transforms & PNG_TRANSFORM_PACKING) | |
1061 #ifdef PNG_READ_PACK_SUPPORTED | |
1062 png_set_packing(png_ptr); | |
1063 #else | |
1064 png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); | |
1065 #endif | |
1066 | |
1067 /* Change the order of packed pixels to least significant bit first | |
1068 * (not useful if you are using png_set_packing). | |
1069 */ | |
1070 if (transforms & PNG_TRANSFORM_PACKSWAP) | |
1071 #ifdef PNG_READ_PACKSWAP_SUPPORTED | |
1072 png_set_packswap(png_ptr); | |
1073 #else | |
1074 png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); | |
1075 #endif | |
1076 | |
1077 /* Expand paletted colors into true RGB triplets | |
1078 * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel | |
1079 * Expand paletted or RGB images with transparency to full alpha | |
1080 * channels so the data will be available as RGBA quartets. | |
1081 */ | |
1082 if (transforms & PNG_TRANSFORM_EXPAND) | |
1083 #ifdef PNG_READ_EXPAND_SUPPORTED | |
1084 png_set_expand(png_ptr); | |
1085 #else | |
1086 png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported"); | |
1087 #endif | |
1088 | |
1089 /* We don't handle background color or gamma transformation or quantizing. | |
1090 */ | |
1091 | |
1092 /* Invert monochrome files to have 0 as white and 1 as black | |
1093 */ | |
1094 if (transforms & PNG_TRANSFORM_INVERT_MONO) | |
1095 #ifdef PNG_READ_INVERT_SUPPORTED | |
1096 png_set_invert_mono(png_ptr); | |
1097 #else | |
1098 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); | |
1099 #endif | |
1100 | |
1101 /* If you want to shift the pixel values from the range [0,255] or | |
1102 * [0,65535] to the original [0,7] or [0,31], or whatever range the | |
1103 * colors were originally in: | |
1104 */ | |
1105 if (transforms & PNG_TRANSFORM_SHIFT) | |
1106 #ifdef PNG_READ_SHIFT_SUPPORTED | |
1107 if (info_ptr->valid & PNG_INFO_sBIT) | |
1108 png_set_shift(png_ptr, &info_ptr->sig_bit); | |
1109 #else | |
1110 png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); | |
1111 #endif | |
1112 | |
1113 /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ | |
1114 if (transforms & PNG_TRANSFORM_BGR) | |
1115 #ifdef PNG_READ_BGR_SUPPORTED | |
1116 png_set_bgr(png_ptr); | |
1117 #else | |
1118 png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); | |
1119 #endif | |
1120 | |
1121 /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ | |
1122 if (transforms & PNG_TRANSFORM_SWAP_ALPHA) | |
1123 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED | |
1124 png_set_swap_alpha(png_ptr); | |
1125 #else | |
1126 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); | |
1127 #endif | |
1128 | |
1129 /* Swap bytes of 16-bit files to least significant byte first */ | |
1130 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) | |
1131 #ifdef PNG_READ_SWAP_SUPPORTED | |
1132 png_set_swap(png_ptr); | |
1133 #else | |
1134 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); | |
1135 #endif | |
1136 | |
1137 /* Added at libpng-1.2.41 */ | |
1138 /* Invert the alpha channel from opacity to transparency */ | |
1139 if (transforms & PNG_TRANSFORM_INVERT_ALPHA) | |
1140 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED | |
1141 png_set_invert_alpha(png_ptr); | |
1142 #else | |
1143 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); | |
1144 #endif | |
1145 | |
1146 /* Added at libpng-1.2.41 */ | |
1147 /* Expand grayscale image to RGB */ | |
1148 if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) | |
1149 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED | |
1150 png_set_gray_to_rgb(png_ptr); | |
1151 #else | |
1152 png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported"); | |
1153 #endif | |
1154 | |
1155 /* Added at libpng-1.5.4 */ | |
1156 if (transforms & PNG_TRANSFORM_EXPAND_16) | |
1157 #ifdef PNG_READ_EXPAND_16_SUPPORTED | |
1158 png_set_expand_16(png_ptr); | |
1159 #else | |
1160 png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported"); | |
1161 #endif | |
1162 | |
1163 /* We don't handle adding filler bytes */ | |
1164 | |
1165 /* We use png_read_image and rely on that for interlace handling, but we also | |
1166 * call png_read_update_info therefore must turn on interlace handling now: | |
1167 */ | |
1168 (void)png_set_interlace_handling(png_ptr); | |
1169 | |
1170 /* Optional call to gamma correct and add the background to the palette | |
1171 * and update info structure. REQUIRED if you are expecting libpng to | |
1172 * update the palette for you (i.e., you selected such a transform above). | |
1173 */ | |
1174 png_read_update_info(png_ptr, info_ptr); | |
1175 | |
1176 /* -------------- image transformations end here ------------------- */ | |
1177 | |
1178 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); | |
1179 if (info_ptr->row_pointers == NULL) | |
1180 { | |
1181 png_uint_32 iptr; | |
1182 | |
1183 info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr, | |
1184 info_ptr->height * (sizeof (png_bytep)))); | |
1185 | |
1186 for (iptr=0; iptr<info_ptr->height; iptr++) | |
1187 info_ptr->row_pointers[iptr] = NULL; | |
1188 | |
1189 info_ptr->free_me |= PNG_FREE_ROWS; | |
1190 | |
1191 for (iptr = 0; iptr < info_ptr->height; iptr++) | |
1192 info_ptr->row_pointers[iptr] = png_voidcast(png_bytep, | |
1193 png_malloc(png_ptr, info_ptr->rowbytes)); | |
1194 } | |
1195 | |
1196 png_read_image(png_ptr, info_ptr->row_pointers); | |
1197 info_ptr->valid |= PNG_INFO_IDAT; | |
1198 | |
1199 /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ | |
1200 png_read_end(png_ptr, info_ptr); | |
1201 | |
1202 PNG_UNUSED(params) | |
1203 } | |
1204 #endif /* PNG_INFO_IMAGE_SUPPORTED */ | |
1205 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ | |
1206 | |
1207 #ifdef PNG_SIMPLIFIED_READ_SUPPORTED | |
1208 /* SIMPLIFIED READ | |
1209 * | |
1210 * This code currently relies on the sequential reader, though it could easily | |
1211 * be made to work with the progressive one. | |
1212 */ | |
1213 /* Arguments to png_image_finish_read: */ | |
1214 | |
1215 /* Encoding of PNG data (used by the color-map code) */ | |
1216 # define P_NOTSET 0 /* File encoding not yet known */ | |
1217 # define P_sRGB 1 /* 8-bit encoded to sRGB gamma */ | |
1218 # define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ | |
1219 # define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ | |
1220 # define P_LINEAR8 4 /* 8-bit linear: only from a file value */ | |
1221 | |
1222 /* Color-map processing: after libpng has run on the PNG image further | |
1223 * processing may be needed to conver the data to color-map indicies. | |
1224 */ | |
1225 #define PNG_CMAP_NONE 0 | |
1226 #define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */ | |
1227 #define PNG_CMAP_TRANS 2 /* Process GA data to a background index */ | |
1228 #define PNG_CMAP_RGB 3 /* Process RGB data */ | |
1229 #define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */ | |
1230 | |
1231 /* The following document where the background is for each processing case. */ | |
1232 #define PNG_CMAP_NONE_BACKGROUND 256 | |
1233 #define PNG_CMAP_GA_BACKGROUND 231 | |
1234 #define PNG_CMAP_TRANS_BACKGROUND 254 | |
1235 #define PNG_CMAP_RGB_BACKGROUND 256 | |
1236 #define PNG_CMAP_RGB_ALPHA_BACKGROUND 216 | |
1237 | |
1238 typedef struct | |
1239 { | |
1240 /* Arguments: */ | |
1241 png_imagep image; | |
1242 png_voidp buffer; | |
1243 png_int_32 row_stride; | |
1244 png_voidp colormap; | |
1245 png_const_colorp background; | |
1246 /* Local variables: */ | |
1247 png_voidp local_row; | |
1248 png_voidp first_row; | |
1249 ptrdiff_t row_bytes; /* step between rows */ | |
1250 int file_encoding; /* E_ values above */ | |
1251 png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ | |
1252 int colormap_processing; /* PNG_CMAP_ values above */ | |
1253 } png_image_read_control; | |
1254 | |
1255 /* Do all the *safe* initialization - 'safe' means that png_error won't be | |
1256 * called, so setting up the jmp_buf is not required. This means that anything | |
1257 * called from here must *not* call png_malloc - it has to call png_malloc_warn | |
1258 * instead so that control is returned safely back to this routine. | |
1259 */ | |
1260 static int | |
1261 png_image_read_init(png_imagep image) | |
1262 { | |
1263 if (image->opaque == NULL) | |
1264 { | |
1265 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, | |
1266 png_safe_error, png_safe_warning); | |
1267 | |
1268 /* And set the rest of the structure to NULL to ensure that the various | |
1269 * fields are consistent. | |
1270 */ | |
1271 memset(image, 0, (sizeof *image)); | |
1272 image->version = PNG_IMAGE_VERSION; | |
1273 | |
1274 if (png_ptr != NULL) | |
1275 { | |
1276 png_infop info_ptr = png_create_info_struct(png_ptr); | |
1277 | |
1278 if (info_ptr != NULL) | |
1279 { | |
1280 png_controlp control = png_voidcast(png_controlp, | |
1281 png_malloc_warn(png_ptr, (sizeof *control))); | |
1282 | |
1283 if (control != NULL) | |
1284 { | |
1285 memset(control, 0, (sizeof *control)); | |
1286 | |
1287 control->png_ptr = png_ptr; | |
1288 control->info_ptr = info_ptr; | |
1289 control->for_write = 0; | |
1290 | |
1291 image->opaque = control; | |
1292 return 1; | |
1293 } | |
1294 | |
1295 /* Error clean up */ | |
1296 png_destroy_info_struct(png_ptr, &info_ptr); | |
1297 } | |
1298 | |
1299 png_destroy_read_struct(&png_ptr, NULL, NULL); | |
1300 } | |
1301 | |
1302 return png_image_error(image, "png_image_read: out of memory"); | |
1303 } | |
1304 | |
1305 return png_image_error(image, "png_image_read: opaque pointer not NULL"); | |
1306 } | |
1307 | |
1308 /* Utility to find the base format of a PNG file from a png_struct. */ | |
1309 static png_uint_32 | |
1310 png_image_format(png_structrp png_ptr) | |
1311 { | |
1312 png_uint_32 format = 0; | |
1313 | |
1314 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) | |
1315 format |= PNG_FORMAT_FLAG_COLOR; | |
1316 | |
1317 if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) | |
1318 format |= PNG_FORMAT_FLAG_ALPHA; | |
1319 | |
1320 /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS | |
1321 * sets the png_struct fields; that's all we are interested in here. The | |
1322 * precise interaction with an app call to png_set_tRNS and PNG file reading | |
1323 * is unclear. | |
1324 */ | |
1325 else if (png_ptr->num_trans > 0) | |
1326 format |= PNG_FORMAT_FLAG_ALPHA; | |
1327 | |
1328 if (png_ptr->bit_depth == 16) | |
1329 format |= PNG_FORMAT_FLAG_LINEAR; | |
1330 | |
1331 if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE) | |
1332 format |= PNG_FORMAT_FLAG_COLORMAP; | |
1333 | |
1334 return format; | |
1335 } | |
1336 | |
1337 /* Is the given gamma significantly different from sRGB? The test is the same | |
1338 * one used in pngrtran.c when deciding whether to do gamma correction. The | |
1339 * arithmetic optimizes the division by using the fact that the inverse of the | |
1340 * file sRGB gamma is 2.2 | |
1341 */ | |
1342 static int | |
1343 png_gamma_not_sRGB(png_fixed_point g) | |
1344 { | |
1345 if (g < PNG_FP_1) | |
1346 { | |
1347 /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ | |
1348 if (g == 0) | |
1349 return 0; | |
1350 | |
1351 return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); | |
1352 } | |
1353 | |
1354 return 1; | |
1355 } | |
1356 | |
1357 /* Do the main body of a 'png_image_begin_read' function; read the PNG file | |
1358 * header and fill in all the information. This is executed in a safe context, | |
1359 * unlike the init routine above. | |
1360 */ | |
1361 static int | |
1362 png_image_read_header(png_voidp argument) | |
1363 { | |
1364 png_imagep image = png_voidcast(png_imagep, argument); | |
1365 png_structrp png_ptr = image->opaque->png_ptr; | |
1366 png_inforp info_ptr = image->opaque->info_ptr; | |
1367 | |
1368 png_set_benign_errors(png_ptr, 1/*warn*/); | |
1369 png_read_info(png_ptr, info_ptr); | |
1370 | |
1371 /* Do this the fast way; just read directly out of png_struct. */ | |
1372 image->width = png_ptr->width; | |
1373 image->height = png_ptr->height; | |
1374 | |
1375 { | |
1376 png_uint_32 format = png_image_format(png_ptr); | |
1377 | |
1378 image->format = format; | |
1379 | |
1380 #ifdef PNG_COLORSPACE_SUPPORTED | |
1381 /* Does the colorspace match sRGB? If there is no color endpoint | |
1382 * (colorant) information assume yes, otherwise require the | |
1383 * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the | |
1384 * colorspace has been determined to be invalid ignore it. | |
1385 */ | |
1386 if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags | |
1387 & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| | |
1388 PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) | |
1389 image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; | |
1390 #endif | |
1391 } | |
1392 | |
1393 /* We need the maximum number of entries regardless of the format the | |
1394 * application sets here. | |
1395 */ | |
1396 { | |
1397 png_uint_32 cmap_entries; | |
1398 | |
1399 switch (png_ptr->color_type) | |
1400 { | |
1401 case PNG_COLOR_TYPE_GRAY: | |
1402 cmap_entries = 1U << png_ptr->bit_depth; | |
1403 break; | |
1404 | |
1405 case PNG_COLOR_TYPE_PALETTE: | |
1406 cmap_entries = png_ptr->num_palette; | |
1407 break; | |
1408 | |
1409 default: | |
1410 cmap_entries = 256; | |
1411 break; | |
1412 } | |
1413 | |
1414 if (cmap_entries > 256) | |
1415 cmap_entries = 256; | |
1416 | |
1417 image->colormap_entries = cmap_entries; | |
1418 } | |
1419 | |
1420 return 1; | |
1421 } | |
1422 | |
1423 #ifdef PNG_STDIO_SUPPORTED | |
1424 int PNGAPI | |
1425 png_image_begin_read_from_stdio(png_imagep image, FILE* file) | |
1426 { | |
1427 if (image != NULL && image->version == PNG_IMAGE_VERSION) | |
1428 { | |
1429 if (file != NULL) | |
1430 { | |
1431 if (png_image_read_init(image)) | |
1432 { | |
1433 /* This is slightly evil, but png_init_io doesn't do anything other | |
1434 * than this and we haven't changed the standard IO functions so | |
1435 * this saves a 'safe' function. | |
1436 */ | |
1437 image->opaque->png_ptr->io_ptr = file; | |
1438 return png_safe_execute(image, png_image_read_header, image); | |
1439 } | |
1440 } | |
1441 | |
1442 else | |
1443 return png_image_error(image, | |
1444 "png_image_begin_read_from_stdio: invalid argument"); | |
1445 } | |
1446 | |
1447 else if (image != NULL) | |
1448 return png_image_error(image, | |
1449 "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); | |
1450 | |
1451 return 0; | |
1452 } | |
1453 | |
1454 int PNGAPI | |
1455 png_image_begin_read_from_file(png_imagep image, const char *file_name) | |
1456 { | |
1457 if (image != NULL && image->version == PNG_IMAGE_VERSION) | |
1458 { | |
1459 if (file_name != NULL) | |
1460 { | |
1461 FILE *fp = fopen(file_name, "rb"); | |
1462 | |
1463 if (fp != NULL) | |
1464 { | |
1465 if (png_image_read_init(image)) | |
1466 { | |
1467 image->opaque->png_ptr->io_ptr = fp; | |
1468 image->opaque->owned_file = 1; | |
1469 return png_safe_execute(image, png_image_read_header, image); | |
1470 } | |
1471 | |
1472 /* Clean up: just the opened file. */ | |
1473 (void)fclose(fp); | |
1474 } | |
1475 | |
1476 else | |
1477 return png_image_error(image, strerror(errno)); | |
1478 } | |
1479 | |
1480 else | |
1481 return png_image_error(image, | |
1482 "png_image_begin_read_from_file: invalid argument"); | |
1483 } | |
1484 | |
1485 else if (image != NULL) | |
1486 return png_image_error(image, | |
1487 "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); | |
1488 | |
1489 return 0; | |
1490 } | |
1491 #endif /* PNG_STDIO_SUPPORTED */ | |
1492 | |
1493 static void PNGCBAPI | |
1494 png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) | |
1495 { | |
1496 if (png_ptr != NULL) | |
1497 { | |
1498 png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); | |
1499 if (image != NULL) | |
1500 { | |
1501 png_controlp cp = image->opaque; | |
1502 if (cp != NULL) | |
1503 { | |
1504 png_const_bytep memory = cp->memory; | |
1505 png_size_t size = cp->size; | |
1506 | |
1507 if (memory != NULL && size >= need) | |
1508 { | |
1509 memcpy(out, memory, need); | |
1510 cp->memory = memory + need; | |
1511 cp->size = size - need; | |
1512 return; | |
1513 } | |
1514 | |
1515 png_error(png_ptr, "read beyond end of data"); | |
1516 } | |
1517 } | |
1518 | |
1519 png_error(png_ptr, "invalid memory read"); | |
1520 } | |
1521 } | |
1522 | |
1523 int PNGAPI png_image_begin_read_from_memory(png_imagep image, | |
1524 png_const_voidp memory, png_size_t size) | |
1525 { | |
1526 if (image != NULL && image->version == PNG_IMAGE_VERSION) | |
1527 { | |
1528 if (memory != NULL && size > 0) | |
1529 { | |
1530 if (png_image_read_init(image)) | |
1531 { | |
1532 /* Now set the IO functions to read from the memory buffer and | |
1533 * store it into io_ptr. Again do this in-place to avoid calling a | |
1534 * libpng function that requires error handling. | |
1535 */ | |
1536 image->opaque->memory = png_voidcast(png_const_bytep, memory); | |
1537 image->opaque->size = size; | |
1538 image->opaque->png_ptr->io_ptr = image; | |
1539 image->opaque->png_ptr->read_data_fn = png_image_memory_read; | |
1540 | |
1541 return png_safe_execute(image, png_image_read_header, image); | |
1542 } | |
1543 } | |
1544 | |
1545 else | |
1546 return png_image_error(image, | |
1547 "png_image_begin_read_from_memory: invalid argument"); | |
1548 } | |
1549 | |
1550 else if (image != NULL) | |
1551 return png_image_error(image, | |
1552 "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); | |
1553 | |
1554 return 0; | |
1555 } | |
1556 | |
1557 /* Utility function to skip chunks that are not used by the simplified image | |
1558 * read functions and an appropriate macro to call it. | |
1559 */ | |
1560 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | |
1561 static void | |
1562 png_image_skip_unused_chunks(png_structrp png_ptr) | |
1563 { | |
1564 /* Prepare the reader to ignore all recognized chunks whose data will not | |
1565 * be used, i.e., all chunks recognized by libpng except for those | |
1566 * involved in basic image reading: | |
1567 * | |
1568 * IHDR, PLTE, IDAT, IEND | |
1569 * | |
1570 * Or image data handling: | |
1571 * | |
1572 * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT. | |
1573 * | |
1574 * This provides a small performance improvement and eliminates any | |
1575 * potential vulnerability to security problems in the unused chunks. | |
1576 * | |
1577 * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored | |
1578 * too. This allows the simplified API to be compiled without iCCP support, | |
1579 * however if the support is there the chunk is still checked to detect | |
1580 * errors (which are unfortunately quite common.) | |
1581 */ | |
1582 { | |
1583 static PNG_CONST png_byte chunks_to_process[] = { | |
1584 98, 75, 71, 68, '\0', /* bKGD */ | |
1585 99, 72, 82, 77, '\0', /* cHRM */ | |
1586 103, 65, 77, 65, '\0', /* gAMA */ | |
1587 # ifdef PNG_READ_iCCP_SUPPORTED | |
1588 105, 67, 67, 80, '\0', /* iCCP */ | |
1589 # endif | |
1590 115, 66, 73, 84, '\0', /* sBIT */ | |
1591 115, 82, 71, 66, '\0', /* sRGB */ | |
1592 }; | |
1593 | |
1594 /* Ignore unknown chunks and all other chunks except for the | |
1595 * IHDR, PLTE, tRNS, IDAT, and IEND chunks. | |
1596 */ | |
1597 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, | |
1598 NULL, -1); | |
1599 | |
1600 /* But do not ignore image data handling chunks */ | |
1601 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, | |
1602 chunks_to_process, (sizeof chunks_to_process)/5); | |
1603 } | |
1604 } | |
1605 | |
1606 # define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) | |
1607 #else | |
1608 # define PNG_SKIP_CHUNKS(p) ((void)0) | |
1609 #endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ | |
1610 | |
1611 /* The following macro gives the exact rounded answer for all values in the | |
1612 * range 0..255 (it actually divides by 51.2, but the rounding still generates | |
1613 * the correct numbers 0..5 | |
1614 */ | |
1615 #define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8) | |
1616 | |
1617 /* Utility functions to make particular color-maps */ | |
1618 static void | |
1619 set_file_encoding(png_image_read_control *display) | |
1620 { | |
1621 png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; | |
1622 if (png_gamma_significant(g)) | |
1623 { | |
1624 if (png_gamma_not_sRGB(g)) | |
1625 { | |
1626 display->file_encoding = P_FILE; | |
1627 display->gamma_to_linear = png_reciprocal(g); | |
1628 } | |
1629 | |
1630 else | |
1631 display->file_encoding = P_sRGB; | |
1632 } | |
1633 | |
1634 else | |
1635 display->file_encoding = P_LINEAR8; | |
1636 } | |
1637 | |
1638 static unsigned int | |
1639 decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) | |
1640 { | |
1641 if (encoding == P_FILE) /* double check */ | |
1642 encoding = display->file_encoding; | |
1643 | |
1644 if (encoding == P_NOTSET) /* must be the file encoding */ | |
1645 { | |
1646 set_file_encoding(display); | |
1647 encoding = display->file_encoding; | |
1648 } | |
1649 | |
1650 switch (encoding) | |
1651 { | |
1652 case P_FILE: | |
1653 value = png_gamma_16bit_correct(value*257, display->gamma_to_linear); | |
1654 break; | |
1655 | |
1656 case P_sRGB: | |
1657 value = png_sRGB_table[value]; | |
1658 break; | |
1659 | |
1660 case P_LINEAR: | |
1661 break; | |
1662 | |
1663 case P_LINEAR8: | |
1664 value *= 257; | |
1665 break; | |
1666 | |
1667 default: | |
1668 png_error(display->image->opaque->png_ptr, | |
1669 "unexpected encoding (internal error)"); | |
1670 break; | |
1671 } | |
1672 | |
1673 return value; | |
1674 } | |
1675 | |
1676 static png_uint_32 | |
1677 png_colormap_compose(png_image_read_control *display, | |
1678 png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, | |
1679 png_uint_32 background, int encoding) | |
1680 { | |
1681 /* The file value is composed on the background, the background has the given | |
1682 * encoding and so does the result, the file is encoded with P_FILE and the | |
1683 * file and alpha are 8-bit values. The (output) encoding will always be | |
1684 * P_LINEAR or P_sRGB. | |
1685 */ | |
1686 png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); | |
1687 png_uint_32 b = decode_gamma(display, background, encoding); | |
1688 | |
1689 /* The alpha is always an 8-bit value (it comes from the palette), the value | |
1690 * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. | |
1691 */ | |
1692 f = f * alpha + b * (255-alpha); | |
1693 | |
1694 if (encoding == P_LINEAR) | |
1695 { | |
1696 /* Scale to 65535; divide by 255, approximately (in fact this is extremely | |
1697 * accurate, it divides by 255.00000005937181414556, with no overflow.) | |
1698 */ | |
1699 f *= 257; /* Now scaled by 65535 */ | |
1700 f += f >> 16; | |
1701 f = (f+32768) >> 16; | |
1702 } | |
1703 | |
1704 else /* P_sRGB */ | |
1705 f = PNG_sRGB_FROM_LINEAR(f); | |
1706 | |
1707 return f; | |
1708 } | |
1709 | |
1710 /* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must | |
1711 * be 8-bit. | |
1712 */ | |
1713 static void | |
1714 png_create_colormap_entry(png_image_read_control *display, | |
1715 png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, | |
1716 png_uint_32 alpha, int encoding) | |
1717 { | |
1718 png_imagep image = display->image; | |
1719 const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ? | |
1720 P_LINEAR : P_sRGB; | |
1721 const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && | |
1722 (red != green || green != blue); | |
1723 | |
1724 if (ip > 255) | |
1725 png_error(image->opaque->png_ptr, "color-map index out of range"); | |
1726 | |
1727 /* Update the cache with whether the file gamma is significantly different | |
1728 * from sRGB. | |
1729 */ | |
1730 if (encoding == P_FILE) | |
1731 { | |
1732 if (display->file_encoding == P_NOTSET) | |
1733 set_file_encoding(display); | |
1734 | |
1735 /* Note that the cached value may be P_FILE too, but if it is then the | |
1736 * gamma_to_linear member has been set. | |
1737 */ | |
1738 encoding = display->file_encoding; | |
1739 } | |
1740 | |
1741 if (encoding == P_FILE) | |
1742 { | |
1743 png_fixed_point g = display->gamma_to_linear; | |
1744 | |
1745 red = png_gamma_16bit_correct(red*257, g); | |
1746 green = png_gamma_16bit_correct(green*257, g); | |
1747 blue = png_gamma_16bit_correct(blue*257, g); | |
1748 | |
1749 if (convert_to_Y || output_encoding == P_LINEAR) | |
1750 { | |
1751 alpha *= 257; | |
1752 encoding = P_LINEAR; | |
1753 } | |
1754 | |
1755 else | |
1756 { | |
1757 red = PNG_sRGB_FROM_LINEAR(red * 255); | |
1758 green = PNG_sRGB_FROM_LINEAR(green * 255); | |
1759 blue = PNG_sRGB_FROM_LINEAR(blue * 255); | |
1760 encoding = P_sRGB; | |
1761 } | |
1762 } | |
1763 | |
1764 else if (encoding == P_LINEAR8) | |
1765 { | |
1766 /* This encoding occurs quite frequently in test cases because PngSuite | |
1767 * includes a gAMA 1.0 chunk with most images. | |
1768 */ | |
1769 red *= 257; | |
1770 green *= 257; | |
1771 blue *= 257; | |
1772 alpha *= 257; | |
1773 encoding = P_LINEAR; | |
1774 } | |
1775 | |
1776 else if (encoding == P_sRGB && (convert_to_Y || output_encoding == P_LINEAR)) | |
1777 { | |
1778 /* The values are 8-bit sRGB values, but must be converted to 16-bit | |
1779 * linear. | |
1780 */ | |
1781 red = png_sRGB_table[red]; | |
1782 green = png_sRGB_table[green]; | |
1783 blue = png_sRGB_table[blue]; | |
1784 alpha *= 257; | |
1785 encoding = P_LINEAR; | |
1786 } | |
1787 | |
1788 /* This is set if the color isn't gray but the output is. */ | |
1789 if (encoding == P_LINEAR) | |
1790 { | |
1791 if (convert_to_Y) | |
1792 { | |
1793 /* NOTE: these values are copied from png_do_rgb_to_gray */ | |
1794 png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green + | |
1795 (png_uint_32)2366 * blue; | |
1796 | |
1797 if (output_encoding == P_LINEAR) | |
1798 y = (y + 16384) >> 15; | |
1799 | |
1800 else | |
1801 { | |
1802 /* y is scaled by 32768, we need it scaled by 255: */ | |
1803 y = (y + 128) >> 8; | |
1804 y *= 255; | |
1805 y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7); | |
1806 encoding = P_sRGB; | |
1807 } | |
1808 | |
1809 blue = red = green = y; | |
1810 } | |
1811 | |
1812 else if (output_encoding == P_sRGB) | |
1813 { | |
1814 red = PNG_sRGB_FROM_LINEAR(red * 255); | |
1815 green = PNG_sRGB_FROM_LINEAR(green * 255); | |
1816 blue = PNG_sRGB_FROM_LINEAR(blue * 255); | |
1817 alpha = PNG_DIV257(alpha); | |
1818 encoding = P_sRGB; | |
1819 } | |
1820 } | |
1821 | |
1822 if (encoding != output_encoding) | |
1823 png_error(image->opaque->png_ptr, "bad encoding (internal error)"); | |
1824 | |
1825 /* Store the value. */ | |
1826 { | |
1827 # ifdef PNG_FORMAT_AFIRST_SUPPORTED | |
1828 const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && | |
1829 (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; | |
1830 # else | |
1831 # define afirst 0 | |
1832 # endif | |
1833 # ifdef PNG_FORMAT_BGR_SUPPORTED | |
1834 const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; | |
1835 # else | |
1836 # define bgr 0 | |
1837 # endif | |
1838 | |
1839 if (output_encoding == P_LINEAR) | |
1840 { | |
1841 png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); | |
1842 | |
1843 entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); | |
1844 | |
1845 /* The linear 16-bit values must be pre-multiplied by the alpha channel | |
1846 * value, if less than 65535 (this is, effectively, composite on black | |
1847 * if the alpha channel is removed.) | |
1848 */ | |
1849 switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) | |
1850 { | |
1851 case 4: | |
1852 entry[afirst ? 0 : 3] = (png_uint_16)alpha; | |
1853 /* FALL THROUGH */ | |
1854 | |
1855 case 3: | |
1856 if (alpha < 65535) | |
1857 { | |
1858 if (alpha > 0) | |
1859 { | |
1860 blue = (blue * alpha + 32767U)/65535U; | |
1861 green = (green * alpha + 32767U)/65535U; | |
1862 red = (red * alpha + 32767U)/65535U; | |
1863 } | |
1864 | |
1865 else | |
1866 red = green = blue = 0; | |
1867 } | |
1868 entry[afirst + (2 ^ bgr)] = (png_uint_16)blue; | |
1869 entry[afirst + 1] = (png_uint_16)green; | |
1870 entry[afirst + bgr] = (png_uint_16)red; | |
1871 break; | |
1872 | |
1873 case 2: | |
1874 entry[1 ^ afirst] = (png_uint_16)alpha; | |
1875 /* FALL THROUGH */ | |
1876 | |
1877 case 1: | |
1878 if (alpha < 65535) | |
1879 { | |
1880 if (alpha > 0) | |
1881 green = (green * alpha + 32767U)/65535U; | |
1882 | |
1883 else | |
1884 green = 0; | |
1885 } | |
1886 entry[afirst] = (png_uint_16)green; | |
1887 break; | |
1888 | |
1889 default: | |
1890 break; | |
1891 } | |
1892 } | |
1893 | |
1894 else /* output encoding is P_sRGB */ | |
1895 { | |
1896 png_bytep entry = png_voidcast(png_bytep, display->colormap); | |
1897 | |
1898 entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); | |
1899 | |
1900 switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) | |
1901 { | |
1902 case 4: | |
1903 entry[afirst ? 0 : 3] = (png_byte)alpha; | |
1904 case 3: | |
1905 entry[afirst + (2 ^ bgr)] = (png_byte)blue; | |
1906 entry[afirst + 1] = (png_byte)green; | |
1907 entry[afirst + bgr] = (png_byte)red; | |
1908 break; | |
1909 | |
1910 case 2: | |
1911 entry[1 ^ afirst] = (png_byte)alpha; | |
1912 case 1: | |
1913 entry[afirst] = (png_byte)green; | |
1914 break; | |
1915 | |
1916 default: | |
1917 break; | |
1918 } | |
1919 } | |
1920 | |
1921 # ifdef afirst | |
1922 # undef afirst | |
1923 # endif | |
1924 # ifdef bgr | |
1925 # undef bgr | |
1926 # endif | |
1927 } | |
1928 } | |
1929 | |
1930 static int | |
1931 make_gray_file_colormap(png_image_read_control *display) | |
1932 { | |
1933 unsigned int i; | |
1934 | |
1935 for (i=0; i<256; ++i) | |
1936 png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); | |
1937 | |
1938 return i; | |
1939 } | |
1940 | |
1941 static int | |
1942 make_gray_colormap(png_image_read_control *display) | |
1943 { | |
1944 unsigned int i; | |
1945 | |
1946 for (i=0; i<256; ++i) | |
1947 png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); | |
1948 | |
1949 return i; | |
1950 } | |
1951 #define PNG_GRAY_COLORMAP_ENTRIES 256 | |
1952 | |
1953 static int | |
1954 make_ga_colormap(png_image_read_control *display) | |
1955 { | |
1956 unsigned int i, a; | |
1957 | |
1958 /* Alpha is retained, the output will be a color-map with entries | |
1959 * selected by six levels of alpha. One transparent entry, 6 gray | |
1960 * levels for all the intermediate alpha values, leaving 230 entries | |
1961 * for the opaque grays. The color-map entries are the six values | |
1962 * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the | |
1963 * relevant entry. | |
1964 * | |
1965 * if (alpha > 229) // opaque | |
1966 * { | |
1967 * // The 231 entries are selected to make the math below work: | |
1968 * base = 0; | |
1969 * entry = (231 * gray + 128) >> 8; | |
1970 * } | |
1971 * else if (alpha < 26) // transparent | |
1972 * { | |
1973 * base = 231; | |
1974 * entry = 0; | |
1975 * } | |
1976 * else // partially opaque | |
1977 * { | |
1978 * base = 226 + 6 * PNG_DIV51(alpha); | |
1979 * entry = PNG_DIV51(gray); | |
1980 * } | |
1981 */ | |
1982 i = 0; | |
1983 while (i < 231) | |
1984 { | |
1985 unsigned int gray = (i * 256 + 115) / 231; | |
1986 png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB); | |
1987 } | |
1988 | |
1989 /* 255 is used here for the component values for consistency with the code | |
1990 * that undoes premultiplication in pngwrite.c. | |
1991 */ | |
1992 png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB); | |
1993 | |
1994 for (a=1; a<5; ++a) | |
1995 { | |
1996 unsigned int g; | |
1997 | |
1998 for (g=0; g<6; ++g) | |
1999 png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, | |
2000 P_sRGB); | |
2001 } | |
2002 | |
2003 return i; | |
2004 } | |
2005 | |
2006 #define PNG_GA_COLORMAP_ENTRIES 256 | |
2007 | |
2008 static int | |
2009 make_rgb_colormap(png_image_read_control *display) | |
2010 { | |
2011 unsigned int i, r; | |
2012 | |
2013 /* Build a 6x6x6 opaque RGB cube */ | |
2014 for (i=r=0; r<6; ++r) | |
2015 { | |
2016 unsigned int g; | |
2017 | |
2018 for (g=0; g<6; ++g) | |
2019 { | |
2020 unsigned int b; | |
2021 | |
2022 for (b=0; b<6; ++b) | |
2023 png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, | |
2024 P_sRGB); | |
2025 } | |
2026 } | |
2027 | |
2028 return i; | |
2029 } | |
2030 | |
2031 #define PNG_RGB_COLORMAP_ENTRIES 216 | |
2032 | |
2033 /* Return a palette index to the above palette given three 8-bit sRGB values. */ | |
2034 #define PNG_RGB_INDEX(r,g,b) \ | |
2035 ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) | |
2036 | |
2037 static int | |
2038 png_image_read_colormap(png_voidp argument) | |
2039 { | |
2040 png_image_read_control *display = | |
2041 png_voidcast(png_image_read_control*, argument); | |
2042 const png_imagep image = display->image; | |
2043 | |
2044 const png_structrp png_ptr = image->opaque->png_ptr; | |
2045 const png_uint_32 output_format = image->format; | |
2046 const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ? | |
2047 P_LINEAR : P_sRGB; | |
2048 | |
2049 unsigned int cmap_entries; | |
2050 unsigned int output_processing; /* Output processing option */ | |
2051 unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */ | |
2052 | |
2053 /* Background information; the background color and the index of this color | |
2054 * in the color-map if it exists (else 256). | |
2055 */ | |
2056 unsigned int background_index = 256; | |
2057 png_uint_32 back_r, back_g, back_b; | |
2058 | |
2059 /* Flags to accumulate things that need to be done to the input. */ | |
2060 int expand_tRNS = 0; | |
2061 | |
2062 /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is | |
2063 * very difficult to do, the results look awful, and it is difficult to see | |
2064 * what possible use it is because the application can't control the | |
2065 * color-map. | |
2066 */ | |
2067 if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 || | |
2068 png_ptr->num_trans > 0) /* alpha in input */ && | |
2069 ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */) | |
2070 { | |
2071 if (output_encoding == P_LINEAR) /* compose on black */ | |
2072 back_b = back_g = back_r = 0; | |
2073 | |
2074 else if (display->background == NULL /* no way to remove it */) | |
2075 png_error(png_ptr, | |
2076 "a background color must be supplied to remove alpha/transparency"); | |
2077 | |
2078 /* Get a copy of the background color (this avoids repeating the checks | |
2079 * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the | |
2080 * output format. | |
2081 */ | |
2082 else | |
2083 { | |
2084 back_g = display->background->green; | |
2085 if (output_format & PNG_FORMAT_FLAG_COLOR) | |
2086 { | |
2087 back_r = display->background->red; | |
2088 back_b = display->background->blue; | |
2089 } | |
2090 else | |
2091 back_b = back_r = back_g; | |
2092 } | |
2093 } | |
2094 | |
2095 else if (output_encoding == P_LINEAR) | |
2096 back_b = back_r = back_g = 65535; | |
2097 | |
2098 else | |
2099 back_b = back_r = back_g = 255; | |
2100 | |
2101 /* Default the input file gamma if required - this is necessary because | |
2102 * libpng assumes that if no gamma information is present the data is in the | |
2103 * output format, but the simplified API deduces the gamma from the input | |
2104 * format. | |
2105 */ | |
2106 if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) | |
2107 { | |
2108 /* Do this directly, not using the png_colorspace functions, to ensure | |
2109 * that it happens even if the colorspace is invalid (though probably if | |
2110 * it is the setting will be ignored) Note that the same thing can be | |
2111 * achieved at the application interface with png_set_gAMA. | |
2112 */ | |
2113 if (png_ptr->bit_depth == 16 && | |
2114 (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) | |
2115 png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; | |
2116 | |
2117 else | |
2118 png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; | |
2119 | |
2120 png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; | |
2121 } | |
2122 | |
2123 /* Decide what to do based on the PNG color type of the input data. The | |
2124 * utility function png_create_colormap_entry deals with most aspects of the | |
2125 * output transformations; this code works out how to produce bytes of | |
2126 * color-map entries from the original format. | |
2127 */ | |
2128 switch (png_ptr->color_type) | |
2129 { | |
2130 case PNG_COLOR_TYPE_GRAY: | |
2131 if (png_ptr->bit_depth <= 8) | |
2132 { | |
2133 /* There at most 256 colors in the output, regardless of | |
2134 * transparency. | |
2135 */ | |
2136 unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0; | |
2137 | |
2138 cmap_entries = 1U << png_ptr->bit_depth; | |
2139 if (cmap_entries > image->colormap_entries) | |
2140 png_error(png_ptr, "gray[8] color-map: too few entries"); | |
2141 | |
2142 step = 255 / (cmap_entries - 1); | |
2143 output_processing = PNG_CMAP_NONE; | |
2144 | |
2145 /* If there is a tRNS chunk then this either selects a transparent | |
2146 * value or, if the output has no alpha, the background color. | |
2147 */ | |
2148 if (png_ptr->num_trans > 0) | |
2149 { | |
2150 trans = png_ptr->trans_color.gray; | |
2151 | |
2152 if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) | |
2153 back_alpha = output_encoding == P_LINEAR ? 65535 : 255; | |
2154 } | |
2155 | |
2156 /* png_create_colormap_entry just takes an RGBA and writes the | |
2157 * corresponding color-map entry using the format from 'image', | |
2158 * including the required conversion to sRGB or linear as | |
2159 * appropriate. The input values are always either sRGB (if the | |
2160 * gamma correction flag is 0) or 0..255 scaled file encoded values | |
2161 * (if the function must gamma correct them). | |
2162 */ | |
2163 for (i=val=0; i<cmap_entries; ++i, val += step) | |
2164 { | |
2165 /* 'i' is a file value. While this will result in duplicated | |
2166 * entries for 8-bit non-sRGB encoded files it is necessary to | |
2167 * have non-gamma corrected values to do tRNS handling. | |
2168 */ | |
2169 if (i != trans) | |
2170 png_create_colormap_entry(display, i, val, val, val, 255, | |
2171 P_FILE/*8-bit with file gamma*/); | |
2172 | |
2173 /* Else this entry is transparent. The colors don't matter if | |
2174 * there is an alpha channel (back_alpha == 0), but it does no | |
2175 * harm to pass them in; the values are not set above so this | |
2176 * passes in white. | |
2177 * | |
2178 * NOTE: this preserves the full precision of the application | |
2179 * supplied background color when it is used. | |
2180 */ | |
2181 else | |
2182 png_create_colormap_entry(display, i, back_r, back_g, back_b, | |
2183 back_alpha, output_encoding); | |
2184 } | |
2185 | |
2186 /* We need libpng to preserve the original encoding. */ | |
2187 data_encoding = P_FILE; | |
2188 | |
2189 /* The rows from libpng, while technically gray values, are now also | |
2190 * color-map indicies; however, they may need to be expanded to 1 | |
2191 * byte per pixel. This is what png_set_packing does (i.e., it | |
2192 * unpacks the bit values into bytes.) | |
2193 */ | |
2194 if (png_ptr->bit_depth < 8) | |
2195 png_set_packing(png_ptr); | |
2196 } | |
2197 | |
2198 else /* bit depth is 16 */ | |
2199 { | |
2200 /* The 16-bit input values can be converted directly to 8-bit gamma | |
2201 * encoded values; however, if a tRNS chunk is present 257 color-map | |
2202 * entries are required. This means that the extra entry requires | |
2203 * special processing; add an alpha channel, sacrifice gray level | |
2204 * 254 and convert transparent (alpha==0) entries to that. | |
2205 * | |
2206 * Use libpng to chop the data to 8 bits. Convert it to sRGB at the | |
2207 * same time to minimize quality loss. If a tRNS chunk is present | |
2208 * this means libpng must handle it too; otherwise it is impossible | |
2209 * to do the exact match on the 16-bit value. | |
2210 * | |
2211 * If the output has no alpha channel *and* the background color is | |
2212 * gray then it is possible to let libpng handle the substitution by | |
2213 * ensuring that the corresponding gray level matches the background | |
2214 * color exactly. | |
2215 */ | |
2216 data_encoding = P_sRGB; | |
2217 | |
2218 if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) | |
2219 png_error(png_ptr, "gray[16] color-map: too few entries"); | |
2220 | |
2221 cmap_entries = make_gray_colormap(display); | |
2222 | |
2223 if (png_ptr->num_trans > 0) | |
2224 { | |
2225 unsigned int back_alpha; | |
2226 | |
2227 if (output_format & PNG_FORMAT_FLAG_ALPHA) | |
2228 back_alpha = 0; | |
2229 | |
2230 else | |
2231 { | |
2232 if (back_r == back_g && back_g == back_b) | |
2233 { | |
2234 /* Background is gray; no special processing will be | |
2235 * required. | |
2236 */ | |
2237 png_color_16 c; | |
2238 png_uint_32 gray = back_g; | |
2239 | |
2240 if (output_encoding == P_LINEAR) | |
2241 { | |
2242 gray = PNG_sRGB_FROM_LINEAR(gray * 255); | |
2243 | |
2244 /* And make sure the corresponding palette entry | |
2245 * matches. | |
2246 */ | |
2247 png_create_colormap_entry(display, gray, back_g, back_g, | |
2248 back_g, 65535, P_LINEAR); | |
2249 } | |
2250 | |
2251 /* The background passed to libpng, however, must be the | |
2252 * sRGB value. | |
2253 */ | |
2254 c.index = 0; /*unused*/ | |
2255 c.gray = c.red = c.green = c.blue = (png_uint_16)gray; | |
2256 | |
2257 /* NOTE: does this work without expanding tRNS to alpha? | |
2258 * It should be the color->gray case below apparently | |
2259 * doesn't. | |
2260 */ | |
2261 png_set_background_fixed(png_ptr, &c, | |
2262 PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, | |
2263 0/*gamma: not used*/); | |
2264 | |
2265 output_processing = PNG_CMAP_NONE; | |
2266 break; | |
2267 } | |
2268 | |
2269 back_alpha = output_encoding == P_LINEAR ? 65535 : 255; | |
2270 } | |
2271 | |
2272 /* output_processing means that the libpng-processed row will be | |
2273 * 8-bit GA and it has to be processing to single byte color-map | |
2274 * values. Entry 254 is replaced by either a completely | |
2275 * transparent entry or by the background color at full | |
2276 * precision (and the background color is not a simple gray leve | |
2277 * in this case.) | |
2278 */ | |
2279 expand_tRNS = 1; | |
2280 output_processing = PNG_CMAP_TRANS; | |
2281 background_index = 254; | |
2282 | |
2283 /* And set (overwrite) color-map entry 254 to the actual | |
2284 * background color at full precision. | |
2285 */ | |
2286 png_create_colormap_entry(display, 254, back_r, back_g, back_b, | |
2287 back_alpha, output_encoding); | |
2288 } | |
2289 | |
2290 else | |
2291 output_processing = PNG_CMAP_NONE; | |
2292 } | |
2293 break; | |
2294 | |
2295 case PNG_COLOR_TYPE_GRAY_ALPHA: | |
2296 /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum | |
2297 * of 65536 combinations. If, however, the alpha channel is to be | |
2298 * removed there are only 256 possibilities if the background is gray. | |
2299 * (Otherwise there is a subset of the 65536 possibilities defined by | |
2300 * the triangle between black, white and the background color.) | |
2301 * | |
2302 * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to | |
2303 * worry about tRNS matching - tRNS is ignored if there is an alpha | |
2304 * channel. | |
2305 */ | |
2306 data_encoding = P_sRGB; | |
2307 | |
2308 if (output_format & PNG_FORMAT_FLAG_ALPHA) | |
2309 { | |
2310 if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) | |
2311 png_error(png_ptr, "gray+alpha color-map: too few entries"); | |
2312 | |
2313 cmap_entries = make_ga_colormap(display); | |
2314 | |
2315 background_index = PNG_CMAP_GA_BACKGROUND; | |
2316 output_processing = PNG_CMAP_GA; | |
2317 } | |
2318 | |
2319 else /* alpha is removed */ | |
2320 { | |
2321 /* Alpha must be removed as the PNG data is processed when the | |
2322 * background is a color because the G and A channels are | |
2323 * independent and the vector addition (non-parallel vectors) is a | |
2324 * 2-D problem. | |
2325 * | |
2326 * This can be reduced to the same algorithm as above by making a | |
2327 * colormap containing gray levels (for the opaque grays), a | |
2328 * background entry (for a transparent pixel) and a set of four six | |
2329 * level color values, one set for each intermediate alpha value. | |
2330 * See the comments in make_ga_colormap for how this works in the | |
2331 * per-pixel processing. | |
2332 * | |
2333 * If the background is gray, however, we only need a 256 entry gray | |
2334 * level color map. It is sufficient to make the entry generated | |
2335 * for the background color be exactly the color specified. | |
2336 */ | |
2337 if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 || | |
2338 (back_r == back_g && back_g == back_b)) | |
2339 { | |
2340 /* Background is gray; no special processing will be required. */ | |
2341 png_color_16 c; | |
2342 png_uint_32 gray = back_g; | |
2343 | |
2344 if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) | |
2345 png_error(png_ptr, "gray-alpha color-map: too few entries"); | |
2346 | |
2347 cmap_entries = make_gray_colormap(display); | |
2348 | |
2349 if (output_encoding == P_LINEAR) | |
2350 { | |
2351 gray = PNG_sRGB_FROM_LINEAR(gray * 255); | |
2352 | |
2353 /* And make sure the corresponding palette entry matches. */ | |
2354 png_create_colormap_entry(display, gray, back_g, back_g, | |
2355 back_g, 65535, P_LINEAR); | |
2356 } | |
2357 | |
2358 /* The background passed to libpng, however, must be the sRGB | |
2359 * value. | |
2360 */ | |
2361 c.index = 0; /*unused*/ | |
2362 c.gray = c.red = c.green = c.blue = (png_uint_16)gray; | |
2363 | |
2364 png_set_background_fixed(png_ptr, &c, | |
2365 PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, | |
2366 0/*gamma: not used*/); | |
2367 | |
2368 output_processing = PNG_CMAP_NONE; | |
2369 } | |
2370 | |
2371 else | |
2372 { | |
2373 png_uint_32 i, a; | |
2374 | |
2375 /* This is the same as png_make_ga_colormap, above, except that | |
2376 * the entries are all opaque. | |
2377 */ | |
2378 if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) | |
2379 png_error(png_ptr, "ga-alpha color-map: too few entries"); | |
2380 | |
2381 i = 0; | |
2382 while (i < 231) | |
2383 { | |
2384 png_uint_32 gray = (i * 256 + 115) / 231; | |
2385 png_create_colormap_entry(display, i++, gray, gray, gray, | |
2386 255, P_sRGB); | |
2387 } | |
2388 | |
2389 /* NOTE: this preserves the full precision of the application | |
2390 * background color. | |
2391 */ | |
2392 background_index = i; | |
2393 png_create_colormap_entry(display, i++, back_r, back_g, back_b, | |
2394 output_encoding == P_LINEAR ? 65535U : 255U, output_encoding); | |
2395 | |
2396 /* For non-opaque input composite on the sRGB background - this | |
2397 * requires inverting the encoding for each component. The input | |
2398 * is still converted to the sRGB encoding because this is a | |
2399 * reasonable approximate to the logarithmic curve of human | |
2400 * visual sensitivity, at least over the narrow range which PNG | |
2401 * represents. Consequently 'G' is always sRGB encoded, while | |
2402 * 'A' is linear. We need the linear background colors. | |
2403 */ | |
2404 if (output_encoding == P_sRGB) /* else already linear */ | |
2405 { | |
2406 /* This may produce a value not exactly matching the | |
2407 * background, but that's ok because these numbers are only | |
2408 * used when alpha != 0 | |
2409 */ | |
2410 back_r = png_sRGB_table[back_r]; | |
2411 back_g = png_sRGB_table[back_g]; | |
2412 back_b = png_sRGB_table[back_b]; | |
2413 } | |
2414 | |
2415 for (a=1; a<5; ++a) | |
2416 { | |
2417 unsigned int g; | |
2418 | |
2419 /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled | |
2420 * by an 8-bit alpha value (0..255). | |
2421 */ | |
2422 png_uint_32 alpha = 51 * a; | |
2423 png_uint_32 back_rx = (255-alpha) * back_r; | |
2424 png_uint_32 back_gx = (255-alpha) * back_g; | |
2425 png_uint_32 back_bx = (255-alpha) * back_b; | |
2426 | |
2427 for (g=0; g<6; ++g) | |
2428 { | |
2429 png_uint_32 gray = png_sRGB_table[g*51] * alpha; | |
2430 | |
2431 png_create_colormap_entry(display, i++, | |
2432 PNG_sRGB_FROM_LINEAR(gray + back_rx), | |
2433 PNG_sRGB_FROM_LINEAR(gray + back_gx), | |
2434 PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); | |
2435 } | |
2436 } | |
2437 | |
2438 cmap_entries = i; | |
2439 output_processing = PNG_CMAP_GA; | |
2440 } | |
2441 } | |
2442 break; | |
2443 | |
2444 case PNG_COLOR_TYPE_RGB: | |
2445 case PNG_COLOR_TYPE_RGB_ALPHA: | |
2446 /* Exclude the case where the output is gray; we can always handle this | |
2447 * with the cases above. | |
2448 */ | |
2449 if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0) | |
2450 { | |
2451 /* The color-map will be grayscale, so we may as well convert the | |
2452 * input RGB values to a simple grayscale and use the grayscale | |
2453 * code above. | |
2454 * | |
2455 * NOTE: calling this apparently damages the recognition of the | |
2456 * transparent color in background color handling; call | |
2457 * png_set_tRNS_to_alpha before png_set_background_fixed. | |
2458 */ | |
2459 png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, | |
2460 -1); | |
2461 data_encoding = P_sRGB; | |
2462 | |
2463 /* The output will now be one or two 8-bit gray or gray+alpha | |
2464 * channels. The more complex case arises when the input has alpha. | |
2465 */ | |
2466 if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || | |
2467 png_ptr->num_trans > 0) && | |
2468 (output_format & PNG_FORMAT_FLAG_ALPHA) != 0) | |
2469 { | |
2470 /* Both input and output have an alpha channel, so no background | |
2471 * processing is required; just map the GA bytes to the right | |
2472 * color-map entry. | |
2473 */ | |
2474 expand_tRNS = 1; | |
2475 | |
2476 if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) | |
2477 png_error(png_ptr, "rgb[ga] color-map: too few entries"); | |
2478 | |
2479 cmap_entries = make_ga_colormap(display); | |
2480 background_index = PNG_CMAP_GA_BACKGROUND; | |
2481 output_processing = PNG_CMAP_GA; | |
2482 } | |
2483 | |
2484 else | |
2485 { | |
2486 /* Either the input or the output has no alpha channel, so there | |
2487 * will be no non-opaque pixels in the color-map; it will just be | |
2488 * grayscale. | |
2489 */ | |
2490 if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) | |
2491 png_error(png_ptr, "rgb[gray] color-map: too few entries"); | |
2492 | |
2493 /* Ideally this code would use libpng to do the gamma correction, | |
2494 * but if an input alpha channel is to be removed we will hit the | |
2495 * libpng bug in gamma+compose+rgb-to-gray (the double gamma | |
2496 * correction bug). Fix this by dropping the gamma correction in | |
2497 * this case and doing it in the palette; this will result in | |
2498 * duplicate palette entries, but that's better than the | |
2499 * alternative of double gamma correction. | |
2500 */ | |
2501 if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || | |
2502 png_ptr->num_trans > 0) && | |
2503 png_gamma_not_sRGB(png_ptr->colorspace.gamma)) | |
2504 { | |
2505 cmap_entries = make_gray_file_colormap(display); | |
2506 data_encoding = P_FILE; | |
2507 } | |
2508 | |
2509 else | |
2510 cmap_entries = make_gray_colormap(display); | |
2511 | |
2512 /* But if the input has alpha or transparency it must be removed | |
2513 */ | |
2514 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || | |
2515 png_ptr->num_trans > 0) | |
2516 { | |
2517 png_color_16 c; | |
2518 png_uint_32 gray = back_g; | |
2519 | |
2520 /* We need to ensure that the application background exists in | |
2521 * the colormap and that completely transparent pixels map to | |
2522 * it. Achieve this simply by ensuring that the entry | |
2523 * selected for the background really is the background color. | |
2524 */ | |
2525 if (data_encoding == P_FILE) /* from the fixup above */ | |
2526 { | |
2527 /* The app supplied a gray which is in output_encoding, we | |
2528 * need to convert it to a value of the input (P_FILE) | |
2529 * encoding then set this palette entry to the required | |
2530 * output encoding. | |
2531 */ | |
2532 if (output_encoding == P_sRGB) | |
2533 gray = png_sRGB_table[gray]; /* now P_LINEAR */ | |
2534 | |
2535 gray = PNG_DIV257(png_gamma_16bit_correct(gray, | |
2536 png_ptr->colorspace.gamma)); /* now P_FILE */ | |
2537 | |
2538 /* And make sure the corresponding palette entry contains | |
2539 * exactly the required sRGB value. | |
2540 */ | |
2541 png_create_colormap_entry(display, gray, back_g, back_g, | |
2542 back_g, 0/*unused*/, output_encoding); | |
2543 } | |
2544 | |
2545 else if (output_encoding == P_LINEAR) | |
2546 { | |
2547 gray = PNG_sRGB_FROM_LINEAR(gray * 255); | |
2548 | |
2549 /* And make sure the corresponding palette entry matches. | |
2550 */ | |
2551 png_create_colormap_entry(display, gray, back_g, back_g, | |
2552 back_g, 0/*unused*/, P_LINEAR); | |
2553 } | |
2554 | |
2555 /* The background passed to libpng, however, must be the | |
2556 * output (normally sRGB) value. | |
2557 */ | |
2558 c.index = 0; /*unused*/ | |
2559 c.gray = c.red = c.green = c.blue = (png_uint_16)gray; | |
2560 | |
2561 /* NOTE: the following is apparently a bug in libpng. Without | |
2562 * it the transparent color recognition in | |
2563 * png_set_background_fixed seems to go wrong. | |
2564 */ | |
2565 expand_tRNS = 1; | |
2566 png_set_background_fixed(png_ptr, &c, | |
2567 PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, | |
2568 0/*gamma: not used*/); | |
2569 } | |
2570 | |
2571 output_processing = PNG_CMAP_NONE; | |
2572 } | |
2573 } | |
2574 | |
2575 else /* output is color */ | |
2576 { | |
2577 /* We could use png_quantize here so long as there is no transparent | |
2578 * color or alpha; png_quantize ignores alpha. Easier overall just | |
2579 * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube. | |
2580 * Consequently we always want libpng to produce sRGB data. | |
2581 */ | |
2582 data_encoding = P_sRGB; | |
2583 | |
2584 /* Is there any transparency or alpha? */ | |
2585 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || | |
2586 png_ptr->num_trans > 0) | |
2587 { | |
2588 /* Is there alpha in the output too? If so all four channels are | |
2589 * processed into a special RGB cube with alpha support. | |
2590 */ | |
2591 if (output_format & PNG_FORMAT_FLAG_ALPHA) | |
2592 { | |
2593 png_uint_32 r; | |
2594 | |
2595 if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) | |
2596 png_error(png_ptr, "rgb+alpha color-map: too few entries"); | |
2597 | |
2598 cmap_entries = make_rgb_colormap(display); | |
2599 | |
2600 /* Add a transparent entry. */ | |
2601 png_create_colormap_entry(display, cmap_entries, 255, 255, | |
2602 255, 0, P_sRGB); | |
2603 | |
2604 /* This is stored as the background index for the processing | |
2605 * algorithm. | |
2606 */ | |
2607 background_index = cmap_entries++; | |
2608 | |
2609 /* Add 27 r,g,b entries each with alpha 0.5. */ | |
2610 for (r=0; r<256; r = (r << 1) | 0x7f) | |
2611 { | |
2612 png_uint_32 g; | |
2613 | |
2614 for (g=0; g<256; g = (g << 1) | 0x7f) | |
2615 { | |
2616 png_uint_32 b; | |
2617 | |
2618 /* This generates components with the values 0, 127 and | |
2619 * 255 | |
2620 */ | |
2621 for (b=0; b<256; b = (b << 1) | 0x7f) | |
2622 png_create_colormap_entry(display, cmap_entries++, | |
2623 r, g, b, 128, P_sRGB); | |
2624 } | |
2625 } | |
2626 | |
2627 expand_tRNS = 1; | |
2628 output_processing = PNG_CMAP_RGB_ALPHA; | |
2629 } | |
2630 | |
2631 else | |
2632 { | |
2633 /* Alpha/transparency must be removed. The background must | |
2634 * exist in the color map (achieved by setting adding it after | |
2635 * the 666 color-map). If the standard processing code will | |
2636 * pick up this entry automatically that's all that is | |
2637 * required; libpng can be called to do the background | |
2638 * processing. | |
2639 */ | |
2640 unsigned int sample_size = | |
2641 PNG_IMAGE_SAMPLE_SIZE(output_format); | |
2642 png_uint_32 r, g, b; /* sRGB background */ | |
2643 | |
2644 if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) | |
2645 png_error(png_ptr, "rgb-alpha color-map: too few entries"); | |
2646 | |
2647 cmap_entries = make_rgb_colormap(display); | |
2648 | |
2649 png_create_colormap_entry(display, cmap_entries, back_r, | |
2650 back_g, back_b, 0/*unused*/, output_encoding); | |
2651 | |
2652 if (output_encoding == P_LINEAR) | |
2653 { | |
2654 r = PNG_sRGB_FROM_LINEAR(back_r * 255); | |
2655 g = PNG_sRGB_FROM_LINEAR(back_g * 255); | |
2656 b = PNG_sRGB_FROM_LINEAR(back_b * 255); | |
2657 } | |
2658 | |
2659 else | |
2660 { | |
2661 r = back_r; | |
2662 g = back_g; | |
2663 b = back_g; | |
2664 } | |
2665 | |
2666 /* Compare the newly-created color-map entry with the one the | |
2667 * PNG_CMAP_RGB algorithm will use. If the two entries don't | |
2668 * match, add the new one and set this as the background | |
2669 * index. | |
2670 */ | |
2671 if (memcmp((png_const_bytep)display->colormap + | |
2672 sample_size * cmap_entries, | |
2673 (png_const_bytep)display->colormap + | |
2674 sample_size * PNG_RGB_INDEX(r,g,b), | |
2675 sample_size) != 0) | |
2676 { | |
2677 /* The background color must be added. */ | |
2678 background_index = cmap_entries++; | |
2679 | |
2680 /* Add 27 r,g,b entries each with created by composing with | |
2681 * the background at alpha 0.5. | |
2682 */ | |
2683 for (r=0; r<256; r = (r << 1) | 0x7f) | |
2684 { | |
2685 for (g=0; g<256; g = (g << 1) | 0x7f) | |
2686 { | |
2687 /* This generates components with the values 0, 127 | |
2688 * and 255 | |
2689 */ | |
2690 for (b=0; b<256; b = (b << 1) | 0x7f) | |
2691 png_create_colormap_entry(display, cmap_entries++, | |
2692 png_colormap_compose(display, r, P_sRGB, 128, | |
2693 back_r, output_encoding), | |
2694 png_colormap_compose(display, g, P_sRGB, 128, | |
2695 back_g, output_encoding), | |
2696 png_colormap_compose(display, b, P_sRGB, 128, | |
2697 back_b, output_encoding), | |
2698 0/*unused*/, output_encoding); | |
2699 } | |
2700 } | |
2701 | |
2702 expand_tRNS = 1; | |
2703 output_processing = PNG_CMAP_RGB_ALPHA; | |
2704 } | |
2705 | |
2706 else /* background color is in the standard color-map */ | |
2707 { | |
2708 png_color_16 c; | |
2709 | |
2710 c.index = 0; /*unused*/ | |
2711 c.red = (png_uint_16)back_r; | |
2712 c.gray = c.green = (png_uint_16)back_g; | |
2713 c.blue = (png_uint_16)back_b; | |
2714 | |
2715 png_set_background_fixed(png_ptr, &c, | |
2716 PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, | |
2717 0/*gamma: not used*/); | |
2718 | |
2719 output_processing = PNG_CMAP_RGB; | |
2720 } | |
2721 } | |
2722 } | |
2723 | |
2724 else /* no alpha or transparency in the input */ | |
2725 { | |
2726 /* Alpha in the output is irrelevant, simply map the opaque input | |
2727 * pixels to the 6x6x6 color-map. | |
2728 */ | |
2729 if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) | |
2730 png_error(png_ptr, "rgb color-map: too few entries"); | |
2731 | |
2732 cmap_entries = make_rgb_colormap(display); | |
2733 output_processing = PNG_CMAP_RGB; | |
2734 } | |
2735 } | |
2736 break; | |
2737 | |
2738 case PNG_COLOR_TYPE_PALETTE: | |
2739 /* It's already got a color-map. It may be necessary to eliminate the | |
2740 * tRNS entries though. | |
2741 */ | |
2742 { | |
2743 unsigned int num_trans = png_ptr->num_trans; | |
2744 png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; | |
2745 png_const_colorp colormap = png_ptr->palette; | |
2746 const int do_background = trans != NULL && | |
2747 (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; | |
2748 unsigned int i; | |
2749 | |
2750 /* Just in case: */ | |
2751 if (trans == NULL) | |
2752 num_trans = 0; | |
2753 | |
2754 output_processing = PNG_CMAP_NONE; | |
2755 data_encoding = P_FILE; /* Don't change from color-map indicies */ | |
2756 cmap_entries = png_ptr->num_palette; | |
2757 if (cmap_entries > 256) | |
2758 cmap_entries = 256; | |
2759 | |
2760 if (cmap_entries > image->colormap_entries) | |
2761 png_error(png_ptr, "palette color-map: too few entries"); | |
2762 | |
2763 for (i=0; i < cmap_entries; ++i) | |
2764 { | |
2765 if (do_background && i < num_trans && trans[i] < 255) | |
2766 { | |
2767 if (trans[i] == 0) | |
2768 png_create_colormap_entry(display, i, back_r, back_g, | |
2769 back_b, 0, output_encoding); | |
2770 | |
2771 else | |
2772 { | |
2773 /* Must compose the PNG file color in the color-map entry | |
2774 * on the sRGB color in 'back'. | |
2775 */ | |
2776 png_create_colormap_entry(display, i, | |
2777 png_colormap_compose(display, colormap[i].red, P_FILE, | |
2778 trans[i], back_r, output_encoding), | |
2779 png_colormap_compose(display, colormap[i].green, P_FILE, | |
2780 trans[i], back_g, output_encoding), | |
2781 png_colormap_compose(display, colormap[i].blue, P_FILE, | |
2782 trans[i], back_b, output_encoding), | |
2783 output_encoding == P_LINEAR ? trans[i] * 257U : | |
2784 trans[i], | |
2785 output_encoding); | |
2786 } | |
2787 } | |
2788 | |
2789 else | |
2790 png_create_colormap_entry(display, i, colormap[i].red, | |
2791 colormap[i].green, colormap[i].blue, | |
2792 i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); | |
2793 } | |
2794 | |
2795 /* The PNG data may have indicies packed in fewer than 8 bits, it | |
2796 * must be expanded if so. | |
2797 */ | |
2798 if (png_ptr->bit_depth < 8) | |
2799 png_set_packing(png_ptr); | |
2800 } | |
2801 break; | |
2802 | |
2803 default: | |
2804 png_error(png_ptr, "invalid PNG color type"); | |
2805 /*NOT REACHED*/ | |
2806 break; | |
2807 } | |
2808 | |
2809 /* Now deal with the output processing */ | |
2810 if (expand_tRNS && png_ptr->num_trans > 0 && | |
2811 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0) | |
2812 png_set_tRNS_to_alpha(png_ptr); | |
2813 | |
2814 switch (data_encoding) | |
2815 { | |
2816 default: | |
2817 png_error(png_ptr, "bad data option (internal error)"); | |
2818 break; | |
2819 | |
2820 case P_sRGB: | |
2821 /* Change to 8-bit sRGB */ | |
2822 png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); | |
2823 /* FALL THROUGH */ | |
2824 | |
2825 case P_FILE: | |
2826 if (png_ptr->bit_depth > 8) | |
2827 png_set_scale_16(png_ptr); | |
2828 break; | |
2829 } | |
2830 | |
2831 if (cmap_entries > 256 || cmap_entries > image->colormap_entries) | |
2832 png_error(png_ptr, "color map overflow (BAD internal error)"); | |
2833 | |
2834 image->colormap_entries = cmap_entries; | |
2835 | |
2836 /* Double check using the recorded background index */ | |
2837 switch (output_processing) | |
2838 { | |
2839 case PNG_CMAP_NONE: | |
2840 if (background_index != PNG_CMAP_NONE_BACKGROUND) | |
2841 goto bad_background; | |
2842 break; | |
2843 | |
2844 case PNG_CMAP_GA: | |
2845 if (background_index != PNG_CMAP_GA_BACKGROUND) | |
2846 goto bad_background; | |
2847 break; | |
2848 | |
2849 case PNG_CMAP_TRANS: | |
2850 if (background_index >= cmap_entries || | |
2851 background_index != PNG_CMAP_TRANS_BACKGROUND) | |
2852 goto bad_background; | |
2853 break; | |
2854 | |
2855 case PNG_CMAP_RGB: | |
2856 if (background_index != PNG_CMAP_RGB_BACKGROUND) | |
2857 goto bad_background; | |
2858 break; | |
2859 | |
2860 case PNG_CMAP_RGB_ALPHA: | |
2861 if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND) | |
2862 goto bad_background; | |
2863 break; | |
2864 | |
2865 default: | |
2866 png_error(png_ptr, "bad processing option (internal error)"); | |
2867 | |
2868 bad_background: | |
2869 png_error(png_ptr, "bad background index (internal error)"); | |
2870 } | |
2871 | |
2872 display->colormap_processing = output_processing; | |
2873 | |
2874 return 1/*ok*/; | |
2875 } | |
2876 | |
2877 /* The final part of the color-map read called from png_image_finish_read. */ | |
2878 static int | |
2879 png_image_read_and_map(png_voidp argument) | |
2880 { | |
2881 png_image_read_control *display = png_voidcast(png_image_read_control*, | |
2882 argument); | |
2883 png_imagep image = display->image; | |
2884 png_structrp png_ptr = image->opaque->png_ptr; | |
2885 int passes; | |
2886 | |
2887 /* Called when the libpng data must be transformed into the color-mapped | |
2888 * form. There is a local row buffer in display->local and this routine must | |
2889 * do the interlace handling. | |
2890 */ | |
2891 switch (png_ptr->interlaced) | |
2892 { | |
2893 case PNG_INTERLACE_NONE: | |
2894 passes = 1; | |
2895 break; | |
2896 | |
2897 case PNG_INTERLACE_ADAM7: | |
2898 passes = PNG_INTERLACE_ADAM7_PASSES; | |
2899 break; | |
2900 | |
2901 default: | |
2902 png_error(png_ptr, "unknown interlace type"); | |
2903 } | |
2904 | |
2905 { | |
2906 png_uint_32 height = image->height; | |
2907 png_uint_32 width = image->width; | |
2908 int proc = display->colormap_processing; | |
2909 png_bytep first_row = png_voidcast(png_bytep, display->first_row); | |
2910 ptrdiff_t step_row = display->row_bytes; | |
2911 int pass; | |
2912 | |
2913 for (pass = 0; pass < passes; ++pass) | |
2914 { | |
2915 unsigned int startx, stepx, stepy; | |
2916 png_uint_32 y; | |
2917 | |
2918 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) | |
2919 { | |
2920 /* The row may be empty for a short image: */ | |
2921 if (PNG_PASS_COLS(width, pass) == 0) | |
2922 continue; | |
2923 | |
2924 startx = PNG_PASS_START_COL(pass); | |
2925 stepx = PNG_PASS_COL_OFFSET(pass); | |
2926 y = PNG_PASS_START_ROW(pass); | |
2927 stepy = PNG_PASS_ROW_OFFSET(pass); | |
2928 } | |
2929 | |
2930 else | |
2931 { | |
2932 y = 0; | |
2933 startx = 0; | |
2934 stepx = stepy = 1; | |
2935 } | |
2936 | |
2937 for (; y<height; y += stepy) | |
2938 { | |
2939 png_bytep inrow = png_voidcast(png_bytep, display->local_row); | |
2940 png_bytep outrow = first_row + y * step_row; | |
2941 png_const_bytep end_row = outrow + width; | |
2942 | |
2943 /* Read read the libpng data into the temporary buffer. */ | |
2944 png_read_row(png_ptr, inrow, NULL); | |
2945 | |
2946 /* Now process the row according to the processing option, note | |
2947 * that the caller verifies that the format of the libpng output | |
2948 * data is as required. | |
2949 */ | |
2950 outrow += startx; | |
2951 switch (proc) | |
2952 { | |
2953 case PNG_CMAP_GA: | |
2954 for (; outrow < end_row; outrow += stepx) | |
2955 { | |
2956 /* The data is always in the PNG order */ | |
2957 unsigned int gray = *inrow++; | |
2958 unsigned int alpha = *inrow++; | |
2959 unsigned int entry; | |
2960 | |
2961 /* NOTE: this code is copied as a comment in | |
2962 * make_ga_colormap above. Please update the | |
2963 * comment if you change this code! | |
2964 */ | |
2965 if (alpha > 229) /* opaque */ | |
2966 { | |
2967 entry = (231 * gray + 128) >> 8; | |
2968 } | |
2969 else if (alpha < 26) /* transparent */ | |
2970 { | |
2971 entry = 231; | |
2972 } | |
2973 else /* partially opaque */ | |
2974 { | |
2975 entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray); | |
2976 } | |
2977 | |
2978 *outrow = (png_byte)entry; | |
2979 } | |
2980 break; | |
2981 | |
2982 case PNG_CMAP_TRANS: | |
2983 for (; outrow < end_row; outrow += stepx) | |
2984 { | |
2985 png_byte gray = *inrow++; | |
2986 png_byte alpha = *inrow++; | |
2987 | |
2988 if (alpha == 0) | |
2989 *outrow = PNG_CMAP_TRANS_BACKGROUND; | |
2990 | |
2991 else if (gray != PNG_CMAP_TRANS_BACKGROUND) | |
2992 *outrow = gray; | |
2993 | |
2994 else | |
2995 *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1); | |
2996 } | |
2997 break; | |
2998 | |
2999 case PNG_CMAP_RGB: | |
3000 for (; outrow < end_row; outrow += stepx) | |
3001 { | |
3002 *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); | |
3003 inrow += 3; | |
3004 } | |
3005 break; | |
3006 | |
3007 case PNG_CMAP_RGB_ALPHA: | |
3008 for (; outrow < end_row; outrow += stepx) | |
3009 { | |
3010 unsigned int alpha = inrow[3]; | |
3011 | |
3012 /* Because the alpha entries only hold alpha==0.5 values | |
3013 * split the processing at alpha==0.25 (64) and 0.75 | |
3014 * (196). | |
3015 */ | |
3016 | |
3017 if (alpha >= 196) | |
3018 *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], | |
3019 inrow[2]); | |
3020 | |
3021 else if (alpha < 64) | |
3022 *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; | |
3023 | |
3024 else | |
3025 { | |
3026 /* Likewise there are three entries for each of r, g | |
3027 * and b. We could select the entry by popcount on | |
3028 * the top two bits on those architectures that | |
3029 * support it, this is what the code below does, | |
3030 * crudely. | |
3031 */ | |
3032 unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1; | |
3033 | |
3034 /* Here are how the values map: | |
3035 * | |
3036 * 0x00 .. 0x3f -> 0 | |
3037 * 0x40 .. 0xbf -> 1 | |
3038 * 0xc0 .. 0xff -> 2 | |
3039 * | |
3040 * So, as above with the explicit alpha checks, the | |
3041 * breakpoints are at 64 and 196. | |
3042 */ | |
3043 if (inrow[0] & 0x80) back_i += 9; /* red */ | |
3044 if (inrow[0] & 0x40) back_i += 9; | |
3045 if (inrow[0] & 0x80) back_i += 3; /* green */ | |
3046 if (inrow[0] & 0x40) back_i += 3; | |
3047 if (inrow[0] & 0x80) back_i += 1; /* blue */ | |
3048 if (inrow[0] & 0x40) back_i += 1; | |
3049 | |
3050 *outrow = (png_byte)back_i; | |
3051 } | |
3052 | |
3053 inrow += 4; | |
3054 } | |
3055 break; | |
3056 | |
3057 default: | |
3058 break; | |
3059 } | |
3060 } | |
3061 } | |
3062 } | |
3063 | |
3064 return 1; | |
3065 } | |
3066 | |
3067 static int | |
3068 png_image_read_colormapped(png_voidp argument) | |
3069 { | |
3070 png_image_read_control *display = png_voidcast(png_image_read_control*, | |
3071 argument); | |
3072 png_imagep image = display->image; | |
3073 png_controlp control = image->opaque; | |
3074 png_structrp png_ptr = control->png_ptr; | |
3075 png_inforp info_ptr = control->info_ptr; | |
3076 | |
3077 int passes = 0; /* As a flag */ | |
3078 | |
3079 PNG_SKIP_CHUNKS(png_ptr); | |
3080 | |
3081 /* Update the 'info' structure and make sure the result is as required; first | |
3082 * make sure to turn on the interlace handling if it will be required | |
3083 * (because it can't be turned on *after* the call to png_read_update_info!) | |
3084 */ | |
3085 if (display->colormap_processing == PNG_CMAP_NONE) | |
3086 passes = png_set_interlace_handling(png_ptr); | |
3087 | |
3088 png_read_update_info(png_ptr, info_ptr); | |
3089 | |
3090 /* The expected output can be deduced from the colormap_processing option. */ | |
3091 switch (display->colormap_processing) | |
3092 { | |
3093 case PNG_CMAP_NONE: | |
3094 /* Output must be one channel and one byte per pixel, the output | |
3095 * encoding can be anything. | |
3096 */ | |
3097 if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE || | |
3098 info_ptr->color_type == PNG_COLOR_TYPE_GRAY) && | |
3099 info_ptr->bit_depth == 8) | |
3100 break; | |
3101 | |
3102 goto bad_output; | |
3103 | |
3104 case PNG_CMAP_TRANS: | |
3105 case PNG_CMAP_GA: | |
3106 /* Output must be two channels and the 'G' one must be sRGB, the latter | |
3107 * can be checked with an exact number because it should have been set | |
3108 * to this number above! | |
3109 */ | |
3110 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && | |
3111 info_ptr->bit_depth == 8 && | |
3112 png_ptr->screen_gamma == PNG_GAMMA_sRGB && | |
3113 image->colormap_entries == 256) | |
3114 break; | |
3115 | |
3116 goto bad_output; | |
3117 | |
3118 case PNG_CMAP_RGB: | |
3119 /* Output must be 8-bit sRGB encoded RGB */ | |
3120 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB && | |
3121 info_ptr->bit_depth == 8 && | |
3122 png_ptr->screen_gamma == PNG_GAMMA_sRGB && | |
3123 image->colormap_entries == 216) | |
3124 break; | |
3125 | |
3126 goto bad_output; | |
3127 | |
3128 case PNG_CMAP_RGB_ALPHA: | |
3129 /* Output must be 8-bit sRGB encoded RGBA */ | |
3130 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA && | |
3131 info_ptr->bit_depth == 8 && | |
3132 png_ptr->screen_gamma == PNG_GAMMA_sRGB && | |
3133 image->colormap_entries == 244 /* 216 + 1 + 27 */) | |
3134 break; | |
3135 | |
3136 /* goto bad_output; */ | |
3137 /* FALL THROUGH */ | |
3138 | |
3139 default: | |
3140 bad_output: | |
3141 png_error(png_ptr, "bad color-map processing (internal error)"); | |
3142 } | |
3143 | |
3144 /* Now read the rows. Do this here if it is possible to read directly into | |
3145 * the output buffer, otherwise allocate a local row buffer of the maximum | |
3146 * size libpng requires and call the relevant processing routine safely. | |
3147 */ | |
3148 { | |
3149 png_voidp first_row = display->buffer; | |
3150 ptrdiff_t row_bytes = display->row_stride; | |
3151 | |
3152 /* The following expression is designed to work correctly whether it gives | |
3153 * a signed or an unsigned result. | |
3154 */ | |
3155 if (row_bytes < 0) | |
3156 { | |
3157 char *ptr = png_voidcast(char*, first_row); | |
3158 ptr += (image->height-1) * (-row_bytes); | |
3159 first_row = png_voidcast(png_voidp, ptr); | |
3160 } | |
3161 | |
3162 display->first_row = first_row; | |
3163 display->row_bytes = row_bytes; | |
3164 } | |
3165 | |
3166 if (passes == 0) | |
3167 { | |
3168 int result; | |
3169 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); | |
3170 | |
3171 display->local_row = row; | |
3172 result = png_safe_execute(image, png_image_read_and_map, display); | |
3173 display->local_row = NULL; | |
3174 png_free(png_ptr, row); | |
3175 | |
3176 return result; | |
3177 } | |
3178 | |
3179 else | |
3180 { | |
3181 png_alloc_size_t row_bytes = display->row_bytes; | |
3182 | |
3183 while (--passes >= 0) | |
3184 { | |
3185 png_uint_32 y = image->height; | |
3186 png_bytep row = png_voidcast(png_bytep, display->first_row); | |
3187 | |
3188 while (y-- > 0) | |
3189 { | |
3190 png_read_row(png_ptr, row, NULL); | |
3191 row += row_bytes; | |
3192 } | |
3193 } | |
3194 | |
3195 return 1; | |
3196 } | |
3197 } | |
3198 | |
3199 /* Just the row reading part of png_image_read. */ | |
3200 static int | |
3201 png_image_read_composite(png_voidp argument) | |
3202 { | |
3203 png_image_read_control *display = png_voidcast(png_image_read_control*, | |
3204 argument); | |
3205 png_imagep image = display->image; | |
3206 png_structrp png_ptr = image->opaque->png_ptr; | |
3207 int passes; | |
3208 | |
3209 switch (png_ptr->interlaced) | |
3210 { | |
3211 case PNG_INTERLACE_NONE: | |
3212 passes = 1; | |
3213 break; | |
3214 | |
3215 case PNG_INTERLACE_ADAM7: | |
3216 passes = PNG_INTERLACE_ADAM7_PASSES; | |
3217 break; | |
3218 | |
3219 default: | |
3220 png_error(png_ptr, "unknown interlace type"); | |
3221 } | |
3222 | |
3223 { | |
3224 png_uint_32 height = image->height; | |
3225 png_uint_32 width = image->width; | |
3226 ptrdiff_t step_row = display->row_bytes; | |
3227 unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; | |
3228 int pass; | |
3229 | |
3230 for (pass = 0; pass < passes; ++pass) | |
3231 { | |
3232 unsigned int startx, stepx, stepy; | |
3233 png_uint_32 y; | |
3234 | |
3235 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) | |
3236 { | |
3237 /* The row may be empty for a short image: */ | |
3238 if (PNG_PASS_COLS(width, pass) == 0) | |
3239 continue; | |
3240 | |
3241 startx = PNG_PASS_START_COL(pass) * channels; | |
3242 stepx = PNG_PASS_COL_OFFSET(pass) * channels; | |
3243 y = PNG_PASS_START_ROW(pass); | |
3244 stepy = PNG_PASS_ROW_OFFSET(pass); | |
3245 } | |
3246 | |
3247 else | |
3248 { | |
3249 y = 0; | |
3250 startx = 0; | |
3251 stepx = channels; | |
3252 stepy = 1; | |
3253 } | |
3254 | |
3255 for (; y<height; y += stepy) | |
3256 { | |
3257 png_bytep inrow = png_voidcast(png_bytep, display->local_row); | |
3258 png_bytep outrow; | |
3259 png_const_bytep end_row; | |
3260 | |
3261 /* Read the row, which is packed: */ | |
3262 png_read_row(png_ptr, inrow, NULL); | |
3263 | |
3264 outrow = png_voidcast(png_bytep, display->first_row); | |
3265 outrow += y * step_row; | |
3266 end_row = outrow + width * channels; | |
3267 | |
3268 /* Now do the composition on each pixel in this row. */ | |
3269 outrow += startx; | |
3270 for (; outrow < end_row; outrow += stepx) | |
3271 { | |
3272 png_byte alpha = inrow[channels]; | |
3273 | |
3274 if (alpha > 0) /* else no change to the output */ | |
3275 { | |
3276 unsigned int c; | |
3277 | |
3278 for (c=0; c<channels; ++c) | |
3279 { | |
3280 png_uint_32 component = inrow[c]; | |
3281 | |
3282 if (alpha < 255) /* else just use component */ | |
3283 { | |
3284 /* This is PNG_OPTIMIZED_ALPHA, the component value | |
3285 * is a linear 8-bit value. Combine this with the | |
3286 * current outrow[c] value which is sRGB encoded. | |
3287 * Arithmetic here is 16-bits to preserve the output | |
3288 * values correctly. | |
3289 */ | |
3290 component *= 257*255; /* =65535 */ | |
3291 component += (255-alpha)*png_sRGB_table[outrow[c]]; | |
3292 | |
3293 /* So 'component' is scaled by 255*65535 and is | |
3294 * therefore appropriate for the sRGB to linear | |
3295 * conversion table. | |
3296 */ | |
3297 component = PNG_sRGB_FROM_LINEAR(component); | |
3298 } | |
3299 | |
3300 outrow[c] = (png_byte)component; | |
3301 } | |
3302 } | |
3303 | |
3304 inrow += channels+1; /* components and alpha channel */ | |
3305 } | |
3306 } | |
3307 } | |
3308 } | |
3309 | |
3310 return 1; | |
3311 } | |
3312 | |
3313 /* The do_local_background case; called when all the following transforms are to | |
3314 * be done: | |
3315 * | |
3316 * PNG_RGB_TO_GRAY | |
3317 * PNG_COMPOSITE | |
3318 * PNG_GAMMA | |
3319 * | |
3320 * This is a work-round for the fact that both the PNG_RGB_TO_GRAY and | |
3321 * PNG_COMPOSITE code performs gamma correction, so we get double gamma | |
3322 * correction. The fix-up is to prevent the PNG_COMPOSITE operation happening | |
3323 * inside libpng, so this routine sees an 8 or 16-bit gray+alpha row and handles | |
3324 * the removal or pre-multiplication of the alpha channel. | |
3325 */ | |
3326 static int | |
3327 png_image_read_background(png_voidp argument) | |
3328 { | |
3329 png_image_read_control *display = png_voidcast(png_image_read_control*, | |
3330 argument); | |
3331 png_imagep image = display->image; | |
3332 png_structrp png_ptr = image->opaque->png_ptr; | |
3333 png_inforp info_ptr = image->opaque->info_ptr; | |
3334 png_uint_32 height = image->height; | |
3335 png_uint_32 width = image->width; | |
3336 int pass, passes; | |
3337 | |
3338 /* Double check the convoluted logic below. We expect to get here with | |
3339 * libpng doing rgb to gray and gamma correction but background processing | |
3340 * left to the png_image_read_background function. The rows libpng produce | |
3341 * might be 8 or 16-bit but should always have two channels; gray plus alpha. | |
3342 */ | |
3343 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) | |
3344 png_error(png_ptr, "lost rgb to gray"); | |
3345 | |
3346 if ((png_ptr->transformations & PNG_COMPOSE) != 0) | |
3347 png_error(png_ptr, "unexpected compose"); | |
3348 | |
3349 if (png_get_channels(png_ptr, info_ptr) != 2) | |
3350 png_error(png_ptr, "lost/gained channels"); | |
3351 | |
3352 /* Expect the 8-bit case to always remove the alpha channel */ | |
3353 if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 && | |
3354 (image->format & PNG_FORMAT_FLAG_ALPHA) != 0) | |
3355 png_error(png_ptr, "unexpected 8-bit transformation"); | |
3356 | |
3357 switch (png_ptr->interlaced) | |
3358 { | |
3359 case PNG_INTERLACE_NONE: | |
3360 passes = 1; | |
3361 break; | |
3362 | |
3363 case PNG_INTERLACE_ADAM7: | |
3364 passes = PNG_INTERLACE_ADAM7_PASSES; | |
3365 break; | |
3366 | |
3367 default: | |
3368 png_error(png_ptr, "unknown interlace type"); | |
3369 } | |
3370 | |
3371 /* Use direct access to info_ptr here because otherwise the simplified API | |
3372 * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is | |
3373 * checking the value after libpng expansions, not the original value in the | |
3374 * PNG. | |
3375 */ | |
3376 switch (info_ptr->bit_depth) | |
3377 { | |
3378 default: | |
3379 png_error(png_ptr, "unexpected bit depth"); | |
3380 break; | |
3381 | |
3382 case 8: | |
3383 /* 8-bit sRGB gray values with an alpha channel; the alpha channel is | |
3384 * to be removed by composing on a background: either the row if | |
3385 * display->background is NULL or display->background->green if not. | |
3386 * Unlike the code above ALPHA_OPTIMIZED has *not* been done. | |
3387 */ | |
3388 { | |
3389 png_bytep first_row = png_voidcast(png_bytep, display->first_row); | |
3390 ptrdiff_t step_row = display->row_bytes; | |
3391 | |
3392 for (pass = 0; pass < passes; ++pass) | |
3393 { | |
3394 png_bytep row = png_voidcast(png_bytep, | |
3395 display->first_row); | |
3396 unsigned int startx, stepx, stepy; | |
3397 png_uint_32 y; | |
3398 | |
3399 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) | |
3400 { | |
3401 /* The row may be empty for a short image: */ | |
3402 if (PNG_PASS_COLS(width, pass) == 0) | |
3403 continue; | |
3404 | |
3405 startx = PNG_PASS_START_COL(pass); | |
3406 stepx = PNG_PASS_COL_OFFSET(pass); | |
3407 y = PNG_PASS_START_ROW(pass); | |
3408 stepy = PNG_PASS_ROW_OFFSET(pass); | |
3409 } | |
3410 | |
3411 else | |
3412 { | |
3413 y = 0; | |
3414 startx = 0; | |
3415 stepx = stepy = 1; | |
3416 } | |
3417 | |
3418 if (display->background == NULL) | |
3419 { | |
3420 for (; y<height; y += stepy) | |
3421 { | |
3422 png_bytep inrow = png_voidcast(png_bytep, | |
3423 display->local_row); | |
3424 png_bytep outrow = first_row + y * step_row; | |
3425 png_const_bytep end_row = outrow + width; | |
3426 | |
3427 /* Read the row, which is packed: */ | |
3428 png_read_row(png_ptr, inrow, NULL); | |
3429 | |
3430 /* Now do the composition on each pixel in this row. */ | |
3431 outrow += startx; | |
3432 for (; outrow < end_row; outrow += stepx) | |
3433 { | |
3434 png_byte alpha = inrow[1]; | |
3435 | |
3436 if (alpha > 0) /* else no change to the output */ | |
3437 { | |
3438 png_uint_32 component = inrow[0]; | |
3439 | |
3440 if (alpha < 255) /* else just use component */ | |
3441 { | |
3442 /* Since PNG_OPTIMIZED_ALPHA was not set it is | |
3443 * necessary to invert the sRGB transfer | |
3444 * function and multiply the alpha out. | |
3445 */ | |
3446 component = png_sRGB_table[component] * alpha; | |
3447 component += png_sRGB_table[outrow[0]] * | |
3448 (255-alpha); | |
3449 component = PNG_sRGB_FROM_LINEAR(component); | |
3450 } | |
3451 | |
3452 outrow[0] = (png_byte)component; | |
3453 } | |
3454 | |
3455 inrow += 2; /* gray and alpha channel */ | |
3456 } | |
3457 } | |
3458 } | |
3459 | |
3460 else /* constant background value */ | |
3461 { | |
3462 png_byte background8 = display->background->green; | |
3463 png_uint_16 background = png_sRGB_table[background8]; | |
3464 | |
3465 for (; y<height; y += stepy) | |
3466 { | |
3467 png_bytep inrow = png_voidcast(png_bytep, | |
3468 display->local_row); | |
3469 png_bytep outrow = first_row + y * step_row; | |
3470 png_const_bytep end_row = outrow + width; | |
3471 | |
3472 /* Read the row, which is packed: */ | |
3473 png_read_row(png_ptr, inrow, NULL); | |
3474 | |
3475 /* Now do the composition on each pixel in this row. */ | |
3476 outrow += startx; | |
3477 for (; outrow < end_row; outrow += stepx) | |
3478 { | |
3479 png_byte alpha = inrow[1]; | |
3480 | |
3481 if (alpha > 0) /* else use background */ | |
3482 { | |
3483 png_uint_32 component = inrow[0]; | |
3484 | |
3485 if (alpha < 255) /* else just use component */ | |
3486 { | |
3487 component = png_sRGB_table[component] * alpha; | |
3488 component += background * (255-alpha); | |
3489 component = PNG_sRGB_FROM_LINEAR(component); | |
3490 } | |
3491 | |
3492 outrow[0] = (png_byte)component; | |
3493 } | |
3494 | |
3495 else | |
3496 outrow[0] = background8; | |
3497 | |
3498 inrow += 2; /* gray and alpha channel */ | |
3499 } | |
3500 | |
3501 row += display->row_bytes; | |
3502 } | |
3503 } | |
3504 } | |
3505 } | |
3506 break; | |
3507 | |
3508 case 16: | |
3509 /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must | |
3510 * still be done and, maybe, the alpha channel removed. This code also | |
3511 * handles the alpha-first option. | |
3512 */ | |
3513 { | |
3514 png_uint_16p first_row = png_voidcast(png_uint_16p, | |
3515 display->first_row); | |
3516 /* The division by two is safe because the caller passed in a | |
3517 * stride which was multiplied by 2 (below) to get row_bytes. | |
3518 */ | |
3519 ptrdiff_t step_row = display->row_bytes / 2; | |
3520 int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; | |
3521 unsigned int outchannels = 1+preserve_alpha; | |
3522 int swap_alpha = 0; | |
3523 | |
3524 # ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED | |
3525 if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST)) | |
3526 swap_alpha = 1; | |
3527 # endif | |
3528 | |
3529 for (pass = 0; pass < passes; ++pass) | |
3530 { | |
3531 unsigned int startx, stepx, stepy; | |
3532 png_uint_32 y; | |
3533 | |
3534 /* The 'x' start and step are adjusted to output components here. | |
3535 */ | |
3536 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) | |
3537 { | |
3538 /* The row may be empty for a short image: */ | |
3539 if (PNG_PASS_COLS(width, pass) == 0) | |
3540 continue; | |
3541 | |
3542 startx = PNG_PASS_START_COL(pass) * outchannels; | |
3543 stepx = PNG_PASS_COL_OFFSET(pass) * outchannels; | |
3544 y = PNG_PASS_START_ROW(pass); | |
3545 stepy = PNG_PASS_ROW_OFFSET(pass); | |
3546 } | |
3547 | |
3548 else | |
3549 { | |
3550 y = 0; | |
3551 startx = 0; | |
3552 stepx = outchannels; | |
3553 stepy = 1; | |
3554 } | |
3555 | |
3556 for (; y<height; y += stepy) | |
3557 { | |
3558 png_const_uint_16p inrow; | |
3559 png_uint_16p outrow = first_row + y*step_row; | |
3560 png_uint_16p end_row = outrow + width * outchannels; | |
3561 | |
3562 /* Read the row, which is packed: */ | |
3563 png_read_row(png_ptr, png_voidcast(png_bytep, | |
3564 display->local_row), NULL); | |
3565 inrow = png_voidcast(png_const_uint_16p, display->local_row); | |
3566 | |
3567 /* Now do the pre-multiplication on each pixel in this row. | |
3568 */ | |
3569 outrow += startx; | |
3570 for (; outrow < end_row; outrow += stepx) | |
3571 { | |
3572 png_uint_32 component = inrow[0]; | |
3573 png_uint_16 alpha = inrow[1]; | |
3574 | |
3575 if (alpha > 0) /* else 0 */ | |
3576 { | |
3577 if (alpha < 65535) /* else just use component */ | |
3578 { | |
3579 component *= alpha; | |
3580 component += 32767; | |
3581 component /= 65535; | |
3582 } | |
3583 } | |
3584 | |
3585 else | |
3586 component = 0; | |
3587 | |
3588 outrow[swap_alpha] = (png_uint_16)component; | |
3589 if (preserve_alpha) | |
3590 outrow[1 ^ swap_alpha] = alpha; | |
3591 | |
3592 inrow += 2; /* components and alpha channel */ | |
3593 } | |
3594 } | |
3595 } | |
3596 } | |
3597 break; | |
3598 } | |
3599 | |
3600 return 1; | |
3601 } | |
3602 | |
3603 /* The guts of png_image_finish_read as a png_safe_execute callback. */ | |
3604 static int | |
3605 png_image_read_direct(png_voidp argument) | |
3606 { | |
3607 png_image_read_control *display = png_voidcast(png_image_read_control*, | |
3608 argument); | |
3609 png_imagep image = display->image; | |
3610 png_structrp png_ptr = image->opaque->png_ptr; | |
3611 png_inforp info_ptr = image->opaque->info_ptr; | |
3612 | |
3613 png_uint_32 format = image->format; | |
3614 int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; | |
3615 int do_local_compose = 0; | |
3616 int do_local_background = 0; /* to avoid double gamma correction bug */ | |
3617 int passes = 0; | |
3618 | |
3619 /* Add transforms to ensure the correct output format is produced then check | |
3620 * that the required implementation support is there. Always expand; always | |
3621 * need 8 bits minimum, no palette and expanded tRNS. | |
3622 */ | |
3623 png_set_expand(png_ptr); | |
3624 | |
3625 /* Now check the format to see if it was modified. */ | |
3626 { | |
3627 png_uint_32 base_format = png_image_format(png_ptr) & | |
3628 ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */; | |
3629 png_uint_32 change = format ^ base_format; | |
3630 png_fixed_point output_gamma; | |
3631 int mode; /* alpha mode */ | |
3632 | |
3633 /* Do this first so that we have a record if rgb to gray is happening. */ | |
3634 if (change & PNG_FORMAT_FLAG_COLOR) | |
3635 { | |
3636 /* gray<->color transformation required. */ | |
3637 if (format & PNG_FORMAT_FLAG_COLOR) | |
3638 png_set_gray_to_rgb(png_ptr); | |
3639 | |
3640 else | |
3641 { | |
3642 /* libpng can't do both rgb to gray and | |
3643 * background/pre-multiplication if there is also significant gamma | |
3644 * correction, because both operations require linear colors and | |
3645 * the code only supports one transform doing the gamma correction. | |
3646 * Handle this by doing the pre-multiplication or background | |
3647 * operation in this code, if necessary. | |
3648 * | |
3649 * TODO: fix this by rewriting pngrtran.c (!) | |
3650 * | |
3651 * For the moment (given that fixing this in pngrtran.c is an | |
3652 * enormous change) 'do_local_background' is used to indicate that | |
3653 * the problem exists. | |
3654 */ | |
3655 if (base_format & PNG_FORMAT_FLAG_ALPHA) | |
3656 do_local_background = 1/*maybe*/; | |
3657 | |
3658 png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, | |
3659 PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); | |
3660 } | |
3661 | |
3662 change &= ~PNG_FORMAT_FLAG_COLOR; | |
3663 } | |
3664 | |
3665 /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. | |
3666 */ | |
3667 { | |
3668 png_fixed_point input_gamma_default; | |
3669 | |
3670 if ((base_format & PNG_FORMAT_FLAG_LINEAR) && | |
3671 (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) | |
3672 input_gamma_default = PNG_GAMMA_LINEAR; | |
3673 else | |
3674 input_gamma_default = PNG_DEFAULT_sRGB; | |
3675 | |
3676 /* Call png_set_alpha_mode to set the default for the input gamma; the | |
3677 * output gamma is set by a second call below. | |
3678 */ | |
3679 png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); | |
3680 } | |
3681 | |
3682 if (linear) | |
3683 { | |
3684 /* If there *is* an alpha channel in the input it must be multiplied | |
3685 * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. | |
3686 */ | |
3687 if (base_format & PNG_FORMAT_FLAG_ALPHA) | |
3688 mode = PNG_ALPHA_STANDARD; /* associated alpha */ | |
3689 | |
3690 else | |
3691 mode = PNG_ALPHA_PNG; | |
3692 | |
3693 output_gamma = PNG_GAMMA_LINEAR; | |
3694 } | |
3695 | |
3696 else | |
3697 { | |
3698 mode = PNG_ALPHA_PNG; | |
3699 output_gamma = PNG_DEFAULT_sRGB; | |
3700 } | |
3701 | |
3702 /* If 'do_local_background' is set check for the presence of gamma | |
3703 * correction; this is part of the work-round for the libpng bug | |
3704 * described above. | |
3705 * | |
3706 * TODO: fix libpng and remove this. | |
3707 */ | |
3708 if (do_local_background) | |
3709 { | |
3710 png_fixed_point gtest; | |
3711 | |
3712 /* This is 'png_gamma_threshold' from pngrtran.c; the test used for | |
3713 * gamma correction, the screen gamma hasn't been set on png_struct | |
3714 * yet; it's set below. png_struct::gamma, however, is set to the | |
3715 * final value. | |
3716 */ | |
3717 if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, | |
3718 PNG_FP_1) && !png_gamma_significant(gtest)) | |
3719 do_local_background = 0; | |
3720 | |
3721 else if (mode == PNG_ALPHA_STANDARD) | |
3722 { | |
3723 do_local_background = 2/*required*/; | |
3724 mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ | |
3725 } | |
3726 | |
3727 /* else leave as 1 for the checks below */ | |
3728 } | |
3729 | |
3730 /* If the bit-depth changes then handle that here. */ | |
3731 if (change & PNG_FORMAT_FLAG_LINEAR) | |
3732 { | |
3733 if (linear /*16-bit output*/) | |
3734 png_set_expand_16(png_ptr); | |
3735 | |
3736 else /* 8-bit output */ | |
3737 png_set_scale_16(png_ptr); | |
3738 | |
3739 change &= ~PNG_FORMAT_FLAG_LINEAR; | |
3740 } | |
3741 | |
3742 /* Now the background/alpha channel changes. */ | |
3743 if (change & PNG_FORMAT_FLAG_ALPHA) | |
3744 { | |
3745 /* Removing an alpha channel requires composition for the 8-bit | |
3746 * formats; for the 16-bit it is already done, above, by the | |
3747 * pre-multiplication and the channel just needs to be stripped. | |
3748 */ | |
3749 if (base_format & PNG_FORMAT_FLAG_ALPHA) | |
3750 { | |
3751 /* If RGB->gray is happening the alpha channel must be left and the | |
3752 * operation completed locally. | |
3753 * | |
3754 * TODO: fix libpng and remove this. | |
3755 */ | |
3756 if (do_local_background) | |
3757 do_local_background = 2/*required*/; | |
3758 | |
3759 /* 16-bit output: just remove the channel */ | |
3760 else if (linear) /* compose on black (well, pre-multiply) */ | |
3761 png_set_strip_alpha(png_ptr); | |
3762 | |
3763 /* 8-bit output: do an appropriate compose */ | |
3764 else if (display->background != NULL) | |
3765 { | |
3766 png_color_16 c; | |
3767 | |
3768 c.index = 0; /*unused*/ | |
3769 c.red = display->background->red; | |
3770 c.green = display->background->green; | |
3771 c.blue = display->background->blue; | |
3772 c.gray = display->background->green; | |
3773 | |
3774 /* This is always an 8-bit sRGB value, using the 'green' channel | |
3775 * for gray is much better than calculating the luminance here; | |
3776 * we can get off-by-one errors in that calculation relative to | |
3777 * the app expectations and that will show up in transparent | |
3778 * pixels. | |
3779 */ | |
3780 png_set_background_fixed(png_ptr, &c, | |
3781 PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, | |
3782 0/*gamma: not used*/); | |
3783 } | |
3784 | |
3785 else /* compose on row: implemented below. */ | |
3786 { | |
3787 do_local_compose = 1; | |
3788 /* This leaves the alpha channel in the output, so it has to be | |
3789 * removed by the code below. Set the encoding to the 'OPTIMIZE' | |
3790 * one so the code only has to hack on the pixels that require | |
3791 * composition. | |
3792 */ | |
3793 mode = PNG_ALPHA_OPTIMIZED; | |
3794 } | |
3795 } | |
3796 | |
3797 else /* output needs an alpha channel */ | |
3798 { | |
3799 /* This is tricky because it happens before the swap operation has | |
3800 * been accomplished; however, the swap does *not* swap the added | |
3801 * alpha channel (weird API), so it must be added in the correct | |
3802 * place. | |
3803 */ | |
3804 png_uint_32 filler; /* opaque filler */ | |
3805 int where; | |
3806 | |
3807 if (linear) | |
3808 filler = 65535; | |
3809 | |
3810 else | |
3811 filler = 255; | |
3812 | |
3813 # ifdef PNG_FORMAT_AFIRST_SUPPORTED | |
3814 if (format & PNG_FORMAT_FLAG_AFIRST) | |
3815 { | |
3816 where = PNG_FILLER_BEFORE; | |
3817 change &= ~PNG_FORMAT_FLAG_AFIRST; | |
3818 } | |
3819 | |
3820 else | |
3821 # endif | |
3822 where = PNG_FILLER_AFTER; | |
3823 | |
3824 png_set_add_alpha(png_ptr, filler, where); | |
3825 } | |
3826 | |
3827 /* This stops the (irrelevant) call to swap_alpha below. */ | |
3828 change &= ~PNG_FORMAT_FLAG_ALPHA; | |
3829 } | |
3830 | |
3831 /* Now set the alpha mode correctly; this is always done, even if there is | |
3832 * no alpha channel in either the input or the output because it correctly | |
3833 * sets the output gamma. | |
3834 */ | |
3835 png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); | |
3836 | |
3837 # ifdef PNG_FORMAT_BGR_SUPPORTED | |
3838 if (change & PNG_FORMAT_FLAG_BGR) | |
3839 { | |
3840 /* Check only the output format; PNG is never BGR; don't do this if | |
3841 * the output is gray, but fix up the 'format' value in that case. | |
3842 */ | |
3843 if (format & PNG_FORMAT_FLAG_COLOR) | |
3844 png_set_bgr(png_ptr); | |
3845 | |
3846 else | |
3847 format &= ~PNG_FORMAT_FLAG_BGR; | |
3848 | |
3849 change &= ~PNG_FORMAT_FLAG_BGR; | |
3850 } | |
3851 # endif | |
3852 | |
3853 # ifdef PNG_FORMAT_AFIRST_SUPPORTED | |
3854 if (change & PNG_FORMAT_FLAG_AFIRST) | |
3855 { | |
3856 /* Only relevant if there is an alpha channel - it's particularly | |
3857 * important to handle this correctly because do_local_compose may | |
3858 * be set above and then libpng will keep the alpha channel for this | |
3859 * code to remove. | |
3860 */ | |
3861 if (format & PNG_FORMAT_FLAG_ALPHA) | |
3862 { | |
3863 /* Disable this if doing a local background, | |
3864 * TODO: remove this when local background is no longer required. | |
3865 */ | |
3866 if (do_local_background != 2) | |
3867 png_set_swap_alpha(png_ptr); | |
3868 } | |
3869 | |
3870 else | |
3871 format &= ~PNG_FORMAT_FLAG_AFIRST; | |
3872 | |
3873 change &= ~PNG_FORMAT_FLAG_AFIRST; | |
3874 } | |
3875 # endif | |
3876 | |
3877 /* If the *output* is 16-bit then we need to check for a byte-swap on this | |
3878 * architecture. | |
3879 */ | |
3880 if (linear) | |
3881 { | |
3882 PNG_CONST png_uint_16 le = 0x0001; | |
3883 | |
3884 if (*(png_const_bytep)&le) | |
3885 png_set_swap(png_ptr); | |
3886 } | |
3887 | |
3888 /* If change is not now 0 some transformation is missing - error out. */ | |
3889 if (change) | |
3890 png_error(png_ptr, "png_read_image: unsupported transformation"); | |
3891 } | |
3892 | |
3893 PNG_SKIP_CHUNKS(png_ptr); | |
3894 | |
3895 /* Update the 'info' structure and make sure the result is as required; first | |
3896 * make sure to turn on the interlace handling if it will be required | |
3897 * (because it can't be turned on *after* the call to png_read_update_info!) | |
3898 * | |
3899 * TODO: remove the do_local_background fixup below. | |
3900 */ | |
3901 if (!do_local_compose && do_local_background != 2) | |
3902 passes = png_set_interlace_handling(png_ptr); | |
3903 | |
3904 png_read_update_info(png_ptr, info_ptr); | |
3905 | |
3906 { | |
3907 png_uint_32 info_format = 0; | |
3908 | |
3909 if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) | |
3910 info_format |= PNG_FORMAT_FLAG_COLOR; | |
3911 | |
3912 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) | |
3913 { | |
3914 /* do_local_compose removes this channel below. */ | |
3915 if (!do_local_compose) | |
3916 { | |
3917 /* do_local_background does the same if required. */ | |
3918 if (do_local_background != 2 || | |
3919 (format & PNG_FORMAT_FLAG_ALPHA) != 0) | |
3920 info_format |= PNG_FORMAT_FLAG_ALPHA; | |
3921 } | |
3922 } | |
3923 | |
3924 else if (do_local_compose) /* internal error */ | |
3925 png_error(png_ptr, "png_image_read: alpha channel lost"); | |
3926 | |
3927 if (info_ptr->bit_depth == 16) | |
3928 info_format |= PNG_FORMAT_FLAG_LINEAR; | |
3929 | |
3930 # ifdef PNG_FORMAT_BGR_SUPPORTED | |
3931 if (png_ptr->transformations & PNG_BGR) | |
3932 info_format |= PNG_FORMAT_FLAG_BGR; | |
3933 # endif | |
3934 | |
3935 # ifdef PNG_FORMAT_AFIRST_SUPPORTED | |
3936 if (do_local_background == 2) | |
3937 { | |
3938 if (format & PNG_FORMAT_FLAG_AFIRST) | |
3939 info_format |= PNG_FORMAT_FLAG_AFIRST; | |
3940 } | |
3941 | |
3942 if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 || | |
3943 ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && | |
3944 (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) | |
3945 { | |
3946 if (do_local_background == 2) | |
3947 png_error(png_ptr, "unexpected alpha swap transformation"); | |
3948 | |
3949 info_format |= PNG_FORMAT_FLAG_AFIRST; | |
3950 } | |
3951 # endif | |
3952 | |
3953 /* This is actually an internal error. */ | |
3954 if (info_format != format) | |
3955 png_error(png_ptr, "png_read_image: invalid transformations"); | |
3956 } | |
3957 | |
3958 /* Now read the rows. If do_local_compose is set then it is necessary to use | |
3959 * a local row buffer. The output will be GA, RGBA or BGRA and must be | |
3960 * converted to G, RGB or BGR as appropriate. The 'local_row' member of the | |
3961 * display acts as a flag. | |
3962 */ | |
3963 { | |
3964 png_voidp first_row = display->buffer; | |
3965 ptrdiff_t row_bytes = display->row_stride; | |
3966 | |
3967 if (linear) | |
3968 row_bytes *= 2; | |
3969 | |
3970 /* The following expression is designed to work correctly whether it gives | |
3971 * a signed or an unsigned result. | |
3972 */ | |
3973 if (row_bytes < 0) | |
3974 { | |
3975 char *ptr = png_voidcast(char*, first_row); | |
3976 ptr += (image->height-1) * (-row_bytes); | |
3977 first_row = png_voidcast(png_voidp, ptr); | |
3978 } | |
3979 | |
3980 display->first_row = first_row; | |
3981 display->row_bytes = row_bytes; | |
3982 } | |
3983 | |
3984 if (do_local_compose) | |
3985 { | |
3986 int result; | |
3987 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); | |
3988 | |
3989 display->local_row = row; | |
3990 result = png_safe_execute(image, png_image_read_composite, display); | |
3991 display->local_row = NULL; | |
3992 png_free(png_ptr, row); | |
3993 | |
3994 return result; | |
3995 } | |
3996 | |
3997 else if (do_local_background == 2) | |
3998 { | |
3999 int result; | |
4000 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); | |
4001 | |
4002 display->local_row = row; | |
4003 result = png_safe_execute(image, png_image_read_background, display); | |
4004 display->local_row = NULL; | |
4005 png_free(png_ptr, row); | |
4006 | |
4007 return result; | |
4008 } | |
4009 | |
4010 else | |
4011 { | |
4012 png_alloc_size_t row_bytes = display->row_bytes; | |
4013 | |
4014 while (--passes >= 0) | |
4015 { | |
4016 png_uint_32 y = image->height; | |
4017 png_bytep row = png_voidcast(png_bytep, display->first_row); | |
4018 | |
4019 while (y-- > 0) | |
4020 { | |
4021 png_read_row(png_ptr, row, NULL); | |
4022 row += row_bytes; | |
4023 } | |
4024 } | |
4025 | |
4026 return 1; | |
4027 } | |
4028 } | |
4029 | |
4030 int PNGAPI | |
4031 png_image_finish_read(png_imagep image, png_const_colorp background, | |
4032 void *buffer, png_int_32 row_stride, void *colormap) | |
4033 { | |
4034 if (image != NULL && image->version == PNG_IMAGE_VERSION) | |
4035 { | |
4036 png_uint_32 check; | |
4037 | |
4038 if (row_stride == 0) | |
4039 row_stride = PNG_IMAGE_ROW_STRIDE(*image); | |
4040 | |
4041 if (row_stride < 0) | |
4042 check = -row_stride; | |
4043 | |
4044 else | |
4045 check = row_stride; | |
4046 | |
4047 if (image->opaque != NULL && buffer != NULL && | |
4048 check >= PNG_IMAGE_ROW_STRIDE(*image)) | |
4049 { | |
4050 if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || | |
4051 (image->colormap_entries > 0 && colormap != NULL)) | |
4052 { | |
4053 int result; | |
4054 png_image_read_control display; | |
4055 | |
4056 memset(&display, 0, (sizeof display)); | |
4057 display.image = image; | |
4058 display.buffer = buffer; | |
4059 display.row_stride = row_stride; | |
4060 display.colormap = colormap; | |
4061 display.background = background; | |
4062 display.local_row = NULL; | |
4063 | |
4064 /* Choose the correct 'end' routine; for the color-map case all the | |
4065 * setup has already been done. | |
4066 */ | |
4067 if (image->format & PNG_FORMAT_FLAG_COLORMAP) | |
4068 result = | |
4069 png_safe_execute(image, png_image_read_colormap, &display) && | |
4070 png_safe_execute(image, png_image_read_colormapped, &display); | |
4071 | |
4072 else | |
4073 result = | |
4074 png_safe_execute(image, png_image_read_direct, &display); | |
4075 | |
4076 png_image_free(image); | |
4077 return result; | |
4078 } | |
4079 | |
4080 else | |
4081 return png_image_error(image, | |
4082 "png_image_finish_read[color-map]: no color-map"); | |
4083 } | |
4084 | |
4085 else | |
4086 return png_image_error(image, | |
4087 "png_image_finish_read: invalid argument"); | |
4088 } | |
4089 | |
4090 else if (image != NULL) | |
4091 return png_image_error(image, | |
4092 "png_image_finish_read: damaged PNG_IMAGE_VERSION"); | |
4093 | |
4094 return 0; | |
4095 } | |
4096 | |
4097 #endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ | |
4098 #endif /* PNG_READ_SUPPORTED */ |