Rev 1897 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1897 | Rev 3928 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* pngwutil.c - utilities to write a PNG file |
1 | /* pngwutil.c - utilities to write a PNG file |
2 | * |
2 | * |
3 | * Last changed in libpng 1.5.0 [January 6, 2011] |
3 | * Last changed in libpng 1.6.2 [April 25, 2013] |
4 | * Copyright (c) 1998-2011 Glenn Randers-Pehrson |
4 | * Copyright (c) 1998-2013 Glenn Randers-Pehrson |
5 | * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
5 | * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
6 | * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
6 | * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
7 | * |
7 | * |
8 | * This code is released under the libpng license. |
8 | * This code is released under the libpng license. |
9 | * For conditions of distribution and use, see the disclaimer |
9 | * For conditions of distribution and use, see the disclaimer |
Line 27... | Line 27... | ||
27 | buf[2] = (png_byte)((i >> 8) & 0xff); |
27 | buf[2] = (png_byte)((i >> 8) & 0xff); |
28 | buf[3] = (png_byte)(i & 0xff); |
28 | buf[3] = (png_byte)(i & 0xff); |
29 | } |
29 | } |
30 | 30 | ||
Line 31... | Line -... | ||
31 | #ifdef PNG_SAVE_INT_32_SUPPORTED |
- | |
32 | /* The png_save_int_32 function assumes integers are stored in two's |
- | |
33 | * complement format. If this isn't the case, then this routine needs to |
- | |
34 | * be modified to write data in two's complement format. Note that, |
- | |
35 | * the following works correctly even if png_int_32 has more than 32 bits |
- | |
36 | * (compare the more complex code required on read for sign extention.) |
- | |
37 | */ |
- | |
38 | void PNGAPI |
- | |
39 | png_save_int_32(png_bytep buf, png_int_32 i) |
- | |
40 | { |
- | |
41 | buf[0] = (png_byte)((i >> 24) & 0xff); |
- | |
42 | buf[1] = (png_byte)((i >> 16) & 0xff); |
- | |
43 | buf[2] = (png_byte)((i >> 8) & 0xff); |
- | |
44 | buf[3] = (png_byte)(i & 0xff); |
- | |
45 | } |
- | |
46 | #endif |
- | |
47 | - | ||
48 | /* Place a 16-bit number into a buffer in PNG byte order. |
31 | /* Place a 16-bit number into a buffer in PNG byte order. |
49 | * The parameter is declared unsigned int, not png_uint_16, |
32 | * The parameter is declared unsigned int, not png_uint_16, |
50 | * just to avoid potential problems on pre-ANSI C compilers. |
33 | * just to avoid potential problems on pre-ANSI C compilers. |
51 | */ |
34 | */ |
52 | void PNGAPI |
35 | void PNGAPI |
Line 63... | Line 46... | ||
63 | * we should call png_set_sig_bytes() to tell libpng how many of the |
46 | * we should call png_set_sig_bytes() to tell libpng how many of the |
64 | * bytes have already been written. |
47 | * bytes have already been written. |
65 | */ |
48 | */ |
66 | void PNGAPI |
49 | void PNGAPI |
67 | png_write_sig(png_structp png_ptr) |
50 | png_write_sig(png_structrp png_ptr) |
68 | { |
51 | { |
69 | png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; |
52 | png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; |
70 | 53 | ||
Line 71... | Line 54... | ||
71 | #ifdef PNG_IO_STATE_SUPPORTED |
54 | #ifdef PNG_IO_STATE_SUPPORTED |
72 | /* Inform the I/O callback that the signature is being written */ |
55 | /* Inform the I/O callback that the signature is being written */ |
Line 80... | Line 63... | ||
80 | if (png_ptr->sig_bytes < 3) |
63 | if (png_ptr->sig_bytes < 3) |
81 | png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; |
64 | png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; |
82 | } |
65 | } |
Line 83... | Line -... | ||
83 | - | ||
84 | /* Write a PNG chunk all at once. The type is an array of ASCII characters |
- | |
85 | * representing the chunk name. The array must be at least 4 bytes in |
- | |
86 | * length, and does not need to be null terminated. To be safe, pass the |
- | |
87 | * pre-defined chunk names here, and if you need a new one, define it |
- | |
88 | * where the others are defined. The length is the length of the data. |
- | |
89 | * All the data must be present. If that is not possible, use the |
- | |
90 | * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() |
- | |
91 | * functions instead. |
- | |
92 | */ |
- | |
93 | void PNGAPI |
- | |
94 | png_write_chunk(png_structp png_ptr, png_const_bytep chunk_name, |
- | |
95 | png_const_bytep data, png_size_t length) |
- | |
96 | { |
- | |
97 | if (png_ptr == NULL) |
- | |
98 | return; |
- | |
99 | - | ||
100 | png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); |
- | |
101 | png_write_chunk_data(png_ptr, data, (png_size_t)length); |
- | |
102 | png_write_chunk_end(png_ptr); |
- | |
103 | } |
- | |
104 | 66 | ||
105 | /* Write the start of a PNG chunk. The type is the chunk type. |
67 | /* Write the start of a PNG chunk. The type is the chunk type. |
106 | * The total_length is the sum of the lengths of all the data you will be |
68 | * The total_length is the sum of the lengths of all the data you will be |
107 | * passing in png_write_chunk_data(). |
69 | * passing in png_write_chunk_data(). |
108 | */ |
70 | */ |
109 | void PNGAPI |
71 | static void |
110 | png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name, |
72 | png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, |
111 | png_uint_32 length) |
73 | png_uint_32 length) |
112 | { |
74 | { |
Line -... | Line 75... | ||
- | 75 | png_byte buf[8]; |
|
- | 76 | ||
113 | png_byte buf[8]; |
77 | #if defined(PNG_DEBUG) && (PNG_DEBUG > 0) |
114 | 78 | PNG_CSTRING_FROM_CHUNK(buf, chunk_name); |
|
Line 115... | Line 79... | ||
115 | png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, |
79 | png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); |
116 | (unsigned long)length); |
80 | #endif |
Line 117... | Line 81... | ||
117 | 81 | ||
Line 126... | Line 90... | ||
126 | #endif |
90 | #endif |
127 | 91 | ||
Line 128... | Line 92... | ||
128 | /* Write the length and the chunk name */ |
92 | /* Write the length and the chunk name */ |
129 | png_save_uint_32(buf, length); |
93 | png_save_uint_32(buf, length); |
130 | png_memcpy(buf + 4, chunk_name, 4); |
94 | png_save_uint_32(buf + 4, chunk_name); |
131 | png_write_data(png_ptr, buf, (png_size_t)8); |
95 | png_write_data(png_ptr, buf, 8); |
Line 132... | Line 96... | ||
132 | 96 | ||
133 | /* Put the chunk name into png_ptr->chunk_name */ |
97 | /* Put the chunk name into png_ptr->chunk_name */ |
Line 134... | Line 98... | ||
134 | png_memcpy(png_ptr->chunk_name, chunk_name, 4); |
98 | png_ptr->chunk_name = chunk_name; |
135 | 99 | ||
Line 136... | Line 100... | ||
136 | /* Reset the crc and run it over the chunk name */ |
100 | /* Reset the crc and run it over the chunk name */ |
Line 137... | Line 101... | ||
137 | png_reset_crc(png_ptr); |
101 | png_reset_crc(png_ptr); |
138 | 102 | ||
139 | png_calculate_crc(png_ptr, chunk_name, 4); |
103 | png_calculate_crc(png_ptr, buf + 4, 4); |
140 | 104 | ||
141 | #ifdef PNG_IO_STATE_SUPPORTED |
105 | #ifdef PNG_IO_STATE_SUPPORTED |
142 | /* Inform the I/O callback that chunk data will (possibly) be written. |
106 | /* Inform the I/O callback that chunk data will (possibly) be written. |
143 | * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. |
107 | * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. |
Line -... | Line 108... | ||
- | 108 | */ |
|
- | 109 | png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; |
|
- | 110 | #endif |
|
- | 111 | } |
|
- | 112 | ||
- | 113 | void PNGAPI |
|
- | 114 | png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, |
|
144 | */ |
115 | png_uint_32 length) |
145 | png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; |
116 | { |
146 | #endif |
117 | png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); |
147 | } |
118 | } |
148 | 119 | ||
149 | /* Write the data of a PNG chunk started with png_write_chunk_start(). |
120 | /* Write the data of a PNG chunk started with png_write_chunk_header(). |
150 | * Note that multiple calls to this function are allowed, and that the |
121 | * Note that multiple calls to this function are allowed, and that the |
151 | * sum of the lengths from these calls *must* add up to the total_length |
122 | * sum of the lengths from these calls *must* add up to the total_length |
152 | * given to png_write_chunk_start(). |
123 | * given to png_write_chunk_header(). |
153 | */ |
124 | */ |
154 | void PNGAPI |
125 | void PNGAPI |
155 | png_write_chunk_data(png_structp png_ptr, png_const_bytep data, |
126 | png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, |
Line 169... | Line 140... | ||
169 | png_calculate_crc(png_ptr, data, length); |
140 | png_calculate_crc(png_ptr, data, length); |
170 | } |
141 | } |
171 | } |
142 | } |
172 | 143 | ||
Line 173... | Line 144... | ||
173 | /* Finish a chunk started with png_write_chunk_start(). */ |
144 | /* Finish a chunk started with png_write_chunk_header(). */ |
174 | void PNGAPI |
145 | void PNGAPI |
175 | png_write_chunk_end(png_structp png_ptr) |
146 | png_write_chunk_end(png_structrp png_ptr) |
176 | { |
147 | { |
177 | png_byte buf[4]; |
148 | png_byte buf[4]; |
Line 178... | Line 149... | ||
178 | 149 | ||
Line 190... | Line 161... | ||
190 | 161 | ||
Line 191... | Line 162... | ||
191 | png_write_data(png_ptr, buf, (png_size_t)4); |
162 | png_write_data(png_ptr, buf, (png_size_t)4); |
192 | } |
163 | } |
Line 193... | Line 164... | ||
193 | 164 | ||
194 | #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) |
165 | /* Write a PNG chunk all at once. The type is an array of ASCII characters |
195 | /* This pair of functions encapsulates the operation of (a) compressing a |
166 | * representing the chunk name. The array must be at least 4 bytes in |
196 | * text string, and (b) issuing it later as a series of chunk data writes. |
167 | * length, and does not need to be null terminated. To be safe, pass the |
197 | * The compression_state structure is shared context for these functions |
168 | * pre-defined chunk names here, and if you need a new one, define it |
- | 169 | * where the others are defined. The length is the length of the data. |
|
- | 170 | * All the data must be present. If that is not possible, use the |
|
- | 171 | * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() |
|
198 | * set up by the caller in order to make the whole mess thread-safe. |
172 | * functions instead. |
- | 173 | */ |
|
- | 174 | static void |
|
- | 175 | png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, |
|
- | 176 | png_const_bytep data, png_size_t length) |
|
- | 177 | { |
|
- | 178 | if (png_ptr == NULL) |
|
Line -... | Line 179... | ||
- | 179 | return; |
|
- | 180 | ||
- | 181 | /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ |
|
- | 182 | if (length > PNG_UINT_31_MAX) |
|
- | 183 | png_error(png_ptr, "length exceeds PNG maxima"); |
|
- | 184 | ||
- | 185 | png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); |
|
- | 186 | png_write_chunk_data(png_ptr, data, length); |
|
- | 187 | png_write_chunk_end(png_ptr); |
|
- | 188 | } |
|
199 | */ |
189 | |
- | 190 | /* This is the API that calls the internal function above. */ |
|
- | 191 | void PNGAPI |
|
200 | 192 | png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, |
|
201 | typedef struct |
193 | png_const_bytep data, png_size_t length) |
202 | { |
- | |
203 | png_const_bytep input; /* The uncompressed input data */ |
- | |
204 | png_size_t input_len; /* Its length */ |
- | |
205 | int num_output_ptr; /* Number of output pointers used */ |
- | |
206 | int max_output_ptr; /* Size of output_ptr */ |
194 | { |
- | 195 | png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, |
|
Line 207... | Line 196... | ||
207 | png_bytep *output_ptr; /* Array of pointers to output */ |
196 | length); |
208 | } compression_state; |
197 | } |
209 | 198 | ||
- | 199 | /* This is used below to find the size of an image to pass to png_deflate_claim, |
|
210 | /* Compress given text into storage in the png_ptr structure */ |
200 | * so it only needs to be accurate if the size is less than 16384 bytes (the |
211 | static int /* PRIVATE */ |
201 | * point at which a lower LZ window size can be used.) |
212 | png_text_compress(png_structp png_ptr, |
202 | */ |
- | 203 | static png_alloc_size_t |
|
- | 204 | png_image_size(png_structrp png_ptr) |
|
213 | png_const_charp text, png_size_t text_len, int compression, |
205 | { |
- | 206 | /* Only return sizes up to the maximum of a png_uint_32, do this by limiting |
|
Line 214... | Line 207... | ||
214 | compression_state *comp) |
207 | * the width and height used to 15 bits. |
- | 208 | */ |
|
215 | { |
209 | png_uint_32 h = png_ptr->height; |
- | 210 | ||
- | 211 | if (png_ptr->rowbytes < 32768 && h < 32768) |
|
- | 212 | { |
|
- | 213 | if (png_ptr->interlaced) |
|
216 | int ret; |
214 | { |
- | 215 | /* Interlacing makes the image larger because of the replication of |
|
217 | 216 | * both the filter byte and the padding to a byte boundary. |
|
218 | comp->num_output_ptr = 0; |
217 | */ |
Line 219... | Line 218... | ||
219 | comp->max_output_ptr = 0; |
218 | png_uint_32 w = png_ptr->width; |
220 | comp->output_ptr = NULL; |
- | |
221 | comp->input = NULL; |
219 | unsigned int pd = png_ptr->pixel_depth; |
222 | comp->input_len = 0; |
220 | png_alloc_size_t cb_base; |
- | 221 | int pass; |
|
- | 222 | ||
- | 223 | for (cb_base=0, pass=0; pass<=6; ++pass) |
|
- | 224 | { |
|
- | 225 | png_uint_32 pw = PNG_PASS_COLS(w, pass); |
|
223 | 226 | ||
- | 227 | if (pw > 0) |
|
- | 228 | cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); |
|
- | 229 | } |
|
- | 230 | ||
- | 231 | return cb_base; |
|
- | 232 | } |
|
- | 233 | ||
224 | /* We may just want to pass the text right through */ |
234 | else |
225 | if (compression == PNG_TEXT_COMPRESSION_NONE) |
235 | return (png_ptr->rowbytes+1) * h; |
Line -... | Line 236... | ||
- | 236 | } |
|
- | 237 | ||
- | 238 | else |
|
- | 239 | return 0xffffffffU; |
|
- | 240 | } |
|
- | 241 | ||
- | 242 | #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
|
- | 243 | /* This is the code to hack the first two bytes of the deflate stream (the |
|
- | 244 | * deflate header) to correct the windowBits value to match the actual data |
|
- | 245 | * size. Note that the second argument is the *uncompressed* size but the |
|
- | 246 | * first argument is the *compressed* data (and it must be deflate |
|
- | 247 | * compressed.) |
|
- | 248 | */ |
|
- | 249 | static void |
|
- | 250 | optimize_cmf(png_bytep data, png_alloc_size_t data_size) |
|
- | 251 | { |
|
- | 252 | /* Optimize the CMF field in the zlib stream. The resultant zlib stream is |
|
226 | { |
253 | * still compliant to the stream specification. |
- | 254 | */ |
|
- | 255 | if (data_size <= 16384) /* else windowBits must be 15 */ |
|
- | 256 | { |
|
- | 257 | unsigned int z_cmf = data[0]; /* zlib compression method and flags */ |
|
- | 258 | ||
- | 259 | if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) |
|
- | 260 | { |
|
- | 261 | unsigned int z_cinfo; |
|
- | 262 | unsigned int half_z_window_size; |
|
- | 263 | ||
- | 264 | z_cinfo = z_cmf >> 4; |
|
- | 265 | half_z_window_size = 1U << (z_cinfo + 7); |
|
227 | comp->input = (png_const_bytep)text; |
266 | |
- | 267 | if (data_size <= half_z_window_size) /* else no change */ |
|
- | 268 | { |
|
- | 269 | unsigned int tmp; |
|
- | 270 | ||
- | 271 | do |
|
- | 272 | { |
|
- | 273 | half_z_window_size >>= 1; |
|
- | 274 | --z_cinfo; |
|
- | 275 | } |
|
- | 276 | while (z_cinfo > 0 && data_size <= half_z_window_size); |
|
- | 277 | ||
- | 278 | z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); |
|
- | 279 | ||
- | 280 | data[0] = (png_byte)z_cmf; |
|
- | 281 | tmp = data[1] & 0xe0; |
|
- | 282 | tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; |
|
- | 283 | data[1] = (png_byte)tmp; |
|
228 | comp->input_len = text_len; |
284 | } |
- | 285 | } |
|
- | 286 | } |
|
- | 287 | } |
|
- | 288 | #else |
|
- | 289 | # define optimize_cmf(dp,dl) ((void)0) |
|
- | 290 | #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ |
|
- | 291 | ||
- | 292 | /* Initialize the compressor for the appropriate type of compression. */ |
|
229 | return((int)text_len); |
293 | static int |
- | 294 | png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, |
|
- | 295 | png_alloc_size_t data_size) |
|
- | 296 | { |
|
- | 297 | if (png_ptr->zowner != 0) |
|
- | 298 | { |
|
- | 299 | char msg[64]; |
|
- | 300 | ||
- | 301 | PNG_STRING_FROM_CHUNK(msg, owner); |
|
- | 302 | msg[4] = ':'; |
|
230 | } |
303 | msg[5] = ' '; |
- | 304 | PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); |
|
231 | 305 | /* So the message that results is " |
|
- | 306 | * internal error, but is very useful for debugging. i18n requirements |
|
- | 307 | * are minimal. |
|
- | 308 | */ |
|
- | 309 | (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); |
|
- | 310 | # if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC |
|
- | 311 | png_warning(png_ptr, msg); |
|
- | 312 | ||
- | 313 | /* Attempt sane error recovery */ |
|
- | 314 | if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ |
|
232 | if (compression >= PNG_TEXT_COMPRESSION_LAST) |
315 | { |
233 | { |
316 | png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); |
234 | #ifdef PNG_CONSOLE_IO_SUPPORTED |
317 | return Z_STREAM_ERROR; |
235 | char msg[50]; |
318 | } |
Line 236... | Line -... | ||
236 | png_snprintf(msg, 50, "Unknown compression type %d", compression); |
- | |
237 | png_warning(png_ptr, msg); |
- | |
238 | #else |
- | |
239 | png_warning(png_ptr, "Unknown compression type"); |
- | |
240 | #endif |
- | |
241 | } |
- | |
242 | - | ||
243 | /* We can't write the chunk until we find out how much data we have, |
- | |
244 | * which means we need to run the compressor first and save the |
- | |
245 | * output. This shouldn't be a problem, as the vast majority of |
- | |
246 | * comments should be reasonable, but we will set up an array of |
- | |
247 | * malloc'd pointers to be sure. |
- | |
248 | * |
- | |
249 | * If we knew the application was well behaved, we could simplify this |
- | |
250 | * greatly by assuming we can always malloc an output buffer large |
- | |
251 | * enough to hold the compressed text ((1001 * text_len / 1000) + 12) |
- | |
252 | * and malloc this directly. The only time this would be a bad idea is |
- | |
253 | * if we can't malloc more than 64K and we have 64K of random input |
- | |
254 | * data, or if the input string is incredibly large (although this |
- | |
255 | * wouldn't cause a failure, just a slowdown due to swapping). |
- | |
256 | */ |
- | |
257 | - | ||
258 | /* Set up the compression buffers */ |
- | |
259 | /* TODO: the following cast hides a potential overflow problem. */ |
- | |
260 | png_ptr->zstream.avail_in = (uInt)text_len; |
- | |
261 | /* NOTE: assume zlib doesn't overwrite the input */ |
319 | |
- | 320 | png_ptr->zowner = 0; |
|
262 | png_ptr->zstream.next_in = (Bytef *)text; |
321 | # else |
263 | png_ptr->zstream.avail_out = png_ptr->zbuf_size; |
322 | png_error(png_ptr, msg); |
- | 323 | # endif |
|
- | 324 | } |
|
- | 325 | ||
Line 264... | Line 326... | ||
264 | png_ptr->zstream.next_out = png_ptr->zbuf; |
326 | { |
265 | 327 | int level = png_ptr->zlib_level; |
|
- | 328 | int method = png_ptr->zlib_method; |
|
266 | /* This is the same compression loop as in png_write_row() */ |
329 | int windowBits = png_ptr->zlib_window_bits; |
- | 330 | int memLevel = png_ptr->zlib_mem_level; |
|
267 | do |
331 | int strategy; /* set below */ |
268 | { |
332 | int ret; /* zlib return code */ |
Line 269... | Line 333... | ||
269 | /* Compress the data */ |
333 | |
270 | ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); |
334 | if (owner == png_IDAT) |
271 | 335 | { |
|
Line 272... | Line -... | ||
272 | if (ret != Z_OK) |
- | |
273 | { |
336 | if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) |
274 | /* Error */ |
337 | strategy = png_ptr->zlib_strategy; |
- | 338 | ||
- | 339 | else if (png_ptr->do_filter != PNG_FILTER_NONE) |
|
- | 340 | strategy = PNG_Z_DEFAULT_STRATEGY; |
|
- | 341 | ||
- | 342 | else |
|
- | 343 | strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; |
|
- | 344 | } |
|
- | 345 | ||
- | 346 | else |
|
- | 347 | { |
|
275 | if (png_ptr->zstream.msg != NULL) |
348 | # ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED |
- | 349 | level = png_ptr->zlib_text_level; |
|
- | 350 | method = png_ptr->zlib_text_method; |
|
- | 351 | windowBits = png_ptr->zlib_text_window_bits; |
|
- | 352 | memLevel = png_ptr->zlib_text_mem_level; |
|
- | 353 | strategy = png_ptr->zlib_text_strategy; |
|
- | 354 | # else |
|
- | 355 | /* If customization is not supported the values all come from the |
|
- | 356 | * IDAT values except for the strategy, which is fixed to the |
|
- | 357 | * default. (This is the pre-1.6.0 behavior too, although it was |
|
- | 358 | * implemented in a very different way.) |
|
- | 359 | */ |
|
- | 360 | strategy = Z_DEFAULT_STRATEGY; |
|
- | 361 | # endif |
|
- | 362 | } |
|
- | 363 | ||
- | 364 | /* Adjust 'windowBits' down if larger than 'data_size'; to stop this |
|
- | 365 | * happening just pass 32768 as the data_size parameter. Notice that zlib |
|
276 | png_error(png_ptr, png_ptr->zstream.msg); |
366 | * requires an extra 262 bytes in the window in addition to the data to be |
- | 367 | * able to see the whole of the data, so if data_size+262 takes us to the |
|
- | 368 | * next windowBits size we need to fix up the value later. (Because even |
|
- | 369 | * though deflate needs the extra window, inflate does not!) |
|
- | 370 | */ |
|
277 | 371 | if (data_size <= 16384) |
|
- | 372 | { |
|
278 | else |
373 | /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to |
- | 374 | * work round a Microsoft Visual C misbehavior which, contrary to C-90, |
|
- | 375 | * widens the result of the following shift to 64-bits if (and, |
|
Line -... | Line 376... | ||
- | 376 | * apparently, only if) it is used in a test. |
|
- | 377 | */ |
|
- | 378 | unsigned int half_window_size = 1U << (windowBits-1); |
|
279 | png_error(png_ptr, "zlib error"); |
379 | |
280 | } |
380 | while (data_size + 262 <= half_window_size) |
- | 381 | { |
|
281 | 382 | half_window_size >>= 1; |
|
282 | /* Check to see if we need more room */ |
383 | --windowBits; |
283 | if (!(png_ptr->zstream.avail_out)) |
384 | } |
- | 385 | } |
|
Line 284... | Line 386... | ||
284 | { |
386 | |
- | 387 | /* Check against the previous initialized values, if any. */ |
|
Line 285... | Line 388... | ||
285 | /* Make sure the output array has room */ |
388 | if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) && |
- | 389 | (png_ptr->zlib_set_level != level || |
|
- | 390 | png_ptr->zlib_set_method != method || |
|
- | 391 | png_ptr->zlib_set_window_bits != windowBits || |
|
286 | if (comp->num_output_ptr >= comp->max_output_ptr) |
392 | png_ptr->zlib_set_mem_level != memLevel || |
287 | { |
393 | png_ptr->zlib_set_strategy != strategy)) |
- | 394 | { |
|
Line -... | Line 395... | ||
- | 395 | if (deflateEnd(&png_ptr->zstream) != Z_OK) |
|
288 | int old_max; |
396 | png_warning(png_ptr, "deflateEnd failed (ignored)"); |
- | 397 | ||
- | 398 | png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; |
|
289 | 399 | } |
|
Line -... | Line 400... | ||
- | 400 | ||
- | 401 | /* For safety clear out the input and output pointers (currently zlib |
|
- | 402 | * doesn't use them on Init, but it might in the future). |
|
290 | old_max = comp->max_output_ptr; |
403 | */ |
- | 404 | png_ptr->zstream.next_in = NULL; |
|
- | 405 | png_ptr->zstream.avail_in = 0; |
|
- | 406 | png_ptr->zstream.next_out = NULL; |
|
291 | comp->max_output_ptr = comp->num_output_ptr + 4; |
407 | png_ptr->zstream.avail_out = 0; |
- | 408 | ||
- | 409 | /* Now initialize if required, setting the new parameters, otherwise just |
|
- | 410 | * to a simple reset to the previous parameters. |
|
- | 411 | */ |
|
- | 412 | if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) |
|
- | 413 | ret = deflateReset(&png_ptr->zstream); |
|
- | 414 | ||
292 | if (comp->output_ptr != NULL) |
415 | else |
293 | { |
416 | { |
- | 417 | ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, |
|
294 | png_bytepp old_ptr; |
418 | memLevel, strategy); |
295 | - | ||
- | 419 | ||
296 | old_ptr = comp->output_ptr; |
420 | if (ret == Z_OK) |
Line -... | Line 421... | ||
- | 421 | png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; |
|
297 | 422 | } |
|
298 | comp->output_ptr = (png_bytepp)png_malloc(png_ptr, |
423 | |
- | 424 | /* The return code is from either deflateReset or deflateInit2; they have |
|
299 | (png_alloc_size_t) |
425 | * pretty much the same set of error codes. |
- | 426 | */ |
|
- | 427 | if (ret == Z_OK) |
|
- | 428 | png_ptr->zowner = owner; |
|
- | 429 | ||
- | 430 | else |
|
- | 431 | png_zstream_error(png_ptr, ret); |
|
- | 432 | ||
300 | (comp->max_output_ptr * png_sizeof(png_charpp))); |
433 | return ret; |
Line 301... | Line 434... | ||
301 | 434 | } |
|
- | 435 | } |
|
- | 436 | ||
302 | png_memcpy(comp->output_ptr, old_ptr, old_max |
437 | /* Clean up (or trim) a linked list of compression buffers. */ |
- | 438 | void /* PRIVATE */ |
|
- | 439 | png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) |
|
Line -... | Line 440... | ||
- | 440 | { |
|
- | 441 | png_compression_bufferp list = *listp; |
|
- | 442 | ||
- | 443 | if (list != NULL) |
|
- | 444 | { |
|
- | 445 | *listp = NULL; |
|
- | 446 | ||
- | 447 | do |
|
- | 448 | { |
|
- | 449 | png_compression_bufferp next = list->next; |
|
- | 450 | ||
- | 451 | png_free(png_ptr, list); |
|
- | 452 | list = next; |
|
- | 453 | } |
|
- | 454 | while (list != NULL); |
|
- | 455 | } |
|
- | 456 | } |
|
303 | * png_sizeof(png_charp)); |
457 | |
Line -... | Line 458... | ||
- | 458 | #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED |
|
- | 459 | /* This pair of functions encapsulates the operation of (a) compressing a |
|
304 | 460 | * text string, and (b) issuing it later as a series of chunk data writes. |
|
- | 461 | * The compression_state structure is shared context for these functions |
|
305 | png_free(png_ptr, old_ptr); |
462 | * set up by the caller to allow access to the relevant local variables. |
306 | } |
463 | * |
- | 464 | * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size |
|
307 | else |
465 | * temporary buffers. From 1.6.0 it is retained in png_struct so that it will |
308 | comp->output_ptr = (png_bytepp)png_malloc(png_ptr, |
- | |
309 | (png_alloc_size_t) |
- | |
Line -... | Line 466... | ||
- | 466 | * be correctly freed in the event of a write error (previous implementations |
|
- | 467 | * just leaked memory.) |
|
- | 468 | */ |
|
- | 469 | typedef struct |
|
- | 470 | { |
|
- | 471 | png_const_bytep input; /* The uncompressed input data */ |
|
- | 472 | png_alloc_size_t input_len; /* Its length */ |
|
- | 473 | png_uint_32 output_len; /* Final compressed length */ |
|
- | 474 | png_byte output[1024]; /* First block of output */ |
|
- | 475 | } compression_state; |
|
- | 476 | ||
- | 477 | static void |
|
- | 478 | png_text_compress_init(compression_state *comp, png_const_bytep input, |
|
- | 479 | png_alloc_size_t input_len) |
|
- | 480 | { |
|
- | 481 | comp->input = input; |
|
- | 482 | comp->input_len = input_len; |
|
- | 483 | comp->output_len = 0; |
|
- | 484 | } |
|
- | 485 | ||
- | 486 | /* Compress the data in the compression state input */ |
|
- | 487 | static int |
|
- | 488 | png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, |
|
- | 489 | compression_state *comp, png_uint_32 prefix_len) |
|
- | 490 | { |
|
- | 491 | int ret; |
|
- | 492 | ||
- | 493 | /* To find the length of the output it is necessary to first compress the |
|
- | 494 | * input, the result is buffered rather than using the two-pass algorithm |
|
- | 495 | * that is used on the inflate side; deflate is assumed to be slower and a |
|
- | 496 | * PNG writer is assumed to have more memory available than a PNG reader. |
|
- | 497 | * |
|
- | 498 | * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an |
|
310 | (comp->max_output_ptr * png_sizeof(png_charp))); |
499 | * upper limit on the output size, but it is always bigger than the input |
- | 500 | * size so it is likely to be more efficient to use this linked-list |
|
- | 501 | * approach. |
|
- | 502 | */ |
|
- | 503 | ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); |
|
- | 504 | ||
- | 505 | if (ret != Z_OK) |
|
- | 506 | return ret; |
|
311 | } |
507 | |
312 | 508 | /* Set up the compression buffers, we need a loop here to avoid overflowing a |
|
313 | /* Save the data */ |
509 | * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited |
314 | comp->output_ptr[comp->num_output_ptr] = |
- | |
Line -... | Line 510... | ||
- | 510 | * by the output buffer size, so there is no need to check that. Since this |
|
- | 511 | * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits |
|
- | 512 | * in size. |
|
315 | (png_bytep)png_malloc(png_ptr, |
513 | */ |
- | 514 | { |
|
- | 515 | png_compression_bufferp *end = &png_ptr->zbuffer_list; |
|
- | 516 | png_alloc_size_t input_len = comp->input_len; /* may be zero! */ |
|
- | 517 | png_uint_32 output_len; |
|
316 | (png_alloc_size_t)png_ptr->zbuf_size); |
518 | |
317 | 519 | /* zlib updates these for us: */ |
|
- | 520 | png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); |
|
- | 521 | png_ptr->zstream.avail_in = 0; /* Set below */ |
|
318 | png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, |
522 | png_ptr->zstream.next_out = comp->output; |
- | 523 | png_ptr->zstream.avail_out = (sizeof comp->output); |
|
- | 524 | ||
319 | png_ptr->zbuf_size); |
525 | output_len = png_ptr->zstream.avail_out; |
- | 526 | ||
- | 527 | do |
|
- | 528 | { |
|
- | 529 | uInt avail_in = ZLIB_IO_MAX; |
|
320 | 530 | ||
- | 531 | if (avail_in > input_len) |
|
- | 532 | avail_in = (uInt)input_len; |
|
- | 533 | ||
321 | comp->num_output_ptr++; |
534 | input_len -= avail_in; |
322 | 535 | ||
- | 536 | png_ptr->zstream.avail_in = avail_in; |
|
323 | /* and reset the buffer */ |
537 | |
Line 324... | Line -... | ||
324 | png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
- | |
325 | png_ptr->zstream.next_out = png_ptr->zbuf; |
- | |
326 | } |
538 | if (png_ptr->zstream.avail_out == 0) |
327 | /* Continue until we don't have any more to compress */ |
539 | { |
328 | } while (png_ptr->zstream.avail_in); |
540 | png_compression_buffer *next; |
- | 541 | ||
- | 542 | /* Chunk data is limited to 2^31 bytes in length, so the prefix |
|
Line -... | Line 543... | ||
- | 543 | * length must be counted here. |
|
- | 544 | */ |
|
329 | 545 | if (output_len + prefix_len > PNG_UINT_31_MAX) |
|
- | 546 | { |
|
Line 330... | Line 547... | ||
330 | /* Finish the compression */ |
547 | ret = Z_MEM_ERROR; |
331 | do |
548 | break; |
332 | { |
- | |
333 | /* Tell zlib we are finished */ |
549 | } |
Line 334... | Line 550... | ||
334 | ret = deflate(&png_ptr->zstream, Z_FINISH); |
550 | |
335 | 551 | /* Need a new (malloc'ed) buffer, but there may be one present |
|
- | 552 | * already. |
|
Line -... | Line 553... | ||
- | 553 | */ |
|
336 | if (ret == Z_OK) |
554 | next = *end; |
- | 555 | if (next == NULL) |
|
- | 556 | { |
|
- | 557 | next = png_voidcast(png_compression_bufferp, png_malloc_base |
|
- | 558 | (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); |
|
- | 559 | ||
- | 560 | if (next == NULL) |
|
- | 561 | { |
|
337 | { |
562 | ret = Z_MEM_ERROR; |
- | 563 | break; |
|
Line -... | Line 564... | ||
- | 564 | } |
|
- | 565 | ||
- | 566 | /* Link in this buffer (so that it will be freed later) */ |
|
- | 567 | next->next = NULL; |
|
- | 568 | *end = next; |
|
- | 569 | } |
|
- | 570 | ||
- | 571 | png_ptr->zstream.next_out = next->output; |
|
- | 572 | png_ptr->zstream.avail_out = png_ptr->zbuffer_size; |
|
338 | /* Check to see if we need more room */ |
573 | output_len += png_ptr->zstream.avail_out; |
- | 574 | ||
339 | if (!(png_ptr->zstream.avail_out)) |
575 | /* Move 'end' to the next buffer pointer. */ |
- | 576 | end = &next->next; |
|
340 | { |
577 | } |
341 | /* Check to make sure our output array has room */ |
578 | |
342 | if (comp->num_output_ptr >= comp->max_output_ptr) |
579 | /* Compress the data */ |
Line 343... | Line 580... | ||
343 | { |
580 | ret = deflate(&png_ptr->zstream, |
344 | int old_max; |
581 | input_len > 0 ? Z_NO_FLUSH : Z_FINISH); |
- | 582 | ||
345 | 583 | /* Claw back input data that was not consumed (because avail_in is |
|
346 | old_max = comp->max_output_ptr; |
584 | * reset above every time round the loop). |
Line 347... | Line 585... | ||
347 | comp->max_output_ptr = comp->num_output_ptr + 4; |
585 | */ |
348 | if (comp->output_ptr != NULL) |
586 | input_len += png_ptr->zstream.avail_in; |
- | 587 | png_ptr->zstream.avail_in = 0; /* safety */ |
|
- | 588 | } |
|
- | 589 | while (ret == Z_OK); |
|
- | 590 | ||
- | 591 | /* There may be some space left in the last output buffer, this needs to |
|
Line -... | Line 592... | ||
- | 592 | * be subtracted from output_len. |
|
- | 593 | */ |
|
349 | { |
594 | output_len -= png_ptr->zstream.avail_out; |
- | 595 | png_ptr->zstream.avail_out = 0; /* safety */ |
|
- | 596 | comp->output_len = output_len; |
|
- | 597 | ||
Line 350... | Line 598... | ||
350 | png_bytepp old_ptr; |
598 | /* Now double check the output length, put in a custom message if it is |
351 | - | ||
352 | old_ptr = comp->output_ptr; |
599 | * too long. Otherwise ensure the z_stream::msg pointer is set to |
353 | 600 | * something. |
|
354 | /* This could be optimized to realloc() */ |
601 | */ |
- | 602 | if (output_len + prefix_len >= PNG_UINT_31_MAX) |
|
355 | comp->output_ptr = (png_bytepp)png_malloc(png_ptr, |
603 | { |
- | 604 | png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); |
|
- | 605 | ret = Z_MEM_ERROR; |
|
356 | (png_alloc_size_t)(comp->max_output_ptr * |
606 | } |
- | 607 | ||
357 | png_sizeof(png_charp))); |
608 | else |
358 | 609 | png_zstream_error(png_ptr, ret); |
|
359 | png_memcpy(comp->output_ptr, old_ptr, |
610 | |
Line -... | Line 611... | ||
- | 611 | /* Reset zlib for another zTXt/iTXt or image data */ |
|
- | 612 | png_ptr->zowner = 0; |
|
- | 613 | ||
- | 614 | /* The only success case is Z_STREAM_END, input_len must be 0, if not this |
|
- | 615 | * is an internal error. |
|
- | 616 | */ |
|
- | 617 | if (ret == Z_STREAM_END && input_len == 0) |
|
- | 618 | { |
|
- | 619 | /* Fix up the deflate header, if required */ |
|
- | 620 | optimize_cmf(comp->output, comp->input_len); |
|
360 | old_max * png_sizeof(png_charp)); |
621 | |
- | 622 | /* But Z_OK is returned, not Z_STREAM_END; this allows the claim |
|
361 | 623 | * function above to return Z_STREAM_END on an error (though it never |
|
- | 624 | * does in the current versions of zlib.) |
|
- | 625 | */ |
|
- | 626 | return Z_OK; |
|
- | 627 | } |
|
- | 628 | ||
- | 629 | else |
|
- | 630 | return ret; |
|
362 | png_free(png_ptr, old_ptr); |
631 | } |
363 | } |
632 | } |
Line -... | Line 633... | ||
- | 633 | ||
- | 634 | /* Ship the compressed text out via chunk writes */ |
|
- | 635 | static void |
|
- | 636 | png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) |
|
- | 637 | { |
|
- | 638 | png_uint_32 output_len = comp->output_len; |
|
- | 639 | png_const_bytep output = comp->output; |
|
- | 640 | png_uint_32 avail = (sizeof comp->output); |
|
- | 641 | png_compression_buffer *next = png_ptr->zbuffer_list; |
|
- | 642 | ||
364 | 643 | for (;;) |
|
- | 644 | { |
|
- | 645 | if (avail > output_len) |
|
365 | else |
646 | avail = output_len; |
- | 647 | ||
- | 648 | png_write_chunk_data(png_ptr, output, avail); |
|
- | 649 | ||
- | 650 | output_len -= avail; |
|
- | 651 | ||
Line 366... | Line 652... | ||
366 | comp->output_ptr = (png_bytepp)png_malloc(png_ptr, |
652 | if (output_len == 0 || next == NULL) |
367 | (png_alloc_size_t)(comp->max_output_ptr * |
- | |
Line -... | Line 653... | ||
- | 653 | break; |
|
- | 654 | ||
368 | png_sizeof(png_charp))); |
655 | avail = png_ptr->zbuffer_size; |
- | 656 | output = next->output; |
|
369 | } |
657 | next = next->next; |
Line 370... | Line -... | ||
370 | - | ||
371 | /* Save the data */ |
658 | } |
372 | comp->output_ptr[comp->num_output_ptr] = |
- | |
373 | (png_bytep)png_malloc(png_ptr, |
659 | |
374 | (png_alloc_size_t)png_ptr->zbuf_size); |
660 | /* This is an internal error; 'next' must have been NULL! */ |
Line -... | Line 661... | ||
- | 661 | if (output_len > 0) |
|
375 | 662 | png_error(png_ptr, "error writing ancillary chunked compressed data"); |
|
- | 663 | } |
|
376 | png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, |
664 | #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ |
377 | png_ptr->zbuf_size); |
665 | |
378 | 666 | #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ |
|
- | 667 | defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) |
|
- | 668 | /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, |
|
- | 669 | * and if invalid, correct the keyword rather than discarding the entire |
|
Line -... | Line 670... | ||
- | 670 | * chunk. The PNG 1.0 specification requires keywords 1-79 characters in |
|
379 | comp->num_output_ptr++; |
671 | * length, forbids leading or trailing whitespace, multiple internal spaces, |
- | 672 | * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. |
|
380 | 673 | * |
|
Line 381... | Line 674... | ||
381 | /* and reset the buffer pointers */ |
674 | * The 'new_key' buffer must be 80 characters in size (for the keyword plus a |
382 | png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
675 | * trailing '\0'). If this routine returns 0 then there was no keyword, or a |
383 | png_ptr->zstream.next_out = png_ptr->zbuf; |
676 | * valid one could not be generated, and the caller must png_error. |
384 | } |
- | |
385 | } |
- | |
Line -... | Line 677... | ||
- | 677 | */ |
|
- | 678 | static png_uint_32 |
|
386 | else if (ret != Z_STREAM_END) |
679 | png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) |
- | 680 | { |
|
- | 681 | png_const_charp orig_key = key; |
|
387 | { |
682 | png_uint_32 key_len = 0; |
Line 388... | Line 683... | ||
388 | /* We got an error */ |
683 | int bad_character = 0; |
389 | if (png_ptr->zstream.msg != NULL) |
684 | int space = 1; |
Line 390... | Line 685... | ||
390 | png_error(png_ptr, png_ptr->zstream.msg); |
685 | |
391 | - | ||
392 | else |
686 | png_debug(1, "in png_check_keyword"); |
393 | png_error(png_ptr, "zlib error"); |
- | |
Line 394... | Line 687... | ||
394 | } |
687 | |
- | 688 | if (key == NULL) |
|
- | 689 | { |
|
- | 690 | *new_key = 0; |
|
395 | } while (ret != Z_STREAM_END); |
691 | return 0; |
- | 692 | } |
|
- | 693 | ||
- | 694 | while (*key && key_len < 79) |
|
396 | 695 | { |
|
- | 696 | png_byte ch = (png_byte)(0xff & *key++); |
|
- | 697 | ||
- | 698 | if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) |
|
- | 699 | *new_key++ = ch, ++key_len, space = 0; |
|
- | 700 | ||
- | 701 | else if (!space) |
|
397 | /* Text length is number of buffers plus last buffer */ |
702 | { |
398 | text_len = png_ptr->zbuf_size * comp->num_output_ptr; |
703 | /* A space or an invalid character when one wasn't seen immediately |
Line 399... | Line 704... | ||
399 | 704 | * before; output just a space. |
|
400 | if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) |
705 | */ |
401 | text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; |
706 | *new_key++ = 32, ++key_len, space = 1; |
402 | 707 | ||
403 | return((int)text_len); |
708 | /* If the character was not a space then it is invalid. */ |
404 | } |
709 | if (ch != 32) |
405 | 710 | bad_character = ch; |
|
406 | /* Ship the compressed text out via chunk writes */ |
711 | } |
407 | static void /* PRIVATE */ |
712 | |
408 | png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) |
- | |
409 | { |
- | |
410 | int i; |
- | |
411 | 713 | else if (!bad_character) |
|
Line 412... | Line 714... | ||
412 | /* Handle the no-compression case */ |
714 | bad_character = ch; /* just skip it, record the first error */ |
Line 413... | Line 715... | ||
413 | if (comp->input) |
715 | } |
Line 592... | Line 894... | ||
592 | buf[11] = (png_byte)filter_type; |
894 | buf[11] = (png_byte)filter_type; |
593 | buf[12] = (png_byte)interlace_type; |
895 | buf[12] = (png_byte)interlace_type; |
594 | 896 | ||
Line 595... | Line 897... | ||
595 | /* Write the chunk */ |
897 | /* Write the chunk */ |
596 | png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); |
898 | png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); |
597 | - | ||
598 | /* Initialize zlib with PNG info */ |
- | |
599 | png_ptr->zstream.zalloc = png_zalloc; |
- | |
600 | png_ptr->zstream.zfree = png_zfree; |
- | |
601 | png_ptr->zstream.opaque = (voidpf)png_ptr; |
- | |
Line 602... | Line 899... | ||
602 | 899 | ||
603 | if (!(png_ptr->do_filter)) |
900 | if (!(png_ptr->do_filter)) |
604 | { |
901 | { |
605 | if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || |
902 | if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || |
Line 609... | Line 906... | ||
609 | else |
906 | else |
610 | png_ptr->do_filter = PNG_ALL_FILTERS; |
907 | png_ptr->do_filter = PNG_ALL_FILTERS; |
611 | } |
908 | } |
Line 612... | Line -... | ||
612 | - | ||
613 | if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) |
- | |
614 | { |
- | |
615 | if (png_ptr->do_filter != PNG_FILTER_NONE) |
- | |
616 | png_ptr->zlib_strategy = Z_FILTERED; |
- | |
617 | - | ||
618 | else |
- | |
619 | png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; |
- | |
620 | } |
- | |
621 | - | ||
622 | if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) |
- | |
623 | png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; |
- | |
624 | - | ||
625 | if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) |
- | |
626 | png_ptr->zlib_mem_level = 8; |
- | |
627 | - | ||
628 | if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) |
- | |
629 | png_ptr->zlib_window_bits = 15; |
- | |
630 | - | ||
631 | if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) |
- | |
632 | png_ptr->zlib_method = 8; |
- | |
633 | - | ||
634 | ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, |
- | |
635 | png_ptr->zlib_method, png_ptr->zlib_window_bits, |
- | |
636 | png_ptr->zlib_mem_level, png_ptr->zlib_strategy); |
- | |
637 | - | ||
638 | if (ret != Z_OK) |
- | |
639 | { |
- | |
640 | if (ret == Z_VERSION_ERROR) |
- | |
641 | png_error(png_ptr, |
- | |
642 | "zlib failed to initialize compressor -- version error"); |
- | |
643 | - | ||
644 | if (ret == Z_STREAM_ERROR) |
- | |
645 | png_error(png_ptr, |
- | |
646 | "zlib failed to initialize compressor -- stream error"); |
- | |
647 | - | ||
648 | if (ret == Z_MEM_ERROR) |
- | |
649 | png_error(png_ptr, |
- | |
650 | "zlib failed to initialize compressor -- mem error"); |
- | |
651 | - | ||
652 | png_error(png_ptr, "zlib failed to initialize compressor"); |
- | |
653 | } |
- | |
654 | - | ||
655 | png_ptr->zstream.next_out = png_ptr->zbuf; |
- | |
656 | png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
- | |
657 | /* libpng is not interested in zstream.data_type, so set it |
- | |
658 | * to a predefined value, to avoid its evaluation inside zlib |
- | |
659 | */ |
- | |
660 | png_ptr->zstream.data_type = Z_BINARY; |
- | |
661 | 909 | ||
662 | png_ptr->mode = PNG_HAVE_IHDR; |
910 | png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ |
Line 663... | Line 911... | ||
663 | } |
911 | } |
664 | 912 | ||
665 | /* Write the palette. We are careful not to trust png_color to be in the |
913 | /* Write the palette. We are careful not to trust png_color to be in the |
666 | * correct order for PNG, so people can redefine it to any convenient |
914 | * correct order for PNG, so people can redefine it to any convenient |
667 | * structure. |
915 | * structure. |
668 | */ |
916 | */ |
669 | void /* PRIVATE */ |
917 | void /* PRIVATE */ |
670 | png_write_PLTE(png_structp png_ptr, png_const_colorp palette, |
918 | png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, |
671 | png_uint_32 num_pal) |
- | |
672 | { |
919 | png_uint_32 num_pal) |
673 | PNG_PLTE; |
920 | { |
674 | png_uint_32 i; |
921 | png_uint_32 i; |
Line 675... | Line 922... | ||
675 | png_const_colorp pal_ptr; |
922 | png_const_colorp pal_ptr; |
Line 705... | Line 952... | ||
705 | 952 | ||
Line 706... | Line 953... | ||
706 | png_ptr->num_palette = (png_uint_16)num_pal; |
953 | png_ptr->num_palette = (png_uint_16)num_pal; |
707 | png_debug1(3, "num_palette = %d", png_ptr->num_palette); |
954 | png_debug1(3, "num_palette = %d", png_ptr->num_palette); |
Line 708... | Line 955... | ||
708 | 955 | ||
709 | png_write_chunk_start(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); |
956 | png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); |
Line 710... | Line 957... | ||
710 | #ifdef PNG_POINTER_INDEXING_SUPPORTED |
957 | #ifdef PNG_POINTER_INDEXING_SUPPORTED |
711 | 958 | ||
712 | for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) |
959 | for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) |
Line 735... | Line 982... | ||
735 | png_write_chunk_end(png_ptr); |
982 | png_write_chunk_end(png_ptr); |
736 | png_ptr->mode |= PNG_HAVE_PLTE; |
983 | png_ptr->mode |= PNG_HAVE_PLTE; |
737 | } |
984 | } |
738 | 985 | ||
Line -... | Line 986... | ||
- | 986 | /* This is similar to png_text_compress, above, except that it does not require |
|
- | 987 | * all of the data at once and, instead of buffering the compressed result, |
|
- | 988 | * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out |
|
- | 989 | * because it calls the write interface. As a result it does its own error |
|
- | 990 | * reporting and does not return an error code. In the event of error it will |
|
- | 991 | * just call png_error. The input data length may exceed 32-bits. The 'flush' |
|
- | 992 | * parameter is exactly the same as that to deflate, with the following |
|
739 | /* Write an IDAT chunk */ |
993 | * meanings: |
- | 994 | * |
|
- | 995 | * Z_NO_FLUSH: normal incremental output of compressed data |
|
- | 996 | * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush |
|
- | 997 | * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up |
|
- | 998 | * |
|
- | 999 | * The routine manages the acquire and release of the png_ptr->zstream by |
|
- | 1000 | * checking and (at the end) clearing png_ptr->zowner, it does some sanity |
|
- | 1001 | * checks on the 'mode' flags while doing this. |
|
- | 1002 | */ |
|
740 | void /* PRIVATE */ |
1003 | void /* PRIVATE */ |
741 | png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) |
1004 | png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, |
- | 1005 | png_alloc_size_t input_len, int flush) |
|
742 | { |
1006 | { |
743 | PNG_IDAT; |
- | |
744 | - | ||
745 | png_debug(1, "in png_write_IDAT"); |
- | |
746 | - | ||
747 | /* Optimize the CMF field in the zlib stream. */ |
- | |
748 | /* This hack of the zlib stream is compliant to the stream specification. */ |
- | |
749 | if (!(png_ptr->mode & PNG_HAVE_IDAT) && |
1007 | if (png_ptr->zowner != png_IDAT) |
750 | png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) |
- | |
751 | { |
1008 | { |
- | 1009 | /* First time. Ensure we have a temporary buffer for compression and |
|
- | 1010 | * trim the buffer list if it has more than one entry to free memory. |
|
- | 1011 | * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been |
|
752 | unsigned int z_cmf = data[0]; /* zlib compression method and flags */ |
1012 | * created at this point, but the check here is quick and safe. |
- | 1013 | */ |
|
753 | if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) |
1014 | if (png_ptr->zbuffer_list == NULL) |
754 | { |
1015 | { |
755 | /* Avoid memory underflows and multiplication overflows. |
1016 | png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, |
- | 1017 | png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); |
|
- | 1018 | png_ptr->zbuffer_list->next = NULL; |
|
- | 1019 | } |
|
- | 1020 | ||
756 | * |
1021 | else |
- | 1022 | png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); |
|
- | 1023 | ||
757 | * The conditions below are practically always satisfied; |
1024 | /* It is a terminal error if we can't claim the zstream. */ |
- | 1025 | if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) |
|
- | 1026 | png_error(png_ptr, png_ptr->zstream.msg); |
|
- | 1027 | ||
- | 1028 | /* The output state is maintained in png_ptr->zstream, so it must be |
|
758 | * however, they still must be checked. |
1029 | * initialized here after the claim. |
759 | */ |
1030 | */ |
760 | if (length >= 2 && |
1031 | png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; |
761 | png_ptr->height < 16384 && png_ptr->width < 16384) |
1032 | png_ptr->zstream.avail_out = png_ptr->zbuffer_size; |
- | 1033 | } |
|
- | 1034 | ||
- | 1035 | /* Now loop reading and writing until all the input is consumed or an error |
|
- | 1036 | * terminates the operation. The _out values are maintained across calls to |
|
- | 1037 | * this function, but the input must be reset each time. |
|
- | 1038 | */ |
|
- | 1039 | png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); |
|
- | 1040 | png_ptr->zstream.avail_in = 0; /* set below */ |
|
- | 1041 | for (;;) |
|
762 | { |
1042 | { |
- | 1043 | int ret; |
|
- | 1044 | ||
- | 1045 | /* INPUT: from the row data */ |
|
- | 1046 | uInt avail = ZLIB_IO_MAX; |
|
- | 1047 | ||
- | 1048 | if (avail > input_len) |
|
763 | png_uint_32 uncompressed_idat_size = png_ptr->height * |
1049 | avail = (uInt)input_len; /* safe because of the check */ |
- | 1050 | ||
764 | ((png_ptr->width * |
1051 | png_ptr->zstream.avail_in = avail; |
- | 1052 | input_len -= avail; |
|
- | 1053 | ||
765 | png_ptr->channels * png_ptr->bit_depth + 15) >> 3); |
1054 | ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); |
- | 1055 | ||
766 | unsigned int z_cinfo = z_cmf >> 4; |
1056 | /* Include as-yet unconsumed input */ |
- | 1057 | input_len += png_ptr->zstream.avail_in; |
|
- | 1058 | png_ptr->zstream.avail_in = 0; |
|
- | 1059 | ||
- | 1060 | /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note |
|
767 | unsigned int half_z_window_size = 1 << (z_cinfo + 7); |
1061 | * that these two zstream fields are preserved across the calls, therefore |
768 | while (uncompressed_idat_size <= half_z_window_size && |
1062 | * there is no need to set these up on entry to the loop. |
- | 1063 | */ |
|
769 | half_z_window_size >= 256) |
1064 | if (png_ptr->zstream.avail_out == 0) |
770 | { |
1065 | { |
771 | z_cinfo--; |
1066 | png_bytep data = png_ptr->zbuffer_list->output; |
772 | half_z_window_size >>= 1; |
1067 | uInt size = png_ptr->zbuffer_size; |
773 | } |
- | |
Line -... | Line 1068... | ||
- | 1068 | ||
- | 1069 | /* Write an IDAT containing the data then reset the buffer. The |
|
- | 1070 | * first IDAT may need deflate header optimization. |
|
- | 1071 | */ |
|
- | 1072 | # ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
|
- | 1073 | if (!(png_ptr->mode & PNG_HAVE_IDAT) && |
|
774 | 1074 | png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) |
|
- | 1075 | optimize_cmf(data, png_image_size(png_ptr)); |
|
- | 1076 | # endif |
|
- | 1077 | ||
- | 1078 | png_write_complete_chunk(png_ptr, png_IDAT, data, size); |
|
Line -... | Line 1079... | ||
- | 1079 | png_ptr->mode |= PNG_HAVE_IDAT; |
|
- | 1080 | ||
- | 1081 | png_ptr->zstream.next_out = data; |
|
- | 1082 | png_ptr->zstream.avail_out = size; |
|
- | 1083 | ||
775 | z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); |
1084 | /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with |
- | 1085 | * the same flush parameter until it has finished output, for NO_FLUSH |
|
- | 1086 | * it doesn't matter. |
|
- | 1087 | */ |
|
- | 1088 | if (ret == Z_OK && flush != Z_NO_FLUSH) |
|
- | 1089 | continue; |
|
- | 1090 | } |
|
- | 1091 | ||
- | 1092 | /* The order of these checks doesn't matter much; it just effect which |
|
- | 1093 | * possible error might be detected if multiple things go wrong at once. |
|
776 | 1094 | */ |
|
- | 1095 | if (ret == Z_OK) /* most likely return code! */ |
|
- | 1096 | { |
|
777 | if (data[0] != z_cmf) |
1097 | /* If all the input has been consumed then just return. If Z_FINISH |
- | 1098 | * was used as the flush parameter something has gone wrong if we get |
|
778 | { |
1099 | * here. |
- | 1100 | */ |
|
779 | int tmp; |
1101 | if (input_len == 0) |
780 | data[0] = (png_byte)z_cmf; |
1102 | { |
- | 1103 | if (flush == Z_FINISH) |
|
781 | tmp = data[1] & 0xe0; |
1104 | png_error(png_ptr, "Z_OK on Z_FINISH with output space"); |
782 | tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; |
1105 | |
783 | data[1] = (png_byte)tmp; |
1106 | return; |
- | 1107 | } |
|
- | 1108 | } |
|
- | 1109 | ||
- | 1110 | else if (ret == Z_STREAM_END && flush == Z_FINISH) |
|
- | 1111 | { |
|
- | 1112 | /* This is the end of the IDAT data; any pending output must be |
|
- | 1113 | * flushed. For small PNG files we may still be at the beginning. |
|
- | 1114 | */ |
|
- | 1115 | png_bytep data = png_ptr->zbuffer_list->output; |
|
- | 1116 | uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; |
|
- | 1117 | ||
- | 1118 | # ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
|
- | 1119 | if (!(png_ptr->mode & PNG_HAVE_IDAT) && |
|
- | 1120 | png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) |
|
- | 1121 | optimize_cmf(data, png_image_size(png_ptr)); |
|
- | 1122 | # endif |
|
- | 1123 | ||
- | 1124 | png_write_complete_chunk(png_ptr, png_IDAT, data, size); |
|
- | 1125 | png_ptr->zstream.avail_out = 0; |
|
- | 1126 | png_ptr->zstream.next_out = NULL; |
|
- | 1127 | png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; |
|
- | 1128 | ||
784 | } |
1129 | png_ptr->zowner = 0; /* Release the stream */ |
Line 785... | Line 1130... | ||
785 | } |
1130 | return; |
- | 1131 | } |
|
- | 1132 | ||
786 | } |
1133 | else |
787 | 1134 | { |
|
- | 1135 | /* This is an error condition. */ |
|
788 | else |
1136 | png_zstream_error(png_ptr, ret); |
789 | png_error(png_ptr, |
- | |
790 | "Invalid zlib compression method or flags in IDAT"); |
- | |
791 | } |
- | |
792 | 1137 | png_error(png_ptr, png_ptr->zstream.msg); |
|
Line 793... | Line 1138... | ||
793 | png_write_chunk(png_ptr, png_IDAT, data, length); |
1138 | } |
794 | png_ptr->mode |= PNG_HAVE_IDAT; |
1139 | } |
795 | } |
1140 | } |
796 | 1141 | ||
797 | /* Write an IEND chunk */ |
- | |
798 | void /* PRIVATE */ |
- | |
799 | png_write_IEND(png_structp png_ptr) |
1142 | /* Write an IEND chunk */ |
Line 800... | Line 1143... | ||
800 | { |
1143 | void /* PRIVATE */ |
801 | PNG_IEND; |
1144 | png_write_IEND(png_structrp png_ptr) |
802 | 1145 | { |
|
Line 803... | Line 1146... | ||
803 | png_debug(1, "in png_write_IEND"); |
1146 | png_debug(1, "in png_write_IEND"); |
804 | 1147 | ||
805 | png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); |
1148 | png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); |
806 | png_ptr->mode |= PNG_HAVE_IEND; |
1149 | png_ptr->mode |= PNG_HAVE_IEND; |
807 | } |
1150 | } |
808 | - | ||
809 | #ifdef PNG_WRITE_gAMA_SUPPORTED |
1151 | |
Line 810... | Line 1152... | ||
810 | /* Write a gAMA chunk */ |
1152 | #ifdef PNG_WRITE_gAMA_SUPPORTED |
Line 811... | Line 1153... | ||
811 | void /* PRIVATE */ |
1153 | /* Write a gAMA chunk */ |
812 | png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) |
1154 | void /* PRIVATE */ |
813 | { |
1155 | png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) |
814 | PNG_gAMA; |
1156 | { |
815 | png_byte buf[4]; |
1157 | png_byte buf[4]; |
Line 816... | Line 1158... | ||
816 | 1158 | ||
817 | png_debug(1, "in png_write_gAMA"); |
1159 | png_debug(1, "in png_write_gAMA"); |
818 | 1160 | ||
819 | /* file_gamma is saved in 1/100,000ths */ |
1161 | /* file_gamma is saved in 1/100,000ths */ |
820 | png_save_uint_32(buf, (png_uint_32)file_gamma); |
1162 | png_save_uint_32(buf, (png_uint_32)file_gamma); |
821 | png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); |
- | |
822 | } |
1163 | png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); |
Line 823... | Line 1164... | ||
823 | #endif |
1164 | } |
Line 824... | Line 1165... | ||
824 | 1165 | #endif |
|
825 | #ifdef PNG_WRITE_sRGB_SUPPORTED |
1166 | |
826 | /* Write a sRGB chunk */ |
1167 | #ifdef PNG_WRITE_sRGB_SUPPORTED |
Line 827... | Line 1168... | ||
827 | void /* PRIVATE */ |
1168 | /* Write a sRGB chunk */ |
828 | png_write_sRGB(png_structp png_ptr, int srgb_intent) |
1169 | void /* PRIVATE */ |
829 | { |
1170 | png_write_sRGB(png_structrp png_ptr, int srgb_intent) |
830 | PNG_sRGB; |
1171 | { |
Line 831... | Line 1172... | ||
831 | png_byte buf[1]; |
1172 | png_byte buf[1]; |
832 | 1173 | ||
833 | png_debug(1, "in png_write_sRGB"); |
1174 | png_debug(1, "in png_write_sRGB"); |
834 | 1175 | ||
835 | if (srgb_intent >= PNG_sRGB_INTENT_LAST) |
1176 | if (srgb_intent >= PNG_sRGB_INTENT_LAST) |
836 | png_warning(png_ptr, |
1177 | png_warning(png_ptr, |
837 | "Invalid sRGB rendering intent specified"); |
1178 | "Invalid sRGB rendering intent specified"); |
838 | 1179 | ||
839 | buf[0]=(png_byte)srgb_intent; |
1180 | buf[0]=(png_byte)srgb_intent; |
840 | png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); |
1181 | png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); |
841 | } |
- | |
Line 842... | Line 1182... | ||
842 | #endif |
1182 | } |
Line 843... | Line -... | ||
843 | - | ||
844 | #ifdef PNG_WRITE_iCCP_SUPPORTED |
1183 | #endif |
845 | /* Write an iCCP chunk */ |
1184 | |
846 | void /* PRIVATE */ |
- | |
847 | png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, |
- | |
848 | png_const_charp profile, int profile_len) |
- | |
849 | { |
- | |
850 | PNG_iCCP; |
1185 | #ifdef PNG_WRITE_iCCP_SUPPORTED |
851 | png_size_t name_len; |
- | |
852 | png_charp new_name; |
- | |
853 | compression_state comp; |
- | |
854 | int embedded_profile_len = 0; |
- | |
855 | 1186 | /* Write an iCCP chunk */ |
|
856 | png_debug(1, "in png_write_iCCP"); |
1187 | void /* PRIVATE */ |
Line 857... | Line -... | ||
857 | - | ||
858 | comp.num_output_ptr = 0; |
- | |
859 | comp.max_output_ptr = 0; |
- | |
860 | comp.output_ptr = NULL; |
- | |
861 | comp.input = NULL; |
- | |
862 | comp.input_len = 0; |
1188 | png_write_iCCP(png_structrp png_ptr, png_const_charp name, |
Line 863... | Line 1189... | ||
863 | 1189 | png_const_bytep profile) |
|
864 | if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0) |
- | |
865 | return; |
- | |
866 | 1190 | { |
|
Line 867... | Line 1191... | ||
867 | if (compression_type != PNG_COMPRESSION_TYPE_BASE) |
1191 | png_uint_32 name_len; |
868 | png_warning(png_ptr, "Unknown compression type in iCCP chunk"); |
1192 | png_uint_32 profile_len; |
869 | - | ||
Line 870... | Line -... | ||
870 | if (profile == NULL) |
- | |
871 | profile_len = 0; |
1193 | png_byte new_name[81]; /* 1 byte for the compression byte */ |
872 | - | ||
873 | if (profile_len > 3) |
1194 | compression_state comp; |
Line 874... | Line 1195... | ||
874 | embedded_profile_len = |
1195 | |
875 | ((*( (png_const_bytep)profile ))<<24) | |
1196 | png_debug(1, "in png_write_iCCP"); |
876 | ((*( (png_const_bytep)profile + 1))<<16) | |
1197 | |
Line 877... | Line 1198... | ||
877 | ((*( (png_const_bytep)profile + 2))<< 8) | |
1198 | /* These are all internal problems: the profile should have been checked |
878 | ((*( (png_const_bytep)profile + 3)) ); |
- | |
879 | - | ||
880 | if (embedded_profile_len < 0) |
- | |
Line -... | Line 1199... | ||
- | 1199 | * before when it was stored. |
|
881 | { |
1200 | */ |
882 | png_warning(png_ptr, |
- | |
Line 883... | Line -... | ||
883 | "Embedded profile length in iCCP chunk is negative"); |
- | |
884 | - | ||
885 | png_free(png_ptr, new_name); |
1201 | if (profile == NULL) |
Line 886... | Line 1202... | ||
886 | return; |
1202 | png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ |
887 | } |
- | |
888 | 1203 | ||
Line 889... | Line 1204... | ||
889 | if (profile_len < embedded_profile_len) |
1204 | profile_len = png_get_uint_32(profile); |
Line -... | Line 1205... | ||
- | 1205 | ||
- | 1206 | if (profile_len < 132) |
|
- | 1207 | png_error(png_ptr, "ICC profile too short"); |
|
- | 1208 | ||
890 | { |
1209 | if (profile_len & 0x03) |
- | 1210 | png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); |
|
891 | png_warning(png_ptr, |
1211 | |
Line 892... | Line -... | ||
892 | "Embedded profile length too large in iCCP chunk"); |
- | |
893 | 1212 | { |
|
Line 894... | Line 1213... | ||
894 | png_free(png_ptr, new_name); |
1213 | png_uint_32 embedded_profile_len = png_get_uint_32(profile); |
895 | return; |
- | |
896 | } |
1214 | |
897 | 1215 | if (profile_len != embedded_profile_len) |
|
Line 898... | Line 1216... | ||
898 | if (profile_len > embedded_profile_len) |
1216 | png_error(png_ptr, "Profile length does not match profile"); |
899 | { |
1217 | } |
900 | png_warning(png_ptr, |
1218 | |
901 | "Truncating profile to actual length in iCCP chunk"); |
1219 | name_len = png_check_keyword(png_ptr, name, new_name); |
902 | 1220 | ||
903 | profile_len = embedded_profile_len; |
- | |
904 | } |
1221 | if (name_len == 0) |
905 | 1222 | png_error(png_ptr, "iCCP: invalid keyword"); |
|
906 | if (profile_len) |
1223 | |
907 | profile_len = png_text_compress(png_ptr, profile, |
1224 | new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; |
908 | (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); |
1225 | |
909 | 1226 | /* Make sure we include the NULL after the name and the compression type */ |
|
910 | /* Make sure we include the NULL after the name and the compression type */ |
1227 | ++name_len; |
911 | png_write_chunk_start(png_ptr, png_iCCP, |
1228 | |
912 | (png_uint_32)(name_len + profile_len + 2)); |
1229 | png_text_compress_init(&comp, profile, profile_len); |
Line 913... | Line 1230... | ||
913 | 1230 | ||
Line 914... | Line 1231... | ||
914 | new_name[name_len + 1] = 0x00; |
1231 | /* Allow for keyword terminator and compression byte */ |
- | 1232 | if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) |
|
915 | 1233 | png_error(png_ptr, png_ptr->zstream.msg); |
|
- | 1234 | ||
Line 916... | Line 1235... | ||
916 | png_write_chunk_data(png_ptr, (png_bytep)new_name, |
1235 | png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); |
917 | (png_size_t)(name_len + 2)); |
1236 | |
918 | 1237 | png_write_chunk_data(png_ptr, new_name, name_len); |
|
Line 919... | Line 1238... | ||
919 | if (profile_len) |
1238 | |
920 | png_write_compressed_data_out(png_ptr, &comp); |
1239 | png_write_compressed_data_out(png_ptr, &comp); |
Line 975... | Line 1294... | ||
975 | png_save_uint_16(entrybuf + 6, ep->alpha); |
1294 | png_save_uint_16(entrybuf + 6, ep->alpha); |
976 | png_save_uint_16(entrybuf + 8, ep->frequency); |
1295 | png_save_uint_16(entrybuf + 8, ep->frequency); |
977 | } |
1296 | } |
978 | 1297 | ||
Line 979... | Line 1298... | ||
979 | png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); |
1298 | png_write_chunk_data(png_ptr, entrybuf, entry_size); |
980 | } |
1299 | } |
981 | #else |
1300 | #else |
982 | ep=spalette->entries; |
1301 | ep=spalette->entries; |
983 | for (i = 0; i>spalette->nentries; i++) |
1302 | for (i = 0; i>spalette->nentries; i++) |
984 | { |
1303 | { |
Line 999... | Line 1318... | ||
999 | png_save_uint_16(entrybuf + 6, ep[i].alpha); |
1318 | png_save_uint_16(entrybuf + 6, ep[i].alpha); |
1000 | png_save_uint_16(entrybuf + 8, ep[i].frequency); |
1319 | png_save_uint_16(entrybuf + 8, ep[i].frequency); |
1001 | } |
1320 | } |
1002 | 1321 | ||
Line 1003... | Line 1322... | ||
1003 | png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); |
1322 | png_write_chunk_data(png_ptr, entrybuf, entry_size); |
1004 | } |
1323 | } |
1005 | #endif |
1324 | #endif |
Line 1006... | Line 1325... | ||
1006 | 1325 | ||
1007 | png_write_chunk_end(png_ptr); |
- | |
1008 | png_free(png_ptr, new_name); |
1326 | png_write_chunk_end(png_ptr); |
1009 | } |
1327 | } |
Line 1010... | Line 1328... | ||
1010 | #endif |
1328 | #endif |
1011 | 1329 | ||
1012 | #ifdef PNG_WRITE_sBIT_SUPPORTED |
1330 | #ifdef PNG_WRITE_sBIT_SUPPORTED |
1013 | /* Write the sBIT chunk */ |
1331 | /* Write the sBIT chunk */ |
1014 | void /* PRIVATE */ |
1332 | void /* PRIVATE */ |
1015 | png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type) |
- | |
1016 | { |
1333 | png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) |
1017 | PNG_sBIT; |
1334 | { |
Line 1018... | Line 1335... | ||
1018 | png_byte buf[4]; |
1335 | png_byte buf[4]; |
Line 1064... | Line 1381... | ||
1064 | 1381 | ||
Line 1065... | Line 1382... | ||
1065 | buf[size++] = sbit->alpha; |
1382 | buf[size++] = sbit->alpha; |
1066 | } |
1383 | } |
Line 1067... | Line 1384... | ||
1067 | 1384 | ||
1068 | png_write_chunk(png_ptr, png_sBIT, buf, size); |
1385 | png_write_complete_chunk(png_ptr, png_sBIT, buf, size); |
1069 | } |
1386 | } |
Line 1070... | Line 1387... | ||
1070 | #endif |
1387 | #endif |
1071 | 1388 | ||
1072 | #ifdef PNG_WRITE_cHRM_SUPPORTED |
1389 | #ifdef PNG_WRITE_cHRM_SUPPORTED |
1073 | /* Write the cHRM chunk */ |
1390 | /* Write the cHRM chunk */ |
1074 | void /* PRIVATE */ |
- | |
1075 | png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, |
- | |
1076 | png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, |
- | |
1077 | png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, |
1391 | void /* PRIVATE */ |
1078 | png_fixed_point blue_y) |
- | |
1079 | { |
1392 | png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) |
Line 1080... | Line 1393... | ||
1080 | PNG_cHRM; |
1393 | { |
Line 1081... | Line 1394... | ||
1081 | png_byte buf[32]; |
1394 | png_byte buf[32]; |
1082 | - | ||
1083 | png_debug(1, "in png_write_cHRM"); |
- | |
1084 | - | ||
1085 | /* Each value is saved in 1/100,000ths */ |
- | |
1086 | #ifdef PNG_CHECK_cHRM_SUPPORTED |
- | |
1087 | if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, |
1395 | |
1088 | green_x, green_y, blue_x, blue_y)) |
1396 | png_debug(1, "in png_write_cHRM"); |
Line 1089... | Line 1397... | ||
1089 | #endif |
1397 | |
1090 | { |
1398 | /* Each value is saved in 1/100,000ths */ |
Line 1091... | Line 1399... | ||
1091 | png_save_uint_32(buf, (png_uint_32)white_x); |
1399 | png_save_int_32(buf, xy->whitex); |
1092 | png_save_uint_32(buf + 4, (png_uint_32)white_y); |
1400 | png_save_int_32(buf + 4, xy->whitey); |
Line 1093... | Line 1401... | ||
1093 | 1401 | ||
1094 | png_save_uint_32(buf + 8, (png_uint_32)red_x); |
1402 | png_save_int_32(buf + 8, xy->redx); |
Line 1095... | Line 1403... | ||
1095 | png_save_uint_32(buf + 12, (png_uint_32)red_y); |
1403 | png_save_int_32(buf + 12, xy->redy); |
1096 | - | ||
1097 | png_save_uint_32(buf + 16, (png_uint_32)green_x); |
1404 | |
1098 | png_save_uint_32(buf + 20, (png_uint_32)green_y); |
1405 | png_save_int_32(buf + 16, xy->greenx); |
Line 1099... | Line 1406... | ||
1099 | 1406 | png_save_int_32(buf + 20, xy->greeny); |
|
1100 | png_save_uint_32(buf + 24, (png_uint_32)blue_x); |
1407 | |
1101 | png_save_uint_32(buf + 28, (png_uint_32)blue_y); |
1408 | png_save_int_32(buf + 24, xy->bluex); |
1102 | 1409 | png_save_int_32(buf + 28, xy->bluey); |
|
1103 | png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); |
1410 | |
1104 | } |
1411 | png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); |
1105 | } |
- | |
1106 | #endif |
1412 | } |
Line 1107... | Line 1413... | ||
1107 | 1413 | #endif |
|
Line 1108... | Line 1414... | ||
1108 | #ifdef PNG_WRITE_tRNS_SUPPORTED |
1414 | |
1109 | /* Write the tRNS chunk */ |
1415 | #ifdef PNG_WRITE_tRNS_SUPPORTED |
1110 | void /* PRIVATE */ |
1416 | /* Write the tRNS chunk */ |
1111 | png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, |
1417 | void /* PRIVATE */ |
- | 1418 | png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, |
|
1112 | png_const_color_16p tran, int num_trans, int color_type) |
1419 | png_const_color_16p tran, int num_trans, int color_type) |
1113 | { |
1420 | { |
1114 | PNG_tRNS; |
1421 | png_byte buf[6]; |
Line 1115... | Line 1422... | ||
1115 | png_byte buf[6]; |
1422 | |
1116 | 1423 | png_debug(1, "in png_write_tRNS"); |
|
- | 1424 | ||
1117 | png_debug(1, "in png_write_tRNS"); |
1425 | if (color_type == PNG_COLOR_TYPE_PALETTE) |
Line 1118... | Line 1426... | ||
1118 | 1426 | { |
|
1119 | if (color_type == PNG_COLOR_TYPE_PALETTE) |
1427 | if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) |
1120 | { |
1428 | { |
1121 | if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) |
1429 | png_app_warning(png_ptr, |
1122 | { |
1430 | "Invalid number of transparent colors specified"); |
1123 | png_warning(png_ptr, "Invalid number of transparent colors specified"); |
1431 | return; |
1124 | return; |
1432 | } |
Line 1125... | Line 1433... | ||
1125 | } |
1433 | |
1126 | 1434 | /* Write the chunk out as it is */ |
|
Line 1127... | Line 1435... | ||
1127 | /* Write the chunk out as it is */ |
1435 | png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, |
1128 | png_write_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans); |
1436 | (png_size_t)num_trans); |
1129 | } |
1437 | } |
Line 1130... | Line 1438... | ||
1130 | 1438 | ||
1131 | else if (color_type == PNG_COLOR_TYPE_GRAY) |
1439 | else if (color_type == PNG_COLOR_TYPE_GRAY) |
1132 | { |
1440 | { |
Line 1154... | Line 1462... | ||
1154 | #else |
1462 | #else |
1155 | if (buf[0] | buf[2] | buf[4]) |
1463 | if (buf[0] | buf[2] | buf[4]) |
1156 | #endif |
1464 | #endif |
1157 | { |
1465 | { |
1158 | png_warning(png_ptr, |
1466 | png_app_warning(png_ptr, |
1159 | "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); |
1467 | "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); |
1160 | return; |
1468 | return; |
1161 | } |
1469 | } |
1162 | 1470 | ||
Line 1163... | Line 1471... | ||
1163 | png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); |
1471 | png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); |
1164 | } |
1472 | } |
Line 1165... | Line 1473... | ||
1165 | 1473 | ||
1166 | else |
1474 | else |
1167 | { |
1475 | { |
1168 | png_warning(png_ptr, "Can't write tRNS with an alpha channel"); |
1476 | png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); |
1169 | } |
1477 | } |
1170 | } |
1478 | } |
Line 1171... | Line 1479... | ||
1171 | #endif |
1479 | #endif |
1172 | 1480 | ||
1173 | #ifdef PNG_WRITE_bKGD_SUPPORTED |
1481 | #ifdef PNG_WRITE_bKGD_SUPPORTED |
1174 | /* Write the background chunk */ |
1482 | /* Write the background chunk */ |
1175 | void /* PRIVATE */ |
1483 | void /* PRIVATE */ |
1176 | png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type) |
- | |
1177 | { |
1484 | png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) |
Line 1178... | Line 1485... | ||
1178 | PNG_bKGD; |
1485 | { |
Line 1179... | Line 1486... | ||
1179 | png_byte buf[6]; |
1486 | png_byte buf[6]; |
Line 1193... | Line 1500... | ||
1193 | return; |
1500 | return; |
1194 | } |
1501 | } |
1195 | 1502 | ||
Line 1196... | Line 1503... | ||
1196 | buf[0] = back->index; |
1503 | buf[0] = back->index; |
1197 | png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); |
1504 | png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); |
1198 | } |
1505 | } |
Line 1199... | Line 1506... | ||
1199 | 1506 | ||
1200 | else if (color_type & PNG_COLOR_MASK_COLOR) |
1507 | else if (color_type & PNG_COLOR_MASK_COLOR) |
1201 | { |
1508 | { |
Line 1213... | Line 1520... | ||
1213 | 1520 | ||
Line 1214... | Line 1521... | ||
1214 | return; |
1521 | return; |
1215 | } |
1522 | } |
Line 1216... | Line 1523... | ||
1216 | 1523 | ||
1217 | png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); |
1524 | png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); |
Line 1218... | Line 1525... | ||
1218 | } |
1525 | } |
1219 | 1526 | ||
1220 | else |
1527 | else |
Line 1227... | Line 1534... | ||
1227 | return; |
1534 | return; |
1228 | } |
1535 | } |
Line 1229... | Line 1536... | ||
1229 | 1536 | ||
1230 | png_save_uint_16(buf, back->gray); |
1537 | png_save_uint_16(buf, back->gray); |
1231 | png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); |
1538 | png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); |
1232 | } |
1539 | } |
1233 | } |
1540 | } |
Line 1234... | Line 1541... | ||
1234 | #endif |
1541 | #endif |
1235 | 1542 | ||
1236 | #ifdef PNG_WRITE_hIST_SUPPORTED |
1543 | #ifdef PNG_WRITE_hIST_SUPPORTED |
1237 | /* Write the histogram */ |
1544 | /* Write the histogram */ |
1238 | void /* PRIVATE */ |
1545 | void /* PRIVATE */ |
1239 | png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist) |
- | |
1240 | { |
1546 | png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) |
1241 | PNG_hIST; |
1547 | { |
Line 1242... | Line 1548... | ||
1242 | int i; |
1548 | int i; |
Line 1252... | Line 1558... | ||
1252 | png_warning(png_ptr, "Invalid number of histogram entries specified"); |
1558 | png_warning(png_ptr, "Invalid number of histogram entries specified"); |
1253 | return; |
1559 | return; |
1254 | } |
1560 | } |
Line 1255... | Line 1561... | ||
1255 | 1561 | ||
Line 1256... | Line 1562... | ||
1256 | png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); |
1562 | png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); |
1257 | 1563 | ||
1258 | for (i = 0; i < num_hist; i++) |
1564 | for (i = 0; i < num_hist; i++) |
1259 | { |
1565 | { |
Line 1264... | Line 1570... | ||
1264 | png_write_chunk_end(png_ptr); |
1570 | png_write_chunk_end(png_ptr); |
1265 | } |
1571 | } |
1266 | #endif |
1572 | #endif |
Line 1267... | Line -... | ||
1267 | - | ||
1268 | #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ |
- | |
1269 | defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) |
- | |
1270 | /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, |
- | |
1271 | * and if invalid, correct the keyword rather than discarding the entire |
- | |
1272 | * chunk. The PNG 1.0 specification requires keywords 1-79 characters in |
- | |
1273 | * length, forbids leading or trailing whitespace, multiple internal spaces, |
- | |
1274 | * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. |
- | |
1275 | * |
- | |
1276 | * The new_key is allocated to hold the corrected keyword and must be freed |
- | |
1277 | * by the calling routine. This avoids problems with trying to write to |
- | |
1278 | * static keywords without having to have duplicate copies of the strings. |
- | |
1279 | */ |
- | |
1280 | png_size_t /* PRIVATE */ |
- | |
1281 | png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key) |
- | |
1282 | { |
- | |
1283 | png_size_t key_len; |
- | |
1284 | png_const_charp ikp; |
- | |
1285 | png_charp kp, dp; |
- | |
1286 | int kflag; |
- | |
1287 | int kwarn=0; |
- | |
1288 | - | ||
1289 | png_debug(1, "in png_check_keyword"); |
- | |
1290 | - | ||
1291 | *new_key = NULL; |
- | |
1292 | - | ||
1293 | if (key == NULL || (key_len = png_strlen(key)) == 0) |
- | |
1294 | { |
- | |
1295 | png_warning(png_ptr, "zero length keyword"); |
- | |
1296 | return ((png_size_t)0); |
- | |
1297 | } |
- | |
1298 | - | ||
1299 | png_debug1(2, "Keyword to be checked is '%s'", key); |
- | |
1300 | - | ||
1301 | *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); |
- | |
1302 | - | ||
1303 | if (*new_key == NULL) |
- | |
1304 | { |
- | |
1305 | png_warning(png_ptr, "Out of memory while procesing keyword"); |
- | |
1306 | return ((png_size_t)0); |
- | |
1307 | } |
- | |
1308 | - | ||
1309 | /* Replace non-printing characters with a blank and print a warning */ |
- | |
1310 | for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++) |
- | |
1311 | { |
- | |
1312 | if ((png_byte)*ikp < 0x20 || |
- | |
1313 | ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) |
- | |
1314 | { |
- | |
1315 | #ifdef PNG_CONSOLE_IO_SUPPORTED |
- | |
1316 | char msg[40]; |
- | |
1317 | - | ||
1318 | png_snprintf(msg, 40, |
- | |
1319 | "invalid keyword character 0x%02X", (png_byte)*ikp); |
- | |
1320 | png_warning(png_ptr, msg); |
- | |
1321 | #else |
- | |
1322 | png_warning(png_ptr, "invalid character in keyword"); |
- | |
1323 | #endif |
- | |
1324 | *dp = ' '; |
- | |
1325 | } |
- | |
1326 | - | ||
1327 | else |
- | |
1328 | { |
- | |
1329 | *dp = *ikp; |
- | |
1330 | } |
- | |
1331 | } |
- | |
1332 | *dp = '\0'; |
- | |
1333 | - | ||
1334 | /* Remove any trailing white space. */ |
- | |
1335 | kp = *new_key + key_len - 1; |
- | |
1336 | if (*kp == ' ') |
- | |
1337 | { |
- | |
1338 | png_warning(png_ptr, "trailing spaces removed from keyword"); |
- | |
1339 | - | ||
1340 | while (*kp == ' ') |
- | |
1341 | { |
- | |
1342 | *(kp--) = '\0'; |
- | |
1343 | key_len--; |
- | |
1344 | } |
- | |
1345 | } |
- | |
1346 | - | ||
1347 | /* Remove any leading white space. */ |
- | |
1348 | kp = *new_key; |
- | |
1349 | if (*kp == ' ') |
- | |
1350 | { |
- | |
1351 | png_warning(png_ptr, "leading spaces removed from keyword"); |
- | |
1352 | - | ||
1353 | while (*kp == ' ') |
- | |
1354 | { |
- | |
1355 | kp++; |
- | |
1356 | key_len--; |
- | |
1357 | } |
- | |
1358 | } |
- | |
1359 | - | ||
1360 | png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); |
- | |
1361 | - | ||
1362 | /* Remove multiple internal spaces. */ |
- | |
1363 | for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) |
- | |
1364 | { |
- | |
1365 | if (*kp == ' ' && kflag == 0) |
- | |
1366 | { |
- | |
1367 | *(dp++) = *kp; |
- | |
1368 | kflag = 1; |
- | |
1369 | } |
- | |
1370 | - | ||
1371 | else if (*kp == ' ') |
- | |
1372 | { |
- | |
1373 | key_len--; |
- | |
1374 | kwarn = 1; |
- | |
1375 | } |
- | |
1376 | - | ||
1377 | else |
- | |
1378 | { |
- | |
1379 | *(dp++) = *kp; |
- | |
1380 | kflag = 0; |
- | |
1381 | } |
- | |
1382 | } |
- | |
1383 | *dp = '\0'; |
- | |
1384 | if (kwarn) |
- | |
1385 | png_warning(png_ptr, "extra interior spaces removed from keyword"); |
- | |
1386 | - | ||
1387 | if (key_len == 0) |
- | |
1388 | { |
- | |
1389 | png_free(png_ptr, *new_key); |
- | |
1390 | png_warning(png_ptr, "Zero length keyword"); |
- | |
1391 | } |
- | |
1392 | - | ||
1393 | if (key_len > 79) |
- | |
1394 | { |
- | |
1395 | png_warning(png_ptr, "keyword length must be 1 - 79 characters"); |
- | |
1396 | (*new_key)[79] = '\0'; |
- | |
1397 | key_len = 79; |
- | |
1398 | } |
- | |
1399 | - | ||
1400 | return (key_len); |
- | |
1401 | } |
- | |
1402 | #endif |
- | |
1403 | 1573 | ||
1404 | #ifdef PNG_WRITE_tEXt_SUPPORTED |
1574 | #ifdef PNG_WRITE_tEXt_SUPPORTED |
1405 | /* Write a tEXt chunk */ |
1575 | /* Write a tEXt chunk */ |
1406 | void /* PRIVATE */ |
1576 | void /* PRIVATE */ |
1407 | png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text, |
1577 | png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, |
1408 | png_size_t text_len) |
1578 | png_size_t text_len) |
1409 | { |
- | |
1410 | PNG_tEXt; |
1579 | { |
1411 | png_size_t key_len; |
1580 | png_uint_32 key_len; |
Line 1412... | Line 1581... | ||
1412 | png_charp new_key; |
1581 | png_byte new_key[80]; |
Line 1413... | Line 1582... | ||
1413 | 1582 | ||
- | 1583 | png_debug(1, "in png_write_tEXt"); |
|
1414 | png_debug(1, "in png_write_tEXt"); |
1584 | |
- | 1585 | key_len = png_check_keyword(png_ptr, key, new_key); |
|
Line 1415... | Line 1586... | ||
1415 | 1586 | ||
1416 | if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) |
1587 | if (key_len == 0) |
Line 1417... | Line 1588... | ||
1417 | return; |
1588 | png_error(png_ptr, "tEXt: invalid keyword"); |
1418 | 1589 | ||
- | 1590 | if (text == NULL || *text == '\0') |
|
- | 1591 | text_len = 0; |
|
- | 1592 | ||
Line 1419... | Line 1593... | ||
1419 | if (text == NULL || *text == '\0') |
1593 | else |
1420 | text_len = 0; |
1594 | text_len = strlen(text); |
1421 | 1595 | ||
1422 | else |
1596 | if (text_len > PNG_UINT_31_MAX - (key_len+1)) |
1423 | text_len = png_strlen(text); |
1597 | png_error(png_ptr, "tEXt: text too long"); |
1424 | 1598 | ||
1425 | /* Make sure we include the 0 after the key */ |
1599 | /* Make sure we include the 0 after the key */ |
1426 | png_write_chunk_start(png_ptr, png_tEXt, |
1600 | png_write_chunk_header(png_ptr, png_tEXt, |
1427 | (png_uint_32)(key_len + text_len + 1)); |
1601 | (png_uint_32)/*checked above*/(key_len + text_len + 1)); |
1428 | /* |
1602 | /* |
1429 | * We leave it to the application to meet PNG-1.0 requirements on the |
- | |
Line 1430... | Line 1603... | ||
1430 | * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of |
1603 | * We leave it to the application to meet PNG-1.0 requirements on the |
1431 | * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. |
1604 | * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of |
1432 | * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. |
- | |
Line 1433... | Line 1605... | ||
1433 | */ |
1605 | * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. |
1434 | png_write_chunk_data(png_ptr, (png_bytep)new_key, |
- | |
1435 | (png_size_t)(key_len + 1)); |
1606 | * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. |
1436 | 1607 | */ |
|
Line 1437... | Line 1608... | ||
1437 | if (text_len) |
1608 | png_write_chunk_data(png_ptr, new_key, key_len + 1); |
1438 | png_write_chunk_data(png_ptr, (png_const_bytep)text, |
1609 | |
1439 | (png_size_t)text_len); |
1610 | if (text_len) |
1440 | 1611 | png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); |
|
1441 | png_write_chunk_end(png_ptr); |
1612 | |
1442 | png_free(png_ptr, new_key); |
1613 | png_write_chunk_end(png_ptr); |
1443 | } |
- | |
1444 | #endif |
1614 | } |
1445 | - | ||
1446 | #ifdef PNG_WRITE_zTXt_SUPPORTED |
1615 | #endif |
1447 | /* Write a compressed text chunk */ |
1616 | |
Line 1448... | Line 1617... | ||
1448 | void /* PRIVATE */ |
1617 | #ifdef PNG_WRITE_zTXt_SUPPORTED |
- | 1618 | /* Write a compressed text chunk */ |
|
Line 1449... | Line -... | ||
1449 | png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text, |
- | |
1450 | png_size_t text_len, int compression) |
- | |
1451 | { |
- | |
1452 | PNG_zTXt; |
- | |
1453 | png_size_t key_len; |
- | |
1454 | png_byte buf; |
- | |
1455 | png_charp new_key; |
1619 | void /* PRIVATE */ |
1456 | compression_state comp; |
1620 | png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, |
1457 | 1621 | png_size_t text_len, int compression) |
|
1458 | png_debug(1, "in png_write_zTXt"); |
1622 | { |
1459 | 1623 | png_uint_32 key_len; |
|
Line 1460... | Line 1624... | ||
1460 | comp.num_output_ptr = 0; |
1624 | png_byte new_key[81]; |
1461 | comp.max_output_ptr = 0; |
- | |
1462 | comp.output_ptr = NULL; |
1625 | compression_state comp; |
1463 | comp.input = NULL; |
- | |
1464 | comp.input_len = 0; |
- | |
1465 | - | ||
Line 1466... | Line 1626... | ||
1466 | if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) |
1626 | |
Line 1467... | Line 1627... | ||
1467 | { |
1627 | png_debug(1, "in png_write_zTXt"); |
1468 | png_free(png_ptr, new_key); |
1628 | PNG_UNUSED(text_len) /* Always use strlen */ |
1469 | return; |
- | |
Line 1470... | Line 1629... | ||
1470 | } |
1629 | |
1471 | 1630 | if (compression == PNG_TEXT_COMPRESSION_NONE) |
|
1472 | if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) |
1631 | { |
Line 1473... | Line 1632... | ||
1473 | { |
1632 | png_write_tEXt(png_ptr, key, text, 0); |
1474 | png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); |
1633 | return; |
1475 | png_free(png_ptr, new_key); |
1634 | } |
Line -... | Line 1635... | ||
- | 1635 | ||
1476 | return; |
1636 | if (compression != PNG_TEXT_COMPRESSION_zTXt) |
Line 1477... | Line 1637... | ||
1477 | } |
1637 | png_error(png_ptr, "zTXt: invalid compression type"); |
- | 1638 | ||
Line 1478... | Line 1639... | ||
1478 | 1639 | key_len = png_check_keyword(png_ptr, key, new_key); |
|
1479 | text_len = png_strlen(text); |
1640 | |
Line 1480... | Line 1641... | ||
1480 | 1641 | if (key_len == 0) |
|
1481 | /* Compute the compressed data; do it now for the length */ |
1642 | png_error(png_ptr, "zTXt: invalid keyword"); |
Line 1482... | Line 1643... | ||
1482 | text_len = png_text_compress(png_ptr, text, text_len, compression, |
1643 | |
Line 1507... | Line 1668... | ||
1507 | 1668 | ||
Line 1508... | Line 1669... | ||
1508 | #ifdef PNG_WRITE_iTXt_SUPPORTED |
1669 | #ifdef PNG_WRITE_iTXt_SUPPORTED |
1509 | /* Write an iTXt chunk */ |
1670 | /* Write an iTXt chunk */ |
1510 | void /* PRIVATE */ |
1671 | void /* PRIVATE */ |
1511 | png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, |
1672 | png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, |
1512 | png_const_charp lang, png_const_charp lang_key, png_const_charp text) |
1673 | png_const_charp lang, png_const_charp lang_key, png_const_charp text) |
1513 | { |
1674 | { |
1514 | PNG_iTXt; |
- | |
1515 | png_size_t lang_len, key_len, lang_key_len, text_len; |
1675 | png_uint_32 key_len, prefix_len; |
1516 | png_charp new_lang; |
1676 | png_size_t lang_len, lang_key_len; |
1517 | png_charp new_key = NULL; |
- | |
1518 | png_byte cbuf[2]; |
1677 | png_byte new_key[82]; |
1519 | compression_state comp; |
1678 | compression_state comp; |
Line 1520... | Line 1679... | ||
1520 | 1679 | ||
Line 1521... | Line -... | ||
1521 | png_debug(1, "in png_write_iTXt"); |
- | |
1522 | 1680 | png_debug(1, "in png_write_iTXt"); |
|
1523 | comp.num_output_ptr = 0; |
- | |
1524 | comp.max_output_ptr = 0; |
- | |
Line 1525... | Line 1681... | ||
1525 | comp.output_ptr = NULL; |
1681 | |
1526 | comp.input = NULL; |
1682 | key_len = png_check_keyword(png_ptr, key, new_key); |
Line 1527... | Line 1683... | ||
1527 | 1683 | ||
- | 1684 | if (key_len == 0) |
|
1528 | if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) |
1685 | png_error(png_ptr, "iTXt: invalid keyword"); |
1529 | return; |
- | |
1530 | - | ||
1531 | if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0) |
- | |
1532 | { |
- | |
1533 | png_warning(png_ptr, "Empty language field in iTXt chunk"); |
- | |
1534 | new_lang = NULL; |
- | |
1535 | lang_len = 0; |
- | |
1536 | } |
- | |
1537 | - | ||
1538 | if (lang_key == NULL) |
1686 | |
1539 | lang_key_len = 0; |
- | |
1540 | - | ||
1541 | else |
- | |
1542 | lang_key_len = png_strlen(lang_key); |
- | |
1543 | - | ||
1544 | if (text == NULL) |
1687 | /* Set the compression flag */ |
1545 | text_len = 0; |
- | |
1546 | - | ||
1547 | else |
1688 | switch (compression) |
1548 | text_len = png_strlen(text); |
1689 | { |
Line -... | Line 1690... | ||
- | 1690 | case PNG_ITXT_COMPRESSION_NONE: |
|
- | 1691 | case PNG_TEXT_COMPRESSION_NONE: |
|
- | 1692 | compression = new_key[++key_len] = 0; /* no compression */ |
|
- | 1693 | break; |
|
Line 1549... | Line 1694... | ||
1549 | 1694 | ||
1550 | /* Compute the compressed data; do it now for the length */ |
1695 | case PNG_TEXT_COMPRESSION_zTXt: |
1551 | text_len = png_text_compress(png_ptr, text, text_len, compression - 2, |
1696 | case PNG_ITXT_COMPRESSION_zTXt: |
Line 1552... | Line 1697... | ||
1552 | &comp); |
1697 | compression = new_key[++key_len] = 1; /* compressed */ |
1553 | 1698 | break; |
|
1554 | - | ||
1555 | /* Make sure we include the compression flag, the compression byte, |
- | |
1556 | * and the NULs after the key, lang, and lang_key parts |
- | |
1557 | */ |
- | |
Line 1558... | Line 1699... | ||
1558 | 1699 | ||
1559 | png_write_chunk_start(png_ptr, png_iTXt, (png_uint_32)( |
1700 | default: |
1560 | 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ |
1701 | png_error(png_ptr, "iTXt: invalid compression"); |
- | 1702 | } |
|
- | 1703 | ||
- | 1704 | new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; |
|
1561 | + key_len |
1705 | ++key_len; /* for the keywod separator */ |
- | 1706 | ||
- | 1707 | /* We leave it to the application to meet PNG-1.0 requirements on the |
|
1562 | + lang_len |
1708 | * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of |
- | 1709 | * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, |
|
- | 1710 | * specifies that the text is UTF-8 and this really doesn't require any |
|
1563 | + lang_key_len |
1711 | * checking. |
- | 1712 | * |
|
- | 1713 | * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. |
|
Line 1564... | Line 1714... | ||
1564 | + text_len)); |
1714 | * |
1565 | 1715 | * TODO: validate the language tag correctly (see the spec.) |
|
- | 1716 | */ |
|
- | 1717 | if (lang == NULL) lang = ""; /* empty language is valid */ |
|
- | 1718 | lang_len = strlen(lang)+1; |
|
- | 1719 | if (lang_key == NULL) lang_key = ""; /* may be empty */ |
|
1566 | /* We leave it to the application to meet PNG-1.0 requirements on the |
1720 | lang_key_len = strlen(lang_key)+1; |
1567 | * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of |
1721 | if (text == NULL) text = ""; /* may be empty */ |
- | 1722 | ||
- | 1723 | prefix_len = key_len; |
|
- | 1724 | if (lang_len > PNG_UINT_31_MAX-prefix_len) |
|
- | 1725 | prefix_len = PNG_UINT_31_MAX; |
|
Line -... | Line 1726... | ||
- | 1726 | else |
|
- | 1727 | prefix_len = (png_uint_32)(prefix_len + lang_len); |
|
1568 | * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. |
1728 | |
- | 1729 | if (lang_key_len > PNG_UINT_31_MAX-prefix_len) |
|
1569 | * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. |
1730 | prefix_len = PNG_UINT_31_MAX; |
Line 1570... | Line 1731... | ||
1570 | */ |
1731 | else |
1571 | png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1)); |
1732 | prefix_len = (png_uint_32)(prefix_len + lang_key_len); |
- | 1733 | ||
- | 1734 | png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); |
|
Line -... | Line 1735... | ||
- | 1735 | ||
- | 1736 | if (compression) |
|
- | 1737 | { |
|
- | 1738 | if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) |
|
1572 | 1739 | png_error(png_ptr, png_ptr->zstream.msg); |
|
Line 1573... | Line -... | ||
1573 | /* Set the compression flag */ |
- | |
1574 | if (compression == PNG_ITXT_COMPRESSION_NONE || |
1740 | } |
1575 | compression == PNG_TEXT_COMPRESSION_NONE) |
- | |
Line 1576... | Line 1741... | ||
1576 | cbuf[0] = 0; |
1741 | |
1577 | - | ||
Line -... | Line 1742... | ||
- | 1742 | else |
|
- | 1743 | { |
|
- | 1744 | if (comp.input_len > PNG_UINT_31_MAX-prefix_len) |
|
1578 | else /* compression == PNG_ITXT_COMPRESSION_zTXt */ |
1745 | png_error(png_ptr, "iTXt: uncompressed text too long"); |
Line -... | Line 1746... | ||
- | 1746 | ||
1579 | cbuf[0] = 1; |
1747 | /* So the string will fit in a chunk: */ |
Line 1580... | Line 1748... | ||
1580 | 1748 | comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; |
|
1581 | /* Set the compression method */ |
- | |
1582 | cbuf[1] = 0; |
1749 | } |
1583 | 1750 | ||
Line 1584... | Line 1751... | ||
1584 | png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); |
1751 | png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); |
1585 | 1752 | ||
1586 | cbuf[0] = 0; |
1753 | png_write_chunk_data(png_ptr, new_key, key_len); |
1587 | png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf), |
1754 | |
1588 | (png_size_t)(lang_len + 1)); |
1755 | png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); |
1589 | 1756 | ||
1590 | png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf), |
- | |
1591 | (png_size_t)(lang_key_len + 1)); |
1757 | png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); |
Line 1592... | Line 1758... | ||
1592 | 1758 | ||
Line 1593... | Line 1759... | ||
1593 | png_write_compressed_data_out(png_ptr, &comp); |
1759 | if (compression) |
Line 1616... | Line 1782... | ||
1616 | png_save_int_32(buf, x_offset); |
1782 | png_save_int_32(buf, x_offset); |
1617 | png_save_int_32(buf + 4, y_offset); |
1783 | png_save_int_32(buf + 4, y_offset); |
1618 | buf[8] = (png_byte)unit_type; |
1784 | buf[8] = (png_byte)unit_type; |
Line 1619... | Line 1785... | ||
1619 | 1785 | ||
1620 | png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); |
1786 | png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); |
1621 | } |
1787 | } |
1622 | #endif |
1788 | #endif |
1623 | #ifdef PNG_WRITE_pCAL_SUPPORTED |
1789 | #ifdef PNG_WRITE_pCAL_SUPPORTED |
1624 | /* Write the pCAL chunk (described in the PNG extensions document) */ |
1790 | /* Write the pCAL chunk (described in the PNG extensions document) */ |
1625 | void /* PRIVATE */ |
1791 | void /* PRIVATE */ |
1626 | png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, |
1792 | png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, |
1627 | png_int_32 X1, int type, int nparams, png_const_charp units, |
1793 | png_int_32 X1, int type, int nparams, png_const_charp units, |
1628 | png_charpp params) |
1794 | png_charpp params) |
1629 | { |
1795 | { |
1630 | PNG_pCAL; |
1796 | png_uint_32 purpose_len; |
1631 | png_size_t purpose_len, units_len, total_len; |
1797 | png_size_t units_len, total_len; |
1632 | png_uint_32p params_len; |
1798 | png_size_tp params_len; |
1633 | png_byte buf[10]; |
1799 | png_byte buf[10]; |
1634 | png_charp new_purpose; |
1800 | png_byte new_purpose[80]; |
Line 1635... | Line 1801... | ||
1635 | int i; |
1801 | int i; |
Line 1636... | Line 1802... | ||
1636 | 1802 | ||
1637 | png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); |
1803 | png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); |
- | 1804 | ||
- | 1805 | if (type >= PNG_EQUATION_LAST) |
|
- | 1806 | png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); |
|
- | 1807 | ||
- | 1808 | purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); |
|
- | 1809 | ||
- | 1810 | if (purpose_len == 0) |
|
Line 1638... | Line -... | ||
1638 | - | ||
1639 | if (type >= PNG_EQUATION_LAST) |
1811 | png_error(png_ptr, "pCAL: invalid keyword"); |
1640 | png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); |
1812 | |
1641 | 1813 | ++purpose_len; /* terminator */ |
|
1642 | purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; |
1814 | |
Line 1643... | Line 1815... | ||
1643 | png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); |
1815 | png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); |
1644 | units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); |
1816 | units_len = strlen(units) + (nparams == 0 ? 0 : 1); |
Line 1645... | Line 1817... | ||
1645 | png_debug1(3, "pCAL units length = %d", (int)units_len); |
1817 | png_debug1(3, "pCAL units length = %d", (int)units_len); |
1646 | total_len = purpose_len + units_len + 10; |
1818 | total_len = purpose_len + units_len + 10; |
1647 | 1819 | ||
1648 | params_len = (png_uint_32p)png_malloc(png_ptr, |
1820 | params_len = (png_size_tp)png_malloc(png_ptr, |
1649 | (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); |
1821 | (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); |
1650 | 1822 | ||
1651 | /* Find the length of each parameter, making sure we don't count the |
1823 | /* Find the length of each parameter, making sure we don't count the |
1652 | * null terminator for the last parameter. |
1824 | * null terminator for the last parameter. |
1653 | */ |
1825 | */ |
1654 | for (i = 0; i < nparams; i++) |
1826 | for (i = 0; i < nparams; i++) |
Line 1655... | Line 1827... | ||
1655 | { |
1827 | { |
1656 | params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); |
1828 | params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); |
1657 | png_debug2(3, "pCAL parameter %d length = %lu", i, |
1829 | png_debug2(3, "pCAL parameter %d length = %lu", i, |
1658 | (unsigned long)params_len[i]); |
- | |
1659 | total_len += (png_size_t)params_len[i]; |
1830 | (unsigned long)params_len[i]); |
1660 | } |
1831 | total_len += params_len[i]; |
1661 | 1832 | } |
|
1662 | png_debug1(3, "pCAL total length = %d", (int)total_len); |
1833 | |
1663 | png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); |
1834 | png_debug1(3, "pCAL total length = %d", (int)total_len); |
1664 | png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, |
1835 | png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); |
Line 1665... | Line -... | ||
1665 | (png_size_t)purpose_len); |
- | |
1666 | png_save_int_32(buf, X0); |
- | |
1667 | png_save_int_32(buf + 4, X1); |
1836 | png_write_chunk_data(png_ptr, new_purpose, purpose_len); |
1668 | buf[8] = (png_byte)type; |
1837 | png_save_int_32(buf, X0); |
1669 | buf[9] = (png_byte)nparams; |
1838 | png_save_int_32(buf + 4, X1); |
1670 | png_write_chunk_data(png_ptr, buf, (png_size_t)10); |
- | |
1671 | png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); |
1839 | buf[8] = (png_byte)type; |
Line 1672... | Line 1840... | ||
1672 | 1840 | buf[9] = (png_byte)nparams; |
|
1673 | png_free(png_ptr, new_purpose); |
1841 | png_write_chunk_data(png_ptr, buf, (png_size_t)10); |
1674 | 1842 | png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); |
|
1675 | for (i = 0; i < nparams; i++) |
1843 | |
Line 1676... | Line 1844... | ||
1676 | { |
1844 | for (i = 0; i < nparams; i++) |
1677 | png_write_chunk_data(png_ptr, (png_const_bytep)params[i], |
1845 | { |
1678 | (png_size_t)params_len[i]); |
1846 | png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); |
1679 | } |
1847 | } |
1680 | 1848 | ||
1681 | png_free(png_ptr, params_len); |
1849 | png_free(png_ptr, params_len); |
1682 | png_write_chunk_end(png_ptr); |
- | |
1683 | } |
1850 | png_write_chunk_end(png_ptr); |
1684 | #endif |
1851 | } |
Line 1685... | Line 1852... | ||
1685 | 1852 | #endif |
|
Line 1686... | Line 1853... | ||
1686 | #ifdef PNG_WRITE_sCAL_SUPPORTED |
1853 | |
1687 | /* Write the sCAL chunk */ |
1854 | #ifdef PNG_WRITE_sCAL_SUPPORTED |
1688 | void /* PRIVATE */ |
1855 | /* Write the sCAL chunk */ |
Line 1689... | Line 1856... | ||
1689 | png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width, |
1856 | void /* PRIVATE */ |
1690 | png_const_charp height) |
1857 | png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, |
1691 | { |
1858 | png_const_charp height) |
1692 | PNG_sCAL; |
1859 | { |
1693 | png_byte buf[64]; |
1860 | png_byte buf[64]; |
Line 1694... | Line 1861... | ||
1694 | png_size_t wlen, hlen, total_len; |
1861 | png_size_t wlen, hlen, total_len; |
1695 | 1862 | ||
1696 | png_debug(1, "in png_write_sCAL_s"); |
1863 | png_debug(1, "in png_write_sCAL_s"); |
Line 1697... | Line 1864... | ||
1697 | 1864 | ||
1698 | wlen = png_strlen(width); |
1865 | wlen = strlen(width); |
1699 | hlen = png_strlen(height); |
1866 | hlen = strlen(height); |
1700 | total_len = wlen + hlen + 2; |
1867 | total_len = wlen + hlen + 2; |
Line 1701... | Line 1868... | ||
1701 | 1868 | ||
1702 | if (total_len > 64) |
1869 | if (total_len > 64) |
1703 | { |
1870 | { |
1704 | png_warning(png_ptr, "Can't write sCAL (buffer too small)"); |
1871 | png_warning(png_ptr, "Can't write sCAL (buffer too small)"); |
1705 | return; |
1872 | return; |
1706 | } |
1873 | } |
1707 | 1874 | ||
1708 | buf[0] = (png_byte)unit; |
- | |
1709 | png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ |
1875 | buf[0] = (png_byte)unit; |
Line 1710... | Line 1876... | ||
1710 | png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ |
1876 | memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ |
Line 1711... | Line 1877... | ||
1711 | 1877 | memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ |
|
Line 1732... | Line 1898... | ||
1732 | png_save_uint_32(buf, x_pixels_per_unit); |
1898 | png_save_uint_32(buf, x_pixels_per_unit); |
1733 | png_save_uint_32(buf + 4, y_pixels_per_unit); |
1899 | png_save_uint_32(buf + 4, y_pixels_per_unit); |
1734 | buf[8] = (png_byte)unit_type; |
1900 | buf[8] = (png_byte)unit_type; |
Line 1735... | Line 1901... | ||
1735 | 1901 | ||
1736 | png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); |
1902 | png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); |
1737 | } |
1903 | } |
Line 1738... | Line 1904... | ||
1738 | #endif |
1904 | #endif |
1739 | 1905 | ||
1740 | #ifdef PNG_WRITE_tIME_SUPPORTED |
1906 | #ifdef PNG_WRITE_tIME_SUPPORTED |
1741 | /* Write the tIME chunk. Use either png_convert_from_struct_tm() |
1907 | /* Write the tIME chunk. Use either png_convert_from_struct_tm() |
1742 | * or png_convert_from_time_t(), or fill in the structure yourself. |
1908 | * or png_convert_from_time_t(), or fill in the structure yourself. |
1743 | */ |
1909 | */ |
1744 | void /* PRIVATE */ |
1910 | void /* PRIVATE */ |
1745 | png_write_tIME(png_structp png_ptr, png_const_timep mod_time) |
- | |
1746 | { |
1911 | png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) |
Line 1747... | Line 1912... | ||
1747 | PNG_tIME; |
1912 | { |
Line 1748... | Line 1913... | ||
1748 | png_byte buf[7]; |
1913 | png_byte buf[7]; |
Line 1763... | Line 1928... | ||
1763 | buf[4] = mod_time->hour; |
1928 | buf[4] = mod_time->hour; |
1764 | buf[5] = mod_time->minute; |
1929 | buf[5] = mod_time->minute; |
1765 | buf[6] = mod_time->second; |
1930 | buf[6] = mod_time->second; |
1766 | 1931 | ||
Line 1767... | Line 1932... | ||
1767 | png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); |
1932 | png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); |
1768 | } |
1933 | } |
1769 | #endif |
1934 | #endif |
Line 1770... | Line 1935... | ||
1770 | 1935 | ||
1771 | /* Initializes the row writing capability of libpng */ |
1936 | /* Initializes the row writing capability of libpng */ |
1772 | void /* PRIVATE */ |
1937 | void /* PRIVATE */ |
1773 | png_write_start_row(png_structp png_ptr) |
1938 | png_write_start_row(png_structrp png_ptr) |
1774 | { |
1939 | { |
1775 | #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1940 | #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
Line 1776... | Line 1941... | ||
1776 | /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1941 | /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1777 | 1942 | ||
Line 1778... | Line 1943... | ||
1778 | /* Start of interlace block */ |
1943 | /* Start of interlace block */ |
1779 | int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1944 | static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
Line 1780... | Line 1945... | ||
1780 | 1945 | ||
1781 | /* Offset to next interlace block */ |
1946 | /* Offset to next interlace block */ |
Line 1782... | Line 1947... | ||
1782 | int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1947 | static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1783 | 1948 | ||
1784 | /* Start of interlace block in the y direction */ |
1949 | /* Start of interlace block in the y direction */ |
Line 1785... | Line 1950... | ||
1785 | int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
1950 | static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
- | 1951 | ||
Line 1786... | Line 1952... | ||
1786 | 1952 | /* Offset to next interlace block in the y direction */ |
|
Line -... | Line 1953... | ||
- | 1953 | static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
|
1787 | /* Offset to next interlace block in the y direction */ |
1954 | #endif |
- | 1955 | ||
- | 1956 | png_alloc_size_t buf_size; |
|
1788 | int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
1957 | int usr_pixel_depth; |
- | 1958 | ||
Line 1789... | Line 1959... | ||
1789 | #endif |
1959 | png_debug(1, "in png_write_start_row"); |
1790 | 1960 | ||
1791 | png_size_t buf_size; |
- | |
Line 1792... | Line 1961... | ||
1792 | 1961 | usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; |
|
Line 1793... | Line 1962... | ||
1793 | png_debug(1, "in png_write_start_row"); |
1962 | buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; |
1794 | 1963 | ||
Line 1813... | Line 1982... | ||
1813 | /* We only need to keep the previous row if we are using one of these. */ |
1982 | /* We only need to keep the previous row if we are using one of these. */ |
1814 | if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) |
1983 | if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) |
1815 | { |
1984 | { |
1816 | /* Set up previous row buffer */ |
1985 | /* Set up previous row buffer */ |
1817 | png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, |
1986 | png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size); |
1818 | (png_alloc_size_t)buf_size); |
- | |
Line 1819... | Line 1987... | ||
1819 | 1987 | ||
1820 | if (png_ptr->do_filter & PNG_FILTER_UP) |
1988 | if (png_ptr->do_filter & PNG_FILTER_UP) |
1821 | { |
1989 | { |
1822 | png_ptr->up_row = (png_bytep)png_malloc(png_ptr, |
1990 | png_ptr->up_row = (png_bytep)png_malloc(png_ptr, |
Line 1868... | Line 2036... | ||
1868 | { |
2036 | { |
1869 | png_ptr->num_rows = png_ptr->height; |
2037 | png_ptr->num_rows = png_ptr->height; |
1870 | png_ptr->usr_width = png_ptr->width; |
2038 | png_ptr->usr_width = png_ptr->width; |
1871 | } |
2039 | } |
1872 | 2040 | } |
|
1873 | png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
- | |
1874 | png_ptr->zstream.next_out = png_ptr->zbuf; |
- | |
1875 | } |
- | |
1876 | 2041 | ||
Line 1877... | Line 2042... | ||
1877 | /* Internal use only. Called when finished processing a row of data. */ |
2042 | /* Internal use only. Called when finished processing a row of data. */ |
1878 | void /* PRIVATE */ |
2043 | void /* PRIVATE */ |
1879 | png_write_finish_row(png_structp png_ptr) |
2044 | png_write_finish_row(png_structrp png_ptr) |
1880 | { |
2045 | { |
1881 | #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
2046 | #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1882 | /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
2047 | /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
Line 1883... | Line 2048... | ||
1883 | 2048 | ||
1884 | /* Start of interlace block */ |
2049 | /* Start of interlace block */ |
Line 1885... | Line 2050... | ||
1885 | int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
2050 | static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1886 | 2051 | ||
Line 1887... | Line 2052... | ||
1887 | /* Offset to next interlace block */ |
2052 | /* Offset to next interlace block */ |
1888 | int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
2053 | static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
Line 1889... | Line 2054... | ||
1889 | 2054 | ||
1890 | /* Start of interlace block in the y direction */ |
2055 | /* Start of interlace block in the y direction */ |
1891 | int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
2056 | static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
Line 1892... | Line -... | ||
1892 | - | ||
1893 | /* Offset to next interlace block in the y direction */ |
- | |
1894 | int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
2057 | |
Line 1895... | Line 2058... | ||
1895 | #endif |
2058 | /* Offset to next interlace block in the y direction */ |
1896 | 2059 | static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
|
Line 1945... | Line 2108... | ||
1945 | /* Reset the row above the image for the next pass */ |
2108 | /* Reset the row above the image for the next pass */ |
1946 | if (png_ptr->pass < 7) |
2109 | if (png_ptr->pass < 7) |
1947 | { |
2110 | { |
1948 | if (png_ptr->prev_row != NULL) |
2111 | if (png_ptr->prev_row != NULL) |
1949 | png_memset(png_ptr->prev_row, 0, |
2112 | memset(png_ptr->prev_row, 0, |
1950 | (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* |
2113 | (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* |
1951 | png_ptr->usr_bit_depth, png_ptr->width)) + 1); |
2114 | png_ptr->usr_bit_depth, png_ptr->width)) + 1); |
Line 1952... | Line 2115... | ||
1952 | 2115 | ||
1953 | return; |
2116 | return; |
1954 | } |
2117 | } |
1955 | } |
2118 | } |
Line 1956... | Line 2119... | ||
1956 | #endif |
2119 | #endif |
1957 | 2120 | ||
1958 | /* If we get here, we've just written the last row, so we need |
- | |
1959 | to flush the compressor */ |
- | |
1960 | do |
- | |
1961 | { |
2121 | /* If we get here, we've just written the last row, so we need |
1962 | /* Tell the compressor we are done */ |
- | |
1963 | ret = deflate(&png_ptr->zstream, Z_FINISH); |
- | |
1964 | - | ||
1965 | /* Check for an error */ |
- | |
1966 | if (ret == Z_OK) |
- | |
1967 | { |
- | |
1968 | /* Check to see if we need more room */ |
- | |
1969 | if (!(png_ptr->zstream.avail_out)) |
- | |
1970 | { |
- | |
1971 | png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); |
- | |
1972 | png_ptr->zstream.next_out = png_ptr->zbuf; |
- | |
1973 | png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
- | |
1974 | } |
- | |
1975 | } |
- | |
1976 | - | ||
1977 | else if (ret != Z_STREAM_END) |
- | |
1978 | { |
- | |
1979 | if (png_ptr->zstream.msg != NULL) |
- | |
1980 | png_error(png_ptr, png_ptr->zstream.msg); |
- | |
1981 | - | ||
1982 | else |
- | |
1983 | png_error(png_ptr, "zlib error"); |
- | |
1984 | } |
- | |
1985 | } while (ret != Z_STREAM_END); |
- | |
1986 | - | ||
1987 | /* Write any extra space */ |
- | |
1988 | if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) |
- | |
1989 | { |
- | |
1990 | png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - |
- | |
1991 | png_ptr->zstream.avail_out); |
- | |
1992 | } |
- | |
1993 | - | ||
1994 | deflateReset(&png_ptr->zstream); |
2122 | to flush the compressor */ |
Line 1995... | Line 2123... | ||
1995 | png_ptr->zstream.data_type = Z_BINARY; |
2123 | png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); |
1996 | } |
2124 | } |
1997 | 2125 | ||
Line 2008... | Line 2136... | ||
2008 | { |
2136 | { |
2009 | /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
2137 | /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
2010 | 2138 | ||
Line 2011... | Line 2139... | ||
2011 | /* Start of interlace block */ |
2139 | /* Start of interlace block */ |
2012 | int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
2140 | static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
Line 2013... | Line 2141... | ||
2013 | 2141 | ||
2014 | /* Offset to next interlace block */ |
2142 | /* Offset to next interlace block */ |
Line 2015... | Line 2143... | ||
2015 | int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
2143 | static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
Line 2016... | Line 2144... | ||
2016 | 2144 | ||
2017 | png_debug(1, "in png_do_write_interlace"); |
2145 | png_debug(1, "in png_do_write_interlace"); |
Line 2155... | Line 2283... | ||
2155 | sp = row + (png_size_t)i * pixel_bytes; |
2283 | sp = row + (png_size_t)i * pixel_bytes; |
2156 | 2284 | ||
Line 2157... | Line 2285... | ||
2157 | /* Move the pixel */ |
2285 | /* Move the pixel */ |
2158 | if (dp != sp) |
2286 | if (dp != sp) |
2159 | png_memcpy(dp, sp, pixel_bytes); |
2287 | memcpy(dp, sp, pixel_bytes); |
Line 2160... | Line 2288... | ||
2160 | 2288 | ||
2161 | /* Next pixel */ |
2289 | /* Next pixel */ |
2162 | dp += pixel_bytes; |
2290 | dp += pixel_bytes; |
2163 | } |
2291 | } |
Line 2179... | Line 2307... | ||
2179 | /* This filters the row, chooses which filter to use, if it has not already |
2307 | /* This filters the row, chooses which filter to use, if it has not already |
2180 | * been specified by the application, and then writes the row out with the |
2308 | * been specified by the application, and then writes the row out with the |
2181 | * chosen filter. |
2309 | * chosen filter. |
2182 | */ |
2310 | */ |
- | 2311 | static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, |
|
- | 2312 | png_size_t row_bytes); |
|
- | 2313 | ||
2183 | #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) |
2314 | #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) |
2184 | #define PNG_HISHIFT 10 |
2315 | #define PNG_HISHIFT 10 |
2185 | #define PNG_LOMASK ((png_uint_32)0xffffL) |
2316 | #define PNG_LOMASK ((png_uint_32)0xffffL) |
2186 | #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) |
2317 | #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) |
2187 | void /* PRIVATE */ |
2318 | void /* PRIVATE */ |
2188 | png_write_find_filter(png_structp png_ptr, png_row_infop row_info) |
2319 | png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) |
2189 | { |
2320 | { |
2190 | png_bytep best_row; |
2321 | png_bytep best_row; |
2191 | #ifdef PNG_WRITE_FILTER_SUPPORTED |
2322 | #ifdef PNG_WRITE_FILTER_SUPPORTED |
2192 | png_bytep prev_row, row_buf; |
2323 | png_bytep prev_row, row_buf; |
2193 | png_uint_32 mins, bpp; |
2324 | png_uint_32 mins, bpp; |
2194 | png_byte filter_to_do = png_ptr->do_filter; |
2325 | png_byte filter_to_do = png_ptr->do_filter; |
2195 | png_size_t row_bytes = row_info->rowbytes; |
2326 | png_size_t row_bytes = row_info->rowbytes; |
2196 | #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED |
2327 | #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED |
2197 | int num_p_filters = (int)png_ptr->num_prev_filters; |
2328 | int num_p_filters = png_ptr->num_prev_filters; |
2198 | #endif |
2329 | #endif |
Line 2199... | Line 2330... | ||
2199 | 2330 | ||
Line 2200... | Line 2331... | ||
2200 | png_debug(1, "in png_write_find_filter"); |
2331 | png_debug(1, "in png_write_find_filter"); |
Line 2830... | Line 2961... | ||
2830 | best_row = png_ptr->paeth_row; |
2961 | best_row = png_ptr->paeth_row; |
2831 | } |
2962 | } |
2832 | } |
2963 | } |
2833 | #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
2964 | #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
2834 | /* Do the actual writing of the filtered row data from the chosen filter. */ |
2965 | |
2835 | - | ||
Line -... | Line 2966... | ||
- | 2966 | /* Do the actual writing of the filtered row data from the chosen filter. */ |
|
2836 | png_write_filtered_row(png_ptr, best_row); |
2967 | png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); |
Line 2837... | Line 2968... | ||
2837 | 2968 | ||
2838 | #ifdef PNG_WRITE_FILTER_SUPPORTED |
2969 | #ifdef PNG_WRITE_FILTER_SUPPORTED |
2839 | #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED |
2970 | #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED |
2840 | /* Save the type of filter we picked this time for future calculations */ |
2971 | /* Save the type of filter we picked this time for future calculations */ |
Line 2854... | Line 2985... | ||
2854 | } |
2985 | } |
2855 | 2986 | ||
Line 2856... | Line 2987... | ||
2856 | 2987 | ||
2857 | /* Do the actual writing of a previously filtered row. */ |
2988 | /* Do the actual writing of a previously filtered row. */ |
2858 | void /* PRIVATE */ |
2989 | static void |
- | 2990 | png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, |
|
2859 | png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) |
2991 | png_size_t full_row_length/*includes filter byte*/) |
2860 | { |
- | |
2861 | png_size_t avail; |
- | |
2862 | 2992 | { |
|
Line 2863... | Line 2993... | ||
2863 | png_debug(1, "in png_write_filtered_row"); |
2993 | png_debug(1, "in png_write_filtered_row"); |
2864 | - | ||
2865 | png_debug1(2, "filter = %d", filtered_row[0]); |
- | |
2866 | /* Set up the zlib input buffer */ |
- | |
2867 | - | ||
2868 | png_ptr->zstream.next_in = filtered_row; |
- | |
2869 | png_ptr->zstream.avail_in = 0; |
- | |
2870 | avail = png_ptr->row_info.rowbytes + 1; |
- | |
2871 | /* Repeat until we have compressed all the data */ |
- | |
2872 | do |
- | |
2873 | { |
- | |
2874 | int ret; /* Return of zlib */ |
- | |
2875 | - | ||
2876 | /* Record the number of bytes available - zlib supports at least 65535 |
- | |
2877 | * bytes at one step, depending on the size of the zlib type 'uInt', the |
- | |
2878 | * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h). |
- | |
2879 | * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e. |
- | |
2880 | * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a |
- | |
2881 | * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called |
- | |
2882 | * with smaller chunks of data. |
- | |
2883 | */ |
- | |
2884 | if (png_ptr->zstream.avail_in == 0) |
- | |
2885 | { |
- | |
2886 | if (avail > ZLIB_IO_MAX) |
- | |
2887 | { |
- | |
2888 | png_ptr->zstream.avail_in = ZLIB_IO_MAX; |
- | |
Line 2889... | Line -... | ||
2889 | avail -= ZLIB_IO_MAX; |
- | |
2890 | } |
- | |
2891 | - | ||
2892 | else |
- | |
2893 | { |
- | |
2894 | /* So this will fit in the available uInt space: */ |
- | |
2895 | png_ptr->zstream.avail_in = (uInt)avail; |
- | |
2896 | avail = 0; |
- | |
2897 | } |
- | |
2898 | } |
- | |
2899 | - | ||
2900 | /* Compress the data */ |
- | |
2901 | ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); |
- | |
2902 | - | ||
2903 | /* Check for compression errors */ |
- | |
2904 | if (ret != Z_OK) |
- | |
2905 | { |
- | |
2906 | if (png_ptr->zstream.msg != NULL) |
- | |
2907 | png_error(png_ptr, png_ptr->zstream.msg); |
- | |
2908 | - | ||
2909 | else |
- | |
2910 | png_error(png_ptr, "zlib error"); |
- | |
2911 | } |
- | |
2912 | - | ||
2913 | /* See if it is time to write another IDAT */ |
- | |
2914 | if (!(png_ptr->zstream.avail_out)) |
2994 | |
2915 | { |
- | |
2916 | /* Write the IDAT and reset the zlib output buffer */ |
- | |
2917 | png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); |
- | |
2918 | png_ptr->zstream.next_out = png_ptr->zbuf; |
- | |
2919 | png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
- | |
Line 2920... | Line 2995... | ||
2920 | } |
2995 | png_debug1(2, "filter = %d", filtered_row[0]); |
2921 | /* Repeat until all data has been compressed */ |
2996 | |
2922 | } while (avail > 0 || png_ptr->zstream.avail_in > 0); |
2997 | png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); |
2923 | 2998 |