14#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
18#ifdef PNG_WRITE_SUPPORTED
20#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
23write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
26 if (info_ptr->unknown_chunks_num != 0)
28 png_const_unknown_chunkp up;
30 png_debug(5,
"writing extra chunks");
32 for (up = info_ptr->unknown_chunks;
33 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
35 if ((up->location & where) != 0)
40#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
41 int keep = png_handle_as_unknown(png_ptr, up->name);
55 if (keep != PNG_HANDLE_CHUNK_NEVER &&
56 ((up->name[3] & 0x20) ||
57 keep == PNG_HANDLE_CHUNK_ALWAYS ||
58 (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
59 png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
64 png_warning(png_ptr,
"Writing zero-length unknown chunk");
66 png_write_chunk(png_ptr, up->name, up->data, up->size);
83png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
85 png_debug(1,
"in png_write_info_before_PLTE");
87 if (png_ptr == NULL || info_ptr == NULL)
90 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
93 png_write_sig(png_ptr);
95#ifdef PNG_MNG_FEATURES_SUPPORTED
96 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
97 png_ptr->mng_features_permitted != 0)
100 "MNG features are not allowed in a PNG datastream");
101 png_ptr->mng_features_permitted = 0;
106 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
107 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
108 info_ptr->filter_type,
109#ifdef PNG_WRITE_INTERLACING_SUPPORTED
110 info_ptr->interlace_type
130#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
140 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
143#ifdef PNG_WRITE_sBIT_SUPPORTED
152 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
153 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
166#ifdef PNG_WRITE_cLLI_SUPPORTED
167 if ((info_ptr->valid & PNG_INFO_cLLI) != 0)
169 png_write_cLLI_fixed(png_ptr, info_ptr->maxCLL, info_ptr->maxFALL);
172#ifdef PNG_WRITE_mDCV_SUPPORTED
173 if ((info_ptr->valid & PNG_INFO_mDCV) != 0)
175 png_write_mDCV_fixed(png_ptr,
176 info_ptr->mastering_red_x, info_ptr->mastering_red_y,
177 info_ptr->mastering_green_x, info_ptr->mastering_green_y,
178 info_ptr->mastering_blue_x, info_ptr->mastering_blue_y,
179 info_ptr->mastering_white_x, info_ptr->mastering_white_y,
180 info_ptr->mastering_maxDL, info_ptr->mastering_minDL);
184# ifdef PNG_WRITE_cICP_SUPPORTED
185 if ((info_ptr->valid & PNG_INFO_cICP) != 0)
187 png_write_cICP(png_ptr,
188 info_ptr->cicp_colour_primaries,
189 info_ptr->cicp_transfer_function,
190 info_ptr->cicp_matrix_coefficients,
191 info_ptr->cicp_video_full_range_flag);
195# ifdef PNG_WRITE_iCCP_SUPPORTED
196 if ((info_ptr->valid & PNG_INFO_iCCP) != 0)
198 png_write_iCCP(png_ptr, info_ptr->iccp_name,
199 info_ptr->iccp_profile, info_ptr->iccp_proflen);
203# ifdef PNG_WRITE_sRGB_SUPPORTED
204 if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
205 png_write_sRGB(png_ptr, info_ptr->rendering_intent);
208# ifdef PNG_WRITE_gAMA_SUPPORTED
209 if ((info_ptr->valid & PNG_INFO_gAMA) != 0)
210 png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
213# ifdef PNG_WRITE_cHRM_SUPPORTED
214 if ((info_ptr->valid & PNG_INFO_cHRM) != 0)
215 png_write_cHRM_fixed(png_ptr, &info_ptr->cHRM);
218 png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
223png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
225#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
229 png_debug(1,
"in png_write_info");
231 if (png_ptr == NULL || info_ptr == NULL)
234 png_write_info_before_PLTE(png_ptr, info_ptr);
236 if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
237 png_write_PLTE(png_ptr, info_ptr->palette,
238 (png_uint_32)info_ptr->num_palette);
240 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
241 png_error(png_ptr,
"Valid palette required for paletted images");
243#ifdef PNG_WRITE_tRNS_SUPPORTED
244 if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
246#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
248 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
249 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
253 jend = info_ptr->num_trans;
254 if (jend > PNG_MAX_PALETTE_LENGTH)
255 jend = PNG_MAX_PALETTE_LENGTH;
257 for (j = 0; j<jend; ++j)
258 info_ptr->trans_alpha[j] =
259 (png_byte)(255 - info_ptr->trans_alpha[j]);
262 png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
263 info_ptr->num_trans, info_ptr->color_type);
266#ifdef PNG_WRITE_bKGD_SUPPORTED
267 if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
268 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
271#ifdef PNG_WRITE_eXIf_SUPPORTED
272 if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
274 png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
275 png_ptr->mode |= PNG_WROTE_eXIf;
279#ifdef PNG_WRITE_hIST_SUPPORTED
280 if ((info_ptr->valid & PNG_INFO_hIST) != 0)
281 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
284#ifdef PNG_WRITE_oFFs_SUPPORTED
285 if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
286 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
287 info_ptr->offset_unit_type);
290#ifdef PNG_WRITE_pCAL_SUPPORTED
291 if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
292 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
293 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
294 info_ptr->pcal_units, info_ptr->pcal_params);
297#ifdef PNG_WRITE_sCAL_SUPPORTED
298 if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
299 png_write_sCAL_s(png_ptr, (
int)info_ptr->scal_unit,
300 info_ptr->scal_s_width, info_ptr->scal_s_height);
303#ifdef PNG_WRITE_pHYs_SUPPORTED
304 if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
305 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
306 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
309#ifdef PNG_WRITE_tIME_SUPPORTED
310 if ((info_ptr->valid & PNG_INFO_tIME) != 0)
312 png_write_tIME(png_ptr, &(info_ptr->mod_time));
313 png_ptr->mode |= PNG_WROTE_tIME;
317#ifdef PNG_WRITE_sPLT_SUPPORTED
318 if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
319 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
320 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
323#ifdef PNG_WRITE_TEXT_SUPPORTED
325 for (i = 0; i < info_ptr->num_text; i++)
327 png_debug2(2,
"Writing header text chunk %d, type %d", i,
328 info_ptr->text[i].compression);
330 if (info_ptr->text[i].compression > 0)
332#ifdef PNG_WRITE_iTXt_SUPPORTED
334 png_write_iTXt(png_ptr,
335 info_ptr->text[i].compression,
336 info_ptr->text[i].key,
337 info_ptr->text[i].lang,
338 info_ptr->text[i].lang_key,
339 info_ptr->text[i].text);
341 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
342 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
344 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
346 png_warning(png_ptr,
"Unable to write international text");
351 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
353#ifdef PNG_WRITE_zTXt_SUPPORTED
355 png_write_zTXt(png_ptr, info_ptr->text[i].key,
356 info_ptr->text[i].text, info_ptr->text[i].compression);
358 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
360 png_warning(png_ptr,
"Unable to write compressed text");
364 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
366#ifdef PNG_WRITE_tEXt_SUPPORTED
368 png_write_tEXt(png_ptr, info_ptr->text[i].key,
369 info_ptr->text[i].text,
372 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
375 png_warning(png_ptr,
"Unable to write uncompressed text");
381#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
382 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
392png_write_end(png_structrp png_ptr, png_inforp info_ptr)
394 png_debug(1,
"in png_write_end");
399 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
400 png_error(png_ptr,
"No IDATs written into file");
402#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
403 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
404 png_ptr->num_palette_max >= png_ptr->num_palette)
405 png_benign_error(png_ptr,
"Wrote palette index exceeding num_palette");
409 if (info_ptr != NULL)
411#ifdef PNG_WRITE_TEXT_SUPPORTED
414#ifdef PNG_WRITE_tIME_SUPPORTED
416 if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
417 (png_ptr->mode & PNG_WROTE_tIME) == 0)
418 png_write_tIME(png_ptr, &(info_ptr->mod_time));
421#ifdef PNG_WRITE_TEXT_SUPPORTED
423 for (i = 0; i < info_ptr->num_text; i++)
425 png_debug2(2,
"Writing trailer text chunk %d, type %d", i,
426 info_ptr->text[i].compression);
428 if (info_ptr->text[i].compression > 0)
430#ifdef PNG_WRITE_iTXt_SUPPORTED
432 png_write_iTXt(png_ptr,
433 info_ptr->text[i].compression,
434 info_ptr->text[i].key,
435 info_ptr->text[i].lang,
436 info_ptr->text[i].lang_key,
437 info_ptr->text[i].text);
439 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
440 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
442 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
444 png_warning(png_ptr,
"Unable to write international text");
448 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
450#ifdef PNG_WRITE_zTXt_SUPPORTED
452 png_write_zTXt(png_ptr, info_ptr->text[i].key,
453 info_ptr->text[i].text, info_ptr->text[i].compression);
455 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
457 png_warning(png_ptr,
"Unable to write compressed text");
461 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
463#ifdef PNG_WRITE_tEXt_SUPPORTED
465 png_write_tEXt(png_ptr, info_ptr->text[i].key,
466 info_ptr->text[i].text, 0);
468 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
470 png_warning(png_ptr,
"Unable to write uncompressed text");
476#ifdef PNG_WRITE_eXIf_SUPPORTED
477 if ((info_ptr->valid & PNG_INFO_eXIf) != 0 &&
478 (png_ptr->mode & PNG_WROTE_eXIf) == 0)
479 png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
482#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
483 write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
487 png_ptr->mode |= PNG_AFTER_IDAT;
490 png_write_IEND(png_ptr);
499#ifdef PNG_WRITE_FLUSH_SUPPORTED
500# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
506#ifdef PNG_CONVERT_tIME_SUPPORTED
508png_convert_from_struct_tm(png_timep ptime,
const struct tm * ttime)
510 png_debug(1,
"in png_convert_from_struct_tm");
512 ptime->year = (png_uint_16)(1900 + ttime->tm_year);
513 ptime->month = (png_byte)(ttime->tm_mon + 1);
514 ptime->day = (png_byte)ttime->tm_mday;
515 ptime->hour = (png_byte)ttime->tm_hour;
516 ptime->minute = (png_byte)ttime->tm_min;
517 ptime->second = (png_byte)ttime->tm_sec;
521png_convert_from_time_t(png_timep ptime, time_t ttime)
525 png_debug(1,
"in png_convert_from_time_t");
527 tbuf = gmtime(&ttime);
534 memset(ptime, 0,
sizeof(*ptime));
538 png_convert_from_struct_tm(ptime, tbuf);
543PNG_FUNCTION(png_structp,PNGAPI
544png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
545 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
547#ifndef PNG_USER_MEM_SUPPORTED
548 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
549 error_fn, warn_fn, NULL, NULL, NULL);
551 return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
552 warn_fn, NULL, NULL, NULL);
556PNG_FUNCTION(png_structp,PNGAPI
557png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
558 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
559 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
561 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
562 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
569 png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
575 png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
576 png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
577 png_ptr->zlib_mem_level = 8;
578 png_ptr->zlib_window_bits = 15;
579 png_ptr->zlib_method = 8;
581#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
582 png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
583 png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
584 png_ptr->zlib_text_mem_level = 8;
585 png_ptr->zlib_text_window_bits = 15;
586 png_ptr->zlib_text_method = 8;
594#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
598 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
605 png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
612 png_set_write_fn(png_ptr, NULL, NULL, NULL);
625png_write_rows(png_structrp png_ptr, png_bytepp row,
626 png_uint_32 num_rows)
631 png_debug(1,
"in png_write_rows");
637 for (i = 0, rp = row; i < num_rows; i++, rp++)
639 png_write_row(png_ptr, *rp);
647png_write_image(png_structrp png_ptr, png_bytepp image)
656 png_debug(1,
"in png_write_image");
658#ifdef PNG_WRITE_INTERLACING_SUPPORTED
662 num_pass = png_set_interlace_handling(png_ptr);
667 for (pass = 0; pass < num_pass; pass++)
670 for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
672 png_write_row(png_ptr, *rp);
677#ifdef PNG_MNG_FEATURES_SUPPORTED
680png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
682 png_debug(1,
"in png_do_write_intrapixel");
684 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
687 png_uint_32 row_width = row_info->width;
688 if (row_info->bit_depth == 8)
693 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
696 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
702 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
704 *(rp) = (png_byte)(*rp - *(rp + 1));
705 *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
709#ifdef PNG_WRITE_16BIT_SUPPORTED
710 else if (row_info->bit_depth == 16)
715 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
718 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
724 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
726 png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);
727 png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
728 png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
729 png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
730 png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
731 *(rp ) = (png_byte)(red >> 8);
732 *(rp + 1) = (png_byte)red;
733 *(rp + 4) = (png_byte)(blue >> 8);
734 *(rp + 5) = (png_byte)blue;
744png_write_row(png_structrp png_ptr, png_const_bytep row)
747 png_row_info row_info;
749 png_debug2(1,
"in png_write_row (row %u, pass %d)",
750 png_ptr->row_number, png_ptr->pass);
756 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
759 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
761 "png_write_info was never called before png_write_row");
764#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
765 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
766 png_warning(png_ptr,
"PNG_WRITE_INVERT_SUPPORTED is not defined");
769#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
770 if ((png_ptr->transformations & PNG_FILLER) != 0)
771 png_warning(png_ptr,
"PNG_WRITE_FILLER_SUPPORTED is not defined");
773#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
774 defined(PNG_READ_PACKSWAP_SUPPORTED)
775 if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
777 "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
780#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
781 if ((png_ptr->transformations & PNG_PACK) != 0)
782 png_warning(png_ptr,
"PNG_WRITE_PACK_SUPPORTED is not defined");
785#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
786 if ((png_ptr->transformations & PNG_SHIFT) != 0)
787 png_warning(png_ptr,
"PNG_WRITE_SHIFT_SUPPORTED is not defined");
790#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
791 if ((png_ptr->transformations & PNG_BGR) != 0)
792 png_warning(png_ptr,
"PNG_WRITE_BGR_SUPPORTED is not defined");
795#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
796 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
797 png_warning(png_ptr,
"PNG_WRITE_SWAP_SUPPORTED is not defined");
800 png_write_start_row(png_ptr);
803#ifdef PNG_WRITE_INTERLACING_SUPPORTED
805 if (png_ptr->interlaced != 0 &&
806 (png_ptr->transformations & PNG_INTERLACE) != 0)
808 switch (png_ptr->pass)
811 if ((png_ptr->row_number & 0x07) != 0)
813 png_write_finish_row(png_ptr);
819 if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
821 png_write_finish_row(png_ptr);
827 if ((png_ptr->row_number & 0x07) != 4)
829 png_write_finish_row(png_ptr);
835 if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
837 png_write_finish_row(png_ptr);
843 if ((png_ptr->row_number & 0x03) != 2)
845 png_write_finish_row(png_ptr);
851 if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
853 png_write_finish_row(png_ptr);
859 if ((png_ptr->row_number & 0x01) == 0)
861 png_write_finish_row(png_ptr);
873 row_info.color_type = png_ptr->color_type;
874 row_info.width = png_ptr->usr_width;
875 row_info.channels = png_ptr->usr_channels;
876 row_info.bit_depth = png_ptr->usr_bit_depth;
877 row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
878 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
880 png_debug1(3,
"row_info->color_type = %d", row_info.color_type);
881 png_debug1(3,
"row_info->width = %u", row_info.width);
882 png_debug1(3,
"row_info->channels = %d", row_info.channels);
883 png_debug1(3,
"row_info->bit_depth = %d", row_info.bit_depth);
884 png_debug1(3,
"row_info->pixel_depth = %d", row_info.pixel_depth);
885 png_debug1(3,
"row_info->rowbytes = %lu", (
unsigned long)row_info.rowbytes);
888 memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
890#ifdef PNG_WRITE_INTERLACING_SUPPORTED
892 if (png_ptr->interlaced && png_ptr->pass < 6 &&
893 (png_ptr->transformations & PNG_INTERLACE) != 0)
895 png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
897 if (row_info.width == 0)
899 png_write_finish_row(png_ptr);
905#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
907 if (png_ptr->transformations != 0)
908 png_do_write_transformations(png_ptr, &row_info);
914 if (row_info.pixel_depth != png_ptr->pixel_depth ||
915 row_info.pixel_depth != png_ptr->transformed_pixel_depth)
916 png_error(png_ptr,
"internal write transform logic error");
918#ifdef PNG_MNG_FEATURES_SUPPORTED
928 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
929 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
932 png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
937#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
939 if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
940 png_ptr->num_palette_max >= 0)
941 png_do_check_palette_indexes(png_ptr, &row_info);
945 png_write_find_filter(png_ptr, &row_info);
947 if (png_ptr->write_row_fn != NULL)
948 (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
951#ifdef PNG_WRITE_FLUSH_SUPPORTED
954png_set_flush(png_structrp png_ptr,
int nrows)
956 png_debug(1,
"in png_set_flush");
961 png_ptr->flush_dist = (nrows < 0 ? 0 : (png_uint_32)nrows);
966png_write_flush(png_structrp png_ptr)
968 png_debug(1,
"in png_write_flush");
974 if (png_ptr->row_number >= png_ptr->num_rows)
977 png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
978 png_ptr->flush_rows = 0;
985png_write_destroy(png_structrp png_ptr)
987 png_debug(1,
"in png_write_destroy");
990 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
991 deflateEnd(&png_ptr->zstream);
994 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
995 png_free(png_ptr, png_ptr->row_buf);
996 png_ptr->row_buf = NULL;
997#ifdef PNG_WRITE_FILTER_SUPPORTED
998 png_free(png_ptr, png_ptr->prev_row);
999 png_free(png_ptr, png_ptr->try_row);
1000 png_free(png_ptr, png_ptr->tst_row);
1001 png_ptr->prev_row = NULL;
1002 png_ptr->try_row = NULL;
1003 png_ptr->tst_row = NULL;
1006#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
1007 png_free(png_ptr, png_ptr->chunk_list);
1008 png_ptr->chunk_list = NULL;
1025png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
1027 png_debug(1,
"in png_destroy_write_struct");
1029 if (png_ptr_ptr != NULL)
1031 png_structrp png_ptr = *png_ptr_ptr;
1033 if (png_ptr != NULL)
1035 png_destroy_info_struct(png_ptr, info_ptr_ptr);
1037 *png_ptr_ptr = NULL;
1038 png_write_destroy(png_ptr);
1039 png_destroy_png_struct(png_ptr);
1046png_set_filter(png_structrp png_ptr,
int method,
int filters)
1048 png_debug(1,
"in png_set_filter");
1050 if (png_ptr == NULL)
1053#ifdef PNG_MNG_FEATURES_SUPPORTED
1054 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
1055 (method == PNG_INTRAPIXEL_DIFFERENCING))
1056 method = PNG_FILTER_TYPE_BASE;
1059 if (method == PNG_FILTER_TYPE_BASE)
1061 switch (filters & (PNG_ALL_FILTERS | 0x07))
1063#ifdef PNG_WRITE_FILTER_SUPPORTED
1066 case 7: png_app_error(png_ptr,
"Unknown row filter for method 0");
1069 case PNG_FILTER_VALUE_NONE:
1070 png_ptr->do_filter = PNG_FILTER_NONE;
break;
1072#ifdef PNG_WRITE_FILTER_SUPPORTED
1073 case PNG_FILTER_VALUE_SUB:
1074 png_ptr->do_filter = PNG_FILTER_SUB;
break;
1076 case PNG_FILTER_VALUE_UP:
1077 png_ptr->do_filter = PNG_FILTER_UP;
break;
1079 case PNG_FILTER_VALUE_AVG:
1080 png_ptr->do_filter = PNG_FILTER_AVG;
break;
1082 case PNG_FILTER_VALUE_PAETH:
1083 png_ptr->do_filter = PNG_FILTER_PAETH;
break;
1086 png_ptr->do_filter = (png_byte)filters;
break;
1089 png_app_error(png_ptr,
"Unknown row filter for method 0");
1093#ifdef PNG_WRITE_FILTER_SUPPORTED
1107 if (png_ptr->row_buf != NULL)
1110 png_alloc_size_t buf_size;
1116 if (png_ptr->height == 1)
1117 filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1119 if (png_ptr->width == 1)
1120 filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1122 if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0
1123 && png_ptr->prev_row == NULL)
1128 png_app_warning(png_ptr,
1129 "png_set_filter: UP/AVG/PAETH cannot be added after start");
1130 filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1135 if (filters & PNG_FILTER_SUB)
1138 if (filters & PNG_FILTER_UP)
1141 if (filters & PNG_FILTER_AVG)
1144 if (filters & PNG_FILTER_PAETH)
1150 buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth,
1151 png_ptr->width) + 1;
1153 if (png_ptr->try_row == NULL)
1154 png_ptr->try_row = png_voidcast(png_bytep,
1155 png_malloc(png_ptr, buf_size));
1157 if (num_filters > 1)
1159 if (png_ptr->tst_row == NULL)
1160 png_ptr->tst_row = png_voidcast(png_bytep,
1161 png_malloc(png_ptr, buf_size));
1164 png_ptr->do_filter = (png_byte)filters;
1168 png_error(png_ptr,
"Unknown custom filter method");
1171#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
1173#ifdef PNG_FLOATING_POINT_SUPPORTED
1175png_set_filter_heuristics(png_structrp png_ptr,
int heuristic_method,
1176 int num_weights, png_const_doublep filter_weights,
1177 png_const_doublep filter_costs)
1180 PNG_UNUSED(heuristic_method)
1181 PNG_UNUSED(num_weights)
1182 PNG_UNUSED(filter_weights)
1183 PNG_UNUSED(filter_costs)
1187#ifdef PNG_FIXED_POINT_SUPPORTED
1189png_set_filter_heuristics_fixed(png_structrp png_ptr,
int heuristic_method,
1190 int num_weights, png_const_fixed_point_p filter_weights,
1191 png_const_fixed_point_p filter_costs)
1194 PNG_UNUSED(heuristic_method)
1195 PNG_UNUSED(num_weights)
1196 PNG_UNUSED(filter_weights)
1197 PNG_UNUSED(filter_costs)
1202#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
1204png_set_compression_level(png_structrp png_ptr,
int level)
1206 png_debug(1,
"in png_set_compression_level");
1208 if (png_ptr == NULL)
1211 png_ptr->zlib_level = level;
1215png_set_compression_mem_level(png_structrp png_ptr,
int mem_level)
1217 png_debug(1,
"in png_set_compression_mem_level");
1219 if (png_ptr == NULL)
1222 png_ptr->zlib_mem_level = mem_level;
1226png_set_compression_strategy(png_structrp png_ptr,
int strategy)
1228 png_debug(1,
"in png_set_compression_strategy");
1230 if (png_ptr == NULL)
1235 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
1236 png_ptr->zlib_strategy = strategy;
1243png_set_compression_window_bits(png_structrp png_ptr,
int window_bits)
1245 png_debug(1,
"in png_set_compression_window_bits");
1247 if (png_ptr == NULL)
1256 if (window_bits > 15)
1258 png_warning(png_ptr,
"Only compression windows <= 32k supported by PNG");
1262 else if (window_bits < 8)
1264 png_warning(png_ptr,
"Only compression windows >= 256 supported by PNG");
1268 png_ptr->zlib_window_bits = window_bits;
1272png_set_compression_method(png_structrp png_ptr,
int method)
1274 png_debug(1,
"in png_set_compression_method");
1276 if (png_ptr == NULL)
1283 png_warning(png_ptr,
"Only compression method 8 is supported by PNG");
1285 png_ptr->zlib_method = method;
1290#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1292png_set_text_compression_level(png_structrp png_ptr,
int level)
1294 png_debug(1,
"in png_set_text_compression_level");
1296 if (png_ptr == NULL)
1299 png_ptr->zlib_text_level = level;
1303png_set_text_compression_mem_level(png_structrp png_ptr,
int mem_level)
1305 png_debug(1,
"in png_set_text_compression_mem_level");
1307 if (png_ptr == NULL)
1310 png_ptr->zlib_text_mem_level = mem_level;
1314png_set_text_compression_strategy(png_structrp png_ptr,
int strategy)
1316 png_debug(1,
"in png_set_text_compression_strategy");
1318 if (png_ptr == NULL)
1321 png_ptr->zlib_text_strategy = strategy;
1328png_set_text_compression_window_bits(png_structrp png_ptr,
int window_bits)
1330 png_debug(1,
"in png_set_text_compression_window_bits");
1332 if (png_ptr == NULL)
1335 if (window_bits > 15)
1337 png_warning(png_ptr,
"Only compression windows <= 32k supported by PNG");
1341 else if (window_bits < 8)
1343 png_warning(png_ptr,
"Only compression windows >= 256 supported by PNG");
1347 png_ptr->zlib_text_window_bits = window_bits;
1351png_set_text_compression_method(png_structrp png_ptr,
int method)
1353 png_debug(1,
"in png_set_text_compression_method");
1355 if (png_ptr == NULL)
1359 png_warning(png_ptr,
"Only compression method 8 is supported by PNG");
1361 png_ptr->zlib_text_method = method;
1367png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
1369 png_debug(1,
"in png_set_write_status_fn");
1371 if (png_ptr == NULL)
1374 png_ptr->write_row_fn = write_row_fn;
1377#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1379png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1380 write_user_transform_fn)
1382 png_debug(1,
"in png_set_write_user_transform_fn");
1384 if (png_ptr == NULL)
1387 png_ptr->transformations |= PNG_USER_TRANSFORM;
1388 png_ptr->write_user_transform_fn = write_user_transform_fn;
1393#ifdef PNG_INFO_IMAGE_SUPPORTED
1395png_write_png(png_structrp png_ptr, png_inforp info_ptr,
1396 int transforms, voidp params)
1398 png_debug(1,
"in png_write_png");
1400 if (png_ptr == NULL || info_ptr == NULL)
1403 if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
1405 png_app_error(png_ptr,
"no rows for png_write_image to write");
1410 png_write_info(png_ptr, info_ptr);
1415 if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
1416#ifdef PNG_WRITE_INVERT_SUPPORTED
1417 png_set_invert_mono(png_ptr);
1419 png_app_error(png_ptr,
"PNG_TRANSFORM_INVERT_MONO not supported");
1425 if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
1426#ifdef PNG_WRITE_SHIFT_SUPPORTED
1427 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
1428 png_set_shift(png_ptr, &info_ptr->sig_bit);
1430 png_app_error(png_ptr,
"PNG_TRANSFORM_SHIFT not supported");
1434 if ((transforms & PNG_TRANSFORM_PACKING) != 0)
1435#ifdef PNG_WRITE_PACK_SUPPORTED
1436 png_set_packing(png_ptr);
1438 png_app_error(png_ptr,
"PNG_TRANSFORM_PACKING not supported");
1442 if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
1443#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
1444 png_set_swap_alpha(png_ptr);
1446 png_app_error(png_ptr,
"PNG_TRANSFORM_SWAP_ALPHA not supported");
1453 if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
1454 PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
1456#ifdef PNG_WRITE_FILLER_SUPPORTED
1457 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
1459 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1460 png_app_error(png_ptr,
1461 "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
1464 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1467 else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1468 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1470 png_app_error(png_ptr,
"PNG_TRANSFORM_STRIP_FILLER not supported");
1475 if ((transforms & PNG_TRANSFORM_BGR) != 0)
1476#ifdef PNG_WRITE_BGR_SUPPORTED
1477 png_set_bgr(png_ptr);
1479 png_app_error(png_ptr,
"PNG_TRANSFORM_BGR not supported");
1483 if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
1484#ifdef PNG_WRITE_SWAP_SUPPORTED
1485 png_set_swap(png_ptr);
1487 png_app_error(png_ptr,
"PNG_TRANSFORM_SWAP_ENDIAN not supported");
1491 if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
1492#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
1493 png_set_packswap(png_ptr);
1495 png_app_error(png_ptr,
"PNG_TRANSFORM_PACKSWAP not supported");
1499 if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
1500#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1501 png_set_invert_alpha(png_ptr);
1503 png_app_error(png_ptr,
"PNG_TRANSFORM_INVERT_ALPHA not supported");
1509 png_write_image(png_ptr, info_ptr->row_pointers);
1512 png_write_end(png_ptr, info_ptr);
1519#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1522png_image_write_init(png_imagep image)
1524 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1525 png_safe_error, png_safe_warning);
1527 if (png_ptr != NULL)
1529 png_infop info_ptr = png_create_info_struct(png_ptr);
1531 if (info_ptr != NULL)
1533 png_controlp control = png_voidcast(png_controlp,
1534 png_malloc_warn(png_ptr, (
sizeof *control)));
1536 if (control != NULL)
1538 memset(control, 0, (
sizeof *control));
1540 control->png_ptr = png_ptr;
1541 control->info_ptr = info_ptr;
1542 control->for_write = 1;
1544 image->opaque = control;
1549 png_destroy_info_struct(png_ptr, &info_ptr);
1552 png_destroy_write_struct(&png_ptr, NULL);
1555 return png_image_error(image,
"png_image_write_: out of memory");
1563 png_const_voidp buffer;
1564 png_int_32 row_stride;
1565 png_const_voidp colormap;
1566 int convert_to_8bit;
1568 png_const_voidp first_row;
1569 ptrdiff_t row_bytes;
1570 png_voidp local_row;
1573 png_alloc_size_t memory_bytes;
1574 png_alloc_size_t output_bytes;
1582png_write_image_16bit(png_voidp argument)
1586 png_imagep image = display->image;
1587 png_structrp png_ptr = image->opaque->png_ptr;
1589 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1590 display->first_row);
1591 png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
1592 png_uint_16p row_end;
1593 unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
1596 png_uint_32 y = image->height;
1598 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1600# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1601 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1608 aindex = (int)channels;
1610 aindex = (int)channels;
1615 png_error(png_ptr,
"png_write_image: internal call error");
1621 row_end = output_row + image->width * (channels+1);
1625 png_const_uint_16p in_ptr = input_row;
1626 png_uint_16p out_ptr = output_row;
1628 while (out_ptr < row_end)
1630 png_uint_16 alpha = in_ptr[aindex];
1631 png_uint_32 reciprocal = 0;
1634 out_ptr[aindex] = alpha;
1641 if (alpha > 0 && alpha < 65535)
1642 reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
1647 png_uint_16 component = *in_ptr++;
1656 if (component >= alpha)
1662 else if (component > 0 && alpha < 65535)
1664 png_uint_32 calc = component * reciprocal;
1666 component = (png_uint_16)(calc >> 15);
1669 *out_ptr++ = component;
1678 png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
1679 input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
1693# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha))
1696png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
1697 png_uint_32 reciprocal)
1709 if (component >= alpha || alpha < 128)
1715 else if (component > 0)
1724 component *= reciprocal;
1733 return (png_byte)PNG_sRGB_FROM_LINEAR(component);
1741png_write_image_8bit(png_voidp argument)
1745 png_imagep image = display->image;
1746 png_structrp png_ptr = image->opaque->png_ptr;
1748 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1749 display->first_row);
1750 png_bytep output_row = png_voidcast(png_bytep, display->local_row);
1751 png_uint_32 y = image->height;
1752 unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
1755 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1760# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1761 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1770 aindex = (int)channels;
1773 row_end = output_row + image->width * (channels+1);
1777 png_const_uint_16p in_ptr = input_row;
1778 png_bytep out_ptr = output_row;
1780 while (out_ptr < row_end)
1782 png_uint_16 alpha = in_ptr[aindex];
1783 png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
1784 png_uint_32 reciprocal = 0;
1788 out_ptr[aindex] = alphabyte;
1790 if (alphabyte > 0 && alphabyte < 255)
1791 reciprocal = UNP_RECIPROCAL(alpha);
1795 *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
1803 png_write_row(png_ptr, png_voidcast(png_const_bytep,
1804 display->local_row));
1805 input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
1814 png_bytep row_end = output_row + image->width * channels;
1818 png_const_uint_16p in_ptr = input_row;
1819 png_bytep out_ptr = output_row;
1821 while (out_ptr < row_end)
1823 png_uint_32 component = *in_ptr++;
1826 *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
1829 png_write_row(png_ptr, output_row);
1830 input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
1840 png_imagep image = display->image;
1841 const void *cmap = display->colormap;
1842 int entries = image->colormap_entries > 256 ? 256 :
1843 (int)image->colormap_entries;
1846 png_uint_32 format = image->format;
1847 unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
1849# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
1850 defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
1851 int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
1852 (format & PNG_FORMAT_FLAG_ALPHA) != 0;
1857# ifdef PNG_FORMAT_BGR_SUPPORTED
1858 int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
1864 png_color palette[256];
1867 memset(tRNS, 255, (
sizeof tRNS));
1868 memset(palette, 0, (
sizeof palette));
1870 for (i=num_trans=0; i<entries; ++i)
1875 if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
1877 png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
1879 entry += (
unsigned int)i * channels;
1881 if ((channels & 1) != 0)
1885 palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1887 palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1889 palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1894 palette[i].blue = palette[i].red = palette[i].green =
1895 (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
1900 png_uint_16 alpha = entry[afirst ? 0 : channels-1];
1901 png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
1902 png_uint_32 reciprocal = 0;
1908 if (alphabyte > 0 && alphabyte < 255)
1909 reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
1911 tRNS[i] = alphabyte;
1912 if (alphabyte < 255)
1917 palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
1919 palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
1921 palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
1926 palette[i].blue = palette[i].red = palette[i].green =
1927 png_unpremultiply(entry[afirst], alpha, reciprocal);
1933 png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
1935 entry += (
unsigned int)i * channels;
1940 tRNS[i] = entry[afirst ? 0 : 3];
1945 palette[i].blue = entry[afirst + (2 ^ bgr)];
1946 palette[i].green = entry[afirst + 1];
1947 palette[i].red = entry[afirst + bgr];
1951 tRNS[i] = entry[1 ^ afirst];
1956 palette[i].blue = palette[i].red = palette[i].green =
1973 png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
1977 png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
1980 image->colormap_entries = (png_uint_32)entries;
1984png_image_write_main(png_voidp argument)
1988 png_imagep image = display->image;
1989 png_structrp png_ptr = image->opaque->png_ptr;
1990 png_inforp info_ptr = image->opaque->info_ptr;
1991 png_uint_32 format = image->format;
1994 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
1995 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR);
1996 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
1997 int write_16bit = linear && (display->convert_to_8bit == 0);
1999# ifdef PNG_BENIGN_ERRORS_SUPPORTED
2001 png_set_benign_errors(png_ptr, 0);
2008 unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
2010 if (image->width <= 0x7fffffffU/channels)
2013 png_uint_32 png_row_stride = image->width * channels;
2015 if (display->row_stride == 0)
2016 display->row_stride = (png_int_32)png_row_stride;
2018 if (display->row_stride < 0)
2019 check = (png_uint_32)(-display->row_stride);
2022 check = (png_uint_32)display->row_stride;
2024 if (check >= png_row_stride)
2030 if (image->height > 0xffffffffU/png_row_stride)
2031 png_error(image->opaque->png_ptr,
"memory image too large");
2035 png_error(image->opaque->png_ptr,
"supplied row stride too small");
2039 png_error(image->opaque->png_ptr,
"image row stride too large");
2043 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
2045 if (display->colormap != NULL && image->colormap_entries > 0)
2047 png_uint_32 entries = image->colormap_entries;
2049 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
2050 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
2051 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
2052 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
2054 png_image_set_PLTE(display);
2058 png_error(image->opaque->png_ptr,
2059 "no color-map for color-mapped image");
2063 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
2064 write_16bit ? 16 : 8,
2065 ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
2066 ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
2067 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
2075 if (write_16bit != 0)
2078 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
2080 if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2081 png_set_cHRM_fixed(png_ptr, info_ptr,
2090 else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2091 png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
2097 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
2100 png_write_info(png_ptr, info_ptr);
2107 if (write_16bit != 0)
2109 png_uint_16 le = 0x0001;
2111 if ((*(png_const_bytep) & le) != 0)
2112 png_set_swap(png_ptr);
2115# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
2116 if ((format & PNG_FORMAT_FLAG_BGR) != 0)
2118 if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
2119 png_set_bgr(png_ptr);
2120 format &= ~PNG_FORMAT_FLAG_BGR;
2124# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
2125 if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
2127 if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
2128 png_set_swap_alpha(png_ptr);
2129 format &= ~PNG_FORMAT_FLAG_AFIRST;
2136 if (colormap != 0 && image->colormap_entries <= 16)
2137 png_set_packing(png_ptr);
2140 if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
2141 PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
2142 png_error(png_ptr,
"png_write_image: unsupported transformation");
2145 png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
2146 ptrdiff_t row_bytes = display->row_stride;
2149 row_bytes *= (
sizeof (png_uint_16));
2152 row += (image->height-1) * (-row_bytes);
2154 display->first_row = row;
2155 display->row_bytes = row_bytes;
2159 if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
2161 png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
2167# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
2168 png_set_compression_level(png_ptr, 3);
2176 if (linear != 0 && (alpha != 0 || display->convert_to_8bit != 0))
2178 png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
2179 png_get_rowbytes(png_ptr, info_ptr)));
2182 display->local_row = row;
2183 if (write_16bit != 0)
2184 result = png_safe_execute(image, png_write_image_16bit, display);
2186 result = png_safe_execute(image, png_write_image_8bit, display);
2187 display->local_row = NULL;
2189 png_free(png_ptr, row);
2201 png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
2202 ptrdiff_t row_bytes = display->row_bytes;
2203 png_uint_32 y = image->height;
2207 png_write_row(png_ptr, row);
2212 png_write_end(png_ptr, info_ptr);
2217static void (PNGCBAPI
2218image_memory_write)(png_structp png_ptr, png_bytep data,
size_t size)
2222 png_alloc_size_t ob = display->output_bytes;
2225 if (size <= ((png_alloc_size_t)-1) - ob)
2230 if (display->memory_bytes >= ob+size)
2231 memcpy(display->memory+ob, data, size);
2234 display->output_bytes = ob+size;
2239 png_error(png_ptr,
"png_image_write_to_memory: PNG too big");
2242static void (PNGCBAPI
2243image_memory_flush)(png_structp png_ptr)
2249png_image_write_memory(png_voidp argument)
2258 png_set_write_fn(display->image->opaque->png_ptr, display,
2259 image_memory_write, image_memory_flush);
2261 return png_image_write_main(display);
2265png_image_write_to_memory(png_imagep image,
void *memory,
2266 png_alloc_size_t * PNG_RESTRICT memory_bytes,
int convert_to_8bit,
2267 const void *buffer, png_int_32 row_stride,
const void *colormap)
2270 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2272 if (memory_bytes != NULL && buffer != NULL)
2280 if (png_image_write_init(image) != 0)
2285 memset(&display, 0, (
sizeof display));
2286 display.image = image;
2287 display.buffer = buffer;
2288 display.row_stride = row_stride;
2289 display.colormap = colormap;
2290 display.convert_to_8bit = convert_to_8bit;
2291 display.memory = png_voidcast(png_bytep, memory);
2292 display.memory_bytes = *memory_bytes;
2293 display.output_bytes = 0;
2295 result = png_safe_execute(image, png_image_write_memory, &display);
2296 png_image_free(image);
2304 if (memory != NULL && display.output_bytes > *memory_bytes)
2307 *memory_bytes = display.output_bytes;
2318 return png_image_error(image,
2319 "png_image_write_to_memory: invalid argument");
2322 else if (image != NULL)
2323 return png_image_error(image,
2324 "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
2330#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
2332png_image_write_to_stdio(png_imagep image, FILE *file,
int convert_to_8bit,
2333 const void *buffer, png_int_32 row_stride,
const void *colormap)
2336 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2338 if (file != NULL && buffer != NULL)
2340 if (png_image_write_init(image) != 0)
2349 image->opaque->png_ptr->io_ptr = file;
2351 memset(&display, 0, (
sizeof display));
2352 display.image = image;
2353 display.buffer = buffer;
2354 display.row_stride = row_stride;
2355 display.colormap = colormap;
2356 display.convert_to_8bit = convert_to_8bit;
2358 result = png_safe_execute(image, png_image_write_main, &display);
2359 png_image_free(image);
2368 return png_image_error(image,
2369 "png_image_write_to_stdio: invalid argument");
2372 else if (image != NULL)
2373 return png_image_error(image,
2374 "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
2381png_image_write_to_file(png_imagep image,
const char *file_name,
2382 int convert_to_8bit,
const void *buffer, png_int_32 row_stride,
2383 const void *colormap)
2386 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2388 if (file_name != NULL && buffer != NULL)
2390 FILE *fp = fopen(file_name,
"wb");
2394 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2395 row_stride, colormap) != 0)
2400 if (fflush(fp) == 0 && ferror(fp) == 0)
2402 if (fclose(fp) == 0)
2414 (void)remove(file_name);
2418 return png_image_error(image, strerror(error));
2425 (void)remove(file_name);
2431 return png_image_error(image, strerror(errno));
2435 return png_image_error(image,
2436 "png_image_write_to_file: invalid argument");
2439 else if (image != NULL)
2440 return png_image_error(image,
2441 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");