2
2
/* pngwutil.c - utilities to write a PNG file
4
* Last changed in libpng 1.2.40 [September 10, 2009]
4
* Last changed in libpng 1.2.41 [December 3, 2009]
5
5
* Copyright (c) 1998-2009 Glenn Randers-Pehrson
6
6
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7
7
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
58
59
* we should call png_set_sig_bytes() to tell libpng how many of the
59
60
* bytes have already been written.
62
63
png_write_sig(png_structp png_ptr)
64
65
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
106
107
if (png_ptr == NULL)
109
111
/* Write the length and the chunk name */
110
112
png_save_uint_32(buf, length);
111
113
png_memcpy(buf + 4, chunk_name, 4);
193
195
if (compression >= PNG_TEXT_COMPRESSION_LAST)
195
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
197
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
197
199
png_snprintf(msg, 50, "Unknown compression type %d", compression);
198
200
png_warning(png_ptr, msg);
459
461
* 5. The color_type is RGB or RGBA
462
#if defined(PNG_MNG_FEATURES_SUPPORTED)
464
#ifdef PNG_MNG_FEATURES_SUPPORTED
463
465
!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
464
466
((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
465
467
(color_type == PNG_COLOR_TYPE_RGB ||
487
489
png_ptr->bit_depth = (png_byte)bit_depth;
488
490
png_ptr->color_type = (png_byte)color_type;
489
491
png_ptr->interlaced = (png_byte)interlace_type;
490
#if defined(PNG_MNG_FEATURES_SUPPORTED)
492
#ifdef PNG_MNG_FEATURES_SUPPORTED
491
493
png_ptr->filter_type = (png_byte)filter_type;
493
495
png_ptr->compression_type = (png_byte)compression_type;
579
581
png_debug(1, "in png_write_PLTE");
582
#if defined(PNG_MNG_FEATURES_SUPPORTED)
584
#ifdef PNG_MNG_FEATURES_SUPPORTED
583
585
!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
585
587
num_pal == 0) || num_pal > 256)
608
610
png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
609
611
(png_uint_32)(num_pal * 3));
610
#ifndef PNG_NO_POINTER_INDEXING
612
#ifdef PNG_POINTER_INDEXING_SUPPORTED
611
613
for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
613
615
buf[0] = pal_ptr->red;
761
#if defined(PNG_WRITE_iCCP_SUPPORTED)
763
#ifdef PNG_WRITE_iCCP_SUPPORTED
762
764
/* Write an iCCP chunk */
763
765
void /* PRIVATE */
764
766
png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
870
872
png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
872
874
/* Loop through each palette entry, writing appropriately */
873
#ifndef PNG_NO_POINTER_INDEXING
875
#ifdef PNG_POINTER_INDEXING_SUPPORTED
874
876
for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
876
878
if (spalette->depth == 8)
923
#if defined(PNG_WRITE_sBIT_SUPPORTED)
925
#ifdef PNG_WRITE_sBIT_SUPPORTED
924
926
/* Write the sBIT chunk */
925
927
void /* PRIVATE */
926
928
png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
1004
1006
int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5);
1005
1007
int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5);
1007
#if !defined(PNG_NO_CHECK_cHRM)
1009
#ifdef PNG_CHECK_cHRM_SUPPORTED
1008
1010
if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
1009
1011
int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
1042
1044
png_debug(1, "in png_write_cHRM");
1044
1046
/* Each value is saved in 1/100,000ths */
1045
#if !defined(PNG_NO_CHECK_cHRM)
1047
#ifdef PNG_CHECK_cHRM_SUPPORTED
1046
1048
if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
1047
1049
green_x, green_y, blue_x, blue_y))
1068
#if defined(PNG_WRITE_tRNS_SUPPORTED)
1070
#ifdef PNG_WRITE_tRNS_SUPPORTED
1069
1071
/* Write the tRNS chunk */
1070
1072
void /* PRIVATE */
1071
1073
png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
1125
#if defined(PNG_WRITE_bKGD_SUPPORTED)
1127
#ifdef PNG_WRITE_bKGD_SUPPORTED
1126
1128
/* Write the background chunk */
1127
1129
void /* PRIVATE */
1128
1130
png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
1179
#if defined(PNG_WRITE_hIST_SUPPORTED)
1181
#ifdef PNG_WRITE_hIST_SUPPORTED
1180
1182
/* Write the histogram */
1181
1183
void /* PRIVATE */
1182
1184
png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
1343
#if defined(PNG_WRITE_tEXt_SUPPORTED)
1345
#ifdef PNG_WRITE_tEXt_SUPPORTED
1344
1346
/* Write a tEXt chunk */
1345
1347
void /* PRIVATE */
1346
1348
png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
1384
#if defined(PNG_WRITE_zTXt_SUPPORTED)
1386
#ifdef PNG_WRITE_zTXt_SUPPORTED
1385
1387
/* Write a compressed text chunk */
1386
1388
void /* PRIVATE */
1387
1389
png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
1444
#if defined(PNG_WRITE_iTXt_SUPPORTED)
1446
#ifdef PNG_WRITE_iTXt_SUPPORTED
1445
1447
/* Write an iTXt chunk */
1446
1448
void /* PRIVATE */
1447
1449
png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
1533
#if defined(PNG_WRITE_oFFs_SUPPORTED)
1535
#ifdef PNG_WRITE_oFFs_SUPPORTED
1534
1536
/* Write the oFFs chunk */
1535
1537
void /* PRIVATE */
1536
1538
png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1553
1555
png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
1556
#if defined(PNG_WRITE_pCAL_SUPPORTED)
1558
#ifdef PNG_WRITE_pCAL_SUPPORTED
1557
1559
/* Write the pCAL chunk (described in the PNG extensions document) */
1558
1560
void /* PRIVATE */
1559
1561
png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
1619
#if defined(PNG_WRITE_sCAL_SUPPORTED)
1621
#ifdef PNG_WRITE_sCAL_SUPPORTED
1620
1622
/* Write the sCAL chunk */
1621
#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
1623
#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
1622
1624
void /* PRIVATE */
1623
1625
png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
1693
#if defined(PNG_WRITE_pHYs_SUPPORTED)
1695
#ifdef PNG_WRITE_pHYs_SUPPORTED
1694
1696
/* Write the pHYs chunk */
1695
1697
void /* PRIVATE */
1696
1698
png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1718
#if defined(PNG_WRITE_tIME_SUPPORTED)
1720
#ifdef PNG_WRITE_tIME_SUPPORTED
1719
1721
/* Write the tIME chunk. Use either png_convert_from_struct_tm()
1720
1722
* or png_convert_from_time_t(), or fill in the structure yourself.
1753
1755
png_write_start_row(png_structp png_ptr)
1755
1757
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1756
#ifdef PNG_USE_LOCAL_ARRAYS
1757
1758
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1759
1760
/* Start of interlace block */
1768
1769
/* Offset to next interlace block in the y direction */
1769
1770
int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1773
1773
png_size_t buf_size;
1782
1782
(png_uint_32)buf_size);
1783
1783
png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
1785
#ifndef PNG_NO_WRITE_FILTER
1785
#ifdef PNG_WRITE_FILTER_SUPPORTED
1786
1786
/* Set up filtering buffer, if using this filter */
1787
1787
if (png_ptr->do_filter & PNG_FILTER_SUB)
1794
1794
/* We only need to keep the previous row if we are using one of these. */
1795
1795
if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
1797
/* Set up previous row buffer */
1798
png_ptr->prev_row = (png_bytep)png_malloc(png_ptr,
1799
(png_uint_32)buf_size);
1800
png_memset(png_ptr->prev_row, 0, buf_size);
1797
/* Set up previous row buffer */
1798
png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
1799
(png_uint_32)buf_size);
1802
1801
if (png_ptr->do_filter & PNG_FILTER_UP)
1804
1803
png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
1805
(png_uint_32)(png_ptr->rowbytes + 1));
1804
(png_uint_32)(png_ptr->rowbytes + 1));
1806
1805
png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
1809
1808
if (png_ptr->do_filter & PNG_FILTER_AVG)
1811
1810
png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
1812
(png_uint_32)(png_ptr->rowbytes + 1));
1811
(png_uint_32)(png_ptr->rowbytes + 1));
1813
1812
png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
1816
1815
if (png_ptr->do_filter & PNG_FILTER_PAETH)
1818
1817
png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
1819
(png_uint_32)(png_ptr->rowbytes + 1));
1818
(png_uint_32)(png_ptr->rowbytes + 1));
1820
1819
png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
1823
#endif /* PNG_NO_WRITE_FILTER */
1822
#endif /* PNG_WRITE_FILTER_SUPPORTED */
1825
1824
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1826
1825
/* If interlaced, we need to set up width and height of pass */
1854
1853
png_write_finish_row(png_structp png_ptr)
1856
1855
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1857
#ifdef PNG_USE_LOCAL_ARRAYS
1858
1856
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1860
1858
/* Start of interlace block */
1869
1867
/* Offset to next interlace block in the y direction */
1870
1868
int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1962
1959
png_ptr->zstream.data_type = Z_BINARY;
1965
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
1962
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1966
1963
/* Pick out the correct pixels for the interlace pass.
1967
1964
* The basic idea here is to go through the row with a source
1968
1965
* pointer and a destination pointer (sp and dp), and copy the
1973
1970
void /* PRIVATE */
1974
1971
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
1976
#ifdef PNG_USE_LOCAL_ARRAYS
1977
1973
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1979
1975
/* Start of interlace block */
1982
1978
/* Offset to next interlace block */
1983
1979
int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1986
1981
png_debug(1, "in png_do_write_interlace");
1988
1983
/* We don't have to do anything on the last pass (6) */
1989
#if defined(PNG_USELESS_TESTS_SUPPORTED)
1984
#ifdef PNG_USELESS_TESTS_SUPPORTED
1990
1985
if (row != NULL && row_info != NULL && pass < 6)
2146
2141
png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
2148
2143
png_bytep best_row;
2149
#ifndef PNG_NO_WRITE_FILTER
2144
#ifdef PNG_WRITE_FILTER_SUPPORTED
2150
2145
png_bytep prev_row, row_buf;
2151
2146
png_uint_32 mins, bpp;
2152
2147
png_byte filter_to_do = png_ptr->do_filter;
2158
2153
png_debug(1, "in png_write_find_filter");
2155
#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2156
if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
2158
/* These will never be selected so we need not test them. */
2159
filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
2160
2163
/* Find out how many bytes offset each pixel is */
2161
2164
bpp = (row_info->pixel_depth + 7) >> 3;
2163
2166
prev_row = png_ptr->prev_row;
2165
2168
best_row = png_ptr->row_buf;
2166
#ifndef PNG_NO_WRITE_FILTER
2169
#ifdef PNG_WRITE_FILTER_SUPPORTED
2167
2170
row_buf = best_row;
2168
2171
mins = PNG_MAXSUM;
2206
2209
sum += (v < 128) ? v : 256 - v;
2209
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2212
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2210
2213
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2212
2215
png_uint_32 sumhi, sumlo;
2273
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2276
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2274
2277
/* We temporarily increase the "minimum sum" by the factor we
2275
2278
* would reduce the sum of this filter, so that we can do the
2276
2279
* early exit comparison without scaling the sum each time.
2739
2742
best_row = png_ptr->paeth_row;
2742
#endif /* PNG_NO_WRITE_FILTER */
2745
#endif /* PNG_WRITE_FILTER_SUPPORTED */
2743
2746
/* Do the actual writing of the filtered row data from the chosen filter. */
2745
2748
png_write_filtered_row(png_ptr, best_row);
2747
#ifndef PNG_NO_WRITE_FILTER
2748
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2750
#ifdef PNG_WRITE_FILTER_SUPPORTED
2751
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2749
2752
/* Save the type of filter we picked this time for future calculations */
2750
2753
if (png_ptr->num_prev_filters > 0)
2812
2815
/* Finish row - updates counters and flushes zlib if last row */
2813
2816
png_write_finish_row(png_ptr);
2815
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
2818
#ifdef PNG_WRITE_FLUSH_SUPPORTED
2816
2819
png_ptr->flush_rows++;
2818
2821
if (png_ptr->flush_dist > 0 &&