Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: third_party/libpng/pngwrite.c

Issue 1591483003: XFA: Upgrade libpng to 1.6.20. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@xfa
Patch Set: rebase Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/libpng/pngwio.c ('k') | third_party/libpng/pngwtran.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* pngwrite.c - general routines to write a PNG file 2 /* pngwrite.c - general routines to write a PNG file
3 * 3 *
4 * Last changed in libpng 1.6.2 [April 25, 2013] 4 * Last changed in libpng 1.6.19 [November 12, 2015]
5 * Copyright (c) 1998-2013 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 #include "pngpriv.h" 14 #include "pngpriv.h"
14 #if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) 15 #if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
15 # include <errno.h> 16 # include <errno.h>
16 #endif 17 #endif
17 18
18 #ifdef PNG_WRITE_SUPPORTED 19 #ifdef PNG_WRITE_SUPPORTED
19 20
20 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 21 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
21 /* Write out all the unknown chunks for the current given location */ 22 /* Write out all the unknown chunks for the current given location */
22 static void 23 static void
23 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, 24 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
24 unsigned int where) 25 unsigned int where)
25 { 26 {
26 if (info_ptr->unknown_chunks_num) 27 if (info_ptr->unknown_chunks_num != 0)
27 { 28 {
28 png_const_unknown_chunkp up; 29 png_const_unknown_chunkp up;
29 30
30 png_debug(5, "writing extra chunks"); 31 png_debug(5, "writing extra chunks");
31 32
32 for (up = info_ptr->unknown_chunks; 33 for (up = info_ptr->unknown_chunks;
33 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; 34 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
34 ++up) 35 ++up)
35 if (up->location & where) 36 if ((up->location & where) != 0)
36 { 37 {
37 /* If per-chunk unknown chunk handling is enabled use it, otherwise 38 /* If per-chunk unknown chunk handling is enabled use it, otherwise
38 * just write the chunks the application has set. 39 * just write the chunks the application has set.
39 */ 40 */
40 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 41 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
41 int keep = png_handle_as_unknown(png_ptr, up->name); 42 int keep = png_handle_as_unknown(png_ptr, up->name);
42 43
43 /* NOTE: this code is radically different from the read side in the 44 /* NOTE: this code is radically different from the read side in the
44 * matter of handling an ancillary unknown chunk. In the read side 45 * matter of handling an ancillary unknown chunk. In the read side
45 * the default behavior is to discard it, in the code below the default 46 * the default behavior is to discard it, in the code below the default
(...skipping 15 matching lines...) Expand all
61 { 62 {
62 /* TODO: review, what is wrong with a zero length unknown chunk? */ 63 /* TODO: review, what is wrong with a zero length unknown chunk? */
63 if (up->size == 0) 64 if (up->size == 0)
64 png_warning(png_ptr, "Writing zero-length unknown chunk"); 65 png_warning(png_ptr, "Writing zero-length unknown chunk");
65 66
66 png_write_chunk(png_ptr, up->name, up->data, up->size); 67 png_write_chunk(png_ptr, up->name, up->data, up->size);
67 } 68 }
68 } 69 }
69 } 70 }
70 } 71 }
71 #endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */ 72 #endif /* WRITE_UNKNOWN_CHUNKS */
72 73
73 /* Writes all the PNG information. This is the suggested way to use the 74 /* Writes all the PNG information. This is the suggested way to use the
74 * library. If you have a new chunk to add, make a function to write it, 75 * library. If you have a new chunk to add, make a function to write it,
75 * and put it in the correct location here. If you want the chunk written 76 * and put it in the correct location here. If you want the chunk written
76 * after the image data, put it in png_write_end(). I strongly encourage 77 * after the image data, put it in png_write_end(). I strongly encourage
77 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing 78 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
78 * the chunk, as that will keep the code from breaking if you want to just 79 * the chunk, as that will keep the code from breaking if you want to just
79 * write a plain PNG file. If you have long comments, I suggest writing 80 * write a plain PNG file. If you have long comments, I suggest writing
80 * them in png_write_end(), and compressing them. 81 * them in png_write_end(), and compressing them.
81 */ 82 */
82 void PNGAPI 83 void PNGAPI
83 png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) 84 png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
84 { 85 {
85 png_debug(1, "in png_write_info_before_PLTE"); 86 png_debug(1, "in png_write_info_before_PLTE");
86 87
87 if (png_ptr == NULL || info_ptr == NULL) 88 if (png_ptr == NULL || info_ptr == NULL)
88 return; 89 return;
89 90
90 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) 91 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
91 { 92 {
92 /* Write PNG signature */ 93 /* Write PNG signature */
93 png_write_sig(png_ptr); 94 png_write_sig(png_ptr);
94 95
95 #ifdef PNG_MNG_FEATURES_SUPPORTED 96 #ifdef PNG_MNG_FEATURES_SUPPORTED
96 if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ 97 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
97 (png_ptr->mng_features_permitted)) 98 png_ptr->mng_features_permitted != 0)
98 { 99 {
99 png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); 100 png_warning(png_ptr,
100 png_ptr->mng_features_permitted = 0; 101 "MNG features are not allowed in a PNG datastream");
101 } 102 png_ptr->mng_features_permitted = 0;
102 #endif 103 }
103 104 #endif
104 /* Write IHDR information. */ 105
105 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, 106 /* Write IHDR information. */
106 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, 107 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
107 info_ptr->filter_type, 108 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
109 info_ptr->filter_type,
108 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 110 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
109 info_ptr->interlace_type 111 info_ptr->interlace_type
110 #else 112 #else
111 0 113 0
112 #endif 114 #endif
113 ); 115 );
114 116
115 /* The rest of these check to see if the valid field has the appropriate 117 /* The rest of these check to see if the valid field has the appropriate
116 * flag set, and if it does, writes the chunk. 118 * flag set, and if it does, writes the chunk.
117 * 119 *
118 * 1.6.0: COLORSPACE support controls the writing of these chunks too, and 120 * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
119 * the chunks will be written if the WRITE routine is there and information 121 * the chunks will be written if the WRITE routine is there and
120 * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c 122 * information * is available in the COLORSPACE. (See
121 * for where the valid flags get set.) 123 * png_colorspace_sync_info in png.c for where the valid flags get set.)
122 * 124 *
123 * Under certain circumstances the colorspace can be invalidated without 125 * Under certain circumstances the colorspace can be invalidated without
124 * syncing the info_struct 'valid' flags; this happens if libpng detects and 126 * syncing the info_struct 'valid' flags; this happens if libpng detects
125 * error and calls png_error while the color space is being set, yet the 127 * an error and calls png_error while the color space is being set, yet
126 * application continues writing the PNG. So check the 'invalid' flag here 128 * the application continues writing the PNG. So check the 'invalid'
127 * too. 129 * flag here too.
128 */ 130 */
129 #ifdef PNG_GAMMA_SUPPORTED 131 #ifdef PNG_GAMMA_SUPPORTED
130 # ifdef PNG_WRITE_gAMA_SUPPORTED 132 # ifdef PNG_WRITE_gAMA_SUPPORTED
131 if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && 133 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
132 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) && 134 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
133 (info_ptr->valid & PNG_INFO_gAMA)) 135 (info_ptr->valid & PNG_INFO_gAMA) != 0)
134 png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); 136 png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
135 # endif 137 # endif
136 #endif 138 #endif
137 139
138 #ifdef PNG_COLORSPACE_SUPPORTED 140 #ifdef PNG_COLORSPACE_SUPPORTED
139 /* Write only one of sRGB or an ICC profile. If a profile was supplied 141 /* Write only one of sRGB or an ICC profile. If a profile was supplied
140 * and it matches one of the known sRGB ones issue a warning. 142 * and it matches one of the known sRGB ones issue a warning.
141 */ 143 */
142 # ifdef PNG_WRITE_iCCP_SUPPORTED 144 # ifdef PNG_WRITE_iCCP_SUPPORTED
143 if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && 145 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
144 (info_ptr->valid & PNG_INFO_iCCP)) 146 (info_ptr->valid & PNG_INFO_iCCP) != 0)
145 { 147 {
146 # ifdef PNG_WRITE_sRGB_SUPPORTED 148 # ifdef PNG_WRITE_sRGB_SUPPORTED
147 if (info_ptr->valid & PNG_INFO_sRGB) 149 if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
148 png_app_warning(png_ptr, 150 png_app_warning(png_ptr,
149 "profile matches sRGB but writing iCCP instead"); 151 "profile matches sRGB but writing iCCP instead");
150 # endif 152 # endif
151 153
152 png_write_iCCP(png_ptr, info_ptr->iccp_name, 154 png_write_iCCP(png_ptr, info_ptr->iccp_name,
153 info_ptr->iccp_profile); 155 info_ptr->iccp_profile);
154 } 156 }
155 # ifdef PNG_WRITE_sRGB_SUPPORTED 157 # ifdef PNG_WRITE_sRGB_SUPPORTED
156 else 158 else
157 # endif 159 # endif
158 # endif 160 # endif
159 161
160 # ifdef PNG_WRITE_sRGB_SUPPORTED 162 # ifdef PNG_WRITE_sRGB_SUPPORTED
161 if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && 163 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
162 (info_ptr->valid & PNG_INFO_sRGB)) 164 (info_ptr->valid & PNG_INFO_sRGB) != 0)
163 png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); 165 png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
164 # endif /* WRITE_sRGB */ 166 # endif /* WRITE_sRGB */
165 #endif /* COLORSPACE */ 167 #endif /* COLORSPACE */
166 168
167 #ifdef PNG_WRITE_sBIT_SUPPORTED 169 #ifdef PNG_WRITE_sBIT_SUPPORTED
168 if (info_ptr->valid & PNG_INFO_sBIT) 170 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
169 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); 171 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
170 #endif 172 #endif
171 173
172 #ifdef PNG_COLORSPACE_SUPPORTED 174 #ifdef PNG_COLORSPACE_SUPPORTED
173 # ifdef PNG_WRITE_cHRM_SUPPORTED 175 # ifdef PNG_WRITE_cHRM_SUPPORTED
174 if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && 176 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
175 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) && 177 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
176 (info_ptr->valid & PNG_INFO_cHRM)) 178 (info_ptr->valid & PNG_INFO_cHRM) != 0)
177 png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); 179 png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
178 # endif 180 # endif
179 #endif 181 #endif
180 182
181 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 183 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
182 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); 184 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
183 #endif 185 #endif
184 186
185 png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; 187 png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
186 } 188 }
187 } 189 }
188 190
189 void PNGAPI 191 void PNGAPI
190 png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) 192 png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
191 { 193 {
192 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 194 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
193 int i; 195 int i;
194 #endif 196 #endif
195 197
196 png_debug(1, "in png_write_info"); 198 png_debug(1, "in png_write_info");
197 199
198 if (png_ptr == NULL || info_ptr == NULL) 200 if (png_ptr == NULL || info_ptr == NULL)
199 return; 201 return;
200 202
201 png_write_info_before_PLTE(png_ptr, info_ptr); 203 png_write_info_before_PLTE(png_ptr, info_ptr);
202 204
203 if (info_ptr->valid & PNG_INFO_PLTE) 205 if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
204 png_write_PLTE(png_ptr, info_ptr->palette, 206 png_write_PLTE(png_ptr, info_ptr->palette,
205 (png_uint_32)info_ptr->num_palette); 207 (png_uint_32)info_ptr->num_palette);
206 208
207 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 209 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
208 png_error(png_ptr, "Valid palette required for paletted images"); 210 png_error(png_ptr, "Valid palette required for paletted images");
209 211
210 #ifdef PNG_WRITE_tRNS_SUPPORTED 212 #ifdef PNG_WRITE_tRNS_SUPPORTED
211 if (info_ptr->valid & PNG_INFO_tRNS) 213 if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
212 { 214 {
213 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 215 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
214 /* Invert the alpha channel (in tRNS) */ 216 /* Invert the alpha channel (in tRNS) */
215 if ((png_ptr->transformations & PNG_INVERT_ALPHA) && 217 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
216 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 218 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
217 { 219 {
218 int j; 220 int j, jend;
219 for (j = 0; j<(int)info_ptr->num_trans; j++) 221
222 jend = info_ptr->num_trans;
223 if (jend > PNG_MAX_PALETTE_LENGTH)
224 jend = PNG_MAX_PALETTE_LENGTH;
225
226 for (j = 0; j<jend; ++j)
220 info_ptr->trans_alpha[j] = 227 info_ptr->trans_alpha[j] =
221 (png_byte)(255 - info_ptr->trans_alpha[j]); 228 (png_byte)(255 - info_ptr->trans_alpha[j]);
222 } 229 }
223 #endif 230 #endif
224 png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), 231 png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
225 info_ptr->num_trans, info_ptr->color_type); 232 info_ptr->num_trans, info_ptr->color_type);
226 } 233 }
227 #endif 234 #endif
228 #ifdef PNG_WRITE_bKGD_SUPPORTED 235 #ifdef PNG_WRITE_bKGD_SUPPORTED
229 if (info_ptr->valid & PNG_INFO_bKGD) 236 if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
230 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); 237 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
231 #endif 238 #endif
232 239
233 #ifdef PNG_WRITE_hIST_SUPPORTED 240 #ifdef PNG_WRITE_hIST_SUPPORTED
234 if (info_ptr->valid & PNG_INFO_hIST) 241 if ((info_ptr->valid & PNG_INFO_hIST) != 0)
235 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); 242 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
236 #endif 243 #endif
237 244
238 #ifdef PNG_WRITE_oFFs_SUPPORTED 245 #ifdef PNG_WRITE_oFFs_SUPPORTED
239 if (info_ptr->valid & PNG_INFO_oFFs) 246 if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
240 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, 247 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
241 info_ptr->offset_unit_type); 248 info_ptr->offset_unit_type);
242 #endif 249 #endif
243 250
244 #ifdef PNG_WRITE_pCAL_SUPPORTED 251 #ifdef PNG_WRITE_pCAL_SUPPORTED
245 if (info_ptr->valid & PNG_INFO_pCAL) 252 if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
246 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, 253 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
247 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, 254 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
248 info_ptr->pcal_units, info_ptr->pcal_params); 255 info_ptr->pcal_units, info_ptr->pcal_params);
249 #endif 256 #endif
250 257
251 #ifdef PNG_WRITE_sCAL_SUPPORTED 258 #ifdef PNG_WRITE_sCAL_SUPPORTED
252 if (info_ptr->valid & PNG_INFO_sCAL) 259 if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
253 png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, 260 png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
254 info_ptr->scal_s_width, info_ptr->scal_s_height); 261 info_ptr->scal_s_width, info_ptr->scal_s_height);
255 #endif /* sCAL */ 262 #endif /* sCAL */
256 263
257 #ifdef PNG_WRITE_pHYs_SUPPORTED 264 #ifdef PNG_WRITE_pHYs_SUPPORTED
258 if (info_ptr->valid & PNG_INFO_pHYs) 265 if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
259 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, 266 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
260 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); 267 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
261 #endif /* pHYs */ 268 #endif /* pHYs */
262 269
263 #ifdef PNG_WRITE_tIME_SUPPORTED 270 #ifdef PNG_WRITE_tIME_SUPPORTED
264 if (info_ptr->valid & PNG_INFO_tIME) 271 if ((info_ptr->valid & PNG_INFO_tIME) != 0)
265 { 272 {
266 png_write_tIME(png_ptr, &(info_ptr->mod_time)); 273 png_write_tIME(png_ptr, &(info_ptr->mod_time));
267 png_ptr->mode |= PNG_WROTE_tIME; 274 png_ptr->mode |= PNG_WROTE_tIME;
268 } 275 }
269 #endif /* tIME */ 276 #endif /* tIME */
270 277
271 #ifdef PNG_WRITE_sPLT_SUPPORTED 278 #ifdef PNG_WRITE_sPLT_SUPPORTED
272 if (info_ptr->valid & PNG_INFO_sPLT) 279 if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
273 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) 280 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
274 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); 281 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
275 #endif /* sPLT */ 282 #endif /* sPLT */
276 283
277 #ifdef PNG_WRITE_TEXT_SUPPORTED 284 #ifdef PNG_WRITE_TEXT_SUPPORTED
278 /* Check to see if we need to write text chunks */ 285 /* Check to see if we need to write text chunks */
279 for (i = 0; i < info_ptr->num_text; i++) 286 for (i = 0; i < info_ptr->num_text; i++)
280 { 287 {
281 png_debug2(2, "Writing header text chunk %d, type %d", i, 288 png_debug2(2, "Writing header text chunk %d, type %d", i,
282 info_ptr->text[i].compression); 289 info_ptr->text[i].compression);
283 /* An internationalized chunk? */ 290 /* An internationalized chunk? */
284 if (info_ptr->text[i].compression > 0) 291 if (info_ptr->text[i].compression > 0)
285 { 292 {
286 #ifdef PNG_WRITE_iTXt_SUPPORTED 293 #ifdef PNG_WRITE_iTXt_SUPPORTED
287 /* Write international chunk */ 294 /* Write international chunk */
288 png_write_iTXt(png_ptr, 295 png_write_iTXt(png_ptr,
289 info_ptr->text[i].compression, 296 info_ptr->text[i].compression,
290 info_ptr->text[i].key, 297 info_ptr->text[i].key,
291 info_ptr->text[i].lang, 298 info_ptr->text[i].lang,
292 info_ptr->text[i].lang_key, 299 info_ptr->text[i].lang_key,
293 info_ptr->text[i].text); 300 info_ptr->text[i].text);
301 /* Mark this chunk as written */
302 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
303 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
304 else
305 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
294 #else 306 #else
295 png_warning(png_ptr, "Unable to write international text"); 307 png_warning(png_ptr, "Unable to write international text");
296 #endif 308 #endif
297 /* Mark this chunk as written */
298 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
299 } 309 }
300 310
301 /* If we want a compressed text chunk */ 311 /* If we want a compressed text chunk */
302 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) 312 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
303 { 313 {
304 #ifdef PNG_WRITE_zTXt_SUPPORTED 314 #ifdef PNG_WRITE_zTXt_SUPPORTED
305 /* Write compressed chunk */ 315 /* Write compressed chunk */
306 png_write_zTXt(png_ptr, info_ptr->text[i].key, 316 png_write_zTXt(png_ptr, info_ptr->text[i].key,
307 info_ptr->text[i].text, 0, 317 info_ptr->text[i].text, info_ptr->text[i].compression);
308 info_ptr->text[i].compression); 318 /* Mark this chunk as written */
319 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
309 #else 320 #else
310 png_warning(png_ptr, "Unable to write compressed text"); 321 png_warning(png_ptr, "Unable to write compressed text");
311 #endif 322 #endif
312 /* Mark this chunk as written */
313 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
314 } 323 }
315 324
316 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 325 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
317 { 326 {
318 #ifdef PNG_WRITE_tEXt_SUPPORTED 327 #ifdef PNG_WRITE_tEXt_SUPPORTED
319 /* Write uncompressed chunk */ 328 /* Write uncompressed chunk */
320 png_write_tEXt(png_ptr, info_ptr->text[i].key, 329 png_write_tEXt(png_ptr, info_ptr->text[i].key,
321 info_ptr->text[i].text, 330 info_ptr->text[i].text,
322 0); 331 0);
323 /* Mark this chunk as written */ 332 /* Mark this chunk as written */
(...skipping 17 matching lines...) Expand all
341 * comments, I suggest writing them here, and compressing them. 350 * comments, I suggest writing them here, and compressing them.
342 */ 351 */
343 void PNGAPI 352 void PNGAPI
344 png_write_end(png_structrp png_ptr, png_inforp info_ptr) 353 png_write_end(png_structrp png_ptr, png_inforp info_ptr)
345 { 354 {
346 png_debug(1, "in png_write_end"); 355 png_debug(1, "in png_write_end");
347 356
348 if (png_ptr == NULL) 357 if (png_ptr == NULL)
349 return; 358 return;
350 359
351 if (!(png_ptr->mode & PNG_HAVE_IDAT)) 360 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
352 png_error(png_ptr, "No IDATs written into file"); 361 png_error(png_ptr, "No IDATs written into file");
353 362
354 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 363 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
355 if (png_ptr->num_palette_max > png_ptr->num_palette) 364 if (png_ptr->num_palette_max > png_ptr->num_palette)
356 png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); 365 png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
357 #endif 366 #endif
358 367
359 /* See if user wants us to write information chunks */ 368 /* See if user wants us to write information chunks */
360 if (info_ptr != NULL) 369 if (info_ptr != NULL)
361 { 370 {
362 #ifdef PNG_WRITE_TEXT_SUPPORTED 371 #ifdef PNG_WRITE_TEXT_SUPPORTED
363 int i; /* local index variable */ 372 int i; /* local index variable */
364 #endif 373 #endif
365 #ifdef PNG_WRITE_tIME_SUPPORTED 374 #ifdef PNG_WRITE_tIME_SUPPORTED
366 /* Check to see if user has supplied a time chunk */ 375 /* Check to see if user has supplied a time chunk */
367 if ((info_ptr->valid & PNG_INFO_tIME) && 376 if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
368 !(png_ptr->mode & PNG_WROTE_tIME)) 377 (png_ptr->mode & PNG_WROTE_tIME) == 0)
369 png_write_tIME(png_ptr, &(info_ptr->mod_time)); 378 png_write_tIME(png_ptr, &(info_ptr->mod_time));
370 379
371 #endif 380 #endif
372 #ifdef PNG_WRITE_TEXT_SUPPORTED 381 #ifdef PNG_WRITE_TEXT_SUPPORTED
373 /* Loop through comment chunks */ 382 /* Loop through comment chunks */
374 for (i = 0; i < info_ptr->num_text; i++) 383 for (i = 0; i < info_ptr->num_text; i++)
375 { 384 {
376 png_debug2(2, "Writing trailer text chunk %d, type %d", i, 385 png_debug2(2, "Writing trailer text chunk %d, type %d", i,
377 info_ptr->text[i].compression); 386 info_ptr->text[i].compression);
378 /* An internationalized chunk? */ 387 /* An internationalized chunk? */
379 if (info_ptr->text[i].compression > 0) 388 if (info_ptr->text[i].compression > 0)
380 { 389 {
381 #ifdef PNG_WRITE_iTXt_SUPPORTED 390 #ifdef PNG_WRITE_iTXt_SUPPORTED
382 /* Write international chunk */ 391 /* Write international chunk */
383 png_write_iTXt(png_ptr, 392 png_write_iTXt(png_ptr,
384 info_ptr->text[i].compression, 393 info_ptr->text[i].compression,
385 info_ptr->text[i].key, 394 info_ptr->text[i].key,
386 info_ptr->text[i].lang, 395 info_ptr->text[i].lang,
387 info_ptr->text[i].lang_key, 396 info_ptr->text[i].lang_key,
388 info_ptr->text[i].text); 397 info_ptr->text[i].text);
398 /* Mark this chunk as written */
399 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
400 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
401 else
402 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
389 #else 403 #else
390 png_warning(png_ptr, "Unable to write international text"); 404 png_warning(png_ptr, "Unable to write international text");
391 #endif 405 #endif
392 /* Mark this chunk as written */
393 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
394 } 406 }
395 407
396 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) 408 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
397 { 409 {
398 #ifdef PNG_WRITE_zTXt_SUPPORTED 410 #ifdef PNG_WRITE_zTXt_SUPPORTED
399 /* Write compressed chunk */ 411 /* Write compressed chunk */
400 png_write_zTXt(png_ptr, info_ptr->text[i].key, 412 png_write_zTXt(png_ptr, info_ptr->text[i].key,
401 info_ptr->text[i].text, 0, 413 info_ptr->text[i].text, info_ptr->text[i].compression);
402 info_ptr->text[i].compression); 414 /* Mark this chunk as written */
415 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
403 #else 416 #else
404 png_warning(png_ptr, "Unable to write compressed text"); 417 png_warning(png_ptr, "Unable to write compressed text");
405 #endif 418 #endif
406 /* Mark this chunk as written */
407 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
408 } 419 }
409 420
410 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 421 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
411 { 422 {
412 #ifdef PNG_WRITE_tEXt_SUPPORTED 423 #ifdef PNG_WRITE_tEXt_SUPPORTED
413 /* Write uncompressed chunk */ 424 /* Write uncompressed chunk */
414 png_write_tEXt(png_ptr, info_ptr->text[i].key, 425 png_write_tEXt(png_ptr, info_ptr->text[i].key,
415 info_ptr->text[i].text, 0); 426 info_ptr->text[i].text, 0);
427 /* Mark this chunk as written */
428 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
416 #else 429 #else
417 png_warning(png_ptr, "Unable to write uncompressed text"); 430 png_warning(png_ptr, "Unable to write uncompressed text");
418 #endif 431 #endif
419
420 /* Mark this chunk as written */
421 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
422 } 432 }
423 } 433 }
424 #endif 434 #endif
425 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 435 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
426 write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); 436 write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
427 #endif 437 #endif
428 } 438 }
429 439
430 png_ptr->mode |= PNG_AFTER_IDAT; 440 png_ptr->mode |= PNG_AFTER_IDAT;
431 441
432 /* Write end of PNG file */ 442 /* Write end of PNG file */
433 png_write_IEND(png_ptr); 443 png_write_IEND(png_ptr);
444
434 /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, 445 /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
435 * and restored again in libpng-1.2.30, may cause some applications that 446 * and restored again in libpng-1.2.30, may cause some applications that
436 * do not set png_ptr->output_flush_fn to crash. If your application 447 * do not set png_ptr->output_flush_fn to crash. If your application
437 * experiences a problem, please try building libpng with 448 * experiences a problem, please try building libpng with
438 * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to 449 * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
439 * png-mng-implement at lists.sf.net . 450 * png-mng-implement at lists.sf.net .
440 */ 451 */
441 #ifdef PNG_WRITE_FLUSH_SUPPORTED 452 #ifdef PNG_WRITE_FLUSH_SUPPORTED
442 # ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED 453 # ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
443 png_flush(png_ptr); 454 png_flush(png_ptr);
(...skipping 27 matching lines...) Expand all
471 } 482 }
472 #endif 483 #endif
473 484
474 /* Initialize png_ptr structure, and allocate any memory needed */ 485 /* Initialize png_ptr structure, and allocate any memory needed */
475 PNG_FUNCTION(png_structp,PNGAPI 486 PNG_FUNCTION(png_structp,PNGAPI
476 png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 487 png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
477 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) 488 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
478 { 489 {
479 #ifndef PNG_USER_MEM_SUPPORTED 490 #ifndef PNG_USER_MEM_SUPPORTED
480 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 491 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
481 error_fn, warn_fn, NULL, NULL, NULL); 492 error_fn, warn_fn, NULL, NULL, NULL);
482 #else 493 #else
483 return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, 494 return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
484 warn_fn, NULL, NULL, NULL); 495 warn_fn, NULL, NULL, NULL);
485 } 496 }
486 497
487 /* Alternate initialize png_ptr structure, and allocate any memory needed */ 498 /* Alternate initialize png_ptr structure, and allocate any memory needed */
488 PNG_FUNCTION(png_structp,PNGAPI 499 PNG_FUNCTION(png_structp,PNGAPI
489 png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, 500 png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
490 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 501 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
491 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 502 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
492 { 503 {
493 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 504 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
494 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); 505 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
495 #endif /* PNG_USER_MEM_SUPPORTED */ 506 #endif /* USER_MEM */
496 if (png_ptr != NULL) 507 if (png_ptr != NULL)
497 { 508 {
498 /* Set the zlib control values to defaults; they can be overridden by the 509 /* Set the zlib control values to defaults; they can be overridden by the
499 * application after the struct has been created. 510 * application after the struct has been created.
500 */ 511 */
501 png_ptr->zbuffer_size = PNG_ZBUF_SIZE; 512 png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
502 513
503 /* The 'zlib_strategy' setting is irrelevant because png_default_claim in 514 /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
504 * pngwutil.c defaults it according to whether or not filters will be 515 * pngwutil.c defaults it according to whether or not filters will be
505 * used, and ignores this setting. 516 * used, and ignores this setting.
506 */ 517 */
507 png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY; 518 png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
508 png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION; 519 png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
509 png_ptr->zlib_mem_level = 8; 520 png_ptr->zlib_mem_level = 8;
510 png_ptr->zlib_window_bits = 15; 521 png_ptr->zlib_window_bits = 15;
511 png_ptr->zlib_method = 8; 522 png_ptr->zlib_method = 8;
512 523
513 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED 524 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
514 png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY; 525 png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
515 png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION; 526 png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
516 png_ptr->zlib_text_mem_level = 8; 527 png_ptr->zlib_text_mem_level = 8;
517 png_ptr->zlib_text_window_bits = 15; 528 png_ptr->zlib_text_window_bits = 15;
518 png_ptr->zlib_text_method = 8; 529 png_ptr->zlib_text_method = 8;
519 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ 530 #endif /* WRITE_COMPRESSED_TEXT */
520 531
521 /* This is a highly dubious configuration option; by default it is off, 532 /* This is a highly dubious configuration option; by default it is off,
522 * but it may be appropriate for private builds that are testing 533 * but it may be appropriate for private builds that are testing
523 * extensions not conformant to the current specification, or of 534 * extensions not conformant to the current specification, or of
524 * applications that must not fail to write at all costs! 535 * applications that must not fail to write at all costs!
525 */ 536 */
526 #ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED 537 #ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
527 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
528 /* In stable builds only warn if an application error can be completely 538 /* In stable builds only warn if an application error can be completely
529 * handled. 539 * handled.
530 */ 540 */
541 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
531 #endif 542 #endif
532 543
533 /* App warnings are warnings in release (or release candidate) builds but 544 /* App warnings are warnings in release (or release candidate) builds but
534 * are errors during development. 545 * are errors during development.
535 */ 546 */
536 #if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC 547 #if PNG_RELEASE_BUILD
537 png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; 548 png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
538 #endif 549 #endif
539 550
540 /* TODO: delay this, it can be done in png_init_io() (if the app doesn't 551 /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
541 * do it itself) avoiding setting the default function if it is not 552 * do it itself) avoiding setting the default function if it is not
542 * required. 553 * required.
543 */ 554 */
544 png_set_write_fn(png_ptr, NULL, NULL, NULL); 555 png_set_write_fn(png_ptr, NULL, NULL, NULL);
545 } 556 }
546 557
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 for (pass = 0; pass < num_pass; pass++) 610 for (pass = 0; pass < num_pass; pass++)
600 { 611 {
601 /* Loop through image */ 612 /* Loop through image */
602 for (i = 0, rp = image; i < png_ptr->height; i++, rp++) 613 for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
603 { 614 {
604 png_write_row(png_ptr, *rp); 615 png_write_row(png_ptr, *rp);
605 } 616 }
606 } 617 }
607 } 618 }
608 619
620 #ifdef PNG_MNG_FEATURES_SUPPORTED
621 /* Performs intrapixel differencing */
622 static void
623 png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
624 {
625 png_debug(1, "in png_do_write_intrapixel");
626
627 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
628 {
629 int bytes_per_pixel;
630 png_uint_32 row_width = row_info->width;
631 if (row_info->bit_depth == 8)
632 {
633 png_bytep rp;
634 png_uint_32 i;
635
636 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
637 bytes_per_pixel = 3;
638
639 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
640 bytes_per_pixel = 4;
641
642 else
643 return;
644
645 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
646 {
647 *(rp) = (png_byte)(*rp - *(rp + 1));
648 *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
649 }
650 }
651
652 #ifdef PNG_WRITE_16BIT_SUPPORTED
653 else if (row_info->bit_depth == 16)
654 {
655 png_bytep rp;
656 png_uint_32 i;
657
658 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
659 bytes_per_pixel = 6;
660
661 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
662 bytes_per_pixel = 8;
663
664 else
665 return;
666
667 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
668 {
669 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
670 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
671 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
672 png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
673 png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
674 *(rp ) = (png_byte)(red >> 8);
675 *(rp + 1) = (png_byte)red;
676 *(rp + 4) = (png_byte)(blue >> 8);
677 *(rp + 5) = (png_byte)blue;
678 }
679 }
680 #endif /* WRITE_16BIT */
681 }
682 }
683 #endif /* MNG_FEATURES */
684
609 /* Called by user to write a row of image data */ 685 /* Called by user to write a row of image data */
610 void PNGAPI 686 void PNGAPI
611 png_write_row(png_structrp png_ptr, png_const_bytep row) 687 png_write_row(png_structrp png_ptr, png_const_bytep row)
612 { 688 {
613 /* 1.5.6: moved from png_struct to be a local structure: */ 689 /* 1.5.6: moved from png_struct to be a local structure: */
614 png_row_info row_info; 690 png_row_info row_info;
615 691
616 if (png_ptr == NULL) 692 if (png_ptr == NULL)
617 return; 693 return;
618 694
619 png_debug2(1, "in png_write_row (row %u, pass %d)", 695 png_debug2(1, "in png_write_row (row %u, pass %d)",
620 png_ptr->row_number, png_ptr->pass); 696 png_ptr->row_number, png_ptr->pass);
621 697
622 /* Initialize transformations and other stuff if first time */ 698 /* Initialize transformations and other stuff if first time */
623 if (png_ptr->row_number == 0 && png_ptr->pass == 0) 699 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
624 { 700 {
625 /* Make sure we wrote the header info */ 701 /* Make sure we wrote the header info */
626 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) 702 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
627 png_error(png_ptr, 703 png_error(png_ptr,
628 "png_write_info was never called before png_write_row"); 704 "png_write_info was never called before png_write_row");
629 705
630 /* Check for transforms that have been set but were defined out */ 706 /* Check for transforms that have been set but were defined out */
631 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) 707 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
632 if (png_ptr->transformations & PNG_INVERT_MONO) 708 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
633 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); 709 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
634 #endif 710 #endif
635 711
636 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) 712 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
637 if (png_ptr->transformations & PNG_FILLER) 713 if ((png_ptr->transformations & PNG_FILLER) != 0)
638 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); 714 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
639 #endif 715 #endif
640 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 716 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
641 defined(PNG_READ_PACKSWAP_SUPPORTED) 717 defined(PNG_READ_PACKSWAP_SUPPORTED)
642 if (png_ptr->transformations & PNG_PACKSWAP) 718 if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
643 png_warning(png_ptr, 719 png_warning(png_ptr,
644 "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); 720 "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
645 #endif 721 #endif
646 722
647 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) 723 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
648 if (png_ptr->transformations & PNG_PACK) 724 if ((png_ptr->transformations & PNG_PACK) != 0)
649 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); 725 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
650 #endif 726 #endif
651 727
652 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) 728 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
653 if (png_ptr->transformations & PNG_SHIFT) 729 if ((png_ptr->transformations & PNG_SHIFT) != 0)
654 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); 730 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
655 #endif 731 #endif
656 732
657 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) 733 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
658 if (png_ptr->transformations & PNG_BGR) 734 if ((png_ptr->transformations & PNG_BGR) != 0)
659 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); 735 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
660 #endif 736 #endif
661 737
662 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) 738 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
663 if (png_ptr->transformations & PNG_SWAP_BYTES) 739 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
664 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); 740 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
665 #endif 741 #endif
666 742
667 png_write_start_row(png_ptr); 743 png_write_start_row(png_ptr);
668 } 744 }
669 745
670 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 746 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
671 /* If interlaced and not interested in row, return */ 747 /* If interlaced and not interested in row, return */
672 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) 748 if (png_ptr->interlaced != 0 &&
749 (png_ptr->transformations & PNG_INTERLACE) != 0)
673 { 750 {
674 switch (png_ptr->pass) 751 switch (png_ptr->pass)
675 { 752 {
676 case 0: 753 case 0:
677 if (png_ptr->row_number & 0x07) 754 if ((png_ptr->row_number & 0x07) != 0)
678 { 755 {
679 png_write_finish_row(png_ptr); 756 png_write_finish_row(png_ptr);
680 return; 757 return;
681 } 758 }
682 break; 759 break;
683 760
684 case 1: 761 case 1:
685 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) 762 if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
686 { 763 {
687 png_write_finish_row(png_ptr); 764 png_write_finish_row(png_ptr);
688 return; 765 return;
689 } 766 }
690 break; 767 break;
691 768
692 case 2: 769 case 2:
693 if ((png_ptr->row_number & 0x07) != 4) 770 if ((png_ptr->row_number & 0x07) != 4)
694 { 771 {
695 png_write_finish_row(png_ptr); 772 png_write_finish_row(png_ptr);
696 return; 773 return;
697 } 774 }
698 break; 775 break;
699 776
700 case 3: 777 case 3:
701 if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) 778 if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
702 { 779 {
703 png_write_finish_row(png_ptr); 780 png_write_finish_row(png_ptr);
704 return; 781 return;
705 } 782 }
706 break; 783 break;
707 784
708 case 4: 785 case 4:
709 if ((png_ptr->row_number & 0x03) != 2) 786 if ((png_ptr->row_number & 0x03) != 2)
710 { 787 {
711 png_write_finish_row(png_ptr); 788 png_write_finish_row(png_ptr);
712 return; 789 return;
713 } 790 }
714 break; 791 break;
715 792
716 case 5: 793 case 5:
717 if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) 794 if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
718 { 795 {
719 png_write_finish_row(png_ptr); 796 png_write_finish_row(png_ptr);
720 return; 797 return;
721 } 798 }
722 break; 799 break;
723 800
724 case 6: 801 case 6:
725 if (!(png_ptr->row_number & 0x01)) 802 if ((png_ptr->row_number & 0x01) == 0)
726 { 803 {
727 png_write_finish_row(png_ptr); 804 png_write_finish_row(png_ptr);
728 return; 805 return;
729 } 806 }
730 break; 807 break;
731 808
732 default: /* error: ignore it */ 809 default: /* error: ignore it */
733 break; 810 break;
734 } 811 }
735 } 812 }
(...skipping 13 matching lines...) Expand all
749 png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); 826 png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
750 png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); 827 png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
751 png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); 828 png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
752 829
753 /* Copy user's row into buffer, leaving room for filter byte. */ 830 /* Copy user's row into buffer, leaving room for filter byte. */
754 memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes); 831 memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
755 832
756 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 833 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
757 /* Handle interlacing */ 834 /* Handle interlacing */
758 if (png_ptr->interlaced && png_ptr->pass < 6 && 835 if (png_ptr->interlaced && png_ptr->pass < 6 &&
759 (png_ptr->transformations & PNG_INTERLACE)) 836 (png_ptr->transformations & PNG_INTERLACE) != 0)
760 { 837 {
761 png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass); 838 png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
762 /* This should always get caught above, but still ... */ 839 /* This should always get caught above, but still ... */
763 if (!(row_info.width)) 840 if (row_info.width == 0)
764 { 841 {
765 png_write_finish_row(png_ptr); 842 png_write_finish_row(png_ptr);
766 return; 843 return;
767 } 844 }
768 } 845 }
769 #endif 846 #endif
770 847
771 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED 848 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
772 /* Handle other transformations */ 849 /* Handle other transformations */
773 if (png_ptr->transformations) 850 if (png_ptr->transformations != 0)
774 png_do_write_transformations(png_ptr, &row_info); 851 png_do_write_transformations(png_ptr, &row_info);
775 #endif 852 #endif
776 853
777 /* At this point the row_info pixel depth must match the 'transformed' depth, 854 /* At this point the row_info pixel depth must match the 'transformed' depth,
778 * which is also the output depth. 855 * which is also the output depth.
779 */ 856 */
780 if (row_info.pixel_depth != png_ptr->pixel_depth || 857 if (row_info.pixel_depth != png_ptr->pixel_depth ||
781 row_info.pixel_depth != png_ptr->transformed_pixel_depth) 858 row_info.pixel_depth != png_ptr->transformed_pixel_depth)
782 png_error(png_ptr, "internal write transform logic error"); 859 png_error(png_ptr, "internal write transform logic error");
783 860
784 #ifdef PNG_MNG_FEATURES_SUPPORTED 861 #ifdef PNG_MNG_FEATURES_SUPPORTED
785 /* Write filter_method 64 (intrapixel differencing) only if 862 /* Write filter_method 64 (intrapixel differencing) only if
786 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 863 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
787 * 2. Libpng did not write a PNG signature (this filter_method is only 864 * 2. Libpng did not write a PNG signature (this filter_method is only
788 * used in PNG datastreams that are embedded in MNG datastreams) and 865 * used in PNG datastreams that are embedded in MNG datastreams) and
789 * 3. The application called png_permit_mng_features with a mask that 866 * 3. The application called png_permit_mng_features with a mask that
790 * included PNG_FLAG_MNG_FILTER_64 and 867 * included PNG_FLAG_MNG_FILTER_64 and
791 * 4. The filter_method is 64 and 868 * 4. The filter_method is 64 and
792 * 5. The color_type is RGB or RGBA 869 * 5. The color_type is RGB or RGBA
793 */ 870 */
794 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 871 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
795 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 872 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
796 { 873 {
797 /* Intrapixel differencing */ 874 /* Intrapixel differencing */
798 png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1); 875 png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
799 } 876 }
800 #endif 877 #endif
801 878
802 /* Added at libpng-1.5.10 */ 879 /* Added at libpng-1.5.10 */
803 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 880 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
804 /* Check for out-of-range palette index */ 881 /* Check for out-of-range palette index */
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 return; 914 return;
838 915
839 /* We have already written out all of the data */ 916 /* We have already written out all of the data */
840 if (png_ptr->row_number >= png_ptr->num_rows) 917 if (png_ptr->row_number >= png_ptr->num_rows)
841 return; 918 return;
842 919
843 png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH); 920 png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
844 png_ptr->flush_rows = 0; 921 png_ptr->flush_rows = 0;
845 png_flush(png_ptr); 922 png_flush(png_ptr);
846 } 923 }
847 #endif /* PNG_WRITE_FLUSH_SUPPORTED */ 924 #endif /* WRITE_FLUSH */
848
849 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
850 static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */
851 #endif
852 925
853 /* Free any memory used in png_ptr struct without freeing the struct itself. */ 926 /* Free any memory used in png_ptr struct without freeing the struct itself. */
854 static void 927 static void
855 png_write_destroy(png_structrp png_ptr) 928 png_write_destroy(png_structrp png_ptr)
856 { 929 {
857 png_debug(1, "in png_write_destroy"); 930 png_debug(1, "in png_write_destroy");
858 931
859 /* Free any memory zlib uses */ 932 /* Free any memory zlib uses */
860 if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) 933 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
861 deflateEnd(&png_ptr->zstream); 934 deflateEnd(&png_ptr->zstream);
862 935
863 /* Free our memory. png_free checks NULL for us. */ 936 /* Free our memory. png_free checks NULL for us. */
864 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); 937 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
865 png_free(png_ptr, png_ptr->row_buf); 938 png_free(png_ptr, png_ptr->row_buf);
939 png_ptr->row_buf = NULL;
866 #ifdef PNG_WRITE_FILTER_SUPPORTED 940 #ifdef PNG_WRITE_FILTER_SUPPORTED
867 png_free(png_ptr, png_ptr->prev_row); 941 png_free(png_ptr, png_ptr->prev_row);
868 png_free(png_ptr, png_ptr->sub_row); 942 png_free(png_ptr, png_ptr->try_row);
869 png_free(png_ptr, png_ptr->up_row); 943 png_free(png_ptr, png_ptr->tst_row);
870 png_free(png_ptr, png_ptr->avg_row); 944 png_ptr->prev_row = NULL;
871 png_free(png_ptr, png_ptr->paeth_row); 945 png_ptr->try_row = NULL;
872 #endif 946 png_ptr->tst_row = NULL;
873
874 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
875 /* Use this to save a little code space, it doesn't free the filter_costs */
876 png_reset_filter_heuristics(png_ptr);
877 png_free(png_ptr, png_ptr->filter_costs);
878 png_free(png_ptr, png_ptr->inv_filter_costs);
879 #endif 947 #endif
880 948
881 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 949 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
882 png_free(png_ptr, png_ptr->chunk_list); 950 png_free(png_ptr, png_ptr->chunk_list);
951 png_ptr->chunk_list = NULL;
883 #endif 952 #endif
884 953
885 /* The error handling and memory handling information is left intact at this 954 /* The error handling and memory handling information is left intact at this
886 * point: the jmp_buf may still have to be freed. See png_destroy_png_struct 955 * point: the jmp_buf may still have to be freed. See png_destroy_png_struct
887 * for how this happens. 956 * for how this happens.
888 */ 957 */
889 } 958 }
890 959
891 /* Free all memory used by the write. 960 /* Free all memory used by the write.
892 * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for 961 * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
(...skipping 25 matching lines...) Expand all
918 /* Allow the application to select one or more row filters to use. */ 987 /* Allow the application to select one or more row filters to use. */
919 void PNGAPI 988 void PNGAPI
920 png_set_filter(png_structrp png_ptr, int method, int filters) 989 png_set_filter(png_structrp png_ptr, int method, int filters)
921 { 990 {
922 png_debug(1, "in png_set_filter"); 991 png_debug(1, "in png_set_filter");
923 992
924 if (png_ptr == NULL) 993 if (png_ptr == NULL)
925 return; 994 return;
926 995
927 #ifdef PNG_MNG_FEATURES_SUPPORTED 996 #ifdef PNG_MNG_FEATURES_SUPPORTED
928 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 997 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
929 (method == PNG_INTRAPIXEL_DIFFERENCING)) 998 (method == PNG_INTRAPIXEL_DIFFERENCING))
930 method = PNG_FILTER_TYPE_BASE; 999 method = PNG_FILTER_TYPE_BASE;
931 1000
932 #endif 1001 #endif
933 if (method == PNG_FILTER_TYPE_BASE) 1002 if (method == PNG_FILTER_TYPE_BASE)
934 { 1003 {
935 switch (filters & (PNG_ALL_FILTERS | 0x07)) 1004 switch (filters & (PNG_ALL_FILTERS | 0x07))
936 { 1005 {
937 #ifdef PNG_WRITE_FILTER_SUPPORTED 1006 #ifdef PNG_WRITE_FILTER_SUPPORTED
938 case 5: 1007 case 5:
939 case 6: 1008 case 6:
940 case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); 1009 case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
941 /* FALL THROUGH */ 1010 /* FALL THROUGH */
942 #endif /* PNG_WRITE_FILTER_SUPPORTED */ 1011 #endif /* WRITE_FILTER */
943 case PNG_FILTER_VALUE_NONE: 1012 case PNG_FILTER_VALUE_NONE:
944 png_ptr->do_filter = PNG_FILTER_NONE; break; 1013 png_ptr->do_filter = PNG_FILTER_NONE; break;
945 1014
946 #ifdef PNG_WRITE_FILTER_SUPPORTED 1015 #ifdef PNG_WRITE_FILTER_SUPPORTED
947 case PNG_FILTER_VALUE_SUB: 1016 case PNG_FILTER_VALUE_SUB:
948 png_ptr->do_filter = PNG_FILTER_SUB; break; 1017 png_ptr->do_filter = PNG_FILTER_SUB; break;
949 1018
950 case PNG_FILTER_VALUE_UP: 1019 case PNG_FILTER_VALUE_UP:
951 png_ptr->do_filter = PNG_FILTER_UP; break; 1020 png_ptr->do_filter = PNG_FILTER_UP; break;
952 1021
953 case PNG_FILTER_VALUE_AVG: 1022 case PNG_FILTER_VALUE_AVG:
954 png_ptr->do_filter = PNG_FILTER_AVG; break; 1023 png_ptr->do_filter = PNG_FILTER_AVG; break;
955 1024
956 case PNG_FILTER_VALUE_PAETH: 1025 case PNG_FILTER_VALUE_PAETH:
957 png_ptr->do_filter = PNG_FILTER_PAETH; break; 1026 png_ptr->do_filter = PNG_FILTER_PAETH; break;
958 1027
959 default: 1028 default:
960 png_ptr->do_filter = (png_byte)filters; break; 1029 png_ptr->do_filter = (png_byte)filters; break;
961 #else 1030 #else
962 default: 1031 default:
963 png_app_error(png_ptr, "Unknown row filter for method 0"); 1032 png_app_error(png_ptr, "Unknown row filter for method 0");
964 #endif /* PNG_WRITE_FILTER_SUPPORTED */ 1033 #endif /* WRITE_FILTER */
965 } 1034 }
966 1035
1036 #ifdef PNG_WRITE_FILTER_SUPPORTED
967 /* If we have allocated the row_buf, this means we have already started 1037 /* If we have allocated the row_buf, this means we have already started
968 * with the image and we should have allocated all of the filter buffers 1038 * with the image and we should have allocated all of the filter buffers
969 * that have been selected. If prev_row isn't already allocated, then 1039 * that have been selected. If prev_row isn't already allocated, then
970 * it is too late to start using the filters that need it, since we 1040 * it is too late to start using the filters that need it, since we
971 * will be missing the data in the previous row. If an application 1041 * will be missing the data in the previous row. If an application
972 * wants to start and stop using particular filters during compression, 1042 * wants to start and stop using particular filters during compression,
973 * it should start out with all of the filters, and then add and 1043 * it should start out with all of the filters, and then remove them
974 * remove them after the start of compression. 1044 * or add them back after the start of compression.
1045 *
1046 * NOTE: this is a nasty constraint on the code, because it means that the
1047 * prev_row buffer must be maintained even if there are currently no
1048 * 'prev_row' requiring filters active.
975 */ 1049 */
976 if (png_ptr->row_buf != NULL) 1050 if (png_ptr->row_buf != NULL)
977 { 1051 {
978 #ifdef PNG_WRITE_FILTER_SUPPORTED 1052 int num_filters;
979 if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) 1053 png_alloc_size_t buf_size;
1054
1055 /* Repeat the checks in png_write_start_row; 1 pixel high or wide
1056 * images cannot benefit from certain filters. If this isn't done here
1057 * the check below will fire on 1 pixel high images.
1058 */
1059 if (png_ptr->height == 1)
1060 filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1061
1062 if (png_ptr->width == 1)
1063 filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1064
1065 if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0
1066 && png_ptr->prev_row == NULL)
980 { 1067 {
981 png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, 1068 /* This is the error case, however it is benign - the previous row
982 (png_ptr->rowbytes + 1)); 1069 * is not available so the filter can't be used. Just warn here.
983 png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; 1070 */
1071 png_app_warning(png_ptr,
1072 "png_set_filter: UP/AVG/PAETH cannot be added after start");
1073 filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
984 } 1074 }
985 1075
986 if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) 1076 num_filters = 0;
1077
1078 if (filters & PNG_FILTER_SUB)
1079 num_filters++;
1080
1081 if (filters & PNG_FILTER_UP)
1082 num_filters++;
1083
1084 if (filters & PNG_FILTER_AVG)
1085 num_filters++;
1086
1087 if (filters & PNG_FILTER_PAETH)
1088 num_filters++;
1089
1090 /* Allocate needed row buffers if they have not already been
1091 * allocated.
1092 */
1093 buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth,
1094 png_ptr->width) + 1;
1095
1096 if (png_ptr->try_row == NULL)
1097 png_ptr->try_row = png_voidcast(png_bytep,
1098 png_malloc(png_ptr, buf_size));
1099
1100 if (num_filters > 1)
987 { 1101 {
988 if (png_ptr->prev_row == NULL) 1102 if (png_ptr->tst_row == NULL)
989 { 1103 png_ptr->tst_row = png_voidcast(png_bytep,
990 png_warning(png_ptr, "Can't add Up filter after starting"); 1104 png_malloc(png_ptr, buf_size));
991 png_ptr->do_filter = (png_byte)(png_ptr->do_filter &
992 ~PNG_FILTER_UP);
993 }
994
995 else
996 {
997 png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
998 (png_ptr->rowbytes + 1));
999 png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
1000 }
1001 } 1105 }
1002 1106 }
1003 if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) 1107 png_ptr->do_filter = (png_byte)filters;
1004 { 1108 #endif
1005 if (png_ptr->prev_row == NULL)
1006 {
1007 png_warning(png_ptr, "Can't add Average filter after starting");
1008 png_ptr->do_filter = (png_byte)(png_ptr->do_filter &
1009 ~PNG_FILTER_AVG);
1010 }
1011
1012 else
1013 {
1014 png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
1015 (png_ptr->rowbytes + 1));
1016 png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
1017 }
1018 }
1019
1020 if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
1021 png_ptr->paeth_row == NULL)
1022 {
1023 if (png_ptr->prev_row == NULL)
1024 {
1025 png_warning(png_ptr, "Can't add Paeth filter after starting");
1026 png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
1027 }
1028
1029 else
1030 {
1031 png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
1032 (png_ptr->rowbytes + 1));
1033 png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
1034 }
1035 }
1036
1037 if (png_ptr->do_filter == PNG_NO_FILTERS)
1038 #endif /* PNG_WRITE_FILTER_SUPPORTED */
1039 png_ptr->do_filter = PNG_FILTER_NONE;
1040 }
1041 } 1109 }
1042 else 1110 else
1043 png_error(png_ptr, "Unknown custom filter method"); 1111 png_error(png_ptr, "Unknown custom filter method");
1044 } 1112 }
1045 1113
1046 /* This allows us to influence the way in which libpng chooses the "best" 1114 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
1047 * filter for the current scanline. While the "minimum-sum-of-absolute-
1048 * differences metric is relatively fast and effective, there is some
1049 * question as to whether it can be improved upon by trying to keep the
1050 * filtered data going to zlib more consistent, hopefully resulting in
1051 * better compression.
1052 */
1053 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */
1054 /* Convenience reset API. */
1055 static void
1056 png_reset_filter_heuristics(png_structrp png_ptr)
1057 {
1058 /* Clear out any old values in the 'weights' - this must be done because if
1059 * the app calls set_filter_heuristics multiple times with different
1060 * 'num_weights' values we would otherwise potentially have wrong sized
1061 * arrays.
1062 */
1063 png_ptr->num_prev_filters = 0;
1064 png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
1065 if (png_ptr->prev_filters != NULL)
1066 {
1067 png_bytep old = png_ptr->prev_filters;
1068 png_ptr->prev_filters = NULL;
1069 png_free(png_ptr, old);
1070 }
1071 if (png_ptr->filter_weights != NULL)
1072 {
1073 png_uint_16p old = png_ptr->filter_weights;
1074 png_ptr->filter_weights = NULL;
1075 png_free(png_ptr, old);
1076 }
1077
1078 if (png_ptr->inv_filter_weights != NULL)
1079 {
1080 png_uint_16p old = png_ptr->inv_filter_weights;
1081 png_ptr->inv_filter_weights = NULL;
1082 png_free(png_ptr, old);
1083 }
1084
1085 /* Leave the filter_costs - this array is fixed size. */
1086 }
1087
1088 static int
1089 png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method,
1090 int num_weights)
1091 {
1092 if (png_ptr == NULL)
1093 return 0;
1094
1095 /* Clear out the arrays */
1096 png_reset_filter_heuristics(png_ptr);
1097
1098 /* Check arguments; the 'reset' function makes the correct settings for the
1099 * unweighted case, but we must handle the weight case by initializing the
1100 * arrays for the caller.
1101 */
1102 if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1103 {
1104 int i;
1105
1106 if (num_weights > 0)
1107 {
1108 png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
1109 (png_uint_32)((sizeof (png_byte)) * num_weights));
1110
1111 /* To make sure that the weighting starts out fairly */
1112 for (i = 0; i < num_weights; i++)
1113 {
1114 png_ptr->prev_filters[i] = 255;
1115 }
1116
1117 png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
1118 (png_uint_32)((sizeof (png_uint_16)) * num_weights));
1119
1120 png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
1121 (png_uint_32)((sizeof (png_uint_16)) * num_weights));
1122
1123 for (i = 0; i < num_weights; i++)
1124 {
1125 png_ptr->inv_filter_weights[i] =
1126 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
1127 }
1128
1129 /* Safe to set this now */
1130 png_ptr->num_prev_filters = (png_byte)num_weights;
1131 }
1132
1133 /* If, in the future, there are other filter methods, this would
1134 * need to be based on png_ptr->filter.
1135 */
1136 if (png_ptr->filter_costs == NULL)
1137 {
1138 png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
1139 (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
1140
1141 png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
1142 (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
1143 }
1144
1145 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
1146 {
1147 png_ptr->inv_filter_costs[i] =
1148 png_ptr->filter_costs[i] = PNG_COST_FACTOR;
1149 }
1150
1151 /* All the arrays are inited, safe to set this: */
1152 png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED;
1153
1154 /* Return the 'ok' code. */
1155 return 1;
1156 }
1157 else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT ||
1158 heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
1159 {
1160 return 1;
1161 }
1162 else
1163 {
1164 png_warning(png_ptr, "Unknown filter heuristic method");
1165 return 0;
1166 }
1167 }
1168
1169 /* Provide floating and fixed point APIs */ 1115 /* Provide floating and fixed point APIs */
1170 #ifdef PNG_FLOATING_POINT_SUPPORTED 1116 #ifdef PNG_FLOATING_POINT_SUPPORTED
1171 void PNGAPI 1117 void PNGAPI
1172 png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, 1118 png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
1173 int num_weights, png_const_doublep filter_weights, 1119 int num_weights, png_const_doublep filter_weights,
1174 png_const_doublep filter_costs) 1120 png_const_doublep filter_costs)
1175 { 1121 {
1176 png_debug(1, "in png_set_filter_heuristics"); 1122 PNG_UNUSED(png_ptr)
1177 1123 PNG_UNUSED(heuristic_method)
1178 /* The internal API allocates all the arrays and ensures that the elements of 1124 PNG_UNUSED(num_weights)
1179 * those arrays are set to the default value. 1125 PNG_UNUSED(filter_weights)
1180 */ 1126 PNG_UNUSED(filter_costs)
1181 if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
1182 return;
1183
1184 /* If using the weighted method copy in the weights. */
1185 if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1186 {
1187 int i;
1188 for (i = 0; i < num_weights; i++)
1189 {
1190 if (filter_weights[i] <= 0.0)
1191 {
1192 png_ptr->inv_filter_weights[i] =
1193 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
1194 }
1195
1196 else
1197 {
1198 png_ptr->inv_filter_weights[i] =
1199 (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5);
1200
1201 png_ptr->filter_weights[i] =
1202 (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5);
1203 }
1204 }
1205
1206 /* Here is where we set the relative costs of the different filters. We
1207 * should take the desired compression level into account when setting
1208 * the costs, so that Paeth, for instance, has a high relative cost at low
1209 * compression levels, while it has a lower relative cost at higher
1210 * compression settings. The filter types are in order of increasing
1211 * relative cost, so it would be possible to do this with an algorithm.
1212 */
1213 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0)
1214 {
1215 png_ptr->inv_filter_costs[i] =
1216 (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5);
1217
1218 png_ptr->filter_costs[i] =
1219 (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5);
1220 }
1221 }
1222 } 1127 }
1223 #endif /* FLOATING_POINT */ 1128 #endif /* FLOATING_POINT */
1224 1129
1225 #ifdef PNG_FIXED_POINT_SUPPORTED 1130 #ifdef PNG_FIXED_POINT_SUPPORTED
1226 void PNGAPI 1131 void PNGAPI
1227 png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, 1132 png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
1228 int num_weights, png_const_fixed_point_p filter_weights, 1133 int num_weights, png_const_fixed_point_p filter_weights,
1229 png_const_fixed_point_p filter_costs) 1134 png_const_fixed_point_p filter_costs)
1230 { 1135 {
1231 png_debug(1, "in png_set_filter_heuristics_fixed"); 1136 PNG_UNUSED(png_ptr)
1232 1137 PNG_UNUSED(heuristic_method)
1233 /* The internal API allocates all the arrays and ensures that the elements of 1138 PNG_UNUSED(num_weights)
1234 * those arrays are set to the default value. 1139 PNG_UNUSED(filter_weights)
1235 */ 1140 PNG_UNUSED(filter_costs)
1236 if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
1237 return;
1238
1239 /* If using the weighted method copy in the weights. */
1240 if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1241 {
1242 int i;
1243 for (i = 0; i < num_weights; i++)
1244 {
1245 if (filter_weights[i] <= 0)
1246 {
1247 png_ptr->inv_filter_weights[i] =
1248 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
1249 }
1250
1251 else
1252 {
1253 png_ptr->inv_filter_weights[i] = (png_uint_16)
1254 ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1);
1255
1256 png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR*
1257 PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]);
1258 }
1259 }
1260
1261 /* Here is where we set the relative costs of the different filters. We
1262 * should take the desired compression level into account when setting
1263 * the costs, so that Paeth, for instance, has a high relative cost at low
1264 * compression levels, while it has a lower relative cost at higher
1265 * compression settings. The filter types are in order of increasing
1266 * relative cost, so it would be possible to do this with an algorithm.
1267 */
1268 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
1269 if (filter_costs[i] >= PNG_FP_1)
1270 {
1271 png_uint_32 tmp;
1272
1273 /* Use a 32 bit unsigned temporary here because otherwise the
1274 * intermediate value will be a 32 bit *signed* integer (ANSI rules)
1275 * and this will get the wrong answer on division.
1276 */
1277 tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2);
1278 tmp /= filter_costs[i];
1279
1280 png_ptr->inv_filter_costs[i] = (png_uint_16)tmp;
1281
1282 tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF;
1283 tmp /= PNG_FP_1;
1284
1285 png_ptr->filter_costs[i] = (png_uint_16)tmp;
1286 }
1287 }
1288 } 1141 }
1289 #endif /* FIXED_POINT */ 1142 #endif /* FIXED_POINT */
1290 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ 1143 #endif /* WRITE_WEIGHTED_FILTER */
1291 1144
1145 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
1292 void PNGAPI 1146 void PNGAPI
1293 png_set_compression_level(png_structrp png_ptr, int level) 1147 png_set_compression_level(png_structrp png_ptr, int level)
1294 { 1148 {
1295 png_debug(1, "in png_set_compression_level"); 1149 png_debug(1, "in png_set_compression_level");
1296 1150
1297 if (png_ptr == NULL) 1151 if (png_ptr == NULL)
1298 return; 1152 return;
1299 1153
1300 png_ptr->zlib_level = level; 1154 png_ptr->zlib_level = level;
1301 } 1155 }
(...skipping 25 matching lines...) Expand all
1327 1181
1328 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a 1182 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1329 * smaller value of window_bits if it can do so safely. 1183 * smaller value of window_bits if it can do so safely.
1330 */ 1184 */
1331 void PNGAPI 1185 void PNGAPI
1332 png_set_compression_window_bits(png_structrp png_ptr, int window_bits) 1186 png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
1333 { 1187 {
1334 if (png_ptr == NULL) 1188 if (png_ptr == NULL)
1335 return; 1189 return;
1336 1190
1337 /* Prior to 1.6.0 this would warn but then set the window_bits value, this 1191 /* Prior to 1.6.0 this would warn but then set the window_bits value. This
1338 * meant that negative window bits values could be selected which would cause 1192 * meant that negative window bits values could be selected that would cause
1339 * libpng to write a non-standard PNG file with raw deflate or gzip 1193 * libpng to write a non-standard PNG file with raw deflate or gzip
1340 * compressed IDAT or ancillary chunks. Such files can be read and there is 1194 * compressed IDAT or ancillary chunks. Such files can be read and there is
1341 * no warning on read, so this seems like a very bad idea. 1195 * no warning on read, so this seems like a very bad idea.
1342 */ 1196 */
1343 if (window_bits > 15) 1197 if (window_bits > 15)
1344 { 1198 {
1345 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); 1199 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1346 window_bits = 15; 1200 window_bits = 15;
1347 } 1201 }
1348 1202
(...skipping 15 matching lines...) Expand all
1364 return; 1218 return;
1365 1219
1366 /* This would produce an invalid PNG file if it worked, but it doesn't and 1220 /* This would produce an invalid PNG file if it worked, but it doesn't and
1367 * deflate will fault it, so it is harmless to just warn here. 1221 * deflate will fault it, so it is harmless to just warn here.
1368 */ 1222 */
1369 if (method != 8) 1223 if (method != 8)
1370 png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1224 png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1371 1225
1372 png_ptr->zlib_method = method; 1226 png_ptr->zlib_method = method;
1373 } 1227 }
1228 #endif /* WRITE_CUSTOMIZE_COMPRESSION */
1374 1229
1375 /* The following were added to libpng-1.5.4 */ 1230 /* The following were added to libpng-1.5.4 */
1376 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 1231 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1377 void PNGAPI 1232 void PNGAPI
1378 png_set_text_compression_level(png_structrp png_ptr, int level) 1233 png_set_text_compression_level(png_structrp png_ptr, int level)
1379 { 1234 {
1380 png_debug(1, "in png_set_text_compression_level"); 1235 png_debug(1, "in png_set_text_compression_level");
1381 1236
1382 if (png_ptr == NULL) 1237 if (png_ptr == NULL)
1383 return; 1238 return;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 png_debug(1, "in png_set_text_compression_method"); 1292 png_debug(1, "in png_set_text_compression_method");
1438 1293
1439 if (png_ptr == NULL) 1294 if (png_ptr == NULL)
1440 return; 1295 return;
1441 1296
1442 if (method != 8) 1297 if (method != 8)
1443 png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1298 png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1444 1299
1445 png_ptr->zlib_text_method = method; 1300 png_ptr->zlib_text_method = method;
1446 } 1301 }
1447 #endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ 1302 #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
1448 /* end of API added to libpng-1.5.4 */ 1303 /* end of API added to libpng-1.5.4 */
1449 1304
1450 void PNGAPI 1305 void PNGAPI
1451 png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) 1306 png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
1452 { 1307 {
1453 if (png_ptr == NULL) 1308 if (png_ptr == NULL)
1454 return; 1309 return;
1455 1310
1456 png_ptr->write_row_fn = write_row_fn; 1311 png_ptr->write_row_fn = write_row_fn;
1457 } 1312 }
(...skipping 15 matching lines...) Expand all
1473 1328
1474 1329
1475 #ifdef PNG_INFO_IMAGE_SUPPORTED 1330 #ifdef PNG_INFO_IMAGE_SUPPORTED
1476 void PNGAPI 1331 void PNGAPI
1477 png_write_png(png_structrp png_ptr, png_inforp info_ptr, 1332 png_write_png(png_structrp png_ptr, png_inforp info_ptr,
1478 int transforms, voidp params) 1333 int transforms, voidp params)
1479 { 1334 {
1480 if (png_ptr == NULL || info_ptr == NULL) 1335 if (png_ptr == NULL || info_ptr == NULL)
1481 return; 1336 return;
1482 1337
1338 if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
1339 {
1340 png_app_error(png_ptr, "no rows for png_write_image to write");
1341 return;
1342 }
1343
1483 /* Write the file header information. */ 1344 /* Write the file header information. */
1484 png_write_info(png_ptr, info_ptr); 1345 png_write_info(png_ptr, info_ptr);
1485 1346
1486 /* ------ these transformations don't touch the info structure ------- */ 1347 /* ------ these transformations don't touch the info structure ------- */
1487 1348
1349 /* Invert monochrome pixels */
1350 if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
1488 #ifdef PNG_WRITE_INVERT_SUPPORTED 1351 #ifdef PNG_WRITE_INVERT_SUPPORTED
1489 /* Invert monochrome pixels */
1490 if (transforms & PNG_TRANSFORM_INVERT_MONO)
1491 png_set_invert_mono(png_ptr); 1352 png_set_invert_mono(png_ptr);
1492 #endif 1353 #else
1493 1354 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
1494 #ifdef PNG_WRITE_SHIFT_SUPPORTED 1355 #endif
1356
1495 /* Shift the pixels up to a legal bit depth and fill in 1357 /* Shift the pixels up to a legal bit depth and fill in
1496 * as appropriate to correctly scale the image. 1358 * as appropriate to correctly scale the image.
1497 */ 1359 */
1498 if ((transforms & PNG_TRANSFORM_SHIFT) 1360 if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
1499 && (info_ptr->valid & PNG_INFO_sBIT)) 1361 #ifdef PNG_WRITE_SHIFT_SUPPORTED
1500 png_set_shift(png_ptr, &info_ptr->sig_bit); 1362 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
1501 #endif 1363 png_set_shift(png_ptr, &info_ptr->sig_bit);
1502 1364 #else
1365 png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
1366 #endif
1367
1368 /* Pack pixels into bytes */
1369 if ((transforms & PNG_TRANSFORM_PACKING) != 0)
1503 #ifdef PNG_WRITE_PACK_SUPPORTED 1370 #ifdef PNG_WRITE_PACK_SUPPORTED
1504 /* Pack pixels into bytes */ 1371 png_set_packing(png_ptr);
1505 if (transforms & PNG_TRANSFORM_PACKING) 1372 #else
1506 png_set_packing(png_ptr); 1373 png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
1507 #endif 1374 #endif
1508 1375
1376 /* Swap location of alpha bytes from ARGB to RGBA */
1377 if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
1509 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED 1378 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
1510 /* Swap location of alpha bytes from ARGB to RGBA */
1511 if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
1512 png_set_swap_alpha(png_ptr); 1379 png_set_swap_alpha(png_ptr);
1513 #endif 1380 #else
1514 1381 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
1382 #endif
1383
1384 /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
1385 * RGB, note that the code expects the input color type to be G or RGB; no
1386 * alpha channel.
1387 */
1388 if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
1389 PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
1390 {
1515 #ifdef PNG_WRITE_FILLER_SUPPORTED 1391 #ifdef PNG_WRITE_FILLER_SUPPORTED
1516 /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */ 1392 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
1517 if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) 1393 {
1518 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); 1394 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1519 1395 png_app_error(png_ptr,
1520 else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) 1396 "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
1521 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); 1397
1522 #endif 1398 /* Continue if ignored - this is the pre-1.6.10 behavior */
1523 1399 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1400 }
1401
1402 else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1403 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1404 #else
1405 png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
1406 #endif
1407 }
1408
1409 /* Flip BGR pixels to RGB */
1410 if ((transforms & PNG_TRANSFORM_BGR) != 0)
1524 #ifdef PNG_WRITE_BGR_SUPPORTED 1411 #ifdef PNG_WRITE_BGR_SUPPORTED
1525 /* Flip BGR pixels to RGB */
1526 if (transforms & PNG_TRANSFORM_BGR)
1527 png_set_bgr(png_ptr); 1412 png_set_bgr(png_ptr);
1528 #endif 1413 #else
1529 1414 png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
1415 #endif
1416
1417 /* Swap bytes of 16-bit files to most significant byte first */
1418 if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
1530 #ifdef PNG_WRITE_SWAP_SUPPORTED 1419 #ifdef PNG_WRITE_SWAP_SUPPORTED
1531 /* Swap bytes of 16-bit files to most significant byte first */
1532 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
1533 png_set_swap(png_ptr); 1420 png_set_swap(png_ptr);
1534 #endif 1421 #else
1535 1422 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
1423 #endif
1424
1425 /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
1426 if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
1536 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED 1427 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
1537 /* Swap bits of 1, 2, 4 bit packed pixel formats */
1538 if (transforms & PNG_TRANSFORM_PACKSWAP)
1539 png_set_packswap(png_ptr); 1428 png_set_packswap(png_ptr);
1540 #endif 1429 #else
1541 1430 png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
1431 #endif
1432
1433 /* Invert the alpha channel from opacity to transparency */
1434 if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
1542 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 1435 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1543 /* Invert the alpha channel from opacity to transparency */
1544 if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
1545 png_set_invert_alpha(png_ptr); 1436 png_set_invert_alpha(png_ptr);
1437 #else
1438 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
1546 #endif 1439 #endif
1547 1440
1548 /* ----------------------- end of transformations ------------------- */ 1441 /* ----------------------- end of transformations ------------------- */
1549 1442
1550 /* Write the bits */ 1443 /* Write the bits */
1551 if (info_ptr->valid & PNG_INFO_IDAT) 1444 png_write_image(png_ptr, info_ptr->row_pointers);
1552 png_write_image(png_ptr, info_ptr->row_pointers);
1553 1445
1554 /* It is REQUIRED to call this to finish writing the rest of the file */ 1446 /* It is REQUIRED to call this to finish writing the rest of the file */
1555 png_write_end(png_ptr, info_ptr); 1447 png_write_end(png_ptr, info_ptr);
1556 1448
1557 PNG_UNUSED(transforms) /* Quiet compiler warnings */
1558 PNG_UNUSED(params) 1449 PNG_UNUSED(params)
1559 } 1450 }
1560 #endif 1451 #endif
1561 1452
1562 1453
1563 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 1454 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1564 #ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ 1455 # ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
1565 /* Initialize the write structure - general purpose utility. */ 1456 /* Initialize the write structure - general purpose utility. */
1566 static int 1457 static int
1567 png_image_write_init(png_imagep image) 1458 png_image_write_init(png_imagep image)
1568 { 1459 {
1569 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, 1460 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1570 png_safe_error, png_safe_warning); 1461 png_safe_error, png_safe_warning);
1571 1462
1572 if (png_ptr != NULL) 1463 if (png_ptr != NULL)
1573 { 1464 {
1574 png_infop info_ptr = png_create_info_struct(png_ptr); 1465 png_infop info_ptr = png_create_info_struct(png_ptr);
1575 1466
1576 if (info_ptr != NULL) 1467 if (info_ptr != NULL)
1577 { 1468 {
1578 png_controlp control = png_voidcast(png_controlp, 1469 png_controlp control = png_voidcast(png_controlp,
1579 png_malloc_warn(png_ptr, (sizeof *control))); 1470 png_malloc_warn(png_ptr, (sizeof *control)));
1580 1471
1581 if (control != NULL) 1472 if (control != NULL)
1582 { 1473 {
1583 memset(control, 0, (sizeof *control)); 1474 memset(control, 0, (sizeof *control));
1584 1475
1585 control->png_ptr = png_ptr; 1476 control->png_ptr = png_ptr;
1586 control->info_ptr = info_ptr; 1477 control->info_ptr = info_ptr;
1587 control->for_write = 1; 1478 control->for_write = 1;
1588 1479
1589 image->opaque = control; 1480 image->opaque = control;
(...skipping 26 matching lines...) Expand all
1616 } png_image_write_control; 1507 } png_image_write_control;
1617 1508
1618 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to 1509 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1619 * do any necessary byte swapping. The component order is defined by the 1510 * do any necessary byte swapping. The component order is defined by the
1620 * png_image format value. 1511 * png_image format value.
1621 */ 1512 */
1622 static int 1513 static int
1623 png_write_image_16bit(png_voidp argument) 1514 png_write_image_16bit(png_voidp argument)
1624 { 1515 {
1625 png_image_write_control *display = png_voidcast(png_image_write_control*, 1516 png_image_write_control *display = png_voidcast(png_image_write_control*,
1626 argument); 1517 argument);
1627 png_imagep image = display->image; 1518 png_imagep image = display->image;
1628 png_structrp png_ptr = image->opaque->png_ptr; 1519 png_structrp png_ptr = image->opaque->png_ptr;
1629 1520
1630 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, 1521 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1631 display->first_row); 1522 display->first_row);
1632 png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); 1523 png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
1633 png_uint_16p row_end; 1524 png_uint_16p row_end;
1634 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; 1525 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1635 int aindex = 0; 1526 int aindex = 0;
1636 png_uint_32 y = image->height; 1527 png_uint_32 y = image->height;
1637 1528
1638 if (image->format & PNG_FORMAT_FLAG_ALPHA) 1529 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1639 { 1530 {
1640 if (image->format & PNG_FORMAT_FLAG_AFIRST) 1531 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1532 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1641 { 1533 {
1642 aindex = -1; 1534 aindex = -1;
1643 ++input_row; /* To point to the first component */ 1535 ++input_row; /* To point to the first component */
1644 ++output_row; 1536 ++output_row;
1645 } 1537 }
1646 1538 else
1647 else 1539 aindex = channels;
1540 # else
1648 aindex = channels; 1541 aindex = channels;
1542 # endif
1649 } 1543 }
1650 1544
1651 else 1545 else
1652 png_error(png_ptr, "png_write_image: internal call error"); 1546 png_error(png_ptr, "png_write_image: internal call error");
1653 1547
1654 /* Work out the output row end and count over this, note that the increment 1548 /* Work out the output row end and count over this, note that the increment
1655 * above to 'row' means that row_end can actually be beyond the end of the 1549 * above to 'row' means that row_end can actually be beyond the end of the
1656 * row; this is correct. 1550 * row; this is correct.
1657 */ 1551 */
1658 row_end = output_row + image->width * (channels+1); 1552 row_end = output_row + image->width * (channels+1);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1720 } 1614 }
1721 1615
1722 /* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel 1616 /* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
1723 * is present it must be removed from the components, the components are then 1617 * is present it must be removed from the components, the components are then
1724 * written in sRGB encoding. No components are added or removed. 1618 * written in sRGB encoding. No components are added or removed.
1725 * 1619 *
1726 * Calculate an alpha reciprocal to reverse pre-multiplication. As above the 1620 * Calculate an alpha reciprocal to reverse pre-multiplication. As above the
1727 * calculation can be done to 15 bits of accuracy; however, the output needs to 1621 * calculation can be done to 15 bits of accuracy; however, the output needs to
1728 * be scaled in the range 0..255*65535, so include that scaling here. 1622 * be scaled in the range 0..255*65535, so include that scaling here.
1729 */ 1623 */
1730 #define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) 1624 # define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
1731 1625
1732 static png_byte 1626 static png_byte
1733 png_unpremultiply(png_uint_32 component, png_uint_32 alpha, 1627 png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
1734 png_uint_32 reciprocal/*from the above macro*/) 1628 png_uint_32 reciprocal/*from the above macro*/)
1735 { 1629 {
1736 /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 1630 /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
1737 * is represented as some other value there is more likely to be a 1631 * is represented as some other value there is more likely to be a
1738 * discontinuity which will probably damage compression when moving from a 1632 * discontinuity which will probably damage compression when moving from a
1739 * fully transparent area to a nearly transparent one. (The assumption here 1633 * fully transparent area to a nearly transparent one. (The assumption here
1740 * is that opaque areas tend not to be 0 intensity.) 1634 * is that opaque areas tend not to be 0 intensity.)
(...skipping 30 matching lines...) Expand all
1771 } 1665 }
1772 1666
1773 else 1667 else
1774 return 0; 1668 return 0;
1775 } 1669 }
1776 1670
1777 static int 1671 static int
1778 png_write_image_8bit(png_voidp argument) 1672 png_write_image_8bit(png_voidp argument)
1779 { 1673 {
1780 png_image_write_control *display = png_voidcast(png_image_write_control*, 1674 png_image_write_control *display = png_voidcast(png_image_write_control*,
1781 argument); 1675 argument);
1782 png_imagep image = display->image; 1676 png_imagep image = display->image;
1783 png_structrp png_ptr = image->opaque->png_ptr; 1677 png_structrp png_ptr = image->opaque->png_ptr;
1784 1678
1785 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, 1679 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1786 display->first_row); 1680 display->first_row);
1787 png_bytep output_row = png_voidcast(png_bytep, display->local_row); 1681 png_bytep output_row = png_voidcast(png_bytep, display->local_row);
1788 png_uint_32 y = image->height; 1682 png_uint_32 y = image->height;
1789 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; 1683 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1790 1684
1791 if (image->format & PNG_FORMAT_FLAG_ALPHA) 1685 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1792 { 1686 {
1793 png_bytep row_end; 1687 png_bytep row_end;
1794 int aindex; 1688 int aindex;
1795 1689
1796 if (image->format & PNG_FORMAT_FLAG_AFIRST) 1690 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1691 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1797 { 1692 {
1798 aindex = -1; 1693 aindex = -1;
1799 ++input_row; /* To point to the first component */ 1694 ++input_row; /* To point to the first component */
1800 ++output_row; 1695 ++output_row;
1801 } 1696 }
1802 1697
1803 else 1698 else
1804 aindex = channels; 1699 # endif
1700 aindex = channels;
1805 1701
1806 /* Use row_end in place of a loop counter: */ 1702 /* Use row_end in place of a loop counter: */
1807 row_end = output_row + image->width * (channels+1); 1703 row_end = output_row + image->width * (channels+1);
1808 1704
1809 while (y-- > 0) 1705 while (y-- > 0)
1810 { 1706 {
1811 png_const_uint_16p in_ptr = input_row; 1707 png_const_uint_16p in_ptr = input_row;
1812 png_bytep out_ptr = output_row; 1708 png_bytep out_ptr = output_row;
1813 1709
1814 while (out_ptr < row_end) 1710 while (out_ptr < row_end)
(...skipping 13 matching lines...) Expand all
1828 do /* always at least one channel */ 1724 do /* always at least one channel */
1829 *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); 1725 *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
1830 while (--c > 0); 1726 while (--c > 0);
1831 1727
1832 /* Skip to next component (skip the intervening alpha channel) */ 1728 /* Skip to next component (skip the intervening alpha channel) */
1833 ++in_ptr; 1729 ++in_ptr;
1834 ++out_ptr; 1730 ++out_ptr;
1835 } /* while out_ptr < row_end */ 1731 } /* while out_ptr < row_end */
1836 1732
1837 png_write_row(png_ptr, png_voidcast(png_const_bytep, 1733 png_write_row(png_ptr, png_voidcast(png_const_bytep,
1838 display->local_row)); 1734 display->local_row));
1839 input_row += display->row_bytes/(sizeof (png_uint_16)); 1735 input_row += display->row_bytes/(sizeof (png_uint_16));
1840 } /* while y */ 1736 } /* while y */
1841 } 1737 }
1842 1738
1843 else 1739 else
1844 { 1740 {
1845 /* No alpha channel, so the row_end really is the end of the row and it 1741 /* No alpha channel, so the row_end really is the end of the row and it
1846 * is sufficient to loop over the components one by one. 1742 * is sufficient to loop over the components one by one.
1847 */ 1743 */
1848 png_bytep row_end = output_row + image->width * channels; 1744 png_bytep row_end = output_row + image->width * channels;
(...skipping 18 matching lines...) Expand all
1867 1763
1868 return 1; 1764 return 1;
1869 } 1765 }
1870 1766
1871 static void 1767 static void
1872 png_image_set_PLTE(png_image_write_control *display) 1768 png_image_set_PLTE(png_image_write_control *display)
1873 { 1769 {
1874 const png_imagep image = display->image; 1770 const png_imagep image = display->image;
1875 const void *cmap = display->colormap; 1771 const void *cmap = display->colormap;
1876 const int entries = image->colormap_entries > 256 ? 256 : 1772 const int entries = image->colormap_entries > 256 ? 256 :
1877 (int)image->colormap_entries; 1773 (int)image->colormap_entries;
1878 1774
1879 /* NOTE: the caller must check for cmap != NULL and entries != 0 */ 1775 /* NOTE: the caller must check for cmap != NULL and entries != 0 */
1880 const png_uint_32 format = image->format; 1776 const png_uint_32 format = image->format;
1881 const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); 1777 const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
1882 1778
1883 # ifdef PNG_FORMAT_BGR_SUPPORTED 1779 # if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
1780 defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
1884 const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && 1781 const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
1885 (format & PNG_FORMAT_FLAG_ALPHA) != 0; 1782 (format & PNG_FORMAT_FLAG_ALPHA) != 0;
1886 # else 1783 # else
1887 # define afirst 0 1784 # define afirst 0
1888 # endif 1785 # endif
1889 1786
1890 # ifdef PNG_FORMAT_BGR_SUPPORTED 1787 # ifdef PNG_FORMAT_BGR_SUPPORTED
1891 const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; 1788 const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
1892 # else 1789 # else
1893 # define bgr 0 1790 # define bgr 0
1894 # endif 1791 # endif
1895 1792
1896 int i, num_trans; 1793 int i, num_trans;
1897 png_color palette[256]; 1794 png_color palette[256];
1898 png_byte tRNS[256]; 1795 png_byte tRNS[256];
1899 1796
1900 memset(tRNS, 255, (sizeof tRNS)); 1797 memset(tRNS, 255, (sizeof tRNS));
1901 memset(palette, 0, (sizeof palette)); 1798 memset(palette, 0, (sizeof palette));
1902 1799
1903 for (i=num_trans=0; i<entries; ++i) 1800 for (i=num_trans=0; i<entries; ++i)
1904 { 1801 {
1905 /* This gets automatically converted to sRGB with reversal of the 1802 /* This gets automatically converted to sRGB with reversal of the
1906 * pre-multiplication if the color-map has an alpha channel. 1803 * pre-multiplication if the color-map has an alpha channel.
1907 */ 1804 */
1908 if (format & PNG_FORMAT_FLAG_LINEAR) 1805 if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
1909 { 1806 {
1910 png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); 1807 png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
1911 1808
1912 entry += i * channels; 1809 entry += i * channels;
1913 1810
1914 if (channels & 1) /* no alpha */ 1811 if ((channels & 1) != 0) /* no alpha */
1915 { 1812 {
1916 if (channels >= 3) /* RGB */ 1813 if (channels >= 3) /* RGB */
1917 { 1814 {
1918 palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 1815 palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1919 entry[(2 ^ bgr)]); 1816 entry[(2 ^ bgr)]);
1920 palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 1817 palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1921 entry[1]); 1818 entry[1]);
1922 palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 1819 palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1923 entry[bgr]); 1820 entry[bgr]);
1924 } 1821 }
1925 1822
1926 else /* Gray */ 1823 else /* Gray */
1927 palette[i].blue = palette[i].red = palette[i].green = 1824 palette[i].blue = palette[i].red = palette[i].green =
1928 (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry); 1825 (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
1929 } 1826 }
1930 1827
1931 else /* alpha */ 1828 else /* alpha */
1932 { 1829 {
1933 png_uint_16 alpha = entry[afirst ? 0 : channels-1]; 1830 png_uint_16 alpha = entry[afirst ? 0 : channels-1];
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 palette[i].blue = palette[i].red = palette[i].green = 1886 palette[i].blue = palette[i].red = palette[i].green =
1990 entry[afirst]; 1887 entry[afirst];
1991 break; 1888 break;
1992 1889
1993 default: 1890 default:
1994 break; 1891 break;
1995 } 1892 }
1996 } 1893 }
1997 } 1894 }
1998 1895
1999 # ifdef afirst 1896 # ifdef afirst
2000 # undef afirst 1897 # undef afirst
2001 # endif 1898 # endif
2002 # ifdef bgr 1899 # ifdef bgr
2003 # undef bgr 1900 # undef bgr
2004 # endif 1901 # endif
2005 1902
2006 png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, 1903 png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
2007 entries); 1904 entries);
2008 1905
2009 if (num_trans > 0) 1906 if (num_trans > 0)
2010 png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, 1907 png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
2011 num_trans, NULL); 1908 num_trans, NULL);
2012 1909
2013 image->colormap_entries = entries; 1910 image->colormap_entries = entries;
2014 } 1911 }
2015 1912
2016 static int 1913 static int
2017 png_image_write_main(png_voidp argument) 1914 png_image_write_main(png_voidp argument)
2018 { 1915 {
2019 png_image_write_control *display = png_voidcast(png_image_write_control*, 1916 png_image_write_control *display = png_voidcast(png_image_write_control*,
2020 argument); 1917 argument);
2021 png_imagep image = display->image; 1918 png_imagep image = display->image;
2022 png_structrp png_ptr = image->opaque->png_ptr; 1919 png_structrp png_ptr = image->opaque->png_ptr;
2023 png_inforp info_ptr = image->opaque->info_ptr; 1920 png_inforp info_ptr = image->opaque->info_ptr;
2024 png_uint_32 format = image->format; 1921 png_uint_32 format = image->format;
2025 1922
2026 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0; 1923 /* The following four ints are actually booleans */
2027 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */ 1924 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
2028 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0; 1925 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
2029 int write_16bit = linear && !colormap && !display->convert_to_8bit; 1926 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
2030 1927 int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
2031 # ifdef PNG_BENIGN_ERRORS_SUPPORTED 1928
1929 # ifdef PNG_BENIGN_ERRORS_SUPPORTED
2032 /* Make sure we error out on any bad situation */ 1930 /* Make sure we error out on any bad situation */
2033 png_set_benign_errors(png_ptr, 0/*error*/); 1931 png_set_benign_errors(png_ptr, 0/*error*/);
2034 # endif 1932 # endif
2035 1933
2036 /* Default the 'row_stride' parameter if required. */ 1934 /* Default the 'row_stride' parameter if required. */
2037 if (display->row_stride == 0) 1935 if (display->row_stride == 0)
2038 display->row_stride = PNG_IMAGE_ROW_STRIDE(*image); 1936 display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
2039 1937
2040 /* Set the required transforms then write the rows in the correct order. */ 1938 /* Set the required transforms then write the rows in the correct order. */
2041 if (format & PNG_FORMAT_FLAG_COLORMAP) 1939 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
2042 { 1940 {
2043 if (display->colormap != NULL && image->colormap_entries > 0) 1941 if (display->colormap != NULL && image->colormap_entries > 0)
2044 { 1942 {
2045 png_uint_32 entries = image->colormap_entries; 1943 png_uint_32 entries = image->colormap_entries;
2046 1944
2047 png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 1945 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
2048 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), 1946 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
2049 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, 1947 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
2050 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 1948 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
2051 1949
(...skipping 11 matching lines...) Expand all
2063 ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + 1961 ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
2064 ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), 1962 ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
2065 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 1963 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
2066 1964
2067 /* Counter-intuitively the data transformations must be called *after* 1965 /* Counter-intuitively the data transformations must be called *after*
2068 * png_write_info, not before as in the read code, but the 'set' functions 1966 * png_write_info, not before as in the read code, but the 'set' functions
2069 * must still be called before. Just set the color space information, never 1967 * must still be called before. Just set the color space information, never
2070 * write an interlaced image. 1968 * write an interlaced image.
2071 */ 1969 */
2072 1970
2073 if (write_16bit) 1971 if (write_16bit != 0)
2074 { 1972 {
2075 /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ 1973 /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
2076 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); 1974 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
2077 1975
2078 if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) 1976 if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2079 png_set_cHRM_fixed(png_ptr, info_ptr, 1977 png_set_cHRM_fixed(png_ptr, info_ptr,
2080 /* color x y */ 1978 /* color x y */
2081 /* white */ 31270, 32900, 1979 /* white */ 31270, 32900,
2082 /* red */ 64000, 33000, 1980 /* red */ 64000, 33000,
2083 /* green */ 30000, 60000, 1981 /* green */ 30000, 60000,
2084 /* blue */ 15000, 6000 1982 /* blue */ 15000, 6000
2085 ); 1983 );
2086 } 1984 }
2087 1985
2088 else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) 1986 else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2089 png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); 1987 png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
2090 1988
2091 /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit 1989 /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
2092 * space must still be gamma encoded. 1990 * space must still be gamma encoded.
2093 */ 1991 */
2094 else 1992 else
2095 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); 1993 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
2096 1994
2097 /* Write the file header. */ 1995 /* Write the file header. */
2098 png_write_info(png_ptr, info_ptr); 1996 png_write_info(png_ptr, info_ptr);
2099 1997
2100 /* Now set up the data transformations (*after* the header is written), 1998 /* Now set up the data transformations (*after* the header is written),
2101 * remove the handled transformations from the 'format' flags for checking. 1999 * remove the handled transformations from the 'format' flags for checking.
2102 * 2000 *
2103 * First check for a little endian system if writing 16 bit files. 2001 * First check for a little endian system if writing 16-bit files.
2104 */ 2002 */
2105 if (write_16bit) 2003 if (write_16bit != 0)
2106 { 2004 {
2107 PNG_CONST png_uint_16 le = 0x0001; 2005 PNG_CONST png_uint_16 le = 0x0001;
2108 2006
2109 if (*(png_const_bytep)&le) 2007 if ((*(png_const_bytep) & le) != 0)
2110 png_set_swap(png_ptr); 2008 png_set_swap(png_ptr);
2111 } 2009 }
2112 2010
2113 # ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED 2011 # ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
2114 if (format & PNG_FORMAT_FLAG_BGR) 2012 if ((format & PNG_FORMAT_FLAG_BGR) != 0)
2115 { 2013 {
2116 if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0) 2014 if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
2117 png_set_bgr(png_ptr); 2015 png_set_bgr(png_ptr);
2118 format &= ~PNG_FORMAT_FLAG_BGR; 2016 format &= ~PNG_FORMAT_FLAG_BGR;
2119 } 2017 }
2120 # endif 2018 # endif
2121 2019
2122 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 2020 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
2123 if (format & PNG_FORMAT_FLAG_AFIRST) 2021 if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
2124 { 2022 {
2125 if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0) 2023 if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
2126 png_set_swap_alpha(png_ptr); 2024 png_set_swap_alpha(png_ptr);
2127 format &= ~PNG_FORMAT_FLAG_AFIRST; 2025 format &= ~PNG_FORMAT_FLAG_AFIRST;
2128 } 2026 }
2129 # endif 2027 # endif
2130 2028
2131 /* If there are 16 or fewer color-map entries we wrote a lower bit depth 2029 /* If there are 16 or fewer color-map entries we wrote a lower bit depth
2132 * above, but the application data is still byte packed. 2030 * above, but the application data is still byte packed.
2133 */ 2031 */
2134 if (colormap && image->colormap_entries <= 16) 2032 if (colormap != 0 && image->colormap_entries <= 16)
2135 png_set_packing(png_ptr); 2033 png_set_packing(png_ptr);
2136 2034
2137 /* That should have handled all (both) the transforms. */ 2035 /* That should have handled all (both) the transforms. */
2138 if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | 2036 if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
2139 PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0) 2037 PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
2140 png_error(png_ptr, "png_write_image: unsupported transformation"); 2038 png_error(png_ptr, "png_write_image: unsupported transformation");
2141 2039
2142 { 2040 {
2143 png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); 2041 png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
2144 ptrdiff_t row_bytes = display->row_stride; 2042 ptrdiff_t row_bytes = display->row_stride;
2145 2043
2146 if (linear) 2044 if (linear != 0)
2147 row_bytes *= (sizeof (png_uint_16)); 2045 row_bytes *= (sizeof (png_uint_16));
2148 2046
2149 if (row_bytes < 0) 2047 if (row_bytes < 0)
2150 row += (image->height-1) * (-row_bytes); 2048 row += (image->height-1) * (-row_bytes);
2151 2049
2152 display->first_row = row; 2050 display->first_row = row;
2153 display->row_bytes = row_bytes; 2051 display->row_bytes = row_bytes;
2154 } 2052 }
2155 2053
2156 /* Apply 'fast' options if the flag is set. */ 2054 /* Apply 'fast' options if the flag is set. */
2157 if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) 2055 if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
2158 { 2056 {
2159 png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); 2057 png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
2160 /* NOTE: determined by experiment using pngstest, this reflects some 2058 /* NOTE: determined by experiment using pngstest, this reflects some
2161 * balance between the time to write the image once and the time to read 2059 * balance between the time to write the image once and the time to read
2162 * it about 50 times. The speed-up in pngstest was about 10-20% of the 2060 * it about 50 times. The speed-up in pngstest was about 10-20% of the
2163 * total (user) time on a heavily loaded system. 2061 * total (user) time on a heavily loaded system.
2164 */ 2062 */
2063 # ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
2165 png_set_compression_level(png_ptr, 3); 2064 png_set_compression_level(png_ptr, 3);
2065 # endif
2166 } 2066 }
2167 2067
2168 /* Check for the cases that currently require a pre-transform on the row 2068 /* Check for the cases that currently require a pre-transform on the row
2169 * before it is written. This only applies when the input is 16-bit and 2069 * before it is written. This only applies when the input is 16-bit and
2170 * either there is an alpha channel or it is converted to 8-bit. 2070 * either there is an alpha channel or it is converted to 8-bit.
2171 */ 2071 */
2172 if ((linear && alpha) || (!colormap && display->convert_to_8bit)) 2072 if ((linear != 0 && alpha != 0 ) ||
2073 (colormap == 0 && display->convert_to_8bit != 0))
2173 { 2074 {
2174 png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, 2075 png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
2175 png_get_rowbytes(png_ptr, info_ptr))); 2076 png_get_rowbytes(png_ptr, info_ptr)));
2176 int result; 2077 int result;
2177 2078
2178 display->local_row = row; 2079 display->local_row = row;
2179 if (write_16bit) 2080 if (write_16bit != 0)
2180 result = png_safe_execute(image, png_write_image_16bit, display); 2081 result = png_safe_execute(image, png_write_image_16bit, display);
2181 else 2082 else
2182 result = png_safe_execute(image, png_write_image_8bit, display); 2083 result = png_safe_execute(image, png_write_image_8bit, display);
2183 display->local_row = NULL; 2084 display->local_row = NULL;
2184 2085
2185 png_free(png_ptr, row); 2086 png_free(png_ptr, row);
2186 2087
2187 /* Skip the 'write_end' on error: */ 2088 /* Skip the 'write_end' on error: */
2188 if (!result) 2089 if (result == 0)
2189 return 0; 2090 return 0;
2190 } 2091 }
2191 2092
2192 /* Otherwise this is the case where the input is in a format currently 2093 /* Otherwise this is the case where the input is in a format currently
2193 * supported by the rest of the libpng write code; call it directly. 2094 * supported by the rest of the libpng write code; call it directly.
2194 */ 2095 */
2195 else 2096 else
2196 { 2097 {
2197 png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); 2098 png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
2198 ptrdiff_t row_bytes = display->row_bytes; 2099 ptrdiff_t row_bytes = display->row_bytes;
(...skipping 12 matching lines...) Expand all
2211 2112
2212 int PNGAPI 2113 int PNGAPI
2213 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, 2114 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
2214 const void *buffer, png_int_32 row_stride, const void *colormap) 2115 const void *buffer, png_int_32 row_stride, const void *colormap)
2215 { 2116 {
2216 /* Write the image to the given (FILE*). */ 2117 /* Write the image to the given (FILE*). */
2217 if (image != NULL && image->version == PNG_IMAGE_VERSION) 2118 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2218 { 2119 {
2219 if (file != NULL) 2120 if (file != NULL)
2220 { 2121 {
2221 if (png_image_write_init(image)) 2122 if (png_image_write_init(image) != 0)
2222 { 2123 {
2223 png_image_write_control display; 2124 png_image_write_control display;
2224 int result; 2125 int result;
2225 2126
2226 /* This is slightly evil, but png_init_io doesn't do anything other 2127 /* This is slightly evil, but png_init_io doesn't do anything other
2227 * than this and we haven't changed the standard IO functions so 2128 * than this and we haven't changed the standard IO functions so
2228 * this saves a 'safe' function. 2129 * this saves a 'safe' function.
2229 */ 2130 */
2230 image->opaque->png_ptr->io_ptr = file; 2131 image->opaque->png_ptr->io_ptr = file;
2231 2132
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 /* Write the image to the named file. */ 2167 /* Write the image to the named file. */
2267 if (image != NULL && image->version == PNG_IMAGE_VERSION) 2168 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2268 { 2169 {
2269 if (file_name != NULL) 2170 if (file_name != NULL)
2270 { 2171 {
2271 FILE *fp = fopen(file_name, "wb"); 2172 FILE *fp = fopen(file_name, "wb");
2272 2173
2273 if (fp != NULL) 2174 if (fp != NULL)
2274 { 2175 {
2275 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, 2176 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2276 row_stride, colormap)) 2177 row_stride, colormap) != 0)
2277 { 2178 {
2278 int error; /* from fflush/fclose */ 2179 int error; /* from fflush/fclose */
2279 2180
2280 /* Make sure the file is flushed correctly. */ 2181 /* Make sure the file is flushed correctly. */
2281 if (fflush(fp) == 0 && ferror(fp) == 0) 2182 if (fflush(fp) == 0 && ferror(fp) == 0)
2282 { 2183 {
2283 if (fclose(fp) == 0) 2184 if (fclose(fp) == 0)
2284 return 1; 2185 return 1;
2285 2186
2286 error = errno; /* from fclose */ 2187 error = errno; /* from fclose */
(...skipping 30 matching lines...) Expand all
2317 "png_image_write_to_file: invalid argument"); 2218 "png_image_write_to_file: invalid argument");
2318 } 2219 }
2319 2220
2320 else if (image != NULL) 2221 else if (image != NULL)
2321 return png_image_error(image, 2222 return png_image_error(image,
2322 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); 2223 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
2323 2224
2324 else 2225 else
2325 return 0; 2226 return 0;
2326 } 2227 }
2327 #endif /* PNG_STDIO_SUPPORTED */ 2228 # endif /* STDIO */
2328 #endif /* SIMPLIFIED_WRITE */ 2229 #endif /* SIMPLIFIED_WRITE */
2329 #endif /* PNG_WRITE_SUPPORTED */ 2230 #endif /* WRITE */
OLDNEW
« no previous file with comments | « third_party/libpng/pngwio.c ('k') | third_party/libpng/pngwtran.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698