18#ifdef PNG_WRITE_SUPPORTED
20#ifdef PNG_WRITE_INTERLACING_SUPPORTED
24static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
26static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
28static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
30static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
35#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
41png_save_uint_32(png_bytep buf, png_uint_32 i)
43 buf[0] = (png_byte)((i >> 24) & 0xffU);
44 buf[1] = (png_byte)((i >> 16) & 0xffU);
45 buf[2] = (png_byte)((i >> 8) & 0xffU);
46 buf[3] = (png_byte)( i & 0xffU);
54png_save_uint_16(png_bytep buf,
unsigned int i)
56 buf[0] = (png_byte)((i >> 8) & 0xffU);
57 buf[1] = (png_byte)( i & 0xffU);
68png_write_sig(png_structrp png_ptr)
70 png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
72#ifdef PNG_IO_STATE_SUPPORTED
74 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
78 png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
79 (
size_t)(8 - png_ptr->sig_bytes));
81 if (png_ptr->sig_bytes < 3)
82 png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
90png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
95#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
96 PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
97 png_debug2(0,
"Writing %s chunk, length = %lu", buf, (
unsigned long)length);
103#ifdef PNG_IO_STATE_SUPPORTED
107 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
111 png_save_uint_32(buf, length);
112 png_save_uint_32(buf + 4, chunk_name);
113 png_write_data(png_ptr, buf, 8);
116 png_ptr->chunk_name = chunk_name;
119 png_reset_crc(png_ptr);
121 png_calculate_crc(png_ptr, buf + 4, 4);
123#ifdef PNG_IO_STATE_SUPPORTED
127 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
132png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
135 png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
144png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
size_t length)
150 if (data != NULL && length > 0)
152 png_write_data(png_ptr, data, length);
157 png_calculate_crc(png_ptr, data, length);
163png_write_chunk_end(png_structrp png_ptr)
167 if (png_ptr == NULL)
return;
169#ifdef PNG_IO_STATE_SUPPORTED
173 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
177 png_save_uint_32(buf, png_ptr->crc);
179 png_write_data(png_ptr, buf, 4);
192png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
193 png_const_bytep data,
size_t length)
199 if (length > PNG_UINT_31_MAX)
200 png_error(png_ptr,
"length exceeds PNG maximum");
202 png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
203 png_write_chunk_data(png_ptr, data, length);
204 png_write_chunk_end(png_ptr);
209png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
210 png_const_bytep data,
size_t length)
212 png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
220static png_alloc_size_t
221png_image_size(png_structrp png_ptr)
226 png_uint_32 h = png_ptr->height;
228 if (png_ptr->rowbytes < 32768 && h < 32768)
230 if (png_ptr->interlaced != 0)
235 png_uint_32 w = png_ptr->width;
236 unsigned int pd = png_ptr->pixel_depth;
237 png_alloc_size_t cb_base;
240 for (cb_base=0, pass=0; pass<=6; ++pass)
242 png_uint_32 pw = PNG_PASS_COLS(w, pass);
245 cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
252 return (png_ptr->rowbytes+1) * h;
259#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
267optimize_cmf(png_bytep data, png_alloc_size_t data_size)
272 if (data_size <= 16384)
274 unsigned int z_cmf = data[0];
276 if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
278 unsigned int z_cinfo;
279 unsigned int half_z_window_size;
281 z_cinfo = z_cmf >> 4;
282 half_z_window_size = 1U << (z_cinfo + 7);
284 if (data_size <= half_z_window_size)
290 half_z_window_size >>= 1;
293 while (z_cinfo > 0 && data_size <= half_z_window_size);
295 z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
297 data[0] = (png_byte)z_cmf;
298 tmp = data[1] & 0xe0;
299 tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
300 data[1] = (png_byte)tmp;
309png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
310 png_alloc_size_t data_size)
312 if (png_ptr->zowner != 0)
314#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
317 PNG_STRING_FROM_CHUNK(msg, owner);
320 PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
325 (void)png_safecat(msg, (
sizeof msg), 10,
" using zstream");
328 png_warning(png_ptr, msg);
331 if (png_ptr->zowner == png_IDAT)
333 png_ptr->zstream.msg = PNGZ_MSG_CAST(
"in use by IDAT");
334 return Z_STREAM_ERROR;
339 png_error(png_ptr, msg);
344 int level = png_ptr->zlib_level;
345 int method = png_ptr->zlib_method;
346 int windowBits = png_ptr->zlib_window_bits;
347 int memLevel = png_ptr->zlib_mem_level;
351 if (owner == png_IDAT)
353 if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
354 strategy = png_ptr->zlib_strategy;
356 else if (png_ptr->do_filter != PNG_FILTER_NONE)
357 strategy = PNG_Z_DEFAULT_STRATEGY;
360 strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
365#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
366 level = png_ptr->zlib_text_level;
367 method = png_ptr->zlib_text_method;
368 windowBits = png_ptr->zlib_text_window_bits;
369 memLevel = png_ptr->zlib_text_mem_level;
370 strategy = png_ptr->zlib_text_strategy;
377 strategy = Z_DEFAULT_STRATEGY;
388 if (data_size <= 16384)
395 unsigned int half_window_size = 1U << (windowBits-1);
397 while (data_size + 262 <= half_window_size)
399 half_window_size >>= 1;
405 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
406 (png_ptr->zlib_set_level != level ||
407 png_ptr->zlib_set_method != method ||
408 png_ptr->zlib_set_window_bits != windowBits ||
409 png_ptr->zlib_set_mem_level != memLevel ||
410 png_ptr->zlib_set_strategy != strategy))
412 if (deflateEnd(&png_ptr->zstream) != Z_OK)
413 png_warning(png_ptr,
"deflateEnd failed (ignored)");
415 png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
421 png_ptr->zstream.next_in = NULL;
422 png_ptr->zstream.avail_in = 0;
423 png_ptr->zstream.next_out = NULL;
424 png_ptr->zstream.avail_out = 0;
429 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
430 ret = deflateReset(&png_ptr->zstream);
434 ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
438 png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
445 png_ptr->zowner = owner;
448 png_zstream_error(png_ptr, ret);
456png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
458 png_compression_bufferp list = *listp;
466 png_compression_bufferp next = list->next;
468 png_free(png_ptr, list);
471 while (list != NULL);
475#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
488 png_const_bytep input;
489 png_alloc_size_t input_len;
490 png_uint_32 output_len;
491 png_byte output[1024];
496 png_alloc_size_t input_len)
499 comp->input_len = input_len;
500 comp->output_len = 0;
505png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
520 ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
532 png_compression_bufferp *end = &png_ptr->zbuffer_list;
533 png_alloc_size_t input_len = comp->input_len;
534 png_uint_32 output_len;
537 png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
538 png_ptr->zstream.avail_in = 0;
539 png_ptr->zstream.next_out = comp->output;
540 png_ptr->zstream.avail_out = (
sizeof comp->output);
542 output_len = png_ptr->zstream.avail_out;
546 uInt avail_in = ZLIB_IO_MAX;
548 if (avail_in > input_len)
549 avail_in = (uInt)input_len;
551 input_len -= avail_in;
553 png_ptr->zstream.avail_in = avail_in;
555 if (png_ptr->zstream.avail_out == 0)
557 png_compression_buffer *next;
562 if (output_len + prefix_len > PNG_UINT_31_MAX)
574 next = png_voidcast(png_compression_bufferp, png_malloc_base
575 (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
588 png_ptr->zstream.next_out = next->output;
589 png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
590 output_len += png_ptr->zstream.avail_out;
597 ret = deflate(&png_ptr->zstream,
598 input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
603 input_len += png_ptr->zstream.avail_in;
604 png_ptr->zstream.avail_in = 0;
611 output_len -= png_ptr->zstream.avail_out;
612 png_ptr->zstream.avail_out = 0;
613 comp->output_len = output_len;
619 if (output_len + prefix_len >= PNG_UINT_31_MAX)
621 png_ptr->zstream.msg = PNGZ_MSG_CAST(
"compressed data too long");
626 png_zstream_error(png_ptr, ret);
634 if (ret == Z_STREAM_END && input_len == 0)
636#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
638 optimize_cmf(comp->output, comp->input_len);
656 png_uint_32 output_len = comp->output_len;
657 png_const_bytep output = comp->output;
658 png_uint_32 avail = (
sizeof comp->output);
659 png_compression_buffer *next = png_ptr->zbuffer_list;
663 if (avail > output_len)
666 png_write_chunk_data(png_ptr, output, avail);
670 if (output_len == 0 || next == NULL)
673 avail = png_ptr->zbuffer_size;
674 output = next->output;
680 png_error(png_ptr,
"error writing ancillary chunked compressed data");
689png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
690 int bit_depth,
int color_type,
int compression_type,
int filter_type,
694 int is_invalid_depth;
696 png_debug(1,
"in png_write_IHDR");
701 case PNG_COLOR_TYPE_GRAY:
708#ifdef PNG_WRITE_16BIT_SUPPORTED
711 png_ptr->channels = 1;
break;
715 "Invalid bit depth for grayscale image");
719 case PNG_COLOR_TYPE_RGB:
720 is_invalid_depth = (bit_depth != 8);
721#ifdef PNG_WRITE_16BIT_SUPPORTED
722 is_invalid_depth = (is_invalid_depth && bit_depth != 16);
724 if (is_invalid_depth)
725 png_error(png_ptr,
"Invalid bit depth for RGB image");
727 png_ptr->channels = 3;
730 case PNG_COLOR_TYPE_PALETTE:
737 png_ptr->channels = 1;
741 png_error(png_ptr,
"Invalid bit depth for paletted image");
745 case PNG_COLOR_TYPE_GRAY_ALPHA:
746 is_invalid_depth = (bit_depth != 8);
747#ifdef PNG_WRITE_16BIT_SUPPORTED
748 is_invalid_depth = (is_invalid_depth && bit_depth != 16);
750 if (is_invalid_depth)
751 png_error(png_ptr,
"Invalid bit depth for grayscale+alpha image");
753 png_ptr->channels = 2;
756 case PNG_COLOR_TYPE_RGB_ALPHA:
757 is_invalid_depth = (bit_depth != 8);
758#ifdef PNG_WRITE_16BIT_SUPPORTED
759 is_invalid_depth = (is_invalid_depth && bit_depth != 16);
761 if (is_invalid_depth)
762 png_error(png_ptr,
"Invalid bit depth for RGBA image");
764 png_ptr->channels = 4;
768 png_error(png_ptr,
"Invalid image color type specified");
771 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
773 png_warning(png_ptr,
"Invalid compression type specified");
774 compression_type = PNG_COMPRESSION_TYPE_BASE;
787#ifdef PNG_MNG_FEATURES_SUPPORTED
788 !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
789 ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
790 (color_type == PNG_COLOR_TYPE_RGB ||
791 color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
792 (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
794 filter_type != PNG_FILTER_TYPE_BASE)
796 png_warning(png_ptr,
"Invalid filter type specified");
797 filter_type = PNG_FILTER_TYPE_BASE;
800#ifdef PNG_WRITE_INTERLACING_SUPPORTED
801 if (interlace_type != PNG_INTERLACE_NONE &&
802 interlace_type != PNG_INTERLACE_ADAM7)
804 png_warning(png_ptr,
"Invalid interlace type specified");
805 interlace_type = PNG_INTERLACE_ADAM7;
808 interlace_type=PNG_INTERLACE_NONE;
812 png_ptr->bit_depth = (png_byte)bit_depth;
813 png_ptr->color_type = (png_byte)color_type;
814 png_ptr->interlaced = (png_byte)interlace_type;
815#ifdef PNG_MNG_FEATURES_SUPPORTED
816 png_ptr->filter_type = (png_byte)filter_type;
818 png_ptr->compression_type = (png_byte)compression_type;
819 png_ptr->width = width;
820 png_ptr->height = height;
822 png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
823 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
825 png_ptr->usr_width = png_ptr->width;
826 png_ptr->usr_bit_depth = png_ptr->bit_depth;
827 png_ptr->usr_channels = png_ptr->channels;
830 png_save_uint_32(buf, width);
831 png_save_uint_32(buf + 4, height);
832 buf[8] = (png_byte)bit_depth;
833 buf[9] = (png_byte)color_type;
834 buf[10] = (png_byte)compression_type;
835 buf[11] = (png_byte)filter_type;
836 buf[12] = (png_byte)interlace_type;
839 png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
841 if ((png_ptr->do_filter) == PNG_NO_FILTERS)
843 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
844 png_ptr->bit_depth < 8)
845 png_ptr->do_filter = PNG_FILTER_NONE;
848 png_ptr->do_filter = PNG_ALL_FILTERS;
851 png_ptr->mode = PNG_HAVE_IHDR;
859png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
862 png_uint_32 max_palette_length, i;
863 png_const_colorp pal_ptr;
866 png_debug(1,
"in png_write_PLTE");
868 max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
869 (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
872#ifdef PNG_MNG_FEATURES_SUPPORTED
873 (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
875 num_pal == 0) || num_pal > max_palette_length)
877 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
879 png_error(png_ptr,
"Invalid number of colors in palette");
884 png_warning(png_ptr,
"Invalid number of colors in palette");
889 if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
892 "Ignoring request to write a PLTE chunk in grayscale PNG");
897 png_ptr->num_palette = (png_uint_16)num_pal;
898 png_debug1(3,
"num_palette = %d", png_ptr->num_palette);
900 png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
901#ifdef PNG_POINTER_INDEXING_SUPPORTED
903 for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
905 buf[0] = pal_ptr->red;
906 buf[1] = pal_ptr->green;
907 buf[2] = pal_ptr->blue;
908 png_write_chunk_data(png_ptr, buf, 3);
917 for (i = 0; i < num_pal; i++)
919 buf[0] = pal_ptr[i].red;
920 buf[1] = pal_ptr[i].green;
921 buf[2] = pal_ptr[i].blue;
922 png_write_chunk_data(png_ptr, buf, 3);
926 png_write_chunk_end(png_ptr);
927 png_ptr->mode |= PNG_HAVE_PLTE;
948png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
949 png_alloc_size_t input_len,
int flush)
951 if (png_ptr->zowner != png_IDAT)
958 if (png_ptr->zbuffer_list == NULL)
960 png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
961 png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
962 png_ptr->zbuffer_list->next = NULL;
966 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
969 if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
970 png_error(png_ptr, png_ptr->zstream.msg);
975 png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
976 png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
983 png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
984 png_ptr->zstream.avail_in = 0;
990 uInt avail = ZLIB_IO_MAX;
992 if (avail > input_len)
993 avail = (uInt)input_len;
995 png_ptr->zstream.avail_in = avail;
998 ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
1001 input_len += png_ptr->zstream.avail_in;
1002 png_ptr->zstream.avail_in = 0;
1008 if (png_ptr->zstream.avail_out == 0)
1010 png_bytep data = png_ptr->zbuffer_list->output;
1011 uInt size = png_ptr->zbuffer_size;
1016#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
1017 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
1018 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
1019 optimize_cmf(data, png_image_size(png_ptr));
1023 png_write_complete_chunk(png_ptr, png_IDAT, data, size);
1024 png_ptr->mode |= PNG_HAVE_IDAT;
1026 png_ptr->zstream.next_out = data;
1027 png_ptr->zstream.avail_out = size;
1033 if (ret == Z_OK && flush != Z_NO_FLUSH)
1048 if (flush == Z_FINISH)
1049 png_error(png_ptr,
"Z_OK on Z_FINISH with output space");
1055 else if (ret == Z_STREAM_END && flush == Z_FINISH)
1060 png_bytep data = png_ptr->zbuffer_list->output;
1061 uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
1063#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
1064 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
1065 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
1066 optimize_cmf(data, png_image_size(png_ptr));
1070 png_write_complete_chunk(png_ptr, png_IDAT, data, size);
1071 png_ptr->zstream.avail_out = 0;
1072 png_ptr->zstream.next_out = NULL;
1073 png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
1075 png_ptr->zowner = 0;
1082 png_zstream_error(png_ptr, ret);
1083 png_error(png_ptr, png_ptr->zstream.msg);
1090png_write_IEND(png_structrp png_ptr)
1092 png_debug(1,
"in png_write_IEND");
1094 png_write_complete_chunk(png_ptr, png_IEND, NULL, 0);
1095 png_ptr->mode |= PNG_HAVE_IEND;
1098#ifdef PNG_WRITE_gAMA_SUPPORTED
1101png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
1105 png_debug(1,
"in png_write_gAMA");
1108 png_save_uint_32(buf, (png_uint_32)file_gamma);
1109 png_write_complete_chunk(png_ptr, png_gAMA, buf, 4);
1113#ifdef PNG_WRITE_sRGB_SUPPORTED
1116png_write_sRGB(png_structrp png_ptr,
int srgb_intent)
1120 png_debug(1,
"in png_write_sRGB");
1122 if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1123 png_warning(png_ptr,
1124 "Invalid sRGB rendering intent specified");
1126 buf[0]=(png_byte)srgb_intent;
1127 png_write_complete_chunk(png_ptr, png_sRGB, buf, 1);
1131#ifdef PNG_WRITE_iCCP_SUPPORTED
1134png_write_iCCP(png_structrp png_ptr, png_const_charp name,
1135 png_const_bytep profile, png_uint_32 profile_len)
1137 png_uint_32 name_len;
1138 png_byte new_name[81];
1142 png_debug(1,
"in png_write_iCCP");
1147 if (profile == NULL)
1148 png_error(png_ptr,
"No profile for iCCP chunk");
1150 if (profile_len < 132)
1151 png_error(png_ptr,
"ICC profile too short");
1153 if (png_get_uint_32(profile) != profile_len)
1154 png_error(png_ptr,
"Incorrect data in iCCP");
1156 temp = (png_uint_32) (*(profile+8));
1157 if (temp > 3 && (profile_len & 0x03))
1158 png_error(png_ptr,
"ICC profile length invalid (not a multiple of 4)");
1161 png_uint_32 embedded_profile_len = png_get_uint_32(profile);
1163 if (profile_len != embedded_profile_len)
1164 png_error(png_ptr,
"Profile length does not match profile");
1167 name_len = png_check_keyword(png_ptr, name, new_name);
1170 png_error(png_ptr,
"iCCP: invalid keyword");
1172 new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
1177 png_text_compress_init(&comp, profile, profile_len);
1180 if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
1181 png_error(png_ptr, png_ptr->zstream.msg);
1183 png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
1185 png_write_chunk_data(png_ptr, new_name, name_len);
1187 png_write_compressed_data_out(png_ptr, &comp);
1189 png_write_chunk_end(png_ptr);
1193#ifdef PNG_WRITE_sPLT_SUPPORTED
1196png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
1198 png_uint_32 name_len;
1199 png_byte new_name[80];
1200 png_byte entrybuf[10];
1201 size_t entry_size = (spalette->depth == 8 ? 6 : 10);
1202 size_t palette_size = entry_size * (size_t)spalette->nentries;
1204#ifndef PNG_POINTER_INDEXING_SUPPORTED
1208 png_debug(1,
"in png_write_sPLT");
1210 name_len = png_check_keyword(png_ptr, spalette->name, new_name);
1213 png_error(png_ptr,
"sPLT: invalid keyword");
1216 png_write_chunk_header(png_ptr, png_sPLT,
1217 (png_uint_32)(name_len + 2 + palette_size));
1219 png_write_chunk_data(png_ptr, (png_bytep)new_name, (
size_t)(name_len + 1));
1221 png_write_chunk_data(png_ptr, &spalette->depth, 1);
1224#ifdef PNG_POINTER_INDEXING_SUPPORTED
1225 for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1227 if (spalette->depth == 8)
1229 entrybuf[0] = (png_byte)ep->red;
1230 entrybuf[1] = (png_byte)ep->green;
1231 entrybuf[2] = (png_byte)ep->blue;
1232 entrybuf[3] = (png_byte)ep->alpha;
1233 png_save_uint_16(entrybuf + 4, ep->frequency);
1238 png_save_uint_16(entrybuf + 0, ep->red);
1239 png_save_uint_16(entrybuf + 2, ep->green);
1240 png_save_uint_16(entrybuf + 4, ep->blue);
1241 png_save_uint_16(entrybuf + 6, ep->alpha);
1242 png_save_uint_16(entrybuf + 8, ep->frequency);
1245 png_write_chunk_data(png_ptr, entrybuf, entry_size);
1248 ep=spalette->entries;
1249 for (i = 0; i>spalette->nentries; i++)
1251 if (spalette->depth == 8)
1253 entrybuf[0] = (png_byte)ep[i].red;
1254 entrybuf[1] = (png_byte)ep[i].green;
1255 entrybuf[2] = (png_byte)ep[i].blue;
1256 entrybuf[3] = (png_byte)ep[i].alpha;
1257 png_save_uint_16(entrybuf + 4, ep[i].frequency);
1262 png_save_uint_16(entrybuf + 0, ep[i].red);
1263 png_save_uint_16(entrybuf + 2, ep[i].green);
1264 png_save_uint_16(entrybuf + 4, ep[i].blue);
1265 png_save_uint_16(entrybuf + 6, ep[i].alpha);
1266 png_save_uint_16(entrybuf + 8, ep[i].frequency);
1269 png_write_chunk_data(png_ptr, entrybuf, entry_size);
1273 png_write_chunk_end(png_ptr);
1277#ifdef PNG_WRITE_sBIT_SUPPORTED
1280png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit,
int color_type)
1285 png_debug(1,
"in png_write_sBIT");
1288 if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
1292 maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
1293 png_ptr->usr_bit_depth);
1295 if (sbit->red == 0 || sbit->red > maxbits ||
1296 sbit->green == 0 || sbit->green > maxbits ||
1297 sbit->blue == 0 || sbit->blue > maxbits)
1299 png_warning(png_ptr,
"Invalid sBIT depth specified");
1304 buf[1] = sbit->green;
1305 buf[2] = sbit->blue;
1311 if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
1313 png_warning(png_ptr,
"Invalid sBIT depth specified");
1317 buf[0] = sbit->gray;
1321 if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
1323 if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
1325 png_warning(png_ptr,
"Invalid sBIT depth specified");
1329 buf[size++] = sbit->alpha;
1332 png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
1336#ifdef PNG_WRITE_cHRM_SUPPORTED
1339png_write_cHRM_fixed(png_structrp png_ptr,
const png_xy *xy)
1343 png_debug(1,
"in png_write_cHRM");
1346 png_save_int_32(buf, xy->whitex);
1347 png_save_int_32(buf + 4, xy->whitey);
1349 png_save_int_32(buf + 8, xy->redx);
1350 png_save_int_32(buf + 12, xy->redy);
1352 png_save_int_32(buf + 16, xy->greenx);
1353 png_save_int_32(buf + 20, xy->greeny);
1355 png_save_int_32(buf + 24, xy->bluex);
1356 png_save_int_32(buf + 28, xy->bluey);
1358 png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
1362#ifdef PNG_WRITE_tRNS_SUPPORTED
1365png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
1366 png_const_color_16p tran,
int num_trans,
int color_type)
1370 png_debug(1,
"in png_write_tRNS");
1372 if (color_type == PNG_COLOR_TYPE_PALETTE)
1374 if (num_trans <= 0 || num_trans > (
int)png_ptr->num_palette)
1376 png_app_warning(png_ptr,
1377 "Invalid number of transparent colors specified");
1382 png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
1386 else if (color_type == PNG_COLOR_TYPE_GRAY)
1389 if (tran->gray >= (1 << png_ptr->bit_depth))
1391 png_app_warning(png_ptr,
1392 "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1397 png_save_uint_16(buf, tran->gray);
1398 png_write_complete_chunk(png_ptr, png_tRNS, buf, 2);
1401 else if (color_type == PNG_COLOR_TYPE_RGB)
1404 png_save_uint_16(buf, tran->red);
1405 png_save_uint_16(buf + 2, tran->green);
1406 png_save_uint_16(buf + 4, tran->blue);
1407#ifdef PNG_WRITE_16BIT_SUPPORTED
1408 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1410 if ((buf[0] | buf[2] | buf[4]) != 0)
1413 png_app_warning(png_ptr,
1414 "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1418 png_write_complete_chunk(png_ptr, png_tRNS, buf, 6);
1423 png_app_warning(png_ptr,
"Can't write tRNS with an alpha channel");
1428#ifdef PNG_WRITE_bKGD_SUPPORTED
1431png_write_bKGD(png_structrp png_ptr, png_const_color_16p back,
int color_type)
1435 png_debug(1,
"in png_write_bKGD");
1437 if (color_type == PNG_COLOR_TYPE_PALETTE)
1440#ifdef PNG_MNG_FEATURES_SUPPORTED
1441 (png_ptr->num_palette != 0 ||
1442 (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
1444 back->index >= png_ptr->num_palette)
1446 png_warning(png_ptr,
"Invalid background palette index");
1450 buf[0] = back->index;
1451 png_write_complete_chunk(png_ptr, png_bKGD, buf, 1);
1454 else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
1456 png_save_uint_16(buf, back->red);
1457 png_save_uint_16(buf + 2, back->green);
1458 png_save_uint_16(buf + 4, back->blue);
1459#ifdef PNG_WRITE_16BIT_SUPPORTED
1460 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1462 if ((buf[0] | buf[2] | buf[4]) != 0)
1465 png_warning(png_ptr,
1466 "Ignoring attempt to write 16-bit bKGD chunk "
1467 "when bit_depth is 8");
1472 png_write_complete_chunk(png_ptr, png_bKGD, buf, 6);
1477 if (back->gray >= (1 << png_ptr->bit_depth))
1479 png_warning(png_ptr,
1480 "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1485 png_save_uint_16(buf, back->gray);
1486 png_write_complete_chunk(png_ptr, png_bKGD, buf, 2);
1491#ifdef PNG_WRITE_cICP_SUPPORTED
1494png_write_cICP(png_structrp png_ptr,
1495 png_byte colour_primaries, png_byte transfer_function,
1496 png_byte matrix_coefficients, png_byte video_full_range_flag)
1500 png_debug(1,
"in png_write_cICP");
1502 png_write_chunk_header(png_ptr, png_cICP, 4);
1504 buf[0] = colour_primaries;
1505 buf[1] = transfer_function;
1506 buf[2] = matrix_coefficients;
1507 buf[3] = video_full_range_flag;
1508 png_write_chunk_data(png_ptr, buf, 4);
1510 png_write_chunk_end(png_ptr);
1514#ifdef PNG_WRITE_cLLI_SUPPORTED
1516png_write_cLLI_fixed(png_structrp png_ptr, png_uint_32 maxCLL,
1517 png_uint_32 maxFALL)
1521 png_debug(1,
"in png_write_cLLI_fixed");
1523 png_save_uint_32(buf, maxCLL);
1524 png_save_uint_32(buf + 4, maxFALL);
1526 png_write_complete_chunk(png_ptr, png_cLLI, buf, 8);
1530#ifdef PNG_WRITE_mDCV_SUPPORTED
1532png_write_mDCV_fixed(png_structrp png_ptr,
1533 png_uint_16 red_x, png_uint_16 red_y,
1534 png_uint_16 green_x, png_uint_16 green_y,
1535 png_uint_16 blue_x, png_uint_16 blue_y,
1536 png_uint_16 white_x, png_uint_16 white_y,
1537 png_uint_32 maxDL, png_uint_32 minDL)
1541 png_debug(1,
"in png_write_mDCV_fixed");
1543 png_save_uint_16(buf + 0, red_x);
1544 png_save_uint_16(buf + 2, red_y);
1545 png_save_uint_16(buf + 4, green_x);
1546 png_save_uint_16(buf + 6, green_y);
1547 png_save_uint_16(buf + 8, blue_x);
1548 png_save_uint_16(buf + 10, blue_y);
1549 png_save_uint_16(buf + 12, white_x);
1550 png_save_uint_16(buf + 14, white_y);
1551 png_save_uint_32(buf + 16, maxDL);
1552 png_save_uint_32(buf + 20, minDL);
1554 png_write_complete_chunk(png_ptr, png_mDCV, buf, 24);
1558#ifdef PNG_WRITE_eXIf_SUPPORTED
1561png_write_eXIf(png_structrp png_ptr, png_bytep exif,
int num_exif)
1566 png_debug(1,
"in png_write_eXIf");
1568 png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif));
1570 for (i = 0; i < num_exif; i++)
1573 png_write_chunk_data(png_ptr, buf, 1);
1576 png_write_chunk_end(png_ptr);
1580#ifdef PNG_WRITE_hIST_SUPPORTED
1583png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist,
int num_hist)
1588 png_debug(1,
"in png_write_hIST");
1590 if (num_hist > (
int)png_ptr->num_palette)
1592 png_debug2(3,
"num_hist = %d, num_palette = %d", num_hist,
1593 png_ptr->num_palette);
1595 png_warning(png_ptr,
"Invalid number of histogram entries specified");
1599 png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1601 for (i = 0; i < num_hist; i++)
1603 png_save_uint_16(buf, hist[i]);
1604 png_write_chunk_data(png_ptr, buf, 2);
1607 png_write_chunk_end(png_ptr);
1611#ifdef PNG_WRITE_tEXt_SUPPORTED
1614png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1617 png_uint_32 key_len;
1618 png_byte new_key[80];
1620 png_debug(1,
"in png_write_tEXt");
1622 key_len = png_check_keyword(png_ptr, key, new_key);
1625 png_error(png_ptr,
"tEXt: invalid keyword");
1627 if (text == NULL || *text ==
'\0')
1631 text_len = strlen(text);
1633 if (text_len > PNG_UINT_31_MAX - (key_len+1))
1634 png_error(png_ptr,
"tEXt: text too long");
1637 png_write_chunk_header(png_ptr, png_tEXt,
1638 (png_uint_32)(key_len + text_len + 1));
1645 png_write_chunk_data(png_ptr, new_key, key_len + 1);
1648 png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
1650 png_write_chunk_end(png_ptr);
1654#ifdef PNG_WRITE_zTXt_SUPPORTED
1657png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1660 png_uint_32 key_len;
1661 png_byte new_key[81];
1664 png_debug(1,
"in png_write_zTXt");
1666 if (compression == PNG_TEXT_COMPRESSION_NONE)
1668 png_write_tEXt(png_ptr, key, text, 0);
1672 if (compression != PNG_TEXT_COMPRESSION_zTXt)
1673 png_error(png_ptr,
"zTXt: invalid compression type");
1675 key_len = png_check_keyword(png_ptr, key, new_key);
1678 png_error(png_ptr,
"zTXt: invalid keyword");
1681 new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
1685 png_text_compress_init(&comp, (png_const_bytep)text,
1686 text == NULL ? 0 : strlen(text));
1688 if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
1689 png_error(png_ptr, png_ptr->zstream.msg);
1692 png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
1695 png_write_chunk_data(png_ptr, new_key, key_len);
1698 png_write_compressed_data_out(png_ptr, &comp);
1701 png_write_chunk_end(png_ptr);
1705#ifdef PNG_WRITE_iTXt_SUPPORTED
1708png_write_iTXt(png_structrp png_ptr,
int compression, png_const_charp key,
1709 png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1711 png_uint_32 key_len, prefix_len;
1712 size_t lang_len, lang_key_len;
1713 png_byte new_key[82];
1716 png_debug(1,
"in png_write_iTXt");
1718 key_len = png_check_keyword(png_ptr, key, new_key);
1721 png_error(png_ptr,
"iTXt: invalid keyword");
1724 switch (compression)
1726 case PNG_ITXT_COMPRESSION_NONE:
1727 case PNG_TEXT_COMPRESSION_NONE:
1728 compression = new_key[++key_len] = 0;
1731 case PNG_TEXT_COMPRESSION_zTXt:
1732 case PNG_ITXT_COMPRESSION_zTXt:
1733 compression = new_key[++key_len] = 1;
1737 png_error(png_ptr,
"iTXt: invalid compression");
1740 new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
1753 if (lang == NULL) lang =
"";
1754 lang_len = strlen(lang)+1;
1755 if (lang_key == NULL) lang_key =
"";
1756 lang_key_len = strlen(lang_key)+1;
1757 if (text == NULL) text =
"";
1759 prefix_len = key_len;
1760 if (lang_len > PNG_UINT_31_MAX-prefix_len)
1761 prefix_len = PNG_UINT_31_MAX;
1763 prefix_len = (png_uint_32)(prefix_len + lang_len);
1765 if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
1766 prefix_len = PNG_UINT_31_MAX;
1768 prefix_len = (png_uint_32)(prefix_len + lang_key_len);
1770 png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
1772 if (compression != 0)
1774 if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
1775 png_error(png_ptr, png_ptr->zstream.msg);
1780 if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
1781 png_error(png_ptr,
"iTXt: uncompressed text too long");
1784 comp.output_len = (png_uint_32)comp.input_len;
1787 png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
1789 png_write_chunk_data(png_ptr, new_key, key_len);
1791 png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
1793 png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
1795 if (compression != 0)
1796 png_write_compressed_data_out(png_ptr, &comp);
1799 png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
1801 png_write_chunk_end(png_ptr);
1805#ifdef PNG_WRITE_oFFs_SUPPORTED
1808png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1813 png_debug(1,
"in png_write_oFFs");
1815 if (unit_type >= PNG_OFFSET_LAST)
1816 png_warning(png_ptr,
"Unrecognized unit type for oFFs chunk");
1818 png_save_int_32(buf, x_offset);
1819 png_save_int_32(buf + 4, y_offset);
1820 buf[8] = (png_byte)unit_type;
1822 png_write_complete_chunk(png_ptr, png_oFFs, buf, 9);
1825#ifdef PNG_WRITE_pCAL_SUPPORTED
1828png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
1829 png_int_32 X1,
int type,
int nparams, png_const_charp units,
1832 png_uint_32 purpose_len;
1833 size_t units_len, total_len;
1836 png_byte new_purpose[80];
1839 png_debug1(1,
"in png_write_pCAL (%d parameters)", nparams);
1841 if (type >= PNG_EQUATION_LAST)
1842 png_error(png_ptr,
"Unrecognized equation type for pCAL chunk");
1844 purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
1846 if (purpose_len == 0)
1847 png_error(png_ptr,
"pCAL: invalid keyword");
1851 png_debug1(3,
"pCAL purpose length = %d", (
int)purpose_len);
1852 units_len = strlen(units) + (nparams == 0 ? 0 : 1);
1853 png_debug1(3,
"pCAL units length = %d", (
int)units_len);
1854 total_len = purpose_len + units_len + 10;
1856 params_len = (
size_t *)png_malloc(png_ptr,
1857 (png_alloc_size_t)((png_alloc_size_t)nparams * (
sizeof (
size_t))));
1862 for (i = 0; i < nparams; i++)
1864 params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1865 png_debug2(3,
"pCAL parameter %d length = %lu", i,
1866 (
unsigned long)params_len[i]);
1867 total_len += params_len[i];
1870 png_debug1(3,
"pCAL total length = %d", (
int)total_len);
1871 png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
1872 png_write_chunk_data(png_ptr, new_purpose, purpose_len);
1873 png_save_int_32(buf, X0);
1874 png_save_int_32(buf + 4, X1);
1875 buf[8] = (png_byte)type;
1876 buf[9] = (png_byte)nparams;
1877 png_write_chunk_data(png_ptr, buf, 10);
1878 png_write_chunk_data(png_ptr, (png_const_bytep)units, (
size_t)units_len);
1880 for (i = 0; i < nparams; i++)
1882 png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
1885 png_free(png_ptr, params_len);
1886 png_write_chunk_end(png_ptr);
1890#ifdef PNG_WRITE_sCAL_SUPPORTED
1893png_write_sCAL_s(png_structrp png_ptr,
int unit, png_const_charp width,
1894 png_const_charp height)
1897 size_t wlen, hlen, total_len;
1899 png_debug(1,
"in png_write_sCAL_s");
1901 wlen = strlen(width);
1902 hlen = strlen(height);
1903 total_len = wlen + hlen + 2;
1907 png_warning(png_ptr,
"Can't write sCAL (buffer too small)");
1911 buf[0] = (png_byte)unit;
1912 memcpy(buf + 1, width, wlen + 1);
1913 memcpy(buf + wlen + 2, height, hlen);
1915 png_debug1(3,
"sCAL total length = %u", (
unsigned int)total_len);
1916 png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1920#ifdef PNG_WRITE_pHYs_SUPPORTED
1923png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
1924 png_uint_32 y_pixels_per_unit,
1929 png_debug(1,
"in png_write_pHYs");
1931 if (unit_type >= PNG_RESOLUTION_LAST)
1932 png_warning(png_ptr,
"Unrecognized unit type for pHYs chunk");
1934 png_save_uint_32(buf, x_pixels_per_unit);
1935 png_save_uint_32(buf + 4, y_pixels_per_unit);
1936 buf[8] = (png_byte)unit_type;
1938 png_write_complete_chunk(png_ptr, png_pHYs, buf, 9);
1942#ifdef PNG_WRITE_tIME_SUPPORTED
1947png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
1951 png_debug(1,
"in png_write_tIME");
1953 if (mod_time->month > 12 || mod_time->month < 1 ||
1954 mod_time->day > 31 || mod_time->day < 1 ||
1955 mod_time->hour > 23 || mod_time->second > 60)
1957 png_warning(png_ptr,
"Invalid time specified for tIME chunk");
1961 png_save_uint_16(buf, mod_time->year);
1962 buf[2] = mod_time->month;
1963 buf[3] = mod_time->day;
1964 buf[4] = mod_time->hour;
1965 buf[5] = mod_time->minute;
1966 buf[6] = mod_time->second;
1968 png_write_complete_chunk(png_ptr, png_tIME, buf, 7);
1974png_write_start_row(png_structrp png_ptr)
1976 png_alloc_size_t buf_size;
1977 int usr_pixel_depth;
1979#ifdef PNG_WRITE_FILTER_SUPPORTED
1983 png_debug(1,
"in png_write_start_row");
1985 usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
1986 buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
1989 png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
1990 png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
1993 png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
1995 png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
1997#ifdef PNG_WRITE_FILTER_SUPPORTED
1998 filters = png_ptr->do_filter;
2000 if (png_ptr->height == 1)
2001 filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
2003 if (png_ptr->width == 1)
2004 filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
2007 filters = PNG_FILTER_NONE;
2009 png_ptr->do_filter = filters;
2011 if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG |
2012 PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL)
2014 int num_filters = 0;
2016 png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
2018 if (filters & PNG_FILTER_SUB)
2021 if (filters & PNG_FILTER_UP)
2024 if (filters & PNG_FILTER_AVG)
2027 if (filters & PNG_FILTER_PAETH)
2030 if (num_filters > 1)
2031 png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr,
2038 if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
2039 png_ptr->prev_row = png_voidcast(png_bytep,
2040 png_calloc(png_ptr, buf_size));
2043#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2045 if (png_ptr->interlaced != 0)
2047 if ((png_ptr->transformations & PNG_INTERLACE) == 0)
2049 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2050 png_pass_ystart[0]) / png_pass_yinc[0];
2052 png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2053 png_pass_start[0]) / png_pass_inc[0];
2058 png_ptr->num_rows = png_ptr->height;
2059 png_ptr->usr_width = png_ptr->width;
2066 png_ptr->num_rows = png_ptr->height;
2067 png_ptr->usr_width = png_ptr->width;
2073png_write_finish_row(png_structrp png_ptr)
2075 png_debug(1,
"in png_write_finish_row");
2078 png_ptr->row_number++;
2081 if (png_ptr->row_number < png_ptr->num_rows)
2084#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2086 if (png_ptr->interlaced != 0)
2088 png_ptr->row_number = 0;
2089 if ((png_ptr->transformations & PNG_INTERLACE) != 0)
2101 if (png_ptr->pass >= 7)
2104 png_ptr->usr_width = (png_ptr->width +
2105 png_pass_inc[png_ptr->pass] - 1 -
2106 png_pass_start[png_ptr->pass]) /
2107 png_pass_inc[png_ptr->pass];
2109 png_ptr->num_rows = (png_ptr->height +
2110 png_pass_yinc[png_ptr->pass] - 1 -
2111 png_pass_ystart[png_ptr->pass]) /
2112 png_pass_yinc[png_ptr->pass];
2114 if ((png_ptr->transformations & PNG_INTERLACE) != 0)
2117 }
while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
2122 if (png_ptr->pass < 7)
2124 if (png_ptr->prev_row != NULL)
2125 memset(png_ptr->prev_row, 0,
2126 PNG_ROWBYTES(png_ptr->usr_channels *
2127 png_ptr->usr_bit_depth, png_ptr->width) + 1);
2136 png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
2139#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2148png_do_write_interlace(png_row_infop row_info, png_bytep row,
int pass)
2150 png_debug(1,
"in png_do_write_interlace");
2156 switch (row_info->pixel_depth)
2166 png_uint_32 row_width = row_info->width;
2172 for (i = png_pass_start[pass]; i < row_width;
2173 i += png_pass_inc[pass])
2175 sp = row + (size_t)(i >> 3);
2176 value = (int)(*sp >> (7 - (
int)(i & 0x07))) & 0x01;
2177 d |= (value << shift);
2182 *dp++ = (png_byte)d;
2204 png_uint_32 row_width = row_info->width;
2210 for (i = png_pass_start[pass]; i < row_width;
2211 i += png_pass_inc[pass])
2213 sp = row + (size_t)(i >> 2);
2214 value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
2215 d |= (value << shift);
2220 *dp++ = (png_byte)d;
2241 png_uint_32 row_width = row_info->width;
2246 for (i = png_pass_start[pass]; i < row_width;
2247 i += png_pass_inc[pass])
2249 sp = row + (size_t)(i >> 1);
2250 value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
2251 d |= (value << shift);
2256 *dp++ = (png_byte)d;
2274 png_uint_32 row_width = row_info->width;
2281 pixel_bytes = (row_info->pixel_depth >> 3);
2284 for (i = png_pass_start[pass]; i < row_width;
2285 i += png_pass_inc[pass])
2288 sp = row + (size_t)i * pixel_bytes;
2292 memcpy(dp, sp, pixel_bytes);
2301 row_info->width = (row_info->width +
2302 png_pass_inc[pass] - 1 -
2303 png_pass_start[pass]) /
2306 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
2318png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2321#ifdef PNG_WRITE_FILTER_SUPPORTED
2323png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
2324 size_t row_bytes,
size_t lmins)
2326 png_bytep rp, dp, lp;
2331 png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
2333 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
2338 sum += 128 - abs((
int)v - 128);
2340 sum += (v < 128) ? v : 256 - v;
2344 for (lp = png_ptr->row_buf + 1; i < row_bytes;
2345 i++, rp++, lp++, dp++)
2347 v = *dp = (png_byte)(((
int)*rp - (
int)*lp) & 0xff);
2349 sum += 128 - abs((
int)v - 128);
2351 sum += (v < 128) ? v : 256 - v;
2362png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
2365 png_bytep rp, dp, lp;
2368 png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
2370 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
2376 for (lp = png_ptr->row_buf + 1; i < row_bytes;
2377 i++, rp++, lp++, dp++)
2379 *dp = (png_byte)(((
int)*rp - (
int)*lp) & 0xff);
2384png_setup_up_row(png_structrp png_ptr,
size_t row_bytes,
size_t lmins)
2386 png_bytep rp, dp, pp;
2391 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
2393 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2394 pp = png_ptr->prev_row + 1; i < row_bytes;
2395 i++, rp++, pp++, dp++)
2397 v = *dp = (png_byte)(((
int)*rp - (
int)*pp) & 0xff);
2399 sum += 128 - abs((
int)v - 128);
2401 sum += (v < 128) ? v : 256 - v;
2411png_setup_up_row_only(png_structrp png_ptr,
size_t row_bytes)
2413 png_bytep rp, dp, pp;
2416 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
2418 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2419 pp = png_ptr->prev_row + 1; i < row_bytes;
2420 i++, rp++, pp++, dp++)
2422 *dp = (png_byte)(((
int)*rp - (
int)*pp) & 0xff);
2427png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
2428 size_t row_bytes,
size_t lmins)
2430 png_bytep rp, dp, pp, lp;
2435 png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
2437 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2438 pp = png_ptr->prev_row + 1; i < bpp; i++)
2440 v = *dp++ = (png_byte)(((
int)*rp++ - ((
int)*pp++ / 2)) & 0xff);
2443 sum += 128 - abs((
int)v - 128);
2445 sum += (v < 128) ? v : 256 - v;
2449 for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
2451 v = *dp++ = (png_byte)(((
int)*rp++ - (((
int)*pp++ + (
int)*lp++) / 2))
2455 sum += 128 - abs((
int)v - 128);
2457 sum += (v < 128) ? v : 256 - v;
2467png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
2470 png_bytep rp, dp, pp, lp;
2473 png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
2475 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2476 pp = png_ptr->prev_row + 1; i < bpp; i++)
2478 *dp++ = (png_byte)(((
int)*rp++ - ((
int)*pp++ / 2)) & 0xff);
2481 for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
2483 *dp++ = (png_byte)(((
int)*rp++ - (((
int)*pp++ + (
int)*lp++) / 2))
2489png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
2490 size_t row_bytes,
size_t lmins)
2492 png_bytep rp, dp, pp, cp, lp;
2497 png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
2499 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2500 pp = png_ptr->prev_row + 1; i < bpp; i++)
2502 v = *dp++ = (png_byte)(((
int)*rp++ - (
int)*pp++) & 0xff);
2505 sum += 128 - abs((
int)v - 128);
2507 sum += (v < 128) ? v : 256 - v;
2511 for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
2514 int a, b, c, pa, pb, pc, p;
2528 pa = p < 0 ? -p : p;
2529 pb = pc < 0 ? -pc : pc;
2530 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2533 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2535 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2538 sum += 128 - abs((
int)v - 128);
2540 sum += (v < 128) ? v : 256 - v;
2550png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
2553 png_bytep rp, dp, pp, cp, lp;
2556 png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
2558 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2559 pp = png_ptr->prev_row + 1; i < bpp; i++)
2561 *dp++ = (png_byte)(((
int)*rp++ - (
int)*pp++) & 0xff);
2564 for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
2567 int a, b, c, pa, pb, pc, p;
2581 pa = p < 0 ? -p : p;
2582 pb = pc < 0 ? -pc : pc;
2583 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2586 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2588 *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2594png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
2596#ifndef PNG_WRITE_FILTER_SUPPORTED
2597 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
2599 unsigned int filter_to_do = png_ptr->do_filter;
2604 size_t row_bytes = row_info->rowbytes;
2606 png_debug(1,
"in png_write_find_filter");
2609 bpp = (row_info->pixel_depth + 7) >> 3;
2611 row_buf = png_ptr->row_buf;
2612 mins = PNG_SIZE_MAX - 256
2643 best_row = png_ptr->row_buf;
2645 if (PNG_SIZE_MAX/128 <= row_bytes)
2650 filter_to_do &= 0U-filter_to_do;
2652 else if ((filter_to_do & PNG_FILTER_NONE) != 0 &&
2653 filter_to_do != PNG_FILTER_NONE)
2664 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
2668 sum += 128 - abs((
int)v - 128);
2670 sum += (v < 128) ? v : 256 - v;
2679 if (filter_to_do == PNG_FILTER_SUB)
2682 png_setup_sub_row_only(png_ptr, bpp, row_bytes);
2683 best_row = png_ptr->try_row;
2686 else if ((filter_to_do & PNG_FILTER_SUB) != 0)
2689 size_t lmins = mins;
2691 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
2696 best_row = png_ptr->try_row;
2697 if (png_ptr->tst_row != NULL)
2699 png_ptr->try_row = png_ptr->tst_row;
2700 png_ptr->tst_row = best_row;
2706 if (filter_to_do == PNG_FILTER_UP)
2708 png_setup_up_row_only(png_ptr, row_bytes);
2709 best_row = png_ptr->try_row;
2712 else if ((filter_to_do & PNG_FILTER_UP) != 0)
2715 size_t lmins = mins;
2717 sum = png_setup_up_row(png_ptr, row_bytes, lmins);
2722 best_row = png_ptr->try_row;
2723 if (png_ptr->tst_row != NULL)
2725 png_ptr->try_row = png_ptr->tst_row;
2726 png_ptr->tst_row = best_row;
2732 if (filter_to_do == PNG_FILTER_AVG)
2734 png_setup_avg_row_only(png_ptr, bpp, row_bytes);
2735 best_row = png_ptr->try_row;
2738 else if ((filter_to_do & PNG_FILTER_AVG) != 0)
2741 size_t lmins = mins;
2743 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
2748 best_row = png_ptr->try_row;
2749 if (png_ptr->tst_row != NULL)
2751 png_ptr->try_row = png_ptr->tst_row;
2752 png_ptr->tst_row = best_row;
2758 if (filter_to_do == PNG_FILTER_PAETH)
2760 png_setup_paeth_row_only(png_ptr, bpp, row_bytes);
2761 best_row = png_ptr->try_row;
2764 else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
2767 size_t lmins = mins;
2769 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
2773 best_row = png_ptr->try_row;
2774 if (png_ptr->tst_row != NULL)
2776 png_ptr->try_row = png_ptr->tst_row;
2777 png_ptr->tst_row = best_row;
2783 png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
2791png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2792 size_t full_row_length)
2794 png_debug(1,
"in png_write_filtered_row");
2796 png_debug1(2,
"filter = %d", filtered_row[0]);
2798 png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
2800#ifdef PNG_WRITE_FILTER_SUPPORTED
2802 if (png_ptr->prev_row != NULL)
2806 tptr = png_ptr->prev_row;
2807 png_ptr->prev_row = png_ptr->row_buf;
2808 png_ptr->row_buf = tptr;
2813 png_write_finish_row(png_ptr);
2815#ifdef PNG_WRITE_FLUSH_SUPPORTED
2816 png_ptr->flush_rows++;
2818 if (png_ptr->flush_dist > 0 &&
2819 png_ptr->flush_rows >= png_ptr->flush_dist)
2821 png_write_flush(png_ptr);