OLD | NEW |
1 | 1 |
2 /* pngwutil.c - utilities to write a PNG file | 2 /* pngwutil.c - utilities to write a PNG file |
3 * | 3 * |
4 * Last changed in libpng 1.2.43 [February 25, 2010] | 4 * Last changed in libpng 1.2.54 [November 12, 2015] |
5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson | 5 * Copyright (c) 1998-2015 Glenn Randers-Pehrson |
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 * | 8 * |
9 * This code is released under the libpng license. | 9 * This code is released under the libpng license. |
10 * For conditions of distribution and use, see the disclaimer | 10 * For conditions of distribution and use, see the disclaimer |
11 * and license in png.h | 11 * and license in png.h |
12 */ | 12 */ |
13 | 13 |
14 #define PNG_INTERNAL | 14 #define PNG_INTERNAL |
15 #define PNG_NO_PEDANTIC_WARNINGS | 15 #define PNG_NO_PEDANTIC_WARNINGS |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 | 247 |
248 old_max = comp->max_output_ptr; | 248 old_max = comp->max_output_ptr; |
249 comp->max_output_ptr = comp->num_output_ptr + 4; | 249 comp->max_output_ptr = comp->num_output_ptr + 4; |
250 if (comp->output_ptr != NULL) | 250 if (comp->output_ptr != NULL) |
251 { | 251 { |
252 png_charpp old_ptr; | 252 png_charpp old_ptr; |
253 | 253 |
254 old_ptr = comp->output_ptr; | 254 old_ptr = comp->output_ptr; |
255 comp->output_ptr = (png_charpp)png_malloc(png_ptr, | 255 comp->output_ptr = (png_charpp)png_malloc(png_ptr, |
256 (png_uint_32) | 256 (png_uint_32) |
257 (comp->max_output_ptr * png_sizeof(png_charpp))); | 257 (comp->max_output_ptr * png_sizeof(png_charp))); |
258 png_memcpy(comp->output_ptr, old_ptr, old_max | 258 png_memcpy(comp->output_ptr, old_ptr, old_max |
259 * png_sizeof(png_charp)); | 259 * png_sizeof(png_charp)); |
260 png_free(png_ptr, old_ptr); | 260 png_free(png_ptr, old_ptr); |
261 } | 261 } |
262 else | 262 else |
263 comp->output_ptr = (png_charpp)png_malloc(png_ptr, | 263 comp->output_ptr = (png_charpp)png_malloc(png_ptr, |
264 (png_uint_32) | 264 (png_uint_32) |
265 (comp->max_output_ptr * png_sizeof(png_charp))); | 265 (comp->max_output_ptr * png_sizeof(png_charp))); |
266 } | 266 } |
267 | 267 |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 /* Write the palette. We are careful not to trust png_color to be in the | 568 /* Write the palette. We are careful not to trust png_color to be in the |
569 * correct order for PNG, so people can redefine it to any convenient | 569 * correct order for PNG, so people can redefine it to any convenient |
570 * structure. | 570 * structure. |
571 */ | 571 */ |
572 void /* PRIVATE */ | 572 void /* PRIVATE */ |
573 png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) | 573 png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) |
574 { | 574 { |
575 #ifdef PNG_USE_LOCAL_ARRAYS | 575 #ifdef PNG_USE_LOCAL_ARRAYS |
576 PNG_PLTE; | 576 PNG_PLTE; |
577 #endif | 577 #endif |
578 png_uint_32 i; | 578 png_uint_32 max_palette_length, i; |
579 png_colorp pal_ptr; | 579 png_colorp pal_ptr; |
580 png_byte buf[3]; | 580 png_byte buf[3]; |
581 | 581 |
582 png_debug(1, "in png_write_PLTE"); | 582 png_debug(1, "in png_write_PLTE"); |
583 | 583 |
| 584 max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? |
| 585 (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; |
| 586 |
584 if (( | 587 if (( |
585 #ifdef PNG_MNG_FEATURES_SUPPORTED | 588 #ifdef PNG_MNG_FEATURES_SUPPORTED |
586 !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && | 589 !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && |
587 #endif | 590 #endif |
588 num_pal == 0) || num_pal > 256) | 591 num_pal == 0) || num_pal > max_palette_length) |
589 { | 592 { |
590 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | 593 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
591 { | 594 { |
592 png_error(png_ptr, "Invalid number of colors in palette"); | 595 png_error(png_ptr, "Invalid number of colors in palette"); |
593 } | 596 } |
594 else | 597 else |
595 { | 598 { |
596 png_warning(png_ptr, "Invalid number of colors in palette"); | 599 png_warning(png_ptr, "Invalid number of colors in palette"); |
597 return; | 600 return; |
598 } | 601 } |
(...skipping 1153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1752 | 1755 |
1753 png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); | 1756 png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); |
1754 } | 1757 } |
1755 #endif | 1758 #endif |
1756 | 1759 |
1757 /* Initializes the row writing capability of libpng */ | 1760 /* Initializes the row writing capability of libpng */ |
1758 void /* PRIVATE */ | 1761 void /* PRIVATE */ |
1759 png_write_start_row(png_structp png_ptr) | 1762 png_write_start_row(png_structp png_ptr) |
1760 { | 1763 { |
1761 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 1764 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
| 1765 #ifndef PNG_USE_GLOBAL_ARRAYS |
1762 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ | 1766 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1763 | 1767 |
1764 /* Start of interlace block */ | 1768 /* Start of interlace block */ |
1765 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; | 1769 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1766 | 1770 |
1767 /* Offset to next interlace block */ | 1771 /* Offset to next interlace block */ |
1768 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; | 1772 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1769 | 1773 |
1770 /* Start of interlace block in the y direction */ | 1774 /* Start of interlace block in the y direction */ |
1771 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; | 1775 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
1772 | 1776 |
1773 /* Offset to next interlace block in the y direction */ | 1777 /* Offset to next interlace block in the y direction */ |
1774 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; | 1778 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
1775 #endif | 1779 #endif |
| 1780 #endif |
1776 | 1781 |
1777 png_size_t buf_size; | 1782 png_size_t buf_size; |
1778 | 1783 |
1779 png_debug(1, "in png_write_start_row"); | 1784 png_debug(1, "in png_write_start_row"); |
1780 | 1785 |
1781 buf_size = (png_size_t)(PNG_ROWBYTES( | 1786 buf_size = (png_size_t)(PNG_ROWBYTES( |
1782 png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); | 1787 png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); |
1783 | 1788 |
1784 /* Set up row buffer */ | 1789 /* Set up row buffer */ |
1785 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, | 1790 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1850 } | 1855 } |
1851 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | 1856 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
1852 png_ptr->zstream.next_out = png_ptr->zbuf; | 1857 png_ptr->zstream.next_out = png_ptr->zbuf; |
1853 } | 1858 } |
1854 | 1859 |
1855 /* Internal use only. Called when finished processing a row of data. */ | 1860 /* Internal use only. Called when finished processing a row of data. */ |
1856 void /* PRIVATE */ | 1861 void /* PRIVATE */ |
1857 png_write_finish_row(png_structp png_ptr) | 1862 png_write_finish_row(png_structp png_ptr) |
1858 { | 1863 { |
1859 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 1864 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
| 1865 #ifndef PNG_USE_GLOBAL_ARRAYS |
1860 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ | 1866 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1861 | 1867 |
1862 /* Start of interlace block */ | 1868 /* Start of interlace block */ |
1863 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; | 1869 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1864 | 1870 |
1865 /* Offset to next interlace block */ | 1871 /* Offset to next interlace block */ |
1866 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; | 1872 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1867 | 1873 |
1868 /* Start of interlace block in the y direction */ | 1874 /* Start of interlace block in the y direction */ |
1869 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; | 1875 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
1870 | 1876 |
1871 /* Offset to next interlace block in the y direction */ | 1877 /* Offset to next interlace block in the y direction */ |
1872 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; | 1878 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
1873 #endif | 1879 #endif |
| 1880 #endif |
1874 | 1881 |
1875 int ret; | 1882 int ret; |
1876 | 1883 |
1877 png_debug(1, "in png_write_finish_row"); | 1884 png_debug(1, "in png_write_finish_row"); |
1878 | 1885 |
1879 /* Next row */ | 1886 /* Next row */ |
1880 png_ptr->row_number++; | 1887 png_ptr->row_number++; |
1881 | 1888 |
1882 /* See if we are done */ | 1889 /* See if we are done */ |
1883 if (png_ptr->row_number < png_ptr->num_rows) | 1890 if (png_ptr->row_number < png_ptr->num_rows) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 * pointer and a destination pointer (sp and dp), and copy the | 1976 * pointer and a destination pointer (sp and dp), and copy the |
1970 * correct pixels for the pass. As the row gets compacted, | 1977 * correct pixels for the pass. As the row gets compacted, |
1971 * sp will always be >= dp, so we should never overwrite anything. | 1978 * sp will always be >= dp, so we should never overwrite anything. |
1972 * See the default: case for the easiest code to understand. | 1979 * See the default: case for the easiest code to understand. |
1973 */ | 1980 */ |
1974 void /* PRIVATE */ | 1981 void /* PRIVATE */ |
1975 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) | 1982 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) |
1976 { | 1983 { |
1977 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ | 1984 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1978 | 1985 |
| 1986 #ifndef PNG_USE_GLOBAL_ARRAYS |
1979 /* Start of interlace block */ | 1987 /* Start of interlace block */ |
1980 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; | 1988 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1981 | 1989 |
1982 /* Offset to next interlace block */ | 1990 /* Offset to next interlace block */ |
1983 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; | 1991 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
| 1992 #endif |
1984 | 1993 |
1985 png_debug(1, "in png_do_write_interlace"); | 1994 png_debug(1, "in png_do_write_interlace"); |
1986 | 1995 |
1987 /* We don't have to do anything on the last pass (6) */ | 1996 /* We don't have to do anything on the last pass (6) */ |
1988 #ifdef PNG_USELESS_TESTS_SUPPORTED | 1997 #ifdef PNG_USELESS_TESTS_SUPPORTED |
1989 if (row != NULL && row_info != NULL && pass < 6) | 1998 if (row != NULL && row_info != NULL && pass < 6) |
1990 #else | 1999 #else |
1991 if (pass < 6) | 2000 if (pass < 6) |
1992 #endif | 2001 #endif |
1993 { | 2002 { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2143 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) | 2152 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) |
2144 void /* PRIVATE */ | 2153 void /* PRIVATE */ |
2145 png_write_find_filter(png_structp png_ptr, png_row_infop row_info) | 2154 png_write_find_filter(png_structp png_ptr, png_row_infop row_info) |
2146 { | 2155 { |
2147 png_bytep best_row; | 2156 png_bytep best_row; |
2148 #ifdef PNG_WRITE_FILTER_SUPPORTED | 2157 #ifdef PNG_WRITE_FILTER_SUPPORTED |
2149 png_bytep prev_row, row_buf; | 2158 png_bytep prev_row, row_buf; |
2150 png_uint_32 mins, bpp; | 2159 png_uint_32 mins, bpp; |
2151 png_byte filter_to_do = png_ptr->do_filter; | 2160 png_byte filter_to_do = png_ptr->do_filter; |
2152 png_uint_32 row_bytes = row_info->rowbytes; | 2161 png_uint_32 row_bytes = row_info->rowbytes; |
2153 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2154 int num_p_filters = (int)png_ptr->num_prev_filters; | |
2155 #endif | |
2156 | 2162 |
2157 png_debug(1, "in png_write_find_filter"); | 2163 png_debug(1, "in png_write_find_filter"); |
2158 | 2164 |
2159 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2160 if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) | |
2161 { | |
2162 /* These will never be selected so we need not test them. */ | |
2163 filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); | |
2164 } | |
2165 #endif | |
2166 | |
2167 /* Find out how many bytes offset each pixel is */ | 2165 /* Find out how many bytes offset each pixel is */ |
2168 bpp = (row_info->pixel_depth + 7) >> 3; | 2166 bpp = (row_info->pixel_depth + 7) >> 3; |
2169 | 2167 |
2170 prev_row = png_ptr->prev_row; | 2168 prev_row = png_ptr->prev_row; |
2171 #endif | 2169 #endif |
2172 best_row = png_ptr->row_buf; | 2170 best_row = png_ptr->row_buf; |
2173 #ifdef PNG_WRITE_FILTER_SUPPORTED | 2171 #ifdef PNG_WRITE_FILTER_SUPPORTED |
2174 row_buf = best_row; | 2172 row_buf = best_row; |
2175 mins = PNG_MAXSUM; | 2173 mins = PNG_MAXSUM; |
2176 | 2174 |
(...skipping 29 matching lines...) Expand all Loading... |
2206 png_uint_32 sum = 0; | 2204 png_uint_32 sum = 0; |
2207 png_uint_32 i; | 2205 png_uint_32 i; |
2208 int v; | 2206 int v; |
2209 | 2207 |
2210 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) | 2208 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) |
2211 { | 2209 { |
2212 v = *rp; | 2210 v = *rp; |
2213 sum += (v < 128) ? v : 256 - v; | 2211 sum += (v < 128) ? v : 256 - v; |
2214 } | 2212 } |
2215 | 2213 |
2216 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2217 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2218 { | |
2219 png_uint_32 sumhi, sumlo; | |
2220 int j; | |
2221 sumlo = sum & PNG_LOMASK; | |
2222 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ | |
2223 | |
2224 /* Reduce the sum if we match any of the previous rows */ | |
2225 for (j = 0; j < num_p_filters; j++) | |
2226 { | |
2227 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) | |
2228 { | |
2229 sumlo = (sumlo * png_ptr->filter_weights[j]) >> | |
2230 PNG_WEIGHT_SHIFT; | |
2231 sumhi = (sumhi * png_ptr->filter_weights[j]) >> | |
2232 PNG_WEIGHT_SHIFT; | |
2233 } | |
2234 } | |
2235 | |
2236 /* Factor in the cost of this filter (this is here for completeness, | |
2237 * but it makes no sense to have a "cost" for the NONE filter, as | |
2238 * it has the minimum possible computational cost - none). | |
2239 */ | |
2240 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> | |
2241 PNG_COST_SHIFT; | |
2242 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> | |
2243 PNG_COST_SHIFT; | |
2244 | |
2245 if (sumhi > PNG_HIMASK) | |
2246 sum = PNG_MAXSUM; | |
2247 else | |
2248 sum = (sumhi << PNG_HISHIFT) + sumlo; | |
2249 } | |
2250 #endif | |
2251 mins = sum; | 2214 mins = sum; |
2252 } | 2215 } |
2253 | 2216 |
2254 /* Sub filter */ | 2217 /* Sub filter */ |
2255 if (filter_to_do == PNG_FILTER_SUB) | 2218 if (filter_to_do == PNG_FILTER_SUB) |
2256 /* It's the only filter so no testing is needed */ | 2219 /* It's the only filter so no testing is needed */ |
2257 { | 2220 { |
2258 png_bytep rp, lp, dp; | 2221 png_bytep rp, lp, dp; |
2259 png_uint_32 i; | 2222 png_uint_32 i; |
2260 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; | 2223 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; |
2261 i++, rp++, dp++) | 2224 i++, rp++, dp++) |
2262 { | 2225 { |
2263 *dp = *rp; | 2226 *dp = *rp; |
2264 } | 2227 } |
2265 for (lp = row_buf + 1; i < row_bytes; | 2228 for (lp = row_buf + 1; i < row_bytes; |
2266 i++, rp++, lp++, dp++) | 2229 i++, rp++, lp++, dp++) |
2267 { | 2230 { |
2268 *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); | 2231 *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); |
2269 } | 2232 } |
2270 best_row = png_ptr->sub_row; | 2233 best_row = png_ptr->sub_row; |
2271 } | 2234 } |
2272 | 2235 |
2273 else if (filter_to_do & PNG_FILTER_SUB) | 2236 else if (filter_to_do & PNG_FILTER_SUB) |
2274 { | 2237 { |
2275 png_bytep rp, dp, lp; | 2238 png_bytep rp, dp, lp; |
2276 png_uint_32 sum = 0, lmins = mins; | 2239 png_uint_32 sum = 0, lmins = mins; |
2277 png_uint_32 i; | 2240 png_uint_32 i; |
2278 int v; | 2241 int v; |
2279 | 2242 |
2280 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2281 /* We temporarily increase the "minimum sum" by the factor we | |
2282 * would reduce the sum of this filter, so that we can do the | |
2283 * early exit comparison without scaling the sum each time. | |
2284 */ | |
2285 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2286 { | |
2287 int j; | |
2288 png_uint_32 lmhi, lmlo; | |
2289 lmlo = lmins & PNG_LOMASK; | |
2290 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; | |
2291 | |
2292 for (j = 0; j < num_p_filters; j++) | |
2293 { | |
2294 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) | |
2295 { | |
2296 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> | |
2297 PNG_WEIGHT_SHIFT; | |
2298 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> | |
2299 PNG_WEIGHT_SHIFT; | |
2300 } | |
2301 } | |
2302 | |
2303 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> | |
2304 PNG_COST_SHIFT; | |
2305 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> | |
2306 PNG_COST_SHIFT; | |
2307 | |
2308 if (lmhi > PNG_HIMASK) | |
2309 lmins = PNG_MAXSUM; | |
2310 else | |
2311 lmins = (lmhi << PNG_HISHIFT) + lmlo; | |
2312 } | |
2313 #endif | |
2314 | |
2315 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; | 2243 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; |
2316 i++, rp++, dp++) | 2244 i++, rp++, dp++) |
2317 { | 2245 { |
2318 v = *dp = *rp; | 2246 v = *dp = *rp; |
2319 | 2247 |
2320 sum += (v < 128) ? v : 256 - v; | 2248 sum += (v < 128) ? v : 256 - v; |
2321 } | 2249 } |
2322 for (lp = row_buf + 1; i < row_bytes; | 2250 for (lp = row_buf + 1; i < row_bytes; |
2323 i++, rp++, lp++, dp++) | 2251 i++, rp++, lp++, dp++) |
2324 { | 2252 { |
2325 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); | 2253 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); |
2326 | 2254 |
2327 sum += (v < 128) ? v : 256 - v; | 2255 sum += (v < 128) ? v : 256 - v; |
2328 | 2256 |
2329 if (sum > lmins) /* We are already worse, don't continue. */ | 2257 if (sum > lmins) /* We are already worse, don't continue. */ |
2330 break; | 2258 break; |
2331 } | 2259 } |
2332 | 2260 |
2333 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2334 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2335 { | |
2336 int j; | |
2337 png_uint_32 sumhi, sumlo; | |
2338 sumlo = sum & PNG_LOMASK; | |
2339 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; | |
2340 | |
2341 for (j = 0; j < num_p_filters; j++) | |
2342 { | |
2343 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) | |
2344 { | |
2345 sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> | |
2346 PNG_WEIGHT_SHIFT; | |
2347 sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> | |
2348 PNG_WEIGHT_SHIFT; | |
2349 } | |
2350 } | |
2351 | |
2352 sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> | |
2353 PNG_COST_SHIFT; | |
2354 sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> | |
2355 PNG_COST_SHIFT; | |
2356 | |
2357 if (sumhi > PNG_HIMASK) | |
2358 sum = PNG_MAXSUM; | |
2359 else | |
2360 sum = (sumhi << PNG_HISHIFT) + sumlo; | |
2361 } | |
2362 #endif | |
2363 | |
2364 if (sum < mins) | 2261 if (sum < mins) |
2365 { | 2262 { |
2366 mins = sum; | 2263 mins = sum; |
2367 best_row = png_ptr->sub_row; | 2264 best_row = png_ptr->sub_row; |
2368 } | 2265 } |
2369 } | 2266 } |
2370 | 2267 |
2371 /* Up filter */ | 2268 /* Up filter */ |
2372 if (filter_to_do == PNG_FILTER_UP) | 2269 if (filter_to_do == PNG_FILTER_UP) |
2373 { | 2270 { |
2374 png_bytep rp, dp, pp; | 2271 png_bytep rp, dp, pp; |
2375 png_uint_32 i; | 2272 png_uint_32 i; |
2376 | 2273 |
2377 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, | 2274 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, |
2378 pp = prev_row + 1; i < row_bytes; | 2275 pp = prev_row + 1; i < row_bytes; |
2379 i++, rp++, pp++, dp++) | 2276 i++, rp++, pp++, dp++) |
2380 { | 2277 { |
2381 *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); | 2278 *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); |
2382 } | 2279 } |
2383 best_row = png_ptr->up_row; | 2280 best_row = png_ptr->up_row; |
2384 } | 2281 } |
2385 | 2282 |
2386 else if (filter_to_do & PNG_FILTER_UP) | 2283 else if (filter_to_do & PNG_FILTER_UP) |
2387 { | 2284 { |
2388 png_bytep rp, dp, pp; | 2285 png_bytep rp, dp, pp; |
2389 png_uint_32 sum = 0, lmins = mins; | 2286 png_uint_32 sum = 0, lmins = mins; |
2390 png_uint_32 i; | 2287 png_uint_32 i; |
2391 int v; | 2288 int v; |
2392 | 2289 |
2393 | |
2394 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2395 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2396 { | |
2397 int j; | |
2398 png_uint_32 lmhi, lmlo; | |
2399 lmlo = lmins & PNG_LOMASK; | |
2400 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; | |
2401 | |
2402 for (j = 0; j < num_p_filters; j++) | |
2403 { | |
2404 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) | |
2405 { | |
2406 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> | |
2407 PNG_WEIGHT_SHIFT; | |
2408 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> | |
2409 PNG_WEIGHT_SHIFT; | |
2410 } | |
2411 } | |
2412 | |
2413 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> | |
2414 PNG_COST_SHIFT; | |
2415 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> | |
2416 PNG_COST_SHIFT; | |
2417 | |
2418 if (lmhi > PNG_HIMASK) | |
2419 lmins = PNG_MAXSUM; | |
2420 else | |
2421 lmins = (lmhi << PNG_HISHIFT) + lmlo; | |
2422 } | |
2423 #endif | |
2424 | |
2425 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, | 2290 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, |
2426 pp = prev_row + 1; i < row_bytes; i++) | 2291 pp = prev_row + 1; i < row_bytes; i++) |
2427 { | 2292 { |
2428 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); | 2293 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); |
2429 | 2294 |
2430 sum += (v < 128) ? v : 256 - v; | 2295 sum += (v < 128) ? v : 256 - v; |
2431 | 2296 |
2432 if (sum > lmins) /* We are already worse, don't continue. */ | 2297 if (sum > lmins) /* We are already worse, don't continue. */ |
2433 break; | 2298 break; |
2434 } | 2299 } |
2435 | 2300 |
2436 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2437 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2438 { | |
2439 int j; | |
2440 png_uint_32 sumhi, sumlo; | |
2441 sumlo = sum & PNG_LOMASK; | |
2442 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; | |
2443 | |
2444 for (j = 0; j < num_p_filters; j++) | |
2445 { | |
2446 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) | |
2447 { | |
2448 sumlo = (sumlo * png_ptr->filter_weights[j]) >> | |
2449 PNG_WEIGHT_SHIFT; | |
2450 sumhi = (sumhi * png_ptr->filter_weights[j]) >> | |
2451 PNG_WEIGHT_SHIFT; | |
2452 } | |
2453 } | |
2454 | |
2455 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> | |
2456 PNG_COST_SHIFT; | |
2457 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> | |
2458 PNG_COST_SHIFT; | |
2459 | |
2460 if (sumhi > PNG_HIMASK) | |
2461 sum = PNG_MAXSUM; | |
2462 else | |
2463 sum = (sumhi << PNG_HISHIFT) + sumlo; | |
2464 } | |
2465 #endif | |
2466 | |
2467 if (sum < mins) | 2301 if (sum < mins) |
2468 { | 2302 { |
2469 mins = sum; | 2303 mins = sum; |
2470 best_row = png_ptr->up_row; | 2304 best_row = png_ptr->up_row; |
2471 } | 2305 } |
2472 } | 2306 } |
2473 | 2307 |
2474 /* Avg filter */ | 2308 /* Avg filter */ |
2475 if (filter_to_do == PNG_FILTER_AVG) | 2309 if (filter_to_do == PNG_FILTER_AVG) |
2476 { | 2310 { |
(...skipping 12 matching lines...) Expand all Loading... |
2489 best_row = png_ptr->avg_row; | 2323 best_row = png_ptr->avg_row; |
2490 } | 2324 } |
2491 | 2325 |
2492 else if (filter_to_do & PNG_FILTER_AVG) | 2326 else if (filter_to_do & PNG_FILTER_AVG) |
2493 { | 2327 { |
2494 png_bytep rp, dp, pp, lp; | 2328 png_bytep rp, dp, pp, lp; |
2495 png_uint_32 sum = 0, lmins = mins; | 2329 png_uint_32 sum = 0, lmins = mins; |
2496 png_uint_32 i; | 2330 png_uint_32 i; |
2497 int v; | 2331 int v; |
2498 | 2332 |
2499 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2500 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2501 { | |
2502 int j; | |
2503 png_uint_32 lmhi, lmlo; | |
2504 lmlo = lmins & PNG_LOMASK; | |
2505 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; | |
2506 | |
2507 for (j = 0; j < num_p_filters; j++) | |
2508 { | |
2509 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) | |
2510 { | |
2511 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> | |
2512 PNG_WEIGHT_SHIFT; | |
2513 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> | |
2514 PNG_WEIGHT_SHIFT; | |
2515 } | |
2516 } | |
2517 | |
2518 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> | |
2519 PNG_COST_SHIFT; | |
2520 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> | |
2521 PNG_COST_SHIFT; | |
2522 | |
2523 if (lmhi > PNG_HIMASK) | |
2524 lmins = PNG_MAXSUM; | |
2525 else | |
2526 lmins = (lmhi << PNG_HISHIFT) + lmlo; | |
2527 } | |
2528 #endif | |
2529 | |
2530 for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, | 2333 for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, |
2531 pp = prev_row + 1; i < bpp; i++) | 2334 pp = prev_row + 1; i < bpp; i++) |
2532 { | 2335 { |
2533 v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); | 2336 v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); |
2534 | 2337 |
2535 sum += (v < 128) ? v : 256 - v; | 2338 sum += (v < 128) ? v : 256 - v; |
2536 } | 2339 } |
2537 for (lp = row_buf + 1; i < row_bytes; i++) | 2340 for (lp = row_buf + 1; i < row_bytes; i++) |
2538 { | 2341 { |
2539 v = *dp++ = | 2342 v = *dp++ = |
2540 (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); | 2343 (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); |
2541 | 2344 |
2542 sum += (v < 128) ? v : 256 - v; | 2345 sum += (v < 128) ? v : 256 - v; |
2543 | 2346 |
2544 if (sum > lmins) /* We are already worse, don't continue. */ | 2347 if (sum > lmins) /* We are already worse, don't continue. */ |
2545 break; | 2348 break; |
2546 } | 2349 } |
2547 | 2350 |
2548 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2549 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2550 { | |
2551 int j; | |
2552 png_uint_32 sumhi, sumlo; | |
2553 sumlo = sum & PNG_LOMASK; | |
2554 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; | |
2555 | |
2556 for (j = 0; j < num_p_filters; j++) | |
2557 { | |
2558 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) | |
2559 { | |
2560 sumlo = (sumlo * png_ptr->filter_weights[j]) >> | |
2561 PNG_WEIGHT_SHIFT; | |
2562 sumhi = (sumhi * png_ptr->filter_weights[j]) >> | |
2563 PNG_WEIGHT_SHIFT; | |
2564 } | |
2565 } | |
2566 | |
2567 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> | |
2568 PNG_COST_SHIFT; | |
2569 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> | |
2570 PNG_COST_SHIFT; | |
2571 | |
2572 if (sumhi > PNG_HIMASK) | |
2573 sum = PNG_MAXSUM; | |
2574 else | |
2575 sum = (sumhi << PNG_HISHIFT) + sumlo; | |
2576 } | |
2577 #endif | |
2578 | |
2579 if (sum < mins) | 2351 if (sum < mins) |
2580 { | 2352 { |
2581 mins = sum; | 2353 mins = sum; |
2582 best_row = png_ptr->avg_row; | 2354 best_row = png_ptr->avg_row; |
2583 } | 2355 } |
2584 } | 2356 } |
2585 | 2357 |
2586 /* Paeth filter */ | 2358 /* Paeth filter */ |
2587 if (filter_to_do == PNG_FILTER_PAETH) | 2359 if (filter_to_do == PNG_FILTER_PAETH) |
2588 { | 2360 { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2622 best_row = png_ptr->paeth_row; | 2394 best_row = png_ptr->paeth_row; |
2623 } | 2395 } |
2624 | 2396 |
2625 else if (filter_to_do & PNG_FILTER_PAETH) | 2397 else if (filter_to_do & PNG_FILTER_PAETH) |
2626 { | 2398 { |
2627 png_bytep rp, dp, pp, cp, lp; | 2399 png_bytep rp, dp, pp, cp, lp; |
2628 png_uint_32 sum = 0, lmins = mins; | 2400 png_uint_32 sum = 0, lmins = mins; |
2629 png_uint_32 i; | 2401 png_uint_32 i; |
2630 int v; | 2402 int v; |
2631 | 2403 |
2632 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2633 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2634 { | |
2635 int j; | |
2636 png_uint_32 lmhi, lmlo; | |
2637 lmlo = lmins & PNG_LOMASK; | |
2638 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; | |
2639 | |
2640 for (j = 0; j < num_p_filters; j++) | |
2641 { | |
2642 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) | |
2643 { | |
2644 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> | |
2645 PNG_WEIGHT_SHIFT; | |
2646 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> | |
2647 PNG_WEIGHT_SHIFT; | |
2648 } | |
2649 } | |
2650 | |
2651 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> | |
2652 PNG_COST_SHIFT; | |
2653 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> | |
2654 PNG_COST_SHIFT; | |
2655 | |
2656 if (lmhi > PNG_HIMASK) | |
2657 lmins = PNG_MAXSUM; | |
2658 else | |
2659 lmins = (lmhi << PNG_HISHIFT) + lmlo; | |
2660 } | |
2661 #endif | |
2662 | |
2663 for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, | 2404 for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, |
2664 pp = prev_row + 1; i < bpp; i++) | 2405 pp = prev_row + 1; i < bpp; i++) |
2665 { | 2406 { |
2666 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); | 2407 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); |
2667 | 2408 |
2668 sum += (v < 128) ? v : 256 - v; | 2409 sum += (v < 128) ? v : 256 - v; |
2669 } | 2410 } |
2670 | 2411 |
2671 for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) | 2412 for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) |
2672 { | 2413 { |
(...skipping 30 matching lines...) Expand all Loading... |
2703 #endif /* PNG_SLOW_PAETH */ | 2444 #endif /* PNG_SLOW_PAETH */ |
2704 | 2445 |
2705 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); | 2446 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); |
2706 | 2447 |
2707 sum += (v < 128) ? v : 256 - v; | 2448 sum += (v < 128) ? v : 256 - v; |
2708 | 2449 |
2709 if (sum > lmins) /* We are already worse, don't continue. */ | 2450 if (sum > lmins) /* We are already worse, don't continue. */ |
2710 break; | 2451 break; |
2711 } | 2452 } |
2712 | 2453 |
2713 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2714 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) | |
2715 { | |
2716 int j; | |
2717 png_uint_32 sumhi, sumlo; | |
2718 sumlo = sum & PNG_LOMASK; | |
2719 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; | |
2720 | |
2721 for (j = 0; j < num_p_filters; j++) | |
2722 { | |
2723 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) | |
2724 { | |
2725 sumlo = (sumlo * png_ptr->filter_weights[j]) >> | |
2726 PNG_WEIGHT_SHIFT; | |
2727 sumhi = (sumhi * png_ptr->filter_weights[j]) >> | |
2728 PNG_WEIGHT_SHIFT; | |
2729 } | |
2730 } | |
2731 | |
2732 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> | |
2733 PNG_COST_SHIFT; | |
2734 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> | |
2735 PNG_COST_SHIFT; | |
2736 | |
2737 if (sumhi > PNG_HIMASK) | |
2738 sum = PNG_MAXSUM; | |
2739 else | |
2740 sum = (sumhi << PNG_HISHIFT) + sumlo; | |
2741 } | |
2742 #endif | |
2743 | |
2744 if (sum < mins) | 2454 if (sum < mins) |
2745 { | 2455 { |
2746 best_row = png_ptr->paeth_row; | 2456 best_row = png_ptr->paeth_row; |
2747 } | 2457 } |
2748 } | 2458 } |
2749 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | 2459 #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
2750 /* Do the actual writing of the filtered row data from the chosen filter. */ | 2460 /* Do the actual writing of the filtered row data from the chosen filter. */ |
2751 | 2461 |
2752 png_write_filtered_row(png_ptr, best_row); | 2462 png_write_filtered_row(png_ptr, best_row); |
2753 | |
2754 #ifdef PNG_WRITE_FILTER_SUPPORTED | |
2755 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
2756 /* Save the type of filter we picked this time for future calculations */ | |
2757 if (png_ptr->num_prev_filters > 0) | |
2758 { | |
2759 int j; | |
2760 for (j = 1; j < num_p_filters; j++) | |
2761 { | |
2762 png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; | |
2763 } | |
2764 png_ptr->prev_filters[j] = best_row[0]; | |
2765 } | |
2766 #endif | |
2767 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | |
2768 } | 2463 } |
2769 | 2464 |
2770 | 2465 |
2771 /* Do the actual writing of a previously filtered row. */ | 2466 /* Do the actual writing of a previously filtered row. */ |
2772 void /* PRIVATE */ | 2467 void /* PRIVATE */ |
2773 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) | 2468 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) |
2774 { | 2469 { |
2775 png_debug(1, "in png_write_filtered_row"); | 2470 png_debug(1, "in png_write_filtered_row"); |
2776 | 2471 |
2777 png_debug1(2, "filter = %d", filtered_row[0]); | 2472 png_debug1(2, "filter = %d", filtered_row[0]); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2823 png_ptr->flush_rows++; | 2518 png_ptr->flush_rows++; |
2824 | 2519 |
2825 if (png_ptr->flush_dist > 0 && | 2520 if (png_ptr->flush_dist > 0 && |
2826 png_ptr->flush_rows >= png_ptr->flush_dist) | 2521 png_ptr->flush_rows >= png_ptr->flush_dist) |
2827 { | 2522 { |
2828 png_write_flush(png_ptr); | 2523 png_write_flush(png_ptr); |
2829 } | 2524 } |
2830 #endif | 2525 #endif |
2831 } | 2526 } |
2832 #endif /* PNG_WRITE_SUPPORTED */ | 2527 #endif /* PNG_WRITE_SUPPORTED */ |
OLD | NEW |