17#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
21#ifdef PNG_READ_SUPPORTED
24PNG_FUNCTION(png_structp,PNGAPI
25png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
26 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
28#ifndef PNG_USER_MEM_SUPPORTED
29 png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
30 error_fn, warn_fn, NULL, NULL, NULL);
32 return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
33 warn_fn, NULL, NULL, NULL);
39PNG_FUNCTION(png_structp,PNGAPI
40png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
41 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
42 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
44 png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
45 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
50 png_ptr->mode = PNG_IS_READ_STRUCT;
55# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
56 png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
59# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
60 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
66 png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
74 png_set_read_fn(png_ptr, NULL, NULL);
81#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
91png_read_info(png_structrp png_ptr, png_inforp info_ptr)
93#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
97 png_debug(1,
"in png_read_info");
99 if (png_ptr == NULL || info_ptr == NULL)
103 png_read_sig(png_ptr, info_ptr);
107 png_uint_32 length = png_read_chunk_header(png_ptr);
108 png_uint_32 chunk_name = png_ptr->chunk_name;
113 if (chunk_name == png_IDAT)
115 if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
116 png_chunk_error(png_ptr,
"Missing IHDR before IDAT");
118 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
119 (png_ptr->mode & PNG_HAVE_PLTE) == 0)
120 png_chunk_error(png_ptr,
"Missing PLTE before IDAT");
122 else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
123 png_chunk_benign_error(png_ptr,
"Too many IDATs found");
125 png_ptr->mode |= PNG_HAVE_IDAT;
128 else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
130 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
131 png_ptr->mode |= PNG_AFTER_IDAT;
134 if (chunk_name == png_IHDR)
135 png_handle_chunk(png_ptr, info_ptr, length);
137 else if (chunk_name == png_IEND)
138 png_handle_chunk(png_ptr, info_ptr, length);
140#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
141 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
143 png_handle_unknown(png_ptr, info_ptr, length, keep);
145 if (chunk_name == png_PLTE)
146 png_ptr->mode |= PNG_HAVE_PLTE;
148 else if (chunk_name == png_IDAT)
150 png_ptr->idat_size = 0;
156 else if (chunk_name == png_IDAT)
158 png_ptr->idat_size = length;
163 png_handle_chunk(png_ptr, info_ptr, length);
170png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
172 png_debug(1,
"in png_read_update_info");
176 if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
178 png_read_start_row(png_ptr);
180# ifdef PNG_READ_TRANSFORMS_SUPPORTED
181 png_read_transform_info(png_ptr, info_ptr);
189 png_app_error(png_ptr,
190 "png_read_update_info/png_start_read_image: duplicate call");
194#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
201png_start_read_image(png_structrp png_ptr)
203 png_debug(1,
"in png_start_read_image");
207 if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
208 png_read_start_row(png_ptr);
212 png_app_error(png_ptr,
213 "png_start_read_image/png_read_update_info: duplicate call");
218#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
219#ifdef PNG_MNG_FEATURES_SUPPORTED
224png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
226 png_debug(1,
"in png_do_read_intrapixel");
229 (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
232 png_uint_32 row_width = row_info->width;
234 if (row_info->bit_depth == 8)
239 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
242 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
248 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
250 *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
251 *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
254 else if (row_info->bit_depth == 16)
259 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
262 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
268 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
270 png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);
271 png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
272 png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
273 png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
274 png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
275 *(rp ) = (png_byte)((red >> 8) & 0xff);
276 *(rp + 1) = (png_byte)(red & 0xff);
277 *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
278 *(rp + 5) = (png_byte)(blue & 0xff);
286png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
288 png_row_info row_info;
293 png_debug2(1,
"in png_read_row (row %lu, pass %d)",
294 (
unsigned long)png_ptr->row_number, png_ptr->pass);
299 if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
300 png_read_start_row(png_ptr);
303 row_info.width = png_ptr->iwidth;
304 row_info.color_type = png_ptr->color_type;
305 row_info.bit_depth = png_ptr->bit_depth;
306 row_info.channels = png_ptr->channels;
307 row_info.pixel_depth = png_ptr->pixel_depth;
308 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
310#ifdef PNG_WARNINGS_SUPPORTED
311 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
314#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
315 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
316 png_warning(png_ptr,
"PNG_READ_INVERT_SUPPORTED is not defined");
319#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
320 if ((png_ptr->transformations & PNG_FILLER) != 0)
321 png_warning(png_ptr,
"PNG_READ_FILLER_SUPPORTED is not defined");
324#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
325 !defined(PNG_READ_PACKSWAP_SUPPORTED)
326 if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
327 png_warning(png_ptr,
"PNG_READ_PACKSWAP_SUPPORTED is not defined");
330#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
331 if ((png_ptr->transformations & PNG_PACK) != 0)
332 png_warning(png_ptr,
"PNG_READ_PACK_SUPPORTED is not defined");
335#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
336 if ((png_ptr->transformations & PNG_SHIFT) != 0)
337 png_warning(png_ptr,
"PNG_READ_SHIFT_SUPPORTED is not defined");
340#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
341 if ((png_ptr->transformations & PNG_BGR) != 0)
342 png_warning(png_ptr,
"PNG_READ_BGR_SUPPORTED is not defined");
345#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
346 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
347 png_warning(png_ptr,
"PNG_READ_SWAP_SUPPORTED is not defined");
352#ifdef PNG_READ_INTERLACING_SUPPORTED
359 if (png_ptr->interlaced != 0 &&
360 (png_ptr->transformations & PNG_INTERLACE) != 0)
362 switch (png_ptr->pass)
365 if (png_ptr->row_number & 0x07)
368 png_combine_row(png_ptr, dsp_row, 1);
369 png_read_finish_row(png_ptr);
375 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
378 png_combine_row(png_ptr, dsp_row, 1);
380 png_read_finish_row(png_ptr);
386 if ((png_ptr->row_number & 0x07) != 4)
388 if (dsp_row != NULL && (png_ptr->row_number & 4))
389 png_combine_row(png_ptr, dsp_row, 1);
391 png_read_finish_row(png_ptr);
397 if ((png_ptr->row_number & 3) || png_ptr->width < 3)
400 png_combine_row(png_ptr, dsp_row, 1);
402 png_read_finish_row(png_ptr);
408 if ((png_ptr->row_number & 3) != 2)
410 if (dsp_row != NULL && (png_ptr->row_number & 2))
411 png_combine_row(png_ptr, dsp_row, 1);
413 png_read_finish_row(png_ptr);
419 if ((png_ptr->row_number & 1) || png_ptr->width < 2)
422 png_combine_row(png_ptr, dsp_row, 1);
424 png_read_finish_row(png_ptr);
431 if ((png_ptr->row_number & 1) == 0)
433 png_read_finish_row(png_ptr);
441 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
442 png_error(png_ptr,
"Invalid attempt to read row data");
445 png_ptr->row_buf[0]=255;
446 png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
448 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
450 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
451 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
452 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
454 png_error(png_ptr,
"bad adaptive filter value");
462 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
464#ifdef PNG_MNG_FEATURES_SUPPORTED
465 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
466 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
469 png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
473#ifdef PNG_READ_TRANSFORMS_SUPPORTED
474 if (png_ptr->transformations
475# ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
476 || png_ptr->num_palette_max >= 0
479 png_do_read_transformations(png_ptr, &row_info);
483 if (png_ptr->transformed_pixel_depth == 0)
485 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
486 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
487 png_error(png_ptr,
"sequential row overflow");
490 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
491 png_error(png_ptr,
"internal sequential row size calculation error");
493#ifdef PNG_READ_INTERLACING_SUPPORTED
495 if (png_ptr->interlaced != 0 &&
496 (png_ptr->transformations & PNG_INTERLACE) != 0)
498 if (png_ptr->pass < 6)
499 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
500 png_ptr->transformations);
503 png_combine_row(png_ptr, dsp_row, 1);
506 png_combine_row(png_ptr, row, 0);
513 png_combine_row(png_ptr, row, -1);
516 png_combine_row(png_ptr, dsp_row, -1);
518 png_read_finish_row(png_ptr);
520 if (png_ptr->read_row_fn != NULL)
521 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
526#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
552png_read_rows(png_structrp png_ptr, png_bytepp row,
553 png_bytepp display_row, png_uint_32 num_rows)
559 png_debug(1,
"in png_read_rows");
566 if (rp != NULL && dp != NULL)
567 for (i = 0; i < num_rows; i++)
569 png_bytep rptr = *rp++;
570 png_bytep dptr = *dp++;
572 png_read_row(png_ptr, rptr, dptr);
576 for (i = 0; i < num_rows; i++)
578 png_bytep rptr = *rp;
579 png_read_row(png_ptr, rptr, NULL);
584 for (i = 0; i < num_rows; i++)
586 png_bytep dptr = *dp;
587 png_read_row(png_ptr, NULL, dptr);
593#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
607png_read_image(png_structrp png_ptr, png_bytepp image)
609 png_uint_32 i, image_height;
613 png_debug(1,
"in png_read_image");
618#ifdef PNG_READ_INTERLACING_SUPPORTED
619 if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
621 pass = png_set_interlace_handling(png_ptr);
623 png_start_read_image(png_ptr);
627 if (png_ptr->interlaced != 0 &&
628 (png_ptr->transformations & PNG_INTERLACE) == 0)
634 png_warning(png_ptr,
"Interlace handling should be turned on when "
635 "using png_read_image");
637 png_ptr->num_rows = png_ptr->height;
643 pass = png_set_interlace_handling(png_ptr);
646 if (png_ptr->interlaced)
648 "Cannot read interlaced image -- interlace handler disabled");
653 image_height=png_ptr->height;
655 for (j = 0; j < pass; j++)
658 for (i = 0; i < image_height; i++)
660 png_read_row(png_ptr, *rp, NULL);
667#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
673png_read_end(png_structrp png_ptr, png_inforp info_ptr)
675#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
679 png_debug(1,
"in png_read_end");
687#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
688 if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0)
690 png_read_finish_IDAT(png_ptr);
692#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
694 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
695 png_ptr->num_palette_max >= png_ptr->num_palette)
696 png_benign_error(png_ptr,
"Read palette index exceeding num_palette");
701 png_uint_32 length = png_read_chunk_header(png_ptr);
702 png_uint_32 chunk_name = png_ptr->chunk_name;
704 if (chunk_name != png_IDAT)
709 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT;
712 if (chunk_name == png_IEND)
713 png_handle_chunk(png_ptr, info_ptr, length);
715 else if (chunk_name == png_IHDR)
716 png_handle_chunk(png_ptr, info_ptr, length);
718 else if (info_ptr == NULL)
719 png_crc_finish(png_ptr, length);
721#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
722 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
724 if (chunk_name == png_IDAT)
726 if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
727 || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
728 png_benign_error(png_ptr,
".Too many IDATs found");
730 png_handle_unknown(png_ptr, info_ptr, length, keep);
731 if (chunk_name == png_PLTE)
732 png_ptr->mode |= PNG_HAVE_PLTE;
736 else if (chunk_name == png_IDAT)
744 if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
745 || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
746 png_benign_error(png_ptr,
"..Too many IDATs found");
748 png_crc_finish(png_ptr, length);
752 png_handle_chunk(png_ptr, info_ptr, length);
753 }
while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
759png_read_destroy(png_structrp png_ptr)
761 png_debug(1,
"in png_read_destroy");
763#ifdef PNG_READ_GAMMA_SUPPORTED
764 png_destroy_gamma_table(png_ptr);
767 png_free(png_ptr, png_ptr->big_row_buf);
768 png_ptr->big_row_buf = NULL;
769 png_free(png_ptr, png_ptr->big_prev_row);
770 png_ptr->big_prev_row = NULL;
771 png_free(png_ptr, png_ptr->read_buffer);
772 png_ptr->read_buffer = NULL;
774#ifdef PNG_READ_QUANTIZE_SUPPORTED
775 png_free(png_ptr, png_ptr->palette_lookup);
776 png_ptr->palette_lookup = NULL;
777 png_free(png_ptr, png_ptr->quantize_index);
778 png_ptr->quantize_index = NULL;
781 if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)
783 png_zfree(png_ptr, png_ptr->palette);
784 png_ptr->palette = NULL;
786 png_ptr->free_me &= ~PNG_FREE_PLTE;
788#if defined(PNG_tRNS_SUPPORTED) || \
789 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
790 if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)
792 png_free(png_ptr, png_ptr->trans_alpha);
793 png_ptr->trans_alpha = NULL;
795 png_ptr->free_me &= ~PNG_FREE_TRNS;
798 inflateEnd(&png_ptr->zstream);
800#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
801 png_free(png_ptr, png_ptr->save_buffer);
802 png_ptr->save_buffer = NULL;
805#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \
806 defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
807 png_free(png_ptr, png_ptr->unknown_chunk.data);
808 png_ptr->unknown_chunk.data = NULL;
811#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
812 png_free(png_ptr, png_ptr->chunk_list);
813 png_ptr->chunk_list = NULL;
816#if defined(PNG_READ_EXPAND_SUPPORTED) && \
817 (defined(PNG_ARM_NEON_IMPLEMENTATION) || \
818 defined(PNG_RISCV_RVV_IMPLEMENTATION))
819 png_free(png_ptr, png_ptr->riffled_palette);
820 png_ptr->riffled_palette = NULL;
831png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
832 png_infopp end_info_ptr_ptr)
834 png_structrp png_ptr = NULL;
836 png_debug(1,
"in png_destroy_read_struct");
838 if (png_ptr_ptr != NULL)
839 png_ptr = *png_ptr_ptr;
848 png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
849 png_destroy_info_struct(png_ptr, info_ptr_ptr);
852 png_read_destroy(png_ptr);
853 png_destroy_png_struct(png_ptr);
857png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
862 png_ptr->read_row_fn = read_row_fn;
866#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
867#ifdef PNG_INFO_IMAGE_SUPPORTED
869png_read_png(png_structrp png_ptr, png_inforp info_ptr,
870 int transforms, voidp params)
872 png_debug(1,
"in png_read_png");
874 if (png_ptr == NULL || info_ptr == NULL)
880 png_read_info(png_ptr, info_ptr);
881 if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
882 png_error(png_ptr,
"Image is too high to process with png_read_png()");
893 if ((transforms & PNG_TRANSFORM_SCALE_16) != 0)
897#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
898 png_set_scale_16(png_ptr);
900 png_app_error(png_ptr,
"PNG_TRANSFORM_SCALE_16 not supported");
907 if ((transforms & PNG_TRANSFORM_STRIP_16) != 0)
908#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
909 png_set_strip_16(png_ptr);
911 png_app_error(png_ptr,
"PNG_TRANSFORM_STRIP_16 not supported");
917 if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0)
918#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
919 png_set_strip_alpha(png_ptr);
921 png_app_error(png_ptr,
"PNG_TRANSFORM_STRIP_ALPHA not supported");
927 if ((transforms & PNG_TRANSFORM_PACKING) != 0)
928#ifdef PNG_READ_PACK_SUPPORTED
929 png_set_packing(png_ptr);
931 png_app_error(png_ptr,
"PNG_TRANSFORM_PACKING not supported");
937 if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
938#ifdef PNG_READ_PACKSWAP_SUPPORTED
939 png_set_packswap(png_ptr);
941 png_app_error(png_ptr,
"PNG_TRANSFORM_PACKSWAP not supported");
949 if ((transforms & PNG_TRANSFORM_EXPAND) != 0)
950#ifdef PNG_READ_EXPAND_SUPPORTED
951 png_set_expand(png_ptr);
953 png_app_error(png_ptr,
"PNG_TRANSFORM_EXPAND not supported");
961 if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
962#ifdef PNG_READ_INVERT_SUPPORTED
963 png_set_invert_mono(png_ptr);
965 png_app_error(png_ptr,
"PNG_TRANSFORM_INVERT_MONO not supported");
972 if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
973#ifdef PNG_READ_SHIFT_SUPPORTED
974 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
975 png_set_shift(png_ptr, &info_ptr->sig_bit);
977 png_app_error(png_ptr,
"PNG_TRANSFORM_SHIFT not supported");
981 if ((transforms & PNG_TRANSFORM_BGR) != 0)
982#ifdef PNG_READ_BGR_SUPPORTED
983 png_set_bgr(png_ptr);
985 png_app_error(png_ptr,
"PNG_TRANSFORM_BGR not supported");
989 if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
990#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
991 png_set_swap_alpha(png_ptr);
993 png_app_error(png_ptr,
"PNG_TRANSFORM_SWAP_ALPHA not supported");
997 if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
998#ifdef PNG_READ_SWAP_SUPPORTED
999 png_set_swap(png_ptr);
1001 png_app_error(png_ptr,
"PNG_TRANSFORM_SWAP_ENDIAN not supported");
1006 if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
1007#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1008 png_set_invert_alpha(png_ptr);
1010 png_app_error(png_ptr,
"PNG_TRANSFORM_INVERT_ALPHA not supported");
1015 if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0)
1016#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1017 png_set_gray_to_rgb(png_ptr);
1019 png_app_error(png_ptr,
"PNG_TRANSFORM_GRAY_TO_RGB not supported");
1023 if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0)
1024#ifdef PNG_READ_EXPAND_16_SUPPORTED
1025 png_set_expand_16(png_ptr);
1027 png_app_error(png_ptr,
"PNG_TRANSFORM_EXPAND_16 not supported");
1035 (void)png_set_interlace_handling(png_ptr);
1041 png_read_update_info(png_ptr, info_ptr);
1045 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1046 if (info_ptr->row_pointers == NULL)
1050 info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
1051 info_ptr->height * (sizeof (png_bytep))));
1053 for (iptr=0; iptr<info_ptr->height; iptr++)
1054 info_ptr->row_pointers[iptr] = NULL;
1056 info_ptr->free_me |= PNG_FREE_ROWS;
1058 for (iptr = 0; iptr < info_ptr->height; iptr++)
1059 info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
1060 png_malloc(png_ptr, info_ptr->rowbytes));
1063 png_read_image(png_ptr, info_ptr->row_pointers);
1064 info_ptr->valid |= PNG_INFO_IDAT;
1067 png_read_end(png_ptr, info_ptr);
1074#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
1092#define PNG_CMAP_NONE 0
1093#define PNG_CMAP_GA 1
1094#define PNG_CMAP_TRANS 2
1095#define PNG_CMAP_RGB 3
1096#define PNG_CMAP_RGB_ALPHA 4
1099#define PNG_CMAP_NONE_BACKGROUND 256
1100#define PNG_CMAP_GA_BACKGROUND 231
1101#define PNG_CMAP_TRANS_BACKGROUND 254
1102#define PNG_CMAP_RGB_BACKGROUND 256
1103#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
1110 png_int_32 row_stride;
1112 png_const_colorp background;
1114 png_voidp local_row;
1115 png_voidp first_row;
1116 ptrdiff_t row_bytes;
1118 png_fixed_point gamma_to_linear;
1119 int colormap_processing;
1128png_image_read_init(png_imagep image)
1130 if (image->opaque == NULL)
1132 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
1133 png_safe_error, png_safe_warning);
1138 memset(image, 0, (
sizeof *image));
1139 image->version = PNG_IMAGE_VERSION;
1141 if (png_ptr != NULL)
1143 png_infop info_ptr = png_create_info_struct(png_ptr);
1145 if (info_ptr != NULL)
1147 png_controlp control = png_voidcast(png_controlp,
1148 png_malloc_warn(png_ptr, (
sizeof *control)));
1150 if (control != NULL)
1152 memset(control, 0, (
sizeof *control));
1154 control->png_ptr = png_ptr;
1155 control->info_ptr = info_ptr;
1156 control->for_write = 0;
1158 image->opaque = control;
1163 png_destroy_info_struct(png_ptr, &info_ptr);
1166 png_destroy_read_struct(&png_ptr, NULL, NULL);
1169 return png_image_error(image,
"png_image_read: out of memory");
1172 return png_image_error(image,
"png_image_read: opaque pointer not NULL");
1177png_image_format(png_structrp png_ptr)
1179 png_uint_32 format = 0;
1181 if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
1182 format |= PNG_FORMAT_FLAG_COLOR;
1184 if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
1185 format |= PNG_FORMAT_FLAG_ALPHA;
1192 else if (png_ptr->num_trans > 0)
1193 format |= PNG_FORMAT_FLAG_ALPHA;
1195 if (png_ptr->bit_depth == 16)
1196 format |= PNG_FORMAT_FLAG_LINEAR;
1198 if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0)
1199 format |= PNG_FORMAT_FLAG_COLORMAP;
1205chromaticities_match_sRGB(
const png_xy *xy)
1207# define sRGB_TOLERANCE 1000
1208 static const png_xy sRGB_xy =
1217 if (PNG_OUT_OF_RANGE(xy->whitex, sRGB_xy.whitex,sRGB_TOLERANCE) ||
1218 PNG_OUT_OF_RANGE(xy->whitey, sRGB_xy.whitey,sRGB_TOLERANCE) ||
1219 PNG_OUT_OF_RANGE(xy->redx, sRGB_xy.redx, sRGB_TOLERANCE) ||
1220 PNG_OUT_OF_RANGE(xy->redy, sRGB_xy.redy, sRGB_TOLERANCE) ||
1221 PNG_OUT_OF_RANGE(xy->greenx, sRGB_xy.greenx,sRGB_TOLERANCE) ||
1222 PNG_OUT_OF_RANGE(xy->greeny, sRGB_xy.greeny,sRGB_TOLERANCE) ||
1223 PNG_OUT_OF_RANGE(xy->bluex, sRGB_xy.bluex, sRGB_TOLERANCE) ||
1224 PNG_OUT_OF_RANGE(xy->bluey, sRGB_xy.bluey, sRGB_TOLERANCE))
1235png_gamma_not_sRGB(png_fixed_point g)
1238 if (g < PNG_LIB_GAMMA_MIN || g > PNG_LIB_GAMMA_MAX)
1241 return png_gamma_significant((g * 11 + 2)/5 );
1249png_image_is_not_sRGB(png_const_structrp png_ptr)
1260 if (png_has_chunk(png_ptr, cICP) || png_has_chunk(png_ptr, mDCV))
1261 return !chromaticities_match_sRGB(&png_ptr->chromaticities);
1264 if (png_has_chunk(png_ptr, sRGB))
1268 if (png_has_chunk(png_ptr, cHRM))
1269 return !chromaticities_match_sRGB(&png_ptr->chromaticities);
1276png_image_read_header(png_voidp argument)
1278 png_imagep image = png_voidcast(png_imagep, argument);
1279 png_structrp png_ptr = image->opaque->png_ptr;
1280 png_inforp info_ptr = image->opaque->info_ptr;
1282#ifdef PNG_BENIGN_ERRORS_SUPPORTED
1283 png_set_benign_errors(png_ptr, 1);
1285 png_read_info(png_ptr, info_ptr);
1288 image->width = png_ptr->width;
1289 image->height = png_ptr->height;
1292 png_uint_32 format = png_image_format(png_ptr);
1294 image->format = format;
1300 if ((format & PNG_FORMAT_FLAG_COLOR) != 0 &&
1301 png_image_is_not_sRGB(png_ptr))
1302 image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
1309 png_uint_32 cmap_entries;
1311 switch (png_ptr->color_type)
1313 case PNG_COLOR_TYPE_GRAY:
1314 cmap_entries = 1U << png_ptr->bit_depth;
1317 case PNG_COLOR_TYPE_PALETTE:
1318 cmap_entries = (png_uint_32)png_ptr->num_palette;
1326 if (cmap_entries > 256)
1329 image->colormap_entries = cmap_entries;
1335#ifdef PNG_STDIO_SUPPORTED
1337png_image_begin_read_from_stdio(png_imagep image, FILE *file)
1339 if (image != NULL && image->version == PNG_IMAGE_VERSION)
1343 if (png_image_read_init(image) != 0)
1349 image->opaque->png_ptr->io_ptr = file;
1350 return png_safe_execute(image, png_image_read_header, image);
1355 return png_image_error(image,
1356 "png_image_begin_read_from_stdio: invalid argument");
1359 else if (image != NULL)
1360 return png_image_error(image,
1361 "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
1367png_image_begin_read_from_file(png_imagep image,
const char *file_name)
1369 if (image != NULL && image->version == PNG_IMAGE_VERSION)
1371 if (file_name != NULL)
1373 FILE *fp = fopen(file_name,
"rb");
1377 if (png_image_read_init(image) != 0)
1379 image->opaque->png_ptr->io_ptr = fp;
1380 image->opaque->owned_file = 1;
1381 return png_safe_execute(image, png_image_read_header, image);
1389 return png_image_error(image, strerror(errno));
1393 return png_image_error(image,
1394 "png_image_begin_read_from_file: invalid argument");
1397 else if (image != NULL)
1398 return png_image_error(image,
1399 "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
1406png_image_memory_read(png_structp png_ptr, png_bytep out,
size_t need)
1408 if (png_ptr != NULL)
1410 png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
1413 png_controlp cp = image->opaque;
1416 png_const_bytep memory = cp->memory;
1417 size_t size = cp->size;
1419 if (memory != NULL && size >= need)
1421 memcpy(out, memory, need);
1422 cp->memory = memory + need;
1423 cp->size = size - need;
1427 png_error(png_ptr,
"read beyond end of data");
1431 png_error(png_ptr,
"invalid memory read");
1435int PNGAPI png_image_begin_read_from_memory(png_imagep image,
1436 png_const_voidp memory,
size_t size)
1438 if (image != NULL && image->version == PNG_IMAGE_VERSION)
1440 if (memory != NULL && size > 0)
1442 if (png_image_read_init(image) != 0)
1448 image->opaque->memory = png_voidcast(png_const_bytep, memory);
1449 image->opaque->size = size;
1450 image->opaque->png_ptr->io_ptr = image;
1451 image->opaque->png_ptr->read_data_fn = png_image_memory_read;
1453 return png_safe_execute(image, png_image_read_header, image);
1458 return png_image_error(image,
1459 "png_image_begin_read_from_memory: invalid argument");
1462 else if (image != NULL)
1463 return png_image_error(image,
1464 "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
1472#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1474png_image_skip_unused_chunks(png_structrp png_ptr)
1493 static const png_byte chunks_to_process[] = {
1494 98, 75, 71, 68,
'\0',
1495 99, 72, 82, 77,
'\0',
1496 99, 73, 67, 80,
'\0',
1497 103, 65, 77, 65,
'\0',
1498 109, 68, 67, 86,
'\0',
1499 115, 66, 73, 84,
'\0',
1500 115, 82, 71, 66,
'\0',
1506 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
1510 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
1511 chunks_to_process, (
int)(
sizeof chunks_to_process)/5);
1515# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
1517# define PNG_SKIP_CHUNKS(p) ((void)0)
1524#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
1530 png_structrp png_ptr = display->image->opaque->png_ptr;
1531 png_fixed_point g = png_resolve_file_gamma(png_ptr);
1537 png_error(png_ptr,
"internal: default gamma not set");
1539 if (png_gamma_significant(g) != 0)
1541 if (png_gamma_not_sRGB(g) != 0)
1543 display->file_encoding = P_FILE;
1544 display->gamma_to_linear = png_reciprocal(g);
1548 display->file_encoding = P_sRGB;
1552 display->file_encoding = P_LINEAR8;
1558 if (encoding == P_FILE)
1559 encoding = display->file_encoding;
1561 if (encoding == P_NOTSET)
1563 set_file_encoding(display);
1564 encoding = display->file_encoding;
1570 value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
1574 value = png_sRGB_table[value];
1586 png_error(display->image->opaque->png_ptr,
1587 "unexpected encoding (internal error)");
1596 png_uint_32 foreground,
int foreground_encoding, png_uint_32 alpha,
1597 png_uint_32 background,
int encoding)
1604 png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
1605 png_uint_32 b = decode_gamma(display, background, encoding);
1610 f = f * alpha + b * (255-alpha);
1612 if (encoding == P_LINEAR)
1619 f = (f+32768) >> 16;
1623 f = PNG_sRGB_FROM_LINEAR(f);
1633 png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
1634 png_uint_32 alpha,
int encoding)
1636 png_imagep image = display->image;
1637 int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
1639 int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
1640 (red != green || green != blue);
1643 png_error(image->opaque->png_ptr,
"color-map index out of range");
1648 if (encoding == P_FILE)
1650 if (display->file_encoding == P_NOTSET)
1651 set_file_encoding(display);
1656 encoding = display->file_encoding;
1659 if (encoding == P_FILE)
1661 png_fixed_point g = display->gamma_to_linear;
1663 red = png_gamma_16bit_correct(red*257, g);
1664 green = png_gamma_16bit_correct(green*257, g);
1665 blue = png_gamma_16bit_correct(blue*257, g);
1667 if (convert_to_Y != 0 || output_encoding == P_LINEAR)
1670 encoding = P_LINEAR;
1675 red = PNG_sRGB_FROM_LINEAR(red * 255);
1676 green = PNG_sRGB_FROM_LINEAR(green * 255);
1677 blue = PNG_sRGB_FROM_LINEAR(blue * 255);
1682 else if (encoding == P_LINEAR8)
1691 encoding = P_LINEAR;
1694 else if (encoding == P_sRGB &&
1695 (convert_to_Y != 0 || output_encoding == P_LINEAR))
1700 red = png_sRGB_table[red];
1701 green = png_sRGB_table[green];
1702 blue = png_sRGB_table[blue];
1704 encoding = P_LINEAR;
1708 if (encoding == P_LINEAR)
1710 if (convert_to_Y != 0)
1713 png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green +
1714 (png_uint_32)2366 * blue;
1716 if (output_encoding == P_LINEAR)
1717 y = (y + 16384) >> 15;
1724 y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
1725 alpha = PNG_DIV257(alpha);
1729 blue = red = green = y;
1732 else if (output_encoding == P_sRGB)
1734 red = PNG_sRGB_FROM_LINEAR(red * 255);
1735 green = PNG_sRGB_FROM_LINEAR(green * 255);
1736 blue = PNG_sRGB_FROM_LINEAR(blue * 255);
1737 alpha = PNG_DIV257(alpha);
1742 if (encoding != output_encoding)
1743 png_error(image->opaque->png_ptr,
"bad encoding (internal error)");
1747# ifdef PNG_FORMAT_AFIRST_SUPPORTED
1748 int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
1749 (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
1753# ifdef PNG_FORMAT_BGR_SUPPORTED
1754 int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
1759 if (output_encoding == P_LINEAR)
1761 png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
1763 entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
1769 switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
1772 entry[afirst ? 0 : 3] = (png_uint_16)alpha;
1780 blue = (blue * alpha + 32767U)/65535U;
1781 green = (green * alpha + 32767U)/65535U;
1782 red = (red * alpha + 32767U)/65535U;
1786 red = green = blue = 0;
1788 entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
1789 entry[afirst + 1] = (png_uint_16)green;
1790 entry[afirst + bgr] = (png_uint_16)red;
1794 entry[1 ^ afirst] = (png_uint_16)alpha;
1801 green = (green * alpha + 32767U)/65535U;
1806 entry[afirst] = (png_uint_16)green;
1816 png_bytep entry = png_voidcast(png_bytep, display->colormap);
1818 entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
1820 switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
1823 entry[afirst ? 0 : 3] = (png_byte)alpha;
1826 entry[afirst + (2 ^ bgr)] = (png_byte)blue;
1827 entry[afirst + 1] = (png_byte)green;
1828 entry[afirst + bgr] = (png_byte)red;
1832 entry[1 ^ afirst] = (png_byte)alpha;
1835 entry[afirst] = (png_byte)green;
1857 for (i=0; i<256; ++i)
1858 png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
1868 for (i=0; i<256; ++i)
1869 png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
1873#define PNG_GRAY_COLORMAP_ENTRIES 256
1907 unsigned int gray = (i * 256 + 115) / 231;
1908 png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
1914 png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
1921 png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
1928#define PNG_GA_COLORMAP_ENTRIES 256
1936 for (i=r=0; r<6; ++r)
1945 png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
1953#define PNG_RGB_COLORMAP_ENTRIES 216
1956#define PNG_RGB_INDEX(r,g,b) \
1957 ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
1960png_image_read_colormap(png_voidp argument)
1964 png_imagep image = display->image;
1966 png_structrp png_ptr = image->opaque->png_ptr;
1967 png_uint_32 output_format = image->format;
1968 int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
1971 unsigned int cmap_entries;
1972 unsigned int output_processing;
1973 unsigned int data_encoding = P_NOTSET;
1978 unsigned int background_index = 256;
1979 png_uint_32 back_r, back_g, back_b;
1982 int expand_tRNS = 0;
1989 if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
1990 png_ptr->num_trans > 0) &&
1991 ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) )
1993 if (output_encoding == P_LINEAR)
1994 back_b = back_g = back_r = 0;
1996 else if (display->background == NULL )
1998 "background color must be supplied to remove alpha/transparency");
2006 back_g = display->background->green;
2007 if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0)
2009 back_r = display->background->red;
2010 back_b = display->background->blue;
2013 back_b = back_r = back_g;
2017 else if (output_encoding == P_LINEAR)
2018 back_b = back_r = back_g = 65535;
2021 back_b = back_r = back_g = 255;
2032 if (png_ptr->bit_depth == 16 &&
2033 (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
2034 png_ptr->default_gamma = PNG_GAMMA_LINEAR;
2037 png_ptr->default_gamma = PNG_GAMMA_sRGB_INVERSE;
2044 switch (png_ptr->color_type)
2046 case PNG_COLOR_TYPE_GRAY:
2047 if (png_ptr->bit_depth <= 8)
2052 unsigned int step, i, val, trans = 256, back_alpha = 0;
2054 cmap_entries = 1U << png_ptr->bit_depth;
2055 if (cmap_entries > image->colormap_entries)
2056 png_error(png_ptr,
"gray[8] color-map: too few entries");
2058 step = 255 / (cmap_entries - 1);
2059 output_processing = PNG_CMAP_NONE;
2064 if (png_ptr->num_trans > 0)
2066 trans = png_ptr->trans_color.gray;
2068 if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
2069 back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
2079 for (i=val=0; i<cmap_entries; ++i, val += step)
2086 png_create_colormap_entry(display, i, val, val, val, 255,
2098 png_create_colormap_entry(display, i, back_r, back_g, back_b,
2099 back_alpha, output_encoding);
2103 data_encoding = P_FILE;
2110 if (png_ptr->bit_depth < 8)
2111 png_set_packing(png_ptr);
2132 data_encoding = P_sRGB;
2134 if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
2135 png_error(png_ptr,
"gray[16] color-map: too few entries");
2137 cmap_entries = (
unsigned int)make_gray_colormap(display);
2139 if (png_ptr->num_trans > 0)
2141 unsigned int back_alpha;
2143 if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
2148 if (back_r == back_g && back_g == back_b)
2154 png_uint_32 gray = back_g;
2156 if (output_encoding == P_LINEAR)
2158 gray = PNG_sRGB_FROM_LINEAR(gray * 255);
2163 png_create_colormap_entry(display, gray, back_g, back_g,
2164 back_g, 65535, P_LINEAR);
2171 c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
2177 png_set_background_fixed(png_ptr, &c,
2178 PNG_BACKGROUND_GAMMA_SCREEN, 0,
2181 output_processing = PNG_CMAP_NONE;
2190 back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
2202 output_processing = PNG_CMAP_TRANS;
2203 background_index = 254;
2208 png_create_colormap_entry(display, 254, back_r, back_g, back_b,
2209 back_alpha, output_encoding);
2213 output_processing = PNG_CMAP_NONE;
2217 case PNG_COLOR_TYPE_GRAY_ALPHA:
2228 data_encoding = P_sRGB;
2230 if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
2232 if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
2233 png_error(png_ptr,
"gray+alpha color-map: too few entries");
2235 cmap_entries = (
unsigned int)make_ga_colormap(display);
2237 background_index = PNG_CMAP_GA_BACKGROUND;
2238 output_processing = PNG_CMAP_GA;
2259 if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
2260 (back_r == back_g && back_g == back_b))
2264 png_uint_32 gray = back_g;
2266 if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
2267 png_error(png_ptr,
"gray-alpha color-map: too few entries");
2269 cmap_entries = (
unsigned int)make_gray_colormap(display);
2271 if (output_encoding == P_LINEAR)
2273 gray = PNG_sRGB_FROM_LINEAR(gray * 255);
2276 png_create_colormap_entry(display, gray, back_g, back_g,
2277 back_g, 65535, P_LINEAR);
2284 c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
2286 png_set_background_fixed(png_ptr, &c,
2287 PNG_BACKGROUND_GAMMA_SCREEN, 0,
2290 output_processing = PNG_CMAP_NONE;
2300 if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
2301 png_error(png_ptr,
"ga-alpha color-map: too few entries");
2306 png_uint_32 gray = (i * 256 + 115) / 231;
2307 png_create_colormap_entry(display, i++, gray, gray, gray,
2314 background_index = i;
2315 png_create_colormap_entry(display, i++, back_r, back_g, back_b,
2321 output_encoding == P_LINEAR ? 65535U : 255U,
2333 if (output_encoding == P_sRGB)
2339 back_r = png_sRGB_table[back_r];
2340 back_g = png_sRGB_table[back_g];
2341 back_b = png_sRGB_table[back_b];
2351 png_uint_32 alpha = 51 * a;
2352 png_uint_32 back_rx = (255-alpha) * back_r;
2353 png_uint_32 back_gx = (255-alpha) * back_g;
2354 png_uint_32 back_bx = (255-alpha) * back_b;
2358 png_uint_32 gray = png_sRGB_table[g*51] * alpha;
2360 png_create_colormap_entry(display, i++,
2361 PNG_sRGB_FROM_LINEAR(gray + back_rx),
2362 PNG_sRGB_FROM_LINEAR(gray + back_gx),
2363 PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
2368 output_processing = PNG_CMAP_GA;
2373 case PNG_COLOR_TYPE_RGB:
2374 case PNG_COLOR_TYPE_RGB_ALPHA:
2378 if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
2388 png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
2390 data_encoding = P_sRGB;
2395 if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
2396 png_ptr->num_trans > 0) &&
2397 (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
2405 if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
2406 png_error(png_ptr,
"rgb[ga] color-map: too few entries");
2408 cmap_entries = (
unsigned int)make_ga_colormap(display);
2409 background_index = PNG_CMAP_GA_BACKGROUND;
2410 output_processing = PNG_CMAP_GA;
2415 const png_fixed_point gamma = png_resolve_file_gamma(png_ptr);
2421 if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
2422 png_error(png_ptr,
"rgb[gray] color-map: too few entries");
2435 if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
2436 png_ptr->num_trans > 0) &&
2437 png_gamma_not_sRGB(gamma) != 0)
2439 cmap_entries = (
unsigned int)make_gray_file_colormap(display);
2440 data_encoding = P_FILE;
2444 cmap_entries = (
unsigned int)make_gray_colormap(display);
2448 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
2449 png_ptr->num_trans > 0)
2452 png_uint_32 gray = back_g;
2459 if (data_encoding == P_FILE)
2466 if (output_encoding == P_sRGB)
2467 gray = png_sRGB_table[gray];
2469 gray = PNG_DIV257(png_gamma_16bit_correct(gray, gamma));
2475 png_create_colormap_entry(display, gray, back_g, back_g,
2476 back_g, 0, output_encoding);
2479 else if (output_encoding == P_LINEAR)
2481 gray = PNG_sRGB_FROM_LINEAR(gray * 255);
2485 png_create_colormap_entry(display, gray, back_g, back_g,
2486 back_g, 0, P_LINEAR);
2493 c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
2500 png_set_background_fixed(png_ptr, &c,
2501 PNG_BACKGROUND_GAMMA_SCREEN, 0,
2505 output_processing = PNG_CMAP_NONE;
2516 data_encoding = P_sRGB;
2519 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
2520 png_ptr->num_trans > 0)
2525 if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
2529 if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
2530 png_error(png_ptr,
"rgb+alpha color-map: too few entries");
2532 cmap_entries = (
unsigned int)make_rgb_colormap(display);
2535 png_create_colormap_entry(display, cmap_entries, 255, 255,
2541 background_index = cmap_entries++;
2544 for (r=0; r<256; r = (r << 1) | 0x7f)
2548 for (g=0; g<256; g = (g << 1) | 0x7f)
2555 for (b=0; b<256; b = (b << 1) | 0x7f)
2556 png_create_colormap_entry(display, cmap_entries++,
2557 r, g, b, 128, P_sRGB);
2562 output_processing = PNG_CMAP_RGB_ALPHA;
2574 unsigned int sample_size =
2575 PNG_IMAGE_SAMPLE_SIZE(output_format);
2576 png_uint_32 r, g, b;
2578 if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
2579 png_error(png_ptr,
"rgb-alpha color-map: too few entries");
2581 cmap_entries = (
unsigned int)make_rgb_colormap(display);
2583 png_create_colormap_entry(display, cmap_entries, back_r,
2584 back_g, back_b, 0, output_encoding);
2586 if (output_encoding == P_LINEAR)
2588 r = PNG_sRGB_FROM_LINEAR(back_r * 255);
2589 g = PNG_sRGB_FROM_LINEAR(back_g * 255);
2590 b = PNG_sRGB_FROM_LINEAR(back_b * 255);
2605 if (memcmp((png_const_bytep)display->colormap +
2606 sample_size * cmap_entries,
2607 (png_const_bytep)display->colormap +
2608 sample_size * PNG_RGB_INDEX(r,g,b),
2612 background_index = cmap_entries++;
2617 for (r=0; r<256; r = (r << 1) | 0x7f)
2619 for (g=0; g<256; g = (g << 1) | 0x7f)
2624 for (b=0; b<256; b = (b << 1) | 0x7f)
2625 png_create_colormap_entry(display, cmap_entries++,
2626 png_colormap_compose(display, r, P_sRGB, 128,
2627 back_r, output_encoding),
2628 png_colormap_compose(display, g, P_sRGB, 128,
2629 back_g, output_encoding),
2630 png_colormap_compose(display, b, P_sRGB, 128,
2631 back_b, output_encoding),
2632 0, output_encoding);
2637 output_processing = PNG_CMAP_RGB_ALPHA;
2645 c.red = (png_uint_16)back_r;
2646 c.gray = c.green = (png_uint_16)back_g;
2647 c.blue = (png_uint_16)back_b;
2649 png_set_background_fixed(png_ptr, &c,
2650 PNG_BACKGROUND_GAMMA_SCREEN, 0,
2653 output_processing = PNG_CMAP_RGB;
2663 if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
2664 png_error(png_ptr,
"rgb color-map: too few entries");
2666 cmap_entries = (
unsigned int)make_rgb_colormap(display);
2667 output_processing = PNG_CMAP_RGB;
2672 case PNG_COLOR_TYPE_PALETTE:
2677 unsigned int num_trans = png_ptr->num_trans;
2678 png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
2679 png_const_colorp colormap = png_ptr->palette;
2680 int do_background = trans != NULL &&
2681 (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
2688 output_processing = PNG_CMAP_NONE;
2689 data_encoding = P_FILE;
2690 cmap_entries = (
unsigned int)png_ptr->num_palette;
2691 if (cmap_entries > 256)
2694 if (cmap_entries > (
unsigned int)image->colormap_entries)
2695 png_error(png_ptr,
"palette color-map: too few entries");
2697 for (i=0; i < cmap_entries; ++i)
2699 if (do_background != 0 && i < num_trans && trans[i] < 255)
2702 png_create_colormap_entry(display, i, back_r, back_g,
2703 back_b, 0, output_encoding);
2710 png_create_colormap_entry(display, i,
2711 png_colormap_compose(display, colormap[i].red,
2712 P_FILE, trans[i], back_r, output_encoding),
2713 png_colormap_compose(display, colormap[i].green,
2714 P_FILE, trans[i], back_g, output_encoding),
2715 png_colormap_compose(display, colormap[i].blue,
2716 P_FILE, trans[i], back_b, output_encoding),
2717 output_encoding == P_LINEAR ? trans[i] * 257U :
2724 png_create_colormap_entry(display, i, colormap[i].red,
2725 colormap[i].green, colormap[i].blue,
2726 i < num_trans ? trans[i] : 255U, P_FILE);
2732 if (png_ptr->bit_depth < 8)
2733 png_set_packing(png_ptr);
2738 png_error(png_ptr,
"invalid PNG color type");
2743 if (expand_tRNS != 0 && png_ptr->num_trans > 0 &&
2744 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
2745 png_set_tRNS_to_alpha(png_ptr);
2747 switch (data_encoding)
2751 png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
2755 if (png_ptr->bit_depth > 8)
2756 png_set_scale_16(png_ptr);
2761 png_error(png_ptr,
"bad data option (internal error)");
2765 if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
2766 png_error(png_ptr,
"color map overflow (BAD internal error)");
2768 image->colormap_entries = cmap_entries;
2771 switch (output_processing)
2774 if (background_index != PNG_CMAP_NONE_BACKGROUND)
2775 goto bad_background;
2779 if (background_index != PNG_CMAP_GA_BACKGROUND)
2780 goto bad_background;
2783 case PNG_CMAP_TRANS:
2784 if (background_index >= cmap_entries ||
2785 background_index != PNG_CMAP_TRANS_BACKGROUND)
2786 goto bad_background;
2790 if (background_index != PNG_CMAP_RGB_BACKGROUND)
2791 goto bad_background;
2794 case PNG_CMAP_RGB_ALPHA:
2795 if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
2796 goto bad_background;
2800 png_error(png_ptr,
"bad processing option (internal error)");
2803 png_error(png_ptr,
"bad background index (internal error)");
2806 display->colormap_processing = (int)output_processing;
2813png_image_read_and_map(png_voidp argument)
2817 png_imagep image = display->image;
2818 png_structrp png_ptr = image->opaque->png_ptr;
2825 switch (png_ptr->interlaced)
2827 case PNG_INTERLACE_NONE:
2831 case PNG_INTERLACE_ADAM7:
2832 passes = PNG_INTERLACE_ADAM7_PASSES;
2836 png_error(png_ptr,
"unknown interlace type");
2840 png_uint_32 height = image->height;
2841 png_uint_32 width = image->width;
2842 int proc = display->colormap_processing;
2843 png_bytep first_row = png_voidcast(png_bytep, display->first_row);
2844 ptrdiff_t step_row = display->row_bytes;
2847 for (pass = 0; pass < passes; ++pass)
2849 unsigned int startx, stepx, stepy;
2852 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
2855 if (PNG_PASS_COLS(width, pass) == 0)
2858 startx = PNG_PASS_START_COL(pass);
2859 stepx = PNG_PASS_COL_OFFSET(pass);
2860 y = PNG_PASS_START_ROW(pass);
2861 stepy = PNG_PASS_ROW_OFFSET(pass);
2871 for (; y<height; y += stepy)
2873 png_bytep inrow = png_voidcast(png_bytep, display->local_row);
2874 png_bytep outrow = first_row + y * step_row;
2875 png_const_bytep end_row = outrow + width;
2878 png_read_row(png_ptr, inrow, NULL);
2888 for (; outrow < end_row; outrow += stepx)
2891 unsigned int gray = *inrow++;
2892 unsigned int alpha = *inrow++;
2901 entry = (231 * gray + 128) >> 8;
2903 else if (alpha < 26)
2909 entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
2912 *outrow = (png_byte)entry;
2916 case PNG_CMAP_TRANS:
2917 for (; outrow < end_row; outrow += stepx)
2919 png_byte gray = *inrow++;
2920 png_byte alpha = *inrow++;
2923 *outrow = PNG_CMAP_TRANS_BACKGROUND;
2925 else if (gray != PNG_CMAP_TRANS_BACKGROUND)
2929 *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
2934 for (; outrow < end_row; outrow += stepx)
2936 *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
2941 case PNG_CMAP_RGB_ALPHA:
2942 for (; outrow < end_row; outrow += stepx)
2944 unsigned int alpha = inrow[3];
2952 *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
2955 else if (alpha < 64)
2956 *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
2966 unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
2977 if (inrow[0] & 0x80) back_i += 9;
2978 if (inrow[0] & 0x40) back_i += 9;
2979 if (inrow[0] & 0x80) back_i += 3;
2980 if (inrow[0] & 0x40) back_i += 3;
2981 if (inrow[0] & 0x80) back_i += 1;
2982 if (inrow[0] & 0x40) back_i += 1;
2984 *outrow = (png_byte)back_i;
3002png_image_read_colormapped(png_voidp argument)
3006 png_imagep image = display->image;
3007 png_controlp control = image->opaque;
3008 png_structrp png_ptr = control->png_ptr;
3009 png_inforp info_ptr = control->info_ptr;
3013 PNG_SKIP_CHUNKS(png_ptr);
3019 if (display->colormap_processing == PNG_CMAP_NONE)
3020 passes = png_set_interlace_handling(png_ptr);
3022 png_read_update_info(png_ptr, info_ptr);
3025 switch (display->colormap_processing)
3031 if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
3032 info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
3033 info_ptr->bit_depth == 8)
3038 case PNG_CMAP_TRANS:
3044 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
3045 info_ptr->bit_depth == 8 &&
3046 png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
3047 image->colormap_entries == 256)
3054 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
3055 info_ptr->bit_depth == 8 &&
3056 png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
3057 image->colormap_entries == 216)
3062 case PNG_CMAP_RGB_ALPHA:
3064 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3065 info_ptr->bit_depth == 8 &&
3066 png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
3067 image->colormap_entries == 244 )
3074 png_error(png_ptr,
"bad color-map processing (internal error)");
3082 png_voidp first_row = display->buffer;
3083 ptrdiff_t row_bytes = display->row_stride;
3090 char *ptr = png_voidcast(
char*, first_row);
3091 ptr += (image->height-1) * (-row_bytes);
3092 first_row = png_voidcast(png_voidp, ptr);
3095 display->first_row = first_row;
3096 display->row_bytes = row_bytes;
3102 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
3104 display->local_row = row;
3105 result = png_safe_execute(image, png_image_read_and_map, display);
3106 display->local_row = NULL;
3107 png_free(png_ptr, row);
3114 png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
3116 while (--passes >= 0)
3118 png_uint_32 y = image->height;
3119 png_bytep row = png_voidcast(png_bytep, display->first_row);
3123 png_read_row(png_ptr, row, NULL);
3134png_image_read_direct_scaled(png_voidp argument)
3138 png_imagep image = display->image;
3139 png_structrp png_ptr = image->opaque->png_ptr;
3140 png_bytep local_row = png_voidcast(png_bytep, display->local_row);
3141 png_bytep first_row = png_voidcast(png_bytep, display->first_row);
3142 ptrdiff_t row_bytes = display->row_bytes;
3146 switch (png_ptr->interlaced)
3148 case PNG_INTERLACE_NONE:
3152 case PNG_INTERLACE_ADAM7:
3153 passes = PNG_INTERLACE_ADAM7_PASSES;
3157 png_error(png_ptr,
"unknown interlace type");
3161 while (--passes >= 0)
3163 png_uint_32 y = image->height;
3164 png_bytep output_row = first_row;
3169 png_read_row(png_ptr, local_row, NULL);
3172 memcpy(output_row, local_row, (
size_t)row_bytes);
3173 output_row += row_bytes;
3182png_image_read_composite(png_voidp argument)
3186 png_imagep image = display->image;
3187 png_structrp png_ptr = image->opaque->png_ptr;
3190 switch (png_ptr->interlaced)
3192 case PNG_INTERLACE_NONE:
3196 case PNG_INTERLACE_ADAM7:
3197 passes = PNG_INTERLACE_ADAM7_PASSES;
3201 png_error(png_ptr,
"unknown interlace type");
3205 png_uint_32 height = image->height;
3206 png_uint_32 width = image->width;
3207 ptrdiff_t step_row = display->row_bytes;
3208 unsigned int channels =
3209 (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
3210 int optimize_alpha = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3213 for (pass = 0; pass < passes; ++pass)
3215 unsigned int startx, stepx, stepy;
3218 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
3221 if (PNG_PASS_COLS(width, pass) == 0)
3224 startx = PNG_PASS_START_COL(pass) * channels;
3225 stepx = PNG_PASS_COL_OFFSET(pass) * channels;
3226 y = PNG_PASS_START_ROW(pass);
3227 stepy = PNG_PASS_ROW_OFFSET(pass);
3238 for (; y<height; y += stepy)
3240 png_bytep inrow = png_voidcast(png_bytep, display->local_row);
3242 png_const_bytep end_row;
3245 png_read_row(png_ptr, inrow, NULL);
3247 outrow = png_voidcast(png_bytep, display->first_row);
3248 outrow += y * step_row;
3249 end_row = outrow + width * channels;
3253 for (; outrow < end_row; outrow += stepx)
3255 png_byte alpha = inrow[channels];
3261 for (c=0; c<channels; ++c)
3263 png_uint_32 component = inrow[c];
3267 if (optimize_alpha != 0)
3275 component *= 257*255;
3276 component += (255-alpha)*png_sRGB_table[outrow[c]];
3283 if (component > 255*65535)
3284 component = 255*65535;
3290 component = PNG_sRGB_FROM_LINEAR(component);
3300 png_uint_32 background = outrow[c];
3301 component += ((255-alpha) * background + 127) / 255;
3302 if (component > 255)
3307 outrow[c] = (png_byte)component;
3311 inrow += channels+1;
3334png_image_read_background(png_voidp argument)
3338 png_imagep image = display->image;
3339 png_structrp png_ptr = image->opaque->png_ptr;
3340 png_inforp info_ptr = image->opaque->info_ptr;
3341 png_uint_32 height = image->height;
3342 png_uint_32 width = image->width;
3350 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
3351 png_error(png_ptr,
"lost rgb to gray");
3353 if ((png_ptr->transformations & PNG_COMPOSE) != 0)
3354 png_error(png_ptr,
"unexpected compose");
3356 if (png_get_channels(png_ptr, info_ptr) != 2)
3357 png_error(png_ptr,
"lost/gained channels");
3360 if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
3361 (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
3362 png_error(png_ptr,
"unexpected 8-bit transformation");
3364 switch (png_ptr->interlaced)
3366 case PNG_INTERLACE_NONE:
3370 case PNG_INTERLACE_ADAM7:
3371 passes = PNG_INTERLACE_ADAM7_PASSES;
3375 png_error(png_ptr,
"unknown interlace type");
3383 switch (info_ptr->bit_depth)
3392 png_bytep first_row = png_voidcast(png_bytep, display->first_row);
3393 ptrdiff_t step_row = display->row_bytes;
3395 for (pass = 0; pass < passes; ++pass)
3397 unsigned int startx, stepx, stepy;
3400 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
3403 if (PNG_PASS_COLS(width, pass) == 0)
3406 startx = PNG_PASS_START_COL(pass);
3407 stepx = PNG_PASS_COL_OFFSET(pass);
3408 y = PNG_PASS_START_ROW(pass);
3409 stepy = PNG_PASS_ROW_OFFSET(pass);
3419 if (display->background == NULL)
3421 for (; y<height; y += stepy)
3423 png_bytep inrow = png_voidcast(png_bytep,
3424 display->local_row);
3425 png_bytep outrow = first_row + y * step_row;
3426 png_const_bytep end_row = outrow + width;
3429 png_read_row(png_ptr, inrow, NULL);
3433 for (; outrow < end_row; outrow += stepx)
3435 png_byte alpha = inrow[1];
3439 png_uint_32 component = inrow[0];
3447 component = png_sRGB_table[component] * alpha;
3448 component += png_sRGB_table[outrow[0]] *
3450 component = PNG_sRGB_FROM_LINEAR(component);
3453 outrow[0] = (png_byte)component;
3463 png_byte background8 = display->background->green;
3464 png_uint_16 background = png_sRGB_table[background8];
3466 for (; y<height; y += stepy)
3468 png_bytep inrow = png_voidcast(png_bytep,
3469 display->local_row);
3470 png_bytep outrow = first_row + y * step_row;
3471 png_const_bytep end_row = outrow + width;
3474 png_read_row(png_ptr, inrow, NULL);
3478 for (; outrow < end_row; outrow += stepx)
3480 png_byte alpha = inrow[1];
3484 png_uint_32 component = inrow[0];
3488 component = png_sRGB_table[component] * alpha;
3489 component += background * (255-alpha);
3490 component = PNG_sRGB_FROM_LINEAR(component);
3493 outrow[0] = (png_byte)component;
3497 outrow[0] = background8;
3513 png_uint_16p first_row = png_voidcast(png_uint_16p,
3514 display->first_row);
3518 ptrdiff_t step_row = display->row_bytes / 2;
3519 unsigned int preserve_alpha = (image->format &
3520 PNG_FORMAT_FLAG_ALPHA) != 0;
3521 unsigned int outchannels = 1U+preserve_alpha;
3524# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
3525 if (preserve_alpha != 0 &&
3526 (image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
3530 for (pass = 0; pass < passes; ++pass)
3532 unsigned int startx, stepx, stepy;
3537 if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
3540 if (PNG_PASS_COLS(width, pass) == 0)
3543 startx = PNG_PASS_START_COL(pass) * outchannels;
3544 stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
3545 y = PNG_PASS_START_ROW(pass);
3546 stepy = PNG_PASS_ROW_OFFSET(pass);
3553 stepx = outchannels;
3557 for (; y<height; y += stepy)
3559 png_const_uint_16p inrow;
3560 png_uint_16p outrow = first_row + y*step_row;
3561 png_uint_16p end_row = outrow + width * outchannels;
3564 png_read_row(png_ptr, png_voidcast(png_bytep,
3565 display->local_row), NULL);
3566 inrow = png_voidcast(png_const_uint_16p, display->local_row);
3571 for (; outrow < end_row; outrow += stepx)
3573 png_uint_32 component = inrow[0];
3574 png_uint_16 alpha = inrow[1];
3589 outrow[swap_alpha] = (png_uint_16)component;
3590 if (preserve_alpha != 0)
3591 outrow[1 ^ swap_alpha] = alpha;
3602 png_error(png_ptr,
"unexpected bit depth");
3611png_image_read_direct(png_voidp argument)
3615 png_imagep image = display->image;
3616 png_structrp png_ptr = image->opaque->png_ptr;
3617 png_inforp info_ptr = image->opaque->info_ptr;
3619 png_uint_32 format = image->format;
3620 int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
3621 int do_local_compose = 0;
3622 int do_local_background = 0;
3623 int do_local_scale = 0;
3630 png_set_expand(png_ptr);
3634 png_uint_32 base_format = png_image_format(png_ptr) &
3635 ~PNG_FORMAT_FLAG_COLORMAP ;
3636 png_uint_32 change = format ^ base_format;
3637 png_fixed_point output_gamma;
3641 if ((change & PNG_FORMAT_FLAG_COLOR) != 0)
3644 if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
3645 png_set_gray_to_rgb(png_ptr);
3662 if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
3663 do_local_background = 1;
3665 png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
3666 PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
3669 change &= ~PNG_FORMAT_FLAG_COLOR;
3681 png_fixed_point input_gamma_default;
3683 if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
3684 (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
3685 input_gamma_default = PNG_GAMMA_LINEAR;
3687 input_gamma_default = PNG_DEFAULT_sRGB;
3692 png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
3700 if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
3701 mode = PNG_ALPHA_STANDARD;
3704 mode = PNG_ALPHA_PNG;
3706 output_gamma = PNG_GAMMA_LINEAR;
3711 mode = PNG_ALPHA_PNG;
3712 output_gamma = PNG_DEFAULT_sRGB;
3715 if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)
3717 mode = PNG_ALPHA_OPTIMIZED;
3718 change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
3727 if (do_local_background != 0)
3729 png_fixed_point gtest;
3736 if (png_muldiv(>est, output_gamma,
3737 png_resolve_file_gamma(png_ptr), PNG_FP_1) != 0 &&
3738 png_gamma_significant(gtest) == 0)
3739 do_local_background = 0;
3741 else if (mode == PNG_ALPHA_STANDARD)
3743 do_local_background = 2;
3744 mode = PNG_ALPHA_PNG;
3751 if ((change & PNG_FORMAT_FLAG_LINEAR) != 0)
3754 png_set_expand_16(png_ptr);
3758 png_set_scale_16(png_ptr);
3763 if (png_ptr->interlaced != 0)
3767 change &= ~PNG_FORMAT_FLAG_LINEAR;
3771 if ((change & PNG_FORMAT_FLAG_ALPHA) != 0)
3777 if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
3784 if (do_local_background != 0)
3785 do_local_background = 2;
3788 else if (linear != 0)
3789 png_set_strip_alpha(png_ptr);
3792 else if (display->background != NULL)
3797 c.red = display->background->red;
3798 c.green = display->background->green;
3799 c.blue = display->background->blue;
3800 c.gray = display->background->green;
3808 png_set_background_fixed(png_ptr, &c,
3809 PNG_BACKGROUND_GAMMA_SCREEN, 0,
3815 do_local_compose = 1;
3821 mode = PNG_ALPHA_OPTIMIZED;
3841#ifdef PNG_FORMAT_AFIRST_SUPPORTED
3842 if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
3844 where = PNG_FILLER_BEFORE;
3845 change &= ~PNG_FORMAT_FLAG_AFIRST;
3850 where = PNG_FILLER_AFTER;
3852 png_set_add_alpha(png_ptr, filler, where);
3856 change &= ~PNG_FORMAT_FLAG_ALPHA;
3863 png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
3865# ifdef PNG_FORMAT_BGR_SUPPORTED
3866 if ((change & PNG_FORMAT_FLAG_BGR) != 0)
3871 if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
3872 png_set_bgr(png_ptr);
3875 format &= ~PNG_FORMAT_FLAG_BGR;
3877 change &= ~PNG_FORMAT_FLAG_BGR;
3881# ifdef PNG_FORMAT_AFIRST_SUPPORTED
3882 if ((change & PNG_FORMAT_FLAG_AFIRST) != 0)
3889 if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)
3894 if (do_local_background != 2)
3895 png_set_swap_alpha(png_ptr);
3899 format &= ~PNG_FORMAT_FLAG_AFIRST;
3901 change &= ~PNG_FORMAT_FLAG_AFIRST;
3910 png_uint_16 le = 0x0001;
3912 if ((*(png_const_bytep) & le) != 0)
3913 png_set_swap(png_ptr);
3918 png_error(png_ptr,
"png_read_image: unsupported transformation");
3921 PNG_SKIP_CHUNKS(png_ptr);
3929 if (do_local_compose == 0 && do_local_background != 2)
3930 passes = png_set_interlace_handling(png_ptr);
3932 png_read_update_info(png_ptr, info_ptr);
3935 png_uint_32 info_format = 0;
3937 if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
3938 info_format |= PNG_FORMAT_FLAG_COLOR;
3940 if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
3943 if (do_local_compose == 0)
3946 if (do_local_background != 2 ||
3947 (format & PNG_FORMAT_FLAG_ALPHA) != 0)
3948 info_format |= PNG_FORMAT_FLAG_ALPHA;
3952 else if (do_local_compose != 0)
3953 png_error(png_ptr,
"png_image_read: alpha channel lost");
3955 if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) {
3956 info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
3959 if (info_ptr->bit_depth == 16)
3960 info_format |= PNG_FORMAT_FLAG_LINEAR;
3962#ifdef PNG_FORMAT_BGR_SUPPORTED
3963 if ((png_ptr->transformations & PNG_BGR) != 0)
3964 info_format |= PNG_FORMAT_FLAG_BGR;
3967#ifdef PNG_FORMAT_AFIRST_SUPPORTED
3968 if (do_local_background == 2)
3970 if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
3971 info_format |= PNG_FORMAT_FLAG_AFIRST;
3974 if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
3975 ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
3976 (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
3978 if (do_local_background == 2)
3979 png_error(png_ptr,
"unexpected alpha swap transformation");
3981 info_format |= PNG_FORMAT_FLAG_AFIRST;
3986 if (info_format != format)
3987 png_error(png_ptr,
"png_read_image: invalid transformations");
3996 png_voidp first_row = display->buffer;
3997 ptrdiff_t row_bytes = display->row_stride;
4007 char *ptr = png_voidcast(
char*, first_row);
4008 ptr += (image->height-1) * (-row_bytes);
4009 first_row = png_voidcast(png_voidp, ptr);
4012 display->first_row = first_row;
4013 display->row_bytes = row_bytes;
4016 if (do_local_compose != 0)
4019 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
4021 display->local_row = row;
4022 result = png_safe_execute(image, png_image_read_composite, display);
4023 display->local_row = NULL;
4024 png_free(png_ptr, row);
4029 else if (do_local_background == 2)
4032 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
4034 display->local_row = row;
4035 result = png_safe_execute(image, png_image_read_background, display);
4036 display->local_row = NULL;
4037 png_free(png_ptr, row);
4042 else if (do_local_scale != 0)
4050 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
4052 display->local_row = row;
4053 result = png_safe_execute(image, png_image_read_direct_scaled, display);
4054 display->local_row = NULL;
4055 png_free(png_ptr, row);
4062 png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
4064 while (--passes >= 0)
4066 png_uint_32 y = image->height;
4067 png_bytep row = png_voidcast(png_bytep, display->first_row);
4071 png_read_row(png_ptr, row, NULL);
4081png_image_finish_read(png_imagep image, png_const_colorp background,
4082 void *buffer, png_int_32 row_stride,
void *colormap)
4084 if (image != NULL && image->version == PNG_IMAGE_VERSION)
4090 unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
4098 if (image->width <= 0x7fffffffU/channels)
4101 png_uint_32 png_row_stride = image->width * channels;
4103 if (row_stride == 0)
4104 row_stride = (png_int_32)png_row_stride;
4107 check = (png_uint_32)(-row_stride);
4110 check = (png_uint_32)row_stride;
4116 if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
4134 if (image->height <=
4135 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)
4137 if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
4138 (image->colormap_entries > 0 && colormap != NULL))
4143 memset(&display, 0, (
sizeof display));
4144 display.image = image;
4145 display.buffer = buffer;
4146 display.row_stride = row_stride;
4147 display.colormap = colormap;
4148 display.background = background;
4149 display.local_row = NULL;
4154 if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
4156 png_safe_execute(image,
4157 png_image_read_colormap, &display) &&
4158 png_safe_execute(image,
4159 png_image_read_colormapped, &display);
4163 png_safe_execute(image,
4164 png_image_read_direct, &display);
4166 png_image_free(image);
4171 return png_image_error(image,
4172 "png_image_finish_read[color-map]: no color-map");
4176 return png_image_error(image,
4177 "png_image_finish_read: image too large");
4181 return png_image_error(image,
4182 "png_image_finish_read: invalid argument");
4186 return png_image_error(image,
4187 "png_image_finish_read: row_stride too large");
4190 else if (image != NULL)
4191 return png_image_error(image,
4192 "png_image_finish_read: damaged PNG_IMAGE_VERSION");