1 |
william |
31 |
|
2 |
|
|
/* pngrutil.c - utilities to read a PNG file |
3 |
|
|
* |
4 |
|
|
* Last changed in libpng 1.2.38 [July 16, 2009] |
5 |
|
|
* Copyright (c) 1998-2009 Glenn Randers-Pehrson |
6 |
|
|
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 |
|
|
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 |
|
|
* |
9 |
|
|
* This code is released under the libpng license. |
10 |
|
|
* For conditions of distribution and use, see the disclaimer |
11 |
|
|
* and license in png.h |
12 |
|
|
* |
13 |
|
|
* This file contains routines that are only called from within |
14 |
|
|
* libpng itself during the course of reading an image. |
15 |
|
|
*/ |
16 |
|
|
|
17 |
|
|
#define PNG_INTERNAL |
18 |
|
|
#include "png.h" |
19 |
|
|
#if defined(PNG_READ_SUPPORTED) |
20 |
|
|
|
21 |
|
|
#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) |
22 |
|
|
# define WIN32_WCE_OLD |
23 |
|
|
#endif |
24 |
|
|
|
25 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
26 |
|
|
# if defined(WIN32_WCE_OLD) |
27 |
|
|
/* The strtod() function is not supported on WindowsCE */ |
28 |
|
|
__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) |
29 |
|
|
{ |
30 |
|
|
double result = 0; |
31 |
|
|
int len; |
32 |
|
|
wchar_t *str, *end; |
33 |
|
|
|
34 |
|
|
len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); |
35 |
|
|
str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t)); |
36 |
|
|
if ( NULL != str ) |
37 |
|
|
{ |
38 |
|
|
MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); |
39 |
|
|
result = wcstod(str, &end); |
40 |
|
|
len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); |
41 |
|
|
*endptr = (char *)nptr + (png_strlen(nptr) - len + 1); |
42 |
|
|
png_free(png_ptr, str); |
43 |
|
|
} |
44 |
|
|
return result; |
45 |
|
|
} |
46 |
|
|
# else |
47 |
|
|
# define png_strtod(p,a,b) strtod(a,b) |
48 |
|
|
# endif |
49 |
|
|
#endif |
50 |
|
|
|
51 |
|
|
png_uint_32 PNGAPI |
52 |
|
|
png_get_uint_31(png_structp png_ptr, png_bytep buf) |
53 |
|
|
{ |
54 |
|
|
#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED |
55 |
|
|
png_uint_32 i = png_get_uint_32(buf); |
56 |
|
|
#else |
57 |
|
|
/* Avoid an extra function call by inlining the result. */ |
58 |
|
|
png_uint_32 i = ((png_uint_32)(*buf) << 24) + |
59 |
|
|
((png_uint_32)(*(buf + 1)) << 16) + |
60 |
|
|
((png_uint_32)(*(buf + 2)) << 8) + |
61 |
|
|
(png_uint_32)(*(buf + 3)); |
62 |
|
|
#endif |
63 |
|
|
if (i > PNG_UINT_31_MAX) |
64 |
|
|
png_error(png_ptr, "PNG unsigned integer out of range."); |
65 |
|
|
return (i); |
66 |
|
|
} |
67 |
|
|
#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED |
68 |
|
|
/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ |
69 |
|
|
png_uint_32 PNGAPI |
70 |
|
|
png_get_uint_32(png_bytep buf) |
71 |
|
|
{ |
72 |
|
|
png_uint_32 i = ((png_uint_32)(*buf) << 24) + |
73 |
|
|
((png_uint_32)(*(buf + 1)) << 16) + |
74 |
|
|
((png_uint_32)(*(buf + 2)) << 8) + |
75 |
|
|
(png_uint_32)(*(buf + 3)); |
76 |
|
|
|
77 |
|
|
return (i); |
78 |
|
|
} |
79 |
|
|
|
80 |
|
|
/* Grab a signed 32-bit integer from a buffer in big-endian format. The |
81 |
|
|
* data is stored in the PNG file in two's complement format, and it is |
82 |
|
|
* assumed that the machine format for signed integers is the same. |
83 |
|
|
*/ |
84 |
|
|
png_int_32 PNGAPI |
85 |
|
|
png_get_int_32(png_bytep buf) |
86 |
|
|
{ |
87 |
|
|
png_int_32 i = ((png_int_32)(*buf) << 24) + |
88 |
|
|
((png_int_32)(*(buf + 1)) << 16) + |
89 |
|
|
((png_int_32)(*(buf + 2)) << 8) + |
90 |
|
|
(png_int_32)(*(buf + 3)); |
91 |
|
|
|
92 |
|
|
return (i); |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ |
96 |
|
|
png_uint_16 PNGAPI |
97 |
|
|
png_get_uint_16(png_bytep buf) |
98 |
|
|
{ |
99 |
|
|
png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + |
100 |
|
|
(png_uint_16)(*(buf + 1))); |
101 |
|
|
|
102 |
|
|
return (i); |
103 |
|
|
} |
104 |
|
|
#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ |
105 |
|
|
|
106 |
|
|
/* Read the chunk header (length + type name). |
107 |
|
|
* Put the type name into png_ptr->chunk_name, and return the length. |
108 |
|
|
*/ |
109 |
|
|
png_uint_32 /* PRIVATE */ |
110 |
|
|
png_read_chunk_header(png_structp png_ptr) |
111 |
|
|
{ |
112 |
|
|
png_byte buf[8]; |
113 |
|
|
png_uint_32 length; |
114 |
|
|
|
115 |
|
|
/* Read the length and the chunk name */ |
116 |
|
|
png_read_data(png_ptr, buf, 8); |
117 |
|
|
length = png_get_uint_31(png_ptr, buf); |
118 |
|
|
|
119 |
|
|
/* Put the chunk name into png_ptr->chunk_name */ |
120 |
|
|
png_memcpy(png_ptr->chunk_name, buf + 4, 4); |
121 |
|
|
|
122 |
|
|
png_debug2(0, "Reading %s chunk, length = %lu", |
123 |
|
|
png_ptr->chunk_name, length); |
124 |
|
|
|
125 |
|
|
/* Reset the crc and run it over the chunk name */ |
126 |
|
|
png_reset_crc(png_ptr); |
127 |
|
|
png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); |
128 |
|
|
|
129 |
|
|
/* Check to see if chunk name is valid */ |
130 |
|
|
png_check_chunk_name(png_ptr, png_ptr->chunk_name); |
131 |
|
|
|
132 |
|
|
return length; |
133 |
|
|
} |
134 |
|
|
|
135 |
|
|
/* Read data, and (optionally) run it through the CRC. */ |
136 |
|
|
void /* PRIVATE */ |
137 |
|
|
png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) |
138 |
|
|
{ |
139 |
|
|
if (png_ptr == NULL) |
140 |
|
|
return; |
141 |
|
|
png_read_data(png_ptr, buf, length); |
142 |
|
|
png_calculate_crc(png_ptr, buf, length); |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
/* Optionally skip data and then check the CRC. Depending on whether we |
146 |
|
|
* are reading a ancillary or critical chunk, and how the program has set |
147 |
|
|
* things up, we may calculate the CRC on the data and print a message. |
148 |
|
|
* Returns '1' if there was a CRC error, '0' otherwise. |
149 |
|
|
*/ |
150 |
|
|
int /* PRIVATE */ |
151 |
|
|
png_crc_finish(png_structp png_ptr, png_uint_32 skip) |
152 |
|
|
{ |
153 |
|
|
png_size_t i; |
154 |
|
|
png_size_t istop = png_ptr->zbuf_size; |
155 |
|
|
|
156 |
|
|
for (i = (png_size_t)skip; i > istop; i -= istop) |
157 |
|
|
{ |
158 |
|
|
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); |
159 |
|
|
} |
160 |
|
|
if (i) |
161 |
|
|
{ |
162 |
|
|
png_crc_read(png_ptr, png_ptr->zbuf, i); |
163 |
|
|
} |
164 |
|
|
|
165 |
|
|
if (png_crc_error(png_ptr)) |
166 |
|
|
{ |
167 |
|
|
if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ |
168 |
|
|
!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || |
169 |
|
|
(!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ |
170 |
|
|
(png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) |
171 |
|
|
{ |
172 |
|
|
png_chunk_warning(png_ptr, "CRC error"); |
173 |
|
|
} |
174 |
|
|
else |
175 |
|
|
{ |
176 |
|
|
png_chunk_error(png_ptr, "CRC error"); |
177 |
|
|
} |
178 |
|
|
return (1); |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
return (0); |
182 |
|
|
} |
183 |
|
|
|
184 |
|
|
/* Compare the CRC stored in the PNG file with that calculated by libpng from |
185 |
|
|
* the data it has read thus far. |
186 |
|
|
*/ |
187 |
|
|
int /* PRIVATE */ |
188 |
|
|
png_crc_error(png_structp png_ptr) |
189 |
|
|
{ |
190 |
|
|
png_byte crc_bytes[4]; |
191 |
|
|
png_uint_32 crc; |
192 |
|
|
int need_crc = 1; |
193 |
|
|
|
194 |
|
|
if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ |
195 |
|
|
{ |
196 |
|
|
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == |
197 |
|
|
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) |
198 |
|
|
need_crc = 0; |
199 |
|
|
} |
200 |
|
|
else /* critical */ |
201 |
|
|
{ |
202 |
|
|
if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) |
203 |
|
|
need_crc = 0; |
204 |
|
|
} |
205 |
|
|
|
206 |
|
|
png_read_data(png_ptr, crc_bytes, 4); |
207 |
|
|
|
208 |
|
|
if (need_crc) |
209 |
|
|
{ |
210 |
|
|
crc = png_get_uint_32(crc_bytes); |
211 |
|
|
return ((int)(crc != png_ptr->crc)); |
212 |
|
|
} |
213 |
|
|
else |
214 |
|
|
return (0); |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ |
218 |
|
|
defined(PNG_READ_iCCP_SUPPORTED) |
219 |
|
|
/* |
220 |
|
|
* Decompress trailing data in a chunk. The assumption is that chunkdata |
221 |
|
|
* points at an allocated area holding the contents of a chunk with a |
222 |
|
|
* trailing compressed part. What we get back is an allocated area |
223 |
|
|
* holding the original prefix part and an uncompressed version of the |
224 |
|
|
* trailing part (the malloc area passed in is freed). |
225 |
|
|
*/ |
226 |
|
|
void /* PRIVATE */ |
227 |
|
|
png_decompress_chunk(png_structp png_ptr, int comp_type, |
228 |
|
|
png_size_t chunklength, |
229 |
|
|
png_size_t prefix_size, png_size_t *newlength) |
230 |
|
|
{ |
231 |
|
|
static PNG_CONST char msg[] = "Error decoding compressed text"; |
232 |
|
|
png_charp text; |
233 |
|
|
png_size_t text_size; |
234 |
|
|
|
235 |
|
|
if (comp_type == PNG_COMPRESSION_TYPE_BASE) |
236 |
|
|
{ |
237 |
|
|
int ret = Z_OK; |
238 |
|
|
png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size); |
239 |
|
|
png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); |
240 |
|
|
png_ptr->zstream.next_out = png_ptr->zbuf; |
241 |
|
|
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
242 |
|
|
|
243 |
|
|
text_size = 0; |
244 |
|
|
text = NULL; |
245 |
|
|
|
246 |
|
|
while (png_ptr->zstream.avail_in) |
247 |
|
|
{ |
248 |
|
|
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); |
249 |
|
|
if (ret != Z_OK && ret != Z_STREAM_END) |
250 |
|
|
{ |
251 |
|
|
if (png_ptr->zstream.msg != NULL) |
252 |
|
|
png_warning(png_ptr, png_ptr->zstream.msg); |
253 |
|
|
else |
254 |
|
|
png_warning(png_ptr, msg); |
255 |
|
|
inflateReset(&png_ptr->zstream); |
256 |
|
|
png_ptr->zstream.avail_in = 0; |
257 |
|
|
|
258 |
|
|
if (text == NULL) |
259 |
|
|
{ |
260 |
|
|
text_size = prefix_size + png_sizeof(msg) + 1; |
261 |
|
|
text = (png_charp)png_malloc_warn(png_ptr, text_size); |
262 |
|
|
if (text == NULL) |
263 |
|
|
{ |
264 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
265 |
|
|
png_ptr->chunkdata = NULL; |
266 |
|
|
png_error(png_ptr, "Not enough memory to decompress chunk"); |
267 |
|
|
} |
268 |
|
|
png_memcpy(text, png_ptr->chunkdata, prefix_size); |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
text[text_size - 1] = 0x00; |
272 |
|
|
|
273 |
|
|
/* Copy what we can of the error message into the text chunk */ |
274 |
|
|
text_size = (png_size_t)(chunklength - |
275 |
|
|
(text - png_ptr->chunkdata) - 1); |
276 |
|
|
if (text_size > png_sizeof(msg)) |
277 |
|
|
text_size = png_sizeof(msg); |
278 |
|
|
png_memcpy(text + prefix_size, msg, text_size); |
279 |
|
|
break; |
280 |
|
|
} |
281 |
|
|
if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) |
282 |
|
|
{ |
283 |
|
|
if (text == NULL) |
284 |
|
|
{ |
285 |
|
|
text_size = prefix_size + |
286 |
|
|
png_ptr->zbuf_size - png_ptr->zstream.avail_out; |
287 |
|
|
text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); |
288 |
|
|
if (text == NULL) |
289 |
|
|
{ |
290 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
291 |
|
|
png_ptr->chunkdata = NULL; |
292 |
|
|
png_error(png_ptr, |
293 |
|
|
"Not enough memory to decompress chunk."); |
294 |
|
|
} |
295 |
|
|
png_memcpy(text + prefix_size, png_ptr->zbuf, |
296 |
|
|
text_size - prefix_size); |
297 |
|
|
png_memcpy(text, png_ptr->chunkdata, prefix_size); |
298 |
|
|
*(text + text_size) = 0x00; |
299 |
|
|
} |
300 |
|
|
else |
301 |
|
|
{ |
302 |
|
|
png_charp tmp; |
303 |
|
|
|
304 |
|
|
tmp = text; |
305 |
|
|
text = (png_charp)png_malloc_warn(png_ptr, |
306 |
|
|
(png_uint_32)(text_size + |
307 |
|
|
png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); |
308 |
|
|
if (text == NULL) |
309 |
|
|
{ |
310 |
|
|
png_free(png_ptr, tmp); |
311 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
312 |
|
|
png_ptr->chunkdata = NULL; |
313 |
|
|
png_error(png_ptr, |
314 |
|
|
"Not enough memory to decompress chunk.."); |
315 |
|
|
} |
316 |
|
|
png_memcpy(text, tmp, text_size); |
317 |
|
|
png_free(png_ptr, tmp); |
318 |
|
|
png_memcpy(text + text_size, png_ptr->zbuf, |
319 |
|
|
(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); |
320 |
|
|
text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; |
321 |
|
|
*(text + text_size) = 0x00; |
322 |
|
|
} |
323 |
|
|
if (ret == Z_STREAM_END) |
324 |
|
|
break; |
325 |
|
|
else |
326 |
|
|
{ |
327 |
|
|
png_ptr->zstream.next_out = png_ptr->zbuf; |
328 |
|
|
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
329 |
|
|
} |
330 |
|
|
} |
331 |
|
|
} |
332 |
|
|
if (ret != Z_STREAM_END) |
333 |
|
|
{ |
334 |
|
|
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) |
335 |
|
|
char umsg[52]; |
336 |
|
|
|
337 |
|
|
if (ret == Z_BUF_ERROR) |
338 |
|
|
png_snprintf(umsg, 52, |
339 |
|
|
"Buffer error in compressed datastream in %s chunk", |
340 |
|
|
png_ptr->chunk_name); |
341 |
|
|
|
342 |
|
|
else if (ret == Z_DATA_ERROR) |
343 |
|
|
png_snprintf(umsg, 52, |
344 |
|
|
"Data error in compressed datastream in %s chunk", |
345 |
|
|
png_ptr->chunk_name); |
346 |
|
|
|
347 |
|
|
else |
348 |
|
|
png_snprintf(umsg, 52, |
349 |
|
|
"Incomplete compressed datastream in %s chunk", |
350 |
|
|
png_ptr->chunk_name); |
351 |
|
|
|
352 |
|
|
png_warning(png_ptr, umsg); |
353 |
|
|
#else |
354 |
|
|
png_warning(png_ptr, |
355 |
|
|
"Incomplete compressed datastream in chunk other than IDAT"); |
356 |
|
|
#endif |
357 |
|
|
text_size = prefix_size; |
358 |
|
|
if (text == NULL) |
359 |
|
|
{ |
360 |
|
|
text = (png_charp)png_malloc_warn(png_ptr, text_size+1); |
361 |
|
|
if (text == NULL) |
362 |
|
|
{ |
363 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
364 |
|
|
png_ptr->chunkdata = NULL; |
365 |
|
|
png_error(png_ptr, "Not enough memory for text."); |
366 |
|
|
} |
367 |
|
|
png_memcpy(text, png_ptr->chunkdata, prefix_size); |
368 |
|
|
} |
369 |
|
|
*(text + text_size) = 0x00; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
inflateReset(&png_ptr->zstream); |
373 |
|
|
png_ptr->zstream.avail_in = 0; |
374 |
|
|
|
375 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
376 |
|
|
png_ptr->chunkdata = text; |
377 |
|
|
*newlength=text_size; |
378 |
|
|
} |
379 |
|
|
else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ |
380 |
|
|
{ |
381 |
|
|
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) |
382 |
|
|
char umsg[50]; |
383 |
|
|
|
384 |
|
|
png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type); |
385 |
|
|
png_warning(png_ptr, umsg); |
386 |
|
|
#else |
387 |
|
|
png_warning(png_ptr, "Unknown zTXt compression type"); |
388 |
|
|
#endif |
389 |
|
|
|
390 |
|
|
*(png_ptr->chunkdata + prefix_size) = 0x00; |
391 |
|
|
*newlength = prefix_size; |
392 |
|
|
} |
393 |
|
|
} |
394 |
|
|
#endif |
395 |
|
|
|
396 |
|
|
/* Read and check the IDHR chunk */ |
397 |
|
|
void /* PRIVATE */ |
398 |
|
|
png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
399 |
|
|
{ |
400 |
|
|
png_byte buf[13]; |
401 |
|
|
png_uint_32 width, height; |
402 |
|
|
int bit_depth, color_type, compression_type, filter_type; |
403 |
|
|
int interlace_type; |
404 |
|
|
|
405 |
|
|
png_debug(1, "in png_handle_IHDR"); |
406 |
|
|
|
407 |
|
|
if (png_ptr->mode & PNG_HAVE_IHDR) |
408 |
|
|
png_error(png_ptr, "Out of place IHDR"); |
409 |
|
|
|
410 |
|
|
/* Check the length */ |
411 |
|
|
if (length != 13) |
412 |
|
|
png_error(png_ptr, "Invalid IHDR chunk"); |
413 |
|
|
|
414 |
|
|
png_ptr->mode |= PNG_HAVE_IHDR; |
415 |
|
|
|
416 |
|
|
png_crc_read(png_ptr, buf, 13); |
417 |
|
|
png_crc_finish(png_ptr, 0); |
418 |
|
|
|
419 |
|
|
width = png_get_uint_31(png_ptr, buf); |
420 |
|
|
height = png_get_uint_31(png_ptr, buf + 4); |
421 |
|
|
bit_depth = buf[8]; |
422 |
|
|
color_type = buf[9]; |
423 |
|
|
compression_type = buf[10]; |
424 |
|
|
filter_type = buf[11]; |
425 |
|
|
interlace_type = buf[12]; |
426 |
|
|
|
427 |
|
|
/* Set internal variables */ |
428 |
|
|
png_ptr->width = width; |
429 |
|
|
png_ptr->height = height; |
430 |
|
|
png_ptr->bit_depth = (png_byte)bit_depth; |
431 |
|
|
png_ptr->interlaced = (png_byte)interlace_type; |
432 |
|
|
png_ptr->color_type = (png_byte)color_type; |
433 |
|
|
#if defined(PNG_MNG_FEATURES_SUPPORTED) |
434 |
|
|
png_ptr->filter_type = (png_byte)filter_type; |
435 |
|
|
#endif |
436 |
|
|
png_ptr->compression_type = (png_byte)compression_type; |
437 |
|
|
|
438 |
|
|
/* Find number of channels */ |
439 |
|
|
switch (png_ptr->color_type) |
440 |
|
|
{ |
441 |
|
|
case PNG_COLOR_TYPE_GRAY: |
442 |
|
|
case PNG_COLOR_TYPE_PALETTE: |
443 |
|
|
png_ptr->channels = 1; |
444 |
|
|
break; |
445 |
|
|
|
446 |
|
|
case PNG_COLOR_TYPE_RGB: |
447 |
|
|
png_ptr->channels = 3; |
448 |
|
|
break; |
449 |
|
|
|
450 |
|
|
case PNG_COLOR_TYPE_GRAY_ALPHA: |
451 |
|
|
png_ptr->channels = 2; |
452 |
|
|
break; |
453 |
|
|
|
454 |
|
|
case PNG_COLOR_TYPE_RGB_ALPHA: |
455 |
|
|
png_ptr->channels = 4; |
456 |
|
|
break; |
457 |
|
|
} |
458 |
|
|
|
459 |
|
|
/* Set up other useful info */ |
460 |
|
|
png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * |
461 |
|
|
png_ptr->channels); |
462 |
|
|
png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); |
463 |
|
|
png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); |
464 |
|
|
png_debug1(3, "channels = %d", png_ptr->channels); |
465 |
|
|
png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes); |
466 |
|
|
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, |
467 |
|
|
color_type, interlace_type, compression_type, filter_type); |
468 |
|
|
} |
469 |
|
|
|
470 |
|
|
/* Read and check the palette */ |
471 |
|
|
void /* PRIVATE */ |
472 |
|
|
png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
473 |
|
|
{ |
474 |
|
|
png_color palette[PNG_MAX_PALETTE_LENGTH]; |
475 |
|
|
int num, i; |
476 |
|
|
#ifndef PNG_NO_POINTER_INDEXING |
477 |
|
|
png_colorp pal_ptr; |
478 |
|
|
#endif |
479 |
|
|
|
480 |
|
|
png_debug(1, "in png_handle_PLTE"); |
481 |
|
|
|
482 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
483 |
|
|
png_error(png_ptr, "Missing IHDR before PLTE"); |
484 |
|
|
|
485 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
486 |
|
|
{ |
487 |
|
|
png_warning(png_ptr, "Invalid PLTE after IDAT"); |
488 |
|
|
png_crc_finish(png_ptr, length); |
489 |
|
|
return; |
490 |
|
|
} |
491 |
|
|
|
492 |
|
|
else if (png_ptr->mode & PNG_HAVE_PLTE) |
493 |
|
|
png_error(png_ptr, "Duplicate PLTE chunk"); |
494 |
|
|
|
495 |
|
|
png_ptr->mode |= PNG_HAVE_PLTE; |
496 |
|
|
|
497 |
|
|
if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) |
498 |
|
|
{ |
499 |
|
|
png_warning(png_ptr, |
500 |
|
|
"Ignoring PLTE chunk in grayscale PNG"); |
501 |
|
|
png_crc_finish(png_ptr, length); |
502 |
|
|
return; |
503 |
|
|
} |
504 |
|
|
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) |
505 |
|
|
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) |
506 |
|
|
{ |
507 |
|
|
png_crc_finish(png_ptr, length); |
508 |
|
|
return; |
509 |
|
|
} |
510 |
|
|
#endif |
511 |
|
|
|
512 |
|
|
if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) |
513 |
|
|
{ |
514 |
|
|
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) |
515 |
|
|
{ |
516 |
|
|
png_warning(png_ptr, "Invalid palette chunk"); |
517 |
|
|
png_crc_finish(png_ptr, length); |
518 |
|
|
return; |
519 |
|
|
} |
520 |
|
|
|
521 |
|
|
else |
522 |
|
|
{ |
523 |
|
|
png_error(png_ptr, "Invalid palette chunk"); |
524 |
|
|
} |
525 |
|
|
} |
526 |
|
|
|
527 |
|
|
num = (int)length / 3; |
528 |
|
|
|
529 |
|
|
#ifndef PNG_NO_POINTER_INDEXING |
530 |
|
|
for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) |
531 |
|
|
{ |
532 |
|
|
png_byte buf[3]; |
533 |
|
|
|
534 |
|
|
png_crc_read(png_ptr, buf, 3); |
535 |
|
|
pal_ptr->red = buf[0]; |
536 |
|
|
pal_ptr->green = buf[1]; |
537 |
|
|
pal_ptr->blue = buf[2]; |
538 |
|
|
} |
539 |
|
|
#else |
540 |
|
|
for (i = 0; i < num; i++) |
541 |
|
|
{ |
542 |
|
|
png_byte buf[3]; |
543 |
|
|
|
544 |
|
|
png_crc_read(png_ptr, buf, 3); |
545 |
|
|
/* Don't depend upon png_color being any order */ |
546 |
|
|
palette[i].red = buf[0]; |
547 |
|
|
palette[i].green = buf[1]; |
548 |
|
|
palette[i].blue = buf[2]; |
549 |
|
|
} |
550 |
|
|
#endif |
551 |
|
|
|
552 |
|
|
/* If we actually NEED the PLTE chunk (ie for a paletted image), we do |
553 |
|
|
* whatever the normal CRC configuration tells us. However, if we |
554 |
|
|
* have an RGB image, the PLTE can be considered ancillary, so |
555 |
|
|
* we will act as though it is. |
556 |
|
|
*/ |
557 |
|
|
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) |
558 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
559 |
|
|
#endif |
560 |
|
|
{ |
561 |
|
|
png_crc_finish(png_ptr, 0); |
562 |
|
|
} |
563 |
|
|
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) |
564 |
|
|
else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ |
565 |
|
|
{ |
566 |
|
|
/* If we don't want to use the data from an ancillary chunk, |
567 |
|
|
we have two options: an error abort, or a warning and we |
568 |
|
|
ignore the data in this chunk (which should be OK, since |
569 |
|
|
it's considered ancillary for a RGB or RGBA image). */ |
570 |
|
|
if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) |
571 |
|
|
{ |
572 |
|
|
if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) |
573 |
|
|
{ |
574 |
|
|
png_chunk_error(png_ptr, "CRC error"); |
575 |
|
|
} |
576 |
|
|
else |
577 |
|
|
{ |
578 |
|
|
png_chunk_warning(png_ptr, "CRC error"); |
579 |
|
|
return; |
580 |
|
|
} |
581 |
|
|
} |
582 |
|
|
/* Otherwise, we (optionally) emit a warning and use the chunk. */ |
583 |
|
|
else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) |
584 |
|
|
{ |
585 |
|
|
png_chunk_warning(png_ptr, "CRC error"); |
586 |
|
|
} |
587 |
|
|
} |
588 |
|
|
#endif |
589 |
|
|
|
590 |
|
|
png_set_PLTE(png_ptr, info_ptr, palette, num); |
591 |
|
|
|
592 |
|
|
#if defined(PNG_READ_tRNS_SUPPORTED) |
593 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
594 |
|
|
{ |
595 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) |
596 |
|
|
{ |
597 |
|
|
if (png_ptr->num_trans > (png_uint_16)num) |
598 |
|
|
{ |
599 |
|
|
png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); |
600 |
|
|
png_ptr->num_trans = (png_uint_16)num; |
601 |
|
|
} |
602 |
|
|
if (info_ptr->num_trans > (png_uint_16)num) |
603 |
|
|
{ |
604 |
|
|
png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); |
605 |
|
|
info_ptr->num_trans = (png_uint_16)num; |
606 |
|
|
} |
607 |
|
|
} |
608 |
|
|
} |
609 |
|
|
#endif |
610 |
|
|
|
611 |
|
|
} |
612 |
|
|
|
613 |
|
|
void /* PRIVATE */ |
614 |
|
|
png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
615 |
|
|
{ |
616 |
|
|
png_debug(1, "in png_handle_IEND"); |
617 |
|
|
|
618 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) |
619 |
|
|
{ |
620 |
|
|
png_error(png_ptr, "No image in file"); |
621 |
|
|
} |
622 |
|
|
|
623 |
|
|
png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); |
624 |
|
|
|
625 |
|
|
if (length != 0) |
626 |
|
|
{ |
627 |
|
|
png_warning(png_ptr, "Incorrect IEND chunk length"); |
628 |
|
|
} |
629 |
|
|
png_crc_finish(png_ptr, length); |
630 |
|
|
|
631 |
|
|
info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ |
632 |
|
|
} |
633 |
|
|
|
634 |
|
|
#if defined(PNG_READ_gAMA_SUPPORTED) |
635 |
|
|
void /* PRIVATE */ |
636 |
|
|
png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
637 |
|
|
{ |
638 |
|
|
png_fixed_point igamma; |
639 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
640 |
|
|
float file_gamma; |
641 |
|
|
#endif |
642 |
|
|
png_byte buf[4]; |
643 |
|
|
|
644 |
|
|
png_debug(1, "in png_handle_gAMA"); |
645 |
|
|
|
646 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
647 |
|
|
png_error(png_ptr, "Missing IHDR before gAMA"); |
648 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
649 |
|
|
{ |
650 |
|
|
png_warning(png_ptr, "Invalid gAMA after IDAT"); |
651 |
|
|
png_crc_finish(png_ptr, length); |
652 |
|
|
return; |
653 |
|
|
} |
654 |
|
|
else if (png_ptr->mode & PNG_HAVE_PLTE) |
655 |
|
|
/* Should be an error, but we can cope with it */ |
656 |
|
|
png_warning(png_ptr, "Out of place gAMA chunk"); |
657 |
|
|
|
658 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) |
659 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
660 |
|
|
&& !(info_ptr->valid & PNG_INFO_sRGB) |
661 |
|
|
#endif |
662 |
|
|
) |
663 |
|
|
{ |
664 |
|
|
png_warning(png_ptr, "Duplicate gAMA chunk"); |
665 |
|
|
png_crc_finish(png_ptr, length); |
666 |
|
|
return; |
667 |
|
|
} |
668 |
|
|
|
669 |
|
|
if (length != 4) |
670 |
|
|
{ |
671 |
|
|
png_warning(png_ptr, "Incorrect gAMA chunk length"); |
672 |
|
|
png_crc_finish(png_ptr, length); |
673 |
|
|
return; |
674 |
|
|
} |
675 |
|
|
|
676 |
|
|
png_crc_read(png_ptr, buf, 4); |
677 |
|
|
if (png_crc_finish(png_ptr, 0)) |
678 |
|
|
return; |
679 |
|
|
|
680 |
|
|
igamma = (png_fixed_point)png_get_uint_32(buf); |
681 |
|
|
/* Check for zero gamma */ |
682 |
|
|
if (igamma == 0) |
683 |
|
|
{ |
684 |
|
|
png_warning(png_ptr, |
685 |
|
|
"Ignoring gAMA chunk with gamma=0"); |
686 |
|
|
return; |
687 |
|
|
} |
688 |
|
|
|
689 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
690 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) |
691 |
|
|
if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) |
692 |
|
|
{ |
693 |
|
|
png_warning(png_ptr, |
694 |
|
|
"Ignoring incorrect gAMA value when sRGB is also present"); |
695 |
|
|
#ifndef PNG_NO_CONSOLE_IO |
696 |
|
|
fprintf(stderr, "gamma = (%d/100000)", (int)igamma); |
697 |
|
|
#endif |
698 |
|
|
return; |
699 |
|
|
} |
700 |
|
|
#endif /* PNG_READ_sRGB_SUPPORTED */ |
701 |
|
|
|
702 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
703 |
|
|
file_gamma = (float)igamma / (float)100000.0; |
704 |
|
|
# ifdef PNG_READ_GAMMA_SUPPORTED |
705 |
|
|
png_ptr->gamma = file_gamma; |
706 |
|
|
# endif |
707 |
|
|
png_set_gAMA(png_ptr, info_ptr, file_gamma); |
708 |
|
|
#endif |
709 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
710 |
|
|
png_set_gAMA_fixed(png_ptr, info_ptr, igamma); |
711 |
|
|
#endif |
712 |
|
|
} |
713 |
|
|
#endif |
714 |
|
|
|
715 |
|
|
#if defined(PNG_READ_sBIT_SUPPORTED) |
716 |
|
|
void /* PRIVATE */ |
717 |
|
|
png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
718 |
|
|
{ |
719 |
|
|
png_size_t truelen; |
720 |
|
|
png_byte buf[4]; |
721 |
|
|
|
722 |
|
|
png_debug(1, "in png_handle_sBIT"); |
723 |
|
|
|
724 |
|
|
buf[0] = buf[1] = buf[2] = buf[3] = 0; |
725 |
|
|
|
726 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
727 |
|
|
png_error(png_ptr, "Missing IHDR before sBIT"); |
728 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
729 |
|
|
{ |
730 |
|
|
png_warning(png_ptr, "Invalid sBIT after IDAT"); |
731 |
|
|
png_crc_finish(png_ptr, length); |
732 |
|
|
return; |
733 |
|
|
} |
734 |
|
|
else if (png_ptr->mode & PNG_HAVE_PLTE) |
735 |
|
|
{ |
736 |
|
|
/* Should be an error, but we can cope with it */ |
737 |
|
|
png_warning(png_ptr, "Out of place sBIT chunk"); |
738 |
|
|
} |
739 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) |
740 |
|
|
{ |
741 |
|
|
png_warning(png_ptr, "Duplicate sBIT chunk"); |
742 |
|
|
png_crc_finish(png_ptr, length); |
743 |
|
|
return; |
744 |
|
|
} |
745 |
|
|
|
746 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
747 |
|
|
truelen = 3; |
748 |
|
|
else |
749 |
|
|
truelen = (png_size_t)png_ptr->channels; |
750 |
|
|
|
751 |
|
|
if (length != truelen || length > 4) |
752 |
|
|
{ |
753 |
|
|
png_warning(png_ptr, "Incorrect sBIT chunk length"); |
754 |
|
|
png_crc_finish(png_ptr, length); |
755 |
|
|
return; |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
png_crc_read(png_ptr, buf, truelen); |
759 |
|
|
if (png_crc_finish(png_ptr, 0)) |
760 |
|
|
return; |
761 |
|
|
|
762 |
|
|
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) |
763 |
|
|
{ |
764 |
|
|
png_ptr->sig_bit.red = buf[0]; |
765 |
|
|
png_ptr->sig_bit.green = buf[1]; |
766 |
|
|
png_ptr->sig_bit.blue = buf[2]; |
767 |
|
|
png_ptr->sig_bit.alpha = buf[3]; |
768 |
|
|
} |
769 |
|
|
else |
770 |
|
|
{ |
771 |
|
|
png_ptr->sig_bit.gray = buf[0]; |
772 |
|
|
png_ptr->sig_bit.red = buf[0]; |
773 |
|
|
png_ptr->sig_bit.green = buf[0]; |
774 |
|
|
png_ptr->sig_bit.blue = buf[0]; |
775 |
|
|
png_ptr->sig_bit.alpha = buf[1]; |
776 |
|
|
} |
777 |
|
|
png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); |
778 |
|
|
} |
779 |
|
|
#endif |
780 |
|
|
|
781 |
|
|
#if defined(PNG_READ_cHRM_SUPPORTED) |
782 |
|
|
void /* PRIVATE */ |
783 |
|
|
png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
784 |
|
|
{ |
785 |
|
|
png_byte buf[32]; |
786 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
787 |
|
|
float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; |
788 |
|
|
#endif |
789 |
|
|
png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, |
790 |
|
|
int_y_green, int_x_blue, int_y_blue; |
791 |
|
|
|
792 |
|
|
png_uint_32 uint_x, uint_y; |
793 |
|
|
|
794 |
|
|
png_debug(1, "in png_handle_cHRM"); |
795 |
|
|
|
796 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
797 |
|
|
png_error(png_ptr, "Missing IHDR before cHRM"); |
798 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
799 |
|
|
{ |
800 |
|
|
png_warning(png_ptr, "Invalid cHRM after IDAT"); |
801 |
|
|
png_crc_finish(png_ptr, length); |
802 |
|
|
return; |
803 |
|
|
} |
804 |
|
|
else if (png_ptr->mode & PNG_HAVE_PLTE) |
805 |
|
|
/* Should be an error, but we can cope with it */ |
806 |
|
|
png_warning(png_ptr, "Missing PLTE before cHRM"); |
807 |
|
|
|
808 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) |
809 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
810 |
|
|
&& !(info_ptr->valid & PNG_INFO_sRGB) |
811 |
|
|
#endif |
812 |
|
|
) |
813 |
|
|
{ |
814 |
|
|
png_warning(png_ptr, "Duplicate cHRM chunk"); |
815 |
|
|
png_crc_finish(png_ptr, length); |
816 |
|
|
return; |
817 |
|
|
} |
818 |
|
|
|
819 |
|
|
if (length != 32) |
820 |
|
|
{ |
821 |
|
|
png_warning(png_ptr, "Incorrect cHRM chunk length"); |
822 |
|
|
png_crc_finish(png_ptr, length); |
823 |
|
|
return; |
824 |
|
|
} |
825 |
|
|
|
826 |
|
|
png_crc_read(png_ptr, buf, 32); |
827 |
|
|
if (png_crc_finish(png_ptr, 0)) |
828 |
|
|
return; |
829 |
|
|
|
830 |
|
|
uint_x = png_get_uint_32(buf); |
831 |
|
|
uint_y = png_get_uint_32(buf + 4); |
832 |
|
|
int_x_white = (png_fixed_point)uint_x; |
833 |
|
|
int_y_white = (png_fixed_point)uint_y; |
834 |
|
|
|
835 |
|
|
uint_x = png_get_uint_32(buf + 8); |
836 |
|
|
uint_y = png_get_uint_32(buf + 12); |
837 |
|
|
int_x_red = (png_fixed_point)uint_x; |
838 |
|
|
int_y_red = (png_fixed_point)uint_y; |
839 |
|
|
|
840 |
|
|
uint_x = png_get_uint_32(buf + 16); |
841 |
|
|
uint_y = png_get_uint_32(buf + 20); |
842 |
|
|
int_x_green = (png_fixed_point)uint_x; |
843 |
|
|
int_y_green = (png_fixed_point)uint_y; |
844 |
|
|
|
845 |
|
|
uint_x = png_get_uint_32(buf + 24); |
846 |
|
|
uint_y = png_get_uint_32(buf + 28); |
847 |
|
|
int_x_blue = (png_fixed_point)uint_x; |
848 |
|
|
int_y_blue = (png_fixed_point)uint_y; |
849 |
|
|
|
850 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
851 |
|
|
white_x = (float)int_x_white / (float)100000.0; |
852 |
|
|
white_y = (float)int_y_white / (float)100000.0; |
853 |
|
|
red_x = (float)int_x_red / (float)100000.0; |
854 |
|
|
red_y = (float)int_y_red / (float)100000.0; |
855 |
|
|
green_x = (float)int_x_green / (float)100000.0; |
856 |
|
|
green_y = (float)int_y_green / (float)100000.0; |
857 |
|
|
blue_x = (float)int_x_blue / (float)100000.0; |
858 |
|
|
blue_y = (float)int_y_blue / (float)100000.0; |
859 |
|
|
#endif |
860 |
|
|
|
861 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
862 |
|
|
if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) |
863 |
|
|
{ |
864 |
|
|
if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || |
865 |
|
|
PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || |
866 |
|
|
PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || |
867 |
|
|
PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || |
868 |
|
|
PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || |
869 |
|
|
PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || |
870 |
|
|
PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || |
871 |
|
|
PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) |
872 |
|
|
{ |
873 |
|
|
png_warning(png_ptr, |
874 |
|
|
"Ignoring incorrect cHRM value when sRGB is also present"); |
875 |
|
|
#ifndef PNG_NO_CONSOLE_IO |
876 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
877 |
|
|
fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", |
878 |
|
|
white_x, white_y, red_x, red_y); |
879 |
|
|
fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", |
880 |
|
|
green_x, green_y, blue_x, blue_y); |
881 |
|
|
#else |
882 |
|
|
fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", |
883 |
|
|
int_x_white, int_y_white, int_x_red, int_y_red); |
884 |
|
|
fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", |
885 |
|
|
int_x_green, int_y_green, int_x_blue, int_y_blue); |
886 |
|
|
#endif |
887 |
|
|
#endif /* PNG_NO_CONSOLE_IO */ |
888 |
|
|
} |
889 |
|
|
return; |
890 |
|
|
} |
891 |
|
|
#endif /* PNG_READ_sRGB_SUPPORTED */ |
892 |
|
|
|
893 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
894 |
|
|
png_set_cHRM(png_ptr, info_ptr, |
895 |
|
|
white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); |
896 |
|
|
#endif |
897 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
898 |
|
|
png_set_cHRM_fixed(png_ptr, info_ptr, |
899 |
|
|
int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, |
900 |
|
|
int_y_green, int_x_blue, int_y_blue); |
901 |
|
|
#endif |
902 |
|
|
} |
903 |
|
|
#endif |
904 |
|
|
|
905 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
906 |
|
|
void /* PRIVATE */ |
907 |
|
|
png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
908 |
|
|
{ |
909 |
|
|
int intent; |
910 |
|
|
png_byte buf[1]; |
911 |
|
|
|
912 |
|
|
png_debug(1, "in png_handle_sRGB"); |
913 |
|
|
|
914 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
915 |
|
|
png_error(png_ptr, "Missing IHDR before sRGB"); |
916 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
917 |
|
|
{ |
918 |
|
|
png_warning(png_ptr, "Invalid sRGB after IDAT"); |
919 |
|
|
png_crc_finish(png_ptr, length); |
920 |
|
|
return; |
921 |
|
|
} |
922 |
|
|
else if (png_ptr->mode & PNG_HAVE_PLTE) |
923 |
|
|
/* Should be an error, but we can cope with it */ |
924 |
|
|
png_warning(png_ptr, "Out of place sRGB chunk"); |
925 |
|
|
|
926 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) |
927 |
|
|
{ |
928 |
|
|
png_warning(png_ptr, "Duplicate sRGB chunk"); |
929 |
|
|
png_crc_finish(png_ptr, length); |
930 |
|
|
return; |
931 |
|
|
} |
932 |
|
|
|
933 |
|
|
if (length != 1) |
934 |
|
|
{ |
935 |
|
|
png_warning(png_ptr, "Incorrect sRGB chunk length"); |
936 |
|
|
png_crc_finish(png_ptr, length); |
937 |
|
|
return; |
938 |
|
|
} |
939 |
|
|
|
940 |
|
|
png_crc_read(png_ptr, buf, 1); |
941 |
|
|
if (png_crc_finish(png_ptr, 0)) |
942 |
|
|
return; |
943 |
|
|
|
944 |
|
|
intent = buf[0]; |
945 |
|
|
/* Check for bad intent */ |
946 |
|
|
if (intent >= PNG_sRGB_INTENT_LAST) |
947 |
|
|
{ |
948 |
|
|
png_warning(png_ptr, "Unknown sRGB intent"); |
949 |
|
|
return; |
950 |
|
|
} |
951 |
|
|
|
952 |
|
|
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) |
953 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) |
954 |
|
|
{ |
955 |
|
|
png_fixed_point igamma; |
956 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
957 |
|
|
igamma=info_ptr->int_gamma; |
958 |
|
|
#else |
959 |
|
|
# ifdef PNG_FLOATING_POINT_SUPPORTED |
960 |
|
|
igamma=(png_fixed_point)(info_ptr->gamma * 100000.); |
961 |
|
|
# endif |
962 |
|
|
#endif |
963 |
|
|
if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) |
964 |
|
|
{ |
965 |
|
|
png_warning(png_ptr, |
966 |
|
|
"Ignoring incorrect gAMA value when sRGB is also present"); |
967 |
|
|
#ifndef PNG_NO_CONSOLE_IO |
968 |
|
|
# ifdef PNG_FIXED_POINT_SUPPORTED |
969 |
|
|
fprintf(stderr, "incorrect gamma=(%d/100000)\n", |
970 |
|
|
(int)png_ptr->int_gamma); |
971 |
|
|
# else |
972 |
|
|
# ifdef PNG_FLOATING_POINT_SUPPORTED |
973 |
|
|
fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma); |
974 |
|
|
# endif |
975 |
|
|
# endif |
976 |
|
|
#endif |
977 |
|
|
} |
978 |
|
|
} |
979 |
|
|
#endif /* PNG_READ_gAMA_SUPPORTED */ |
980 |
|
|
|
981 |
|
|
#ifdef PNG_READ_cHRM_SUPPORTED |
982 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
983 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) |
984 |
|
|
if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || |
985 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || |
986 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || |
987 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || |
988 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || |
989 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || |
990 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || |
991 |
|
|
PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) |
992 |
|
|
{ |
993 |
|
|
png_warning(png_ptr, |
994 |
|
|
"Ignoring incorrect cHRM value when sRGB is also present"); |
995 |
|
|
} |
996 |
|
|
#endif /* PNG_FIXED_POINT_SUPPORTED */ |
997 |
|
|
#endif /* PNG_READ_cHRM_SUPPORTED */ |
998 |
|
|
|
999 |
|
|
png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); |
1000 |
|
|
} |
1001 |
|
|
#endif /* PNG_READ_sRGB_SUPPORTED */ |
1002 |
|
|
|
1003 |
|
|
#if defined(PNG_READ_iCCP_SUPPORTED) |
1004 |
|
|
void /* PRIVATE */ |
1005 |
|
|
png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1006 |
|
|
/* Note: this does not properly handle chunks that are > 64K under DOS */ |
1007 |
|
|
{ |
1008 |
|
|
png_byte compression_type; |
1009 |
|
|
png_bytep pC; |
1010 |
|
|
png_charp profile; |
1011 |
|
|
png_uint_32 skip = 0; |
1012 |
|
|
png_uint_32 profile_size, profile_length; |
1013 |
|
|
png_size_t slength, prefix_length, data_length; |
1014 |
|
|
|
1015 |
|
|
png_debug(1, "in png_handle_iCCP"); |
1016 |
|
|
|
1017 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1018 |
|
|
png_error(png_ptr, "Missing IHDR before iCCP"); |
1019 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1020 |
|
|
{ |
1021 |
|
|
png_warning(png_ptr, "Invalid iCCP after IDAT"); |
1022 |
|
|
png_crc_finish(png_ptr, length); |
1023 |
|
|
return; |
1024 |
|
|
} |
1025 |
|
|
else if (png_ptr->mode & PNG_HAVE_PLTE) |
1026 |
|
|
/* Should be an error, but we can cope with it */ |
1027 |
|
|
png_warning(png_ptr, "Out of place iCCP chunk"); |
1028 |
|
|
|
1029 |
|
|
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) |
1030 |
|
|
{ |
1031 |
|
|
png_warning(png_ptr, "Duplicate iCCP chunk"); |
1032 |
|
|
png_crc_finish(png_ptr, length); |
1033 |
|
|
return; |
1034 |
|
|
} |
1035 |
|
|
|
1036 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1037 |
|
|
if (length > (png_uint_32)65535L) |
1038 |
|
|
{ |
1039 |
|
|
png_warning(png_ptr, "iCCP chunk too large to fit in memory"); |
1040 |
|
|
skip = length - (png_uint_32)65535L; |
1041 |
|
|
length = (png_uint_32)65535L; |
1042 |
|
|
} |
1043 |
|
|
#endif |
1044 |
|
|
|
1045 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1046 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); |
1047 |
|
|
slength = (png_size_t)length; |
1048 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
1049 |
|
|
|
1050 |
|
|
if (png_crc_finish(png_ptr, skip)) |
1051 |
|
|
{ |
1052 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1053 |
|
|
png_ptr->chunkdata = NULL; |
1054 |
|
|
return; |
1055 |
|
|
} |
1056 |
|
|
|
1057 |
|
|
png_ptr->chunkdata[slength] = 0x00; |
1058 |
|
|
|
1059 |
|
|
for (profile = png_ptr->chunkdata; *profile; profile++) |
1060 |
|
|
/* Empty loop to find end of name */ ; |
1061 |
|
|
|
1062 |
|
|
++profile; |
1063 |
|
|
|
1064 |
|
|
/* There should be at least one zero (the compression type byte) |
1065 |
|
|
* following the separator, and we should be on it |
1066 |
|
|
*/ |
1067 |
|
|
if ( profile >= png_ptr->chunkdata + slength - 1) |
1068 |
|
|
{ |
1069 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1070 |
|
|
png_ptr->chunkdata = NULL; |
1071 |
|
|
png_warning(png_ptr, "Malformed iCCP chunk"); |
1072 |
|
|
return; |
1073 |
|
|
} |
1074 |
|
|
|
1075 |
|
|
/* Compression_type should always be zero */ |
1076 |
|
|
compression_type = *profile++; |
1077 |
|
|
if (compression_type) |
1078 |
|
|
{ |
1079 |
|
|
png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); |
1080 |
|
|
compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 |
1081 |
|
|
wrote nonzero) */ |
1082 |
|
|
} |
1083 |
|
|
|
1084 |
|
|
prefix_length = profile - png_ptr->chunkdata; |
1085 |
|
|
png_decompress_chunk(png_ptr, compression_type, |
1086 |
|
|
slength, prefix_length, &data_length); |
1087 |
|
|
|
1088 |
|
|
profile_length = data_length - prefix_length; |
1089 |
|
|
|
1090 |
|
|
if ( prefix_length > data_length || profile_length < 4) |
1091 |
|
|
{ |
1092 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1093 |
|
|
png_ptr->chunkdata = NULL; |
1094 |
|
|
png_warning(png_ptr, "Profile size field missing from iCCP chunk"); |
1095 |
|
|
return; |
1096 |
|
|
} |
1097 |
|
|
|
1098 |
|
|
/* Check the profile_size recorded in the first 32 bits of the ICC profile */ |
1099 |
|
|
pC = (png_bytep)(png_ptr->chunkdata + prefix_length); |
1100 |
|
|
profile_size = ((*(pC ))<<24) | |
1101 |
|
|
((*(pC + 1))<<16) | |
1102 |
|
|
((*(pC + 2))<< 8) | |
1103 |
|
|
((*(pC + 3)) ); |
1104 |
|
|
|
1105 |
|
|
if (profile_size < profile_length) |
1106 |
|
|
profile_length = profile_size; |
1107 |
|
|
|
1108 |
|
|
if (profile_size > profile_length) |
1109 |
|
|
{ |
1110 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1111 |
|
|
png_ptr->chunkdata = NULL; |
1112 |
|
|
png_warning(png_ptr, "Ignoring truncated iCCP profile."); |
1113 |
|
|
return; |
1114 |
|
|
} |
1115 |
|
|
|
1116 |
|
|
png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, |
1117 |
|
|
compression_type, png_ptr->chunkdata + prefix_length, profile_length); |
1118 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1119 |
|
|
png_ptr->chunkdata = NULL; |
1120 |
|
|
} |
1121 |
|
|
#endif /* PNG_READ_iCCP_SUPPORTED */ |
1122 |
|
|
|
1123 |
|
|
#if defined(PNG_READ_sPLT_SUPPORTED) |
1124 |
|
|
void /* PRIVATE */ |
1125 |
|
|
png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1126 |
|
|
/* Note: this does not properly handle chunks that are > 64K under DOS */ |
1127 |
|
|
{ |
1128 |
|
|
png_bytep entry_start; |
1129 |
|
|
png_sPLT_t new_palette; |
1130 |
|
|
#ifdef PNG_NO_POINTER_INDEXING |
1131 |
|
|
png_sPLT_entryp pp; |
1132 |
|
|
#endif |
1133 |
|
|
int data_length, entry_size, i; |
1134 |
|
|
png_uint_32 skip = 0; |
1135 |
|
|
png_size_t slength; |
1136 |
|
|
|
1137 |
|
|
png_debug(1, "in png_handle_sPLT"); |
1138 |
|
|
|
1139 |
|
|
|
1140 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1141 |
|
|
png_error(png_ptr, "Missing IHDR before sPLT"); |
1142 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1143 |
|
|
{ |
1144 |
|
|
png_warning(png_ptr, "Invalid sPLT after IDAT"); |
1145 |
|
|
png_crc_finish(png_ptr, length); |
1146 |
|
|
return; |
1147 |
|
|
} |
1148 |
|
|
|
1149 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1150 |
|
|
if (length > (png_uint_32)65535L) |
1151 |
|
|
{ |
1152 |
|
|
png_warning(png_ptr, "sPLT chunk too large to fit in memory"); |
1153 |
|
|
skip = length - (png_uint_32)65535L; |
1154 |
|
|
length = (png_uint_32)65535L; |
1155 |
|
|
} |
1156 |
|
|
#endif |
1157 |
|
|
|
1158 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1159 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); |
1160 |
|
|
slength = (png_size_t)length; |
1161 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
1162 |
|
|
|
1163 |
|
|
if (png_crc_finish(png_ptr, skip)) |
1164 |
|
|
{ |
1165 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1166 |
|
|
png_ptr->chunkdata = NULL; |
1167 |
|
|
return; |
1168 |
|
|
} |
1169 |
|
|
|
1170 |
|
|
png_ptr->chunkdata[slength] = 0x00; |
1171 |
|
|
|
1172 |
|
|
for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++) |
1173 |
|
|
/* Empty loop to find end of name */ ; |
1174 |
|
|
++entry_start; |
1175 |
|
|
|
1176 |
|
|
/* A sample depth should follow the separator, and we should be on it */ |
1177 |
|
|
if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) |
1178 |
|
|
{ |
1179 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1180 |
|
|
png_ptr->chunkdata = NULL; |
1181 |
|
|
png_warning(png_ptr, "malformed sPLT chunk"); |
1182 |
|
|
return; |
1183 |
|
|
} |
1184 |
|
|
|
1185 |
|
|
new_palette.depth = *entry_start++; |
1186 |
|
|
entry_size = (new_palette.depth == 8 ? 6 : 10); |
1187 |
|
|
data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata)); |
1188 |
|
|
|
1189 |
|
|
/* Integrity-check the data length */ |
1190 |
|
|
if (data_length % entry_size) |
1191 |
|
|
{ |
1192 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1193 |
|
|
png_ptr->chunkdata = NULL; |
1194 |
|
|
png_warning(png_ptr, "sPLT chunk has bad length"); |
1195 |
|
|
return; |
1196 |
|
|
} |
1197 |
|
|
|
1198 |
|
|
new_palette.nentries = (png_int_32) ( data_length / entry_size); |
1199 |
|
|
if ((png_uint_32) new_palette.nentries > |
1200 |
|
|
(png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry))) |
1201 |
|
|
{ |
1202 |
|
|
png_warning(png_ptr, "sPLT chunk too long"); |
1203 |
|
|
return; |
1204 |
|
|
} |
1205 |
|
|
new_palette.entries = (png_sPLT_entryp)png_malloc_warn( |
1206 |
|
|
png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); |
1207 |
|
|
if (new_palette.entries == NULL) |
1208 |
|
|
{ |
1209 |
|
|
png_warning(png_ptr, "sPLT chunk requires too much memory"); |
1210 |
|
|
return; |
1211 |
|
|
} |
1212 |
|
|
|
1213 |
|
|
#ifndef PNG_NO_POINTER_INDEXING |
1214 |
|
|
for (i = 0; i < new_palette.nentries; i++) |
1215 |
|
|
{ |
1216 |
|
|
png_sPLT_entryp pp = new_palette.entries + i; |
1217 |
|
|
|
1218 |
|
|
if (new_palette.depth == 8) |
1219 |
|
|
{ |
1220 |
|
|
pp->red = *entry_start++; |
1221 |
|
|
pp->green = *entry_start++; |
1222 |
|
|
pp->blue = *entry_start++; |
1223 |
|
|
pp->alpha = *entry_start++; |
1224 |
|
|
} |
1225 |
|
|
else |
1226 |
|
|
{ |
1227 |
|
|
pp->red = png_get_uint_16(entry_start); entry_start += 2; |
1228 |
|
|
pp->green = png_get_uint_16(entry_start); entry_start += 2; |
1229 |
|
|
pp->blue = png_get_uint_16(entry_start); entry_start += 2; |
1230 |
|
|
pp->alpha = png_get_uint_16(entry_start); entry_start += 2; |
1231 |
|
|
} |
1232 |
|
|
pp->frequency = png_get_uint_16(entry_start); entry_start += 2; |
1233 |
|
|
} |
1234 |
|
|
#else |
1235 |
|
|
pp = new_palette.entries; |
1236 |
|
|
for (i = 0; i < new_palette.nentries; i++) |
1237 |
|
|
{ |
1238 |
|
|
|
1239 |
|
|
if (new_palette.depth == 8) |
1240 |
|
|
{ |
1241 |
|
|
pp[i].red = *entry_start++; |
1242 |
|
|
pp[i].green = *entry_start++; |
1243 |
|
|
pp[i].blue = *entry_start++; |
1244 |
|
|
pp[i].alpha = *entry_start++; |
1245 |
|
|
} |
1246 |
|
|
else |
1247 |
|
|
{ |
1248 |
|
|
pp[i].red = png_get_uint_16(entry_start); entry_start += 2; |
1249 |
|
|
pp[i].green = png_get_uint_16(entry_start); entry_start += 2; |
1250 |
|
|
pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; |
1251 |
|
|
pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; |
1252 |
|
|
} |
1253 |
|
|
pp->frequency = png_get_uint_16(entry_start); entry_start += 2; |
1254 |
|
|
} |
1255 |
|
|
#endif |
1256 |
|
|
|
1257 |
|
|
/* Discard all chunk data except the name and stash that */ |
1258 |
|
|
new_palette.name = png_ptr->chunkdata; |
1259 |
|
|
|
1260 |
|
|
png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); |
1261 |
|
|
|
1262 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1263 |
|
|
png_ptr->chunkdata = NULL; |
1264 |
|
|
png_free(png_ptr, new_palette.entries); |
1265 |
|
|
} |
1266 |
|
|
#endif /* PNG_READ_sPLT_SUPPORTED */ |
1267 |
|
|
|
1268 |
|
|
#if defined(PNG_READ_tRNS_SUPPORTED) |
1269 |
|
|
void /* PRIVATE */ |
1270 |
|
|
png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1271 |
|
|
{ |
1272 |
|
|
png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; |
1273 |
|
|
|
1274 |
|
|
png_debug(1, "in png_handle_tRNS"); |
1275 |
|
|
|
1276 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1277 |
|
|
png_error(png_ptr, "Missing IHDR before tRNS"); |
1278 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1279 |
|
|
{ |
1280 |
|
|
png_warning(png_ptr, "Invalid tRNS after IDAT"); |
1281 |
|
|
png_crc_finish(png_ptr, length); |
1282 |
|
|
return; |
1283 |
|
|
} |
1284 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) |
1285 |
|
|
{ |
1286 |
|
|
png_warning(png_ptr, "Duplicate tRNS chunk"); |
1287 |
|
|
png_crc_finish(png_ptr, length); |
1288 |
|
|
return; |
1289 |
|
|
} |
1290 |
|
|
|
1291 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) |
1292 |
|
|
{ |
1293 |
|
|
png_byte buf[2]; |
1294 |
|
|
|
1295 |
|
|
if (length != 2) |
1296 |
|
|
{ |
1297 |
|
|
png_warning(png_ptr, "Incorrect tRNS chunk length"); |
1298 |
|
|
png_crc_finish(png_ptr, length); |
1299 |
|
|
return; |
1300 |
|
|
} |
1301 |
|
|
|
1302 |
|
|
png_crc_read(png_ptr, buf, 2); |
1303 |
|
|
png_ptr->num_trans = 1; |
1304 |
|
|
png_ptr->trans_values.gray = png_get_uint_16(buf); |
1305 |
|
|
} |
1306 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) |
1307 |
|
|
{ |
1308 |
|
|
png_byte buf[6]; |
1309 |
|
|
|
1310 |
|
|
if (length != 6) |
1311 |
|
|
{ |
1312 |
|
|
png_warning(png_ptr, "Incorrect tRNS chunk length"); |
1313 |
|
|
png_crc_finish(png_ptr, length); |
1314 |
|
|
return; |
1315 |
|
|
} |
1316 |
|
|
png_crc_read(png_ptr, buf, (png_size_t)length); |
1317 |
|
|
png_ptr->num_trans = 1; |
1318 |
|
|
png_ptr->trans_values.red = png_get_uint_16(buf); |
1319 |
|
|
png_ptr->trans_values.green = png_get_uint_16(buf + 2); |
1320 |
|
|
png_ptr->trans_values.blue = png_get_uint_16(buf + 4); |
1321 |
|
|
} |
1322 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
1323 |
|
|
{ |
1324 |
|
|
if (!(png_ptr->mode & PNG_HAVE_PLTE)) |
1325 |
|
|
{ |
1326 |
|
|
/* Should be an error, but we can cope with it. */ |
1327 |
|
|
png_warning(png_ptr, "Missing PLTE before tRNS"); |
1328 |
|
|
} |
1329 |
|
|
if (length > (png_uint_32)png_ptr->num_palette || |
1330 |
|
|
length > PNG_MAX_PALETTE_LENGTH) |
1331 |
|
|
{ |
1332 |
|
|
png_warning(png_ptr, "Incorrect tRNS chunk length"); |
1333 |
|
|
png_crc_finish(png_ptr, length); |
1334 |
|
|
return; |
1335 |
|
|
} |
1336 |
|
|
if (length == 0) |
1337 |
|
|
{ |
1338 |
|
|
png_warning(png_ptr, "Zero length tRNS chunk"); |
1339 |
|
|
png_crc_finish(png_ptr, length); |
1340 |
|
|
return; |
1341 |
|
|
} |
1342 |
|
|
png_crc_read(png_ptr, readbuf, (png_size_t)length); |
1343 |
|
|
png_ptr->num_trans = (png_uint_16)length; |
1344 |
|
|
} |
1345 |
|
|
else |
1346 |
|
|
{ |
1347 |
|
|
png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); |
1348 |
|
|
png_crc_finish(png_ptr, length); |
1349 |
|
|
return; |
1350 |
|
|
} |
1351 |
|
|
|
1352 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1353 |
|
|
{ |
1354 |
|
|
png_ptr->num_trans = 0; |
1355 |
|
|
return; |
1356 |
|
|
} |
1357 |
|
|
|
1358 |
|
|
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, |
1359 |
|
|
&(png_ptr->trans_values)); |
1360 |
|
|
} |
1361 |
|
|
#endif |
1362 |
|
|
|
1363 |
|
|
#if defined(PNG_READ_bKGD_SUPPORTED) |
1364 |
|
|
void /* PRIVATE */ |
1365 |
|
|
png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1366 |
|
|
{ |
1367 |
|
|
png_size_t truelen; |
1368 |
|
|
png_byte buf[6]; |
1369 |
|
|
|
1370 |
|
|
png_debug(1, "in png_handle_bKGD"); |
1371 |
|
|
|
1372 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1373 |
|
|
png_error(png_ptr, "Missing IHDR before bKGD"); |
1374 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1375 |
|
|
{ |
1376 |
|
|
png_warning(png_ptr, "Invalid bKGD after IDAT"); |
1377 |
|
|
png_crc_finish(png_ptr, length); |
1378 |
|
|
return; |
1379 |
|
|
} |
1380 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && |
1381 |
|
|
!(png_ptr->mode & PNG_HAVE_PLTE)) |
1382 |
|
|
{ |
1383 |
|
|
png_warning(png_ptr, "Missing PLTE before bKGD"); |
1384 |
|
|
png_crc_finish(png_ptr, length); |
1385 |
|
|
return; |
1386 |
|
|
} |
1387 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) |
1388 |
|
|
{ |
1389 |
|
|
png_warning(png_ptr, "Duplicate bKGD chunk"); |
1390 |
|
|
png_crc_finish(png_ptr, length); |
1391 |
|
|
return; |
1392 |
|
|
} |
1393 |
|
|
|
1394 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
1395 |
|
|
truelen = 1; |
1396 |
|
|
else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) |
1397 |
|
|
truelen = 6; |
1398 |
|
|
else |
1399 |
|
|
truelen = 2; |
1400 |
|
|
|
1401 |
|
|
if (length != truelen) |
1402 |
|
|
{ |
1403 |
|
|
png_warning(png_ptr, "Incorrect bKGD chunk length"); |
1404 |
|
|
png_crc_finish(png_ptr, length); |
1405 |
|
|
return; |
1406 |
|
|
} |
1407 |
|
|
|
1408 |
|
|
png_crc_read(png_ptr, buf, truelen); |
1409 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1410 |
|
|
return; |
1411 |
|
|
|
1412 |
|
|
/* We convert the index value into RGB components so that we can allow |
1413 |
|
|
* arbitrary RGB values for background when we have transparency, and |
1414 |
|
|
* so it is easy to determine the RGB values of the background color |
1415 |
|
|
* from the info_ptr struct. */ |
1416 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
1417 |
|
|
{ |
1418 |
|
|
png_ptr->background.index = buf[0]; |
1419 |
|
|
if (info_ptr && info_ptr->num_palette) |
1420 |
|
|
{ |
1421 |
|
|
if (buf[0] >= info_ptr->num_palette) |
1422 |
|
|
{ |
1423 |
|
|
png_warning(png_ptr, "Incorrect bKGD chunk index value"); |
1424 |
|
|
return; |
1425 |
|
|
} |
1426 |
|
|
png_ptr->background.red = |
1427 |
|
|
(png_uint_16)png_ptr->palette[buf[0]].red; |
1428 |
|
|
png_ptr->background.green = |
1429 |
|
|
(png_uint_16)png_ptr->palette[buf[0]].green; |
1430 |
|
|
png_ptr->background.blue = |
1431 |
|
|
(png_uint_16)png_ptr->palette[buf[0]].blue; |
1432 |
|
|
} |
1433 |
|
|
} |
1434 |
|
|
else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ |
1435 |
|
|
{ |
1436 |
|
|
png_ptr->background.red = |
1437 |
|
|
png_ptr->background.green = |
1438 |
|
|
png_ptr->background.blue = |
1439 |
|
|
png_ptr->background.gray = png_get_uint_16(buf); |
1440 |
|
|
} |
1441 |
|
|
else |
1442 |
|
|
{ |
1443 |
|
|
png_ptr->background.red = png_get_uint_16(buf); |
1444 |
|
|
png_ptr->background.green = png_get_uint_16(buf + 2); |
1445 |
|
|
png_ptr->background.blue = png_get_uint_16(buf + 4); |
1446 |
|
|
} |
1447 |
|
|
|
1448 |
|
|
png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); |
1449 |
|
|
} |
1450 |
|
|
#endif |
1451 |
|
|
|
1452 |
|
|
#if defined(PNG_READ_hIST_SUPPORTED) |
1453 |
|
|
void /* PRIVATE */ |
1454 |
|
|
png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1455 |
|
|
{ |
1456 |
|
|
unsigned int num, i; |
1457 |
|
|
png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; |
1458 |
|
|
|
1459 |
|
|
png_debug(1, "in png_handle_hIST"); |
1460 |
|
|
|
1461 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1462 |
|
|
png_error(png_ptr, "Missing IHDR before hIST"); |
1463 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1464 |
|
|
{ |
1465 |
|
|
png_warning(png_ptr, "Invalid hIST after IDAT"); |
1466 |
|
|
png_crc_finish(png_ptr, length); |
1467 |
|
|
return; |
1468 |
|
|
} |
1469 |
|
|
else if (!(png_ptr->mode & PNG_HAVE_PLTE)) |
1470 |
|
|
{ |
1471 |
|
|
png_warning(png_ptr, "Missing PLTE before hIST"); |
1472 |
|
|
png_crc_finish(png_ptr, length); |
1473 |
|
|
return; |
1474 |
|
|
} |
1475 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) |
1476 |
|
|
{ |
1477 |
|
|
png_warning(png_ptr, "Duplicate hIST chunk"); |
1478 |
|
|
png_crc_finish(png_ptr, length); |
1479 |
|
|
return; |
1480 |
|
|
} |
1481 |
|
|
|
1482 |
|
|
num = length / 2 ; |
1483 |
|
|
if (num != (unsigned int) png_ptr->num_palette || num > |
1484 |
|
|
(unsigned int) PNG_MAX_PALETTE_LENGTH) |
1485 |
|
|
{ |
1486 |
|
|
png_warning(png_ptr, "Incorrect hIST chunk length"); |
1487 |
|
|
png_crc_finish(png_ptr, length); |
1488 |
|
|
return; |
1489 |
|
|
} |
1490 |
|
|
|
1491 |
|
|
for (i = 0; i < num; i++) |
1492 |
|
|
{ |
1493 |
|
|
png_byte buf[2]; |
1494 |
|
|
|
1495 |
|
|
png_crc_read(png_ptr, buf, 2); |
1496 |
|
|
readbuf[i] = png_get_uint_16(buf); |
1497 |
|
|
} |
1498 |
|
|
|
1499 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1500 |
|
|
return; |
1501 |
|
|
|
1502 |
|
|
png_set_hIST(png_ptr, info_ptr, readbuf); |
1503 |
|
|
} |
1504 |
|
|
#endif |
1505 |
|
|
|
1506 |
|
|
#if defined(PNG_READ_pHYs_SUPPORTED) |
1507 |
|
|
void /* PRIVATE */ |
1508 |
|
|
png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1509 |
|
|
{ |
1510 |
|
|
png_byte buf[9]; |
1511 |
|
|
png_uint_32 res_x, res_y; |
1512 |
|
|
int unit_type; |
1513 |
|
|
|
1514 |
|
|
png_debug(1, "in png_handle_pHYs"); |
1515 |
|
|
|
1516 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1517 |
|
|
png_error(png_ptr, "Missing IHDR before pHYs"); |
1518 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1519 |
|
|
{ |
1520 |
|
|
png_warning(png_ptr, "Invalid pHYs after IDAT"); |
1521 |
|
|
png_crc_finish(png_ptr, length); |
1522 |
|
|
return; |
1523 |
|
|
} |
1524 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) |
1525 |
|
|
{ |
1526 |
|
|
png_warning(png_ptr, "Duplicate pHYs chunk"); |
1527 |
|
|
png_crc_finish(png_ptr, length); |
1528 |
|
|
return; |
1529 |
|
|
} |
1530 |
|
|
|
1531 |
|
|
if (length != 9) |
1532 |
|
|
{ |
1533 |
|
|
png_warning(png_ptr, "Incorrect pHYs chunk length"); |
1534 |
|
|
png_crc_finish(png_ptr, length); |
1535 |
|
|
return; |
1536 |
|
|
} |
1537 |
|
|
|
1538 |
|
|
png_crc_read(png_ptr, buf, 9); |
1539 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1540 |
|
|
return; |
1541 |
|
|
|
1542 |
|
|
res_x = png_get_uint_32(buf); |
1543 |
|
|
res_y = png_get_uint_32(buf + 4); |
1544 |
|
|
unit_type = buf[8]; |
1545 |
|
|
png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); |
1546 |
|
|
} |
1547 |
|
|
#endif |
1548 |
|
|
|
1549 |
|
|
#if defined(PNG_READ_oFFs_SUPPORTED) |
1550 |
|
|
void /* PRIVATE */ |
1551 |
|
|
png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1552 |
|
|
{ |
1553 |
|
|
png_byte buf[9]; |
1554 |
|
|
png_int_32 offset_x, offset_y; |
1555 |
|
|
int unit_type; |
1556 |
|
|
|
1557 |
|
|
png_debug(1, "in png_handle_oFFs"); |
1558 |
|
|
|
1559 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1560 |
|
|
png_error(png_ptr, "Missing IHDR before oFFs"); |
1561 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1562 |
|
|
{ |
1563 |
|
|
png_warning(png_ptr, "Invalid oFFs after IDAT"); |
1564 |
|
|
png_crc_finish(png_ptr, length); |
1565 |
|
|
return; |
1566 |
|
|
} |
1567 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) |
1568 |
|
|
{ |
1569 |
|
|
png_warning(png_ptr, "Duplicate oFFs chunk"); |
1570 |
|
|
png_crc_finish(png_ptr, length); |
1571 |
|
|
return; |
1572 |
|
|
} |
1573 |
|
|
|
1574 |
|
|
if (length != 9) |
1575 |
|
|
{ |
1576 |
|
|
png_warning(png_ptr, "Incorrect oFFs chunk length"); |
1577 |
|
|
png_crc_finish(png_ptr, length); |
1578 |
|
|
return; |
1579 |
|
|
} |
1580 |
|
|
|
1581 |
|
|
png_crc_read(png_ptr, buf, 9); |
1582 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1583 |
|
|
return; |
1584 |
|
|
|
1585 |
|
|
offset_x = png_get_int_32(buf); |
1586 |
|
|
offset_y = png_get_int_32(buf + 4); |
1587 |
|
|
unit_type = buf[8]; |
1588 |
|
|
png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); |
1589 |
|
|
} |
1590 |
|
|
#endif |
1591 |
|
|
|
1592 |
|
|
#if defined(PNG_READ_pCAL_SUPPORTED) |
1593 |
|
|
/* Read the pCAL chunk (described in the PNG Extensions document) */ |
1594 |
|
|
void /* PRIVATE */ |
1595 |
|
|
png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1596 |
|
|
{ |
1597 |
|
|
png_int_32 X0, X1; |
1598 |
|
|
png_byte type, nparams; |
1599 |
|
|
png_charp buf, units, endptr; |
1600 |
|
|
png_charpp params; |
1601 |
|
|
png_size_t slength; |
1602 |
|
|
int i; |
1603 |
|
|
|
1604 |
|
|
png_debug(1, "in png_handle_pCAL"); |
1605 |
|
|
|
1606 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1607 |
|
|
png_error(png_ptr, "Missing IHDR before pCAL"); |
1608 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1609 |
|
|
{ |
1610 |
|
|
png_warning(png_ptr, "Invalid pCAL after IDAT"); |
1611 |
|
|
png_crc_finish(png_ptr, length); |
1612 |
|
|
return; |
1613 |
|
|
} |
1614 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) |
1615 |
|
|
{ |
1616 |
|
|
png_warning(png_ptr, "Duplicate pCAL chunk"); |
1617 |
|
|
png_crc_finish(png_ptr, length); |
1618 |
|
|
return; |
1619 |
|
|
} |
1620 |
|
|
|
1621 |
|
|
png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)", |
1622 |
|
|
length + 1); |
1623 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1624 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); |
1625 |
|
|
if (png_ptr->chunkdata == NULL) |
1626 |
|
|
{ |
1627 |
|
|
png_warning(png_ptr, "No memory for pCAL purpose."); |
1628 |
|
|
return; |
1629 |
|
|
} |
1630 |
|
|
slength = (png_size_t)length; |
1631 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
1632 |
|
|
|
1633 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1634 |
|
|
{ |
1635 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1636 |
|
|
png_ptr->chunkdata = NULL; |
1637 |
|
|
return; |
1638 |
|
|
} |
1639 |
|
|
|
1640 |
|
|
png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ |
1641 |
|
|
|
1642 |
|
|
png_debug(3, "Finding end of pCAL purpose string"); |
1643 |
|
|
for (buf = png_ptr->chunkdata; *buf; buf++) |
1644 |
|
|
/* Empty loop */ ; |
1645 |
|
|
|
1646 |
|
|
endptr = png_ptr->chunkdata + slength; |
1647 |
|
|
|
1648 |
|
|
/* We need to have at least 12 bytes after the purpose string |
1649 |
|
|
in order to get the parameter information. */ |
1650 |
|
|
if (endptr <= buf + 12) |
1651 |
|
|
{ |
1652 |
|
|
png_warning(png_ptr, "Invalid pCAL data"); |
1653 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1654 |
|
|
png_ptr->chunkdata = NULL; |
1655 |
|
|
return; |
1656 |
|
|
} |
1657 |
|
|
|
1658 |
|
|
png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); |
1659 |
|
|
X0 = png_get_int_32((png_bytep)buf+1); |
1660 |
|
|
X1 = png_get_int_32((png_bytep)buf+5); |
1661 |
|
|
type = buf[9]; |
1662 |
|
|
nparams = buf[10]; |
1663 |
|
|
units = buf + 11; |
1664 |
|
|
|
1665 |
|
|
png_debug(3, "Checking pCAL equation type and number of parameters"); |
1666 |
|
|
/* Check that we have the right number of parameters for known |
1667 |
|
|
equation types. */ |
1668 |
|
|
if ((type == PNG_EQUATION_LINEAR && nparams != 2) || |
1669 |
|
|
(type == PNG_EQUATION_BASE_E && nparams != 3) || |
1670 |
|
|
(type == PNG_EQUATION_ARBITRARY && nparams != 3) || |
1671 |
|
|
(type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) |
1672 |
|
|
{ |
1673 |
|
|
png_warning(png_ptr, "Invalid pCAL parameters for equation type"); |
1674 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1675 |
|
|
png_ptr->chunkdata = NULL; |
1676 |
|
|
return; |
1677 |
|
|
} |
1678 |
|
|
else if (type >= PNG_EQUATION_LAST) |
1679 |
|
|
{ |
1680 |
|
|
png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); |
1681 |
|
|
} |
1682 |
|
|
|
1683 |
|
|
for (buf = units; *buf; buf++) |
1684 |
|
|
/* Empty loop to move past the units string. */ ; |
1685 |
|
|
|
1686 |
|
|
png_debug(3, "Allocating pCAL parameters array"); |
1687 |
|
|
params = (png_charpp)png_malloc_warn(png_ptr, |
1688 |
|
|
(png_uint_32)(nparams * png_sizeof(png_charp))) ; |
1689 |
|
|
if (params == NULL) |
1690 |
|
|
{ |
1691 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1692 |
|
|
png_ptr->chunkdata = NULL; |
1693 |
|
|
png_warning(png_ptr, "No memory for pCAL params."); |
1694 |
|
|
return; |
1695 |
|
|
} |
1696 |
|
|
|
1697 |
|
|
/* Get pointers to the start of each parameter string. */ |
1698 |
|
|
for (i = 0; i < (int)nparams; i++) |
1699 |
|
|
{ |
1700 |
|
|
buf++; /* Skip the null string terminator from previous parameter. */ |
1701 |
|
|
|
1702 |
|
|
png_debug1(3, "Reading pCAL parameter %d", i); |
1703 |
|
|
for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) |
1704 |
|
|
/* Empty loop to move past each parameter string */ ; |
1705 |
|
|
|
1706 |
|
|
/* Make sure we haven't run out of data yet */ |
1707 |
|
|
if (buf > endptr) |
1708 |
|
|
{ |
1709 |
|
|
png_warning(png_ptr, "Invalid pCAL data"); |
1710 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1711 |
|
|
png_ptr->chunkdata = NULL; |
1712 |
|
|
png_free(png_ptr, params); |
1713 |
|
|
return; |
1714 |
|
|
} |
1715 |
|
|
} |
1716 |
|
|
|
1717 |
|
|
png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, |
1718 |
|
|
units, params); |
1719 |
|
|
|
1720 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1721 |
|
|
png_ptr->chunkdata = NULL; |
1722 |
|
|
png_free(png_ptr, params); |
1723 |
|
|
} |
1724 |
|
|
#endif |
1725 |
|
|
|
1726 |
|
|
#if defined(PNG_READ_sCAL_SUPPORTED) |
1727 |
|
|
/* Read the sCAL chunk */ |
1728 |
|
|
void /* PRIVATE */ |
1729 |
|
|
png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1730 |
|
|
{ |
1731 |
|
|
png_charp ep; |
1732 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
1733 |
|
|
double width, height; |
1734 |
|
|
png_charp vp; |
1735 |
|
|
#else |
1736 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
1737 |
|
|
png_charp swidth, sheight; |
1738 |
|
|
#endif |
1739 |
|
|
#endif |
1740 |
|
|
png_size_t slength; |
1741 |
|
|
|
1742 |
|
|
png_debug(1, "in png_handle_sCAL"); |
1743 |
|
|
|
1744 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1745 |
|
|
png_error(png_ptr, "Missing IHDR before sCAL"); |
1746 |
|
|
else if (png_ptr->mode & PNG_HAVE_IDAT) |
1747 |
|
|
{ |
1748 |
|
|
png_warning(png_ptr, "Invalid sCAL after IDAT"); |
1749 |
|
|
png_crc_finish(png_ptr, length); |
1750 |
|
|
return; |
1751 |
|
|
} |
1752 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) |
1753 |
|
|
{ |
1754 |
|
|
png_warning(png_ptr, "Duplicate sCAL chunk"); |
1755 |
|
|
png_crc_finish(png_ptr, length); |
1756 |
|
|
return; |
1757 |
|
|
} |
1758 |
|
|
|
1759 |
|
|
png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)", |
1760 |
|
|
length + 1); |
1761 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); |
1762 |
|
|
if (png_ptr->chunkdata == NULL) |
1763 |
|
|
{ |
1764 |
|
|
png_warning(png_ptr, "Out of memory while processing sCAL chunk"); |
1765 |
|
|
return; |
1766 |
|
|
} |
1767 |
|
|
slength = (png_size_t)length; |
1768 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
1769 |
|
|
|
1770 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1771 |
|
|
{ |
1772 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1773 |
|
|
png_ptr->chunkdata = NULL; |
1774 |
|
|
return; |
1775 |
|
|
} |
1776 |
|
|
|
1777 |
|
|
png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ |
1778 |
|
|
|
1779 |
|
|
ep = png_ptr->chunkdata + 1; /* Skip unit byte */ |
1780 |
|
|
|
1781 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
1782 |
|
|
width = png_strtod(png_ptr, ep, &vp); |
1783 |
|
|
if (*vp) |
1784 |
|
|
{ |
1785 |
|
|
png_warning(png_ptr, "malformed width string in sCAL chunk"); |
1786 |
|
|
return; |
1787 |
|
|
} |
1788 |
|
|
#else |
1789 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
1790 |
|
|
swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); |
1791 |
|
|
if (swidth == NULL) |
1792 |
|
|
{ |
1793 |
|
|
png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); |
1794 |
|
|
return; |
1795 |
|
|
} |
1796 |
|
|
png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); |
1797 |
|
|
#endif |
1798 |
|
|
#endif |
1799 |
|
|
|
1800 |
|
|
for (ep = png_ptr->chunkdata; *ep; ep++) |
1801 |
|
|
/* Empty loop */ ; |
1802 |
|
|
ep++; |
1803 |
|
|
|
1804 |
|
|
if (png_ptr->chunkdata + slength < ep) |
1805 |
|
|
{ |
1806 |
|
|
png_warning(png_ptr, "Truncated sCAL chunk"); |
1807 |
|
|
#if defined(PNG_FIXED_POINT_SUPPORTED) && \ |
1808 |
|
|
!defined(PNG_FLOATING_POINT_SUPPORTED) |
1809 |
|
|
png_free(png_ptr, swidth); |
1810 |
|
|
#endif |
1811 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1812 |
|
|
png_ptr->chunkdata = NULL; |
1813 |
|
|
return; |
1814 |
|
|
} |
1815 |
|
|
|
1816 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
1817 |
|
|
height = png_strtod(png_ptr, ep, &vp); |
1818 |
|
|
if (*vp) |
1819 |
|
|
{ |
1820 |
|
|
png_warning(png_ptr, "malformed height string in sCAL chunk"); |
1821 |
|
|
return; |
1822 |
|
|
} |
1823 |
|
|
#else |
1824 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
1825 |
|
|
sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); |
1826 |
|
|
if (sheight == NULL) |
1827 |
|
|
{ |
1828 |
|
|
png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); |
1829 |
|
|
return; |
1830 |
|
|
} |
1831 |
|
|
png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); |
1832 |
|
|
#endif |
1833 |
|
|
#endif |
1834 |
|
|
|
1835 |
|
|
if (png_ptr->chunkdata + slength < ep |
1836 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
1837 |
|
|
|| width <= 0. || height <= 0. |
1838 |
|
|
#endif |
1839 |
|
|
) |
1840 |
|
|
{ |
1841 |
|
|
png_warning(png_ptr, "Invalid sCAL data"); |
1842 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1843 |
|
|
png_ptr->chunkdata = NULL; |
1844 |
|
|
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) |
1845 |
|
|
png_free(png_ptr, swidth); |
1846 |
|
|
png_free(png_ptr, sheight); |
1847 |
|
|
#endif |
1848 |
|
|
return; |
1849 |
|
|
} |
1850 |
|
|
|
1851 |
|
|
|
1852 |
|
|
#ifdef PNG_FLOATING_POINT_SUPPORTED |
1853 |
|
|
png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height); |
1854 |
|
|
#else |
1855 |
|
|
#ifdef PNG_FIXED_POINT_SUPPORTED |
1856 |
|
|
png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight); |
1857 |
|
|
#endif |
1858 |
|
|
#endif |
1859 |
|
|
|
1860 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1861 |
|
|
png_ptr->chunkdata = NULL; |
1862 |
|
|
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) |
1863 |
|
|
png_free(png_ptr, swidth); |
1864 |
|
|
png_free(png_ptr, sheight); |
1865 |
|
|
#endif |
1866 |
|
|
} |
1867 |
|
|
#endif |
1868 |
|
|
|
1869 |
|
|
#if defined(PNG_READ_tIME_SUPPORTED) |
1870 |
|
|
void /* PRIVATE */ |
1871 |
|
|
png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1872 |
|
|
{ |
1873 |
|
|
png_byte buf[7]; |
1874 |
|
|
png_time mod_time; |
1875 |
|
|
|
1876 |
|
|
png_debug(1, "in png_handle_tIME"); |
1877 |
|
|
|
1878 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1879 |
|
|
png_error(png_ptr, "Out of place tIME chunk"); |
1880 |
|
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) |
1881 |
|
|
{ |
1882 |
|
|
png_warning(png_ptr, "Duplicate tIME chunk"); |
1883 |
|
|
png_crc_finish(png_ptr, length); |
1884 |
|
|
return; |
1885 |
|
|
} |
1886 |
|
|
|
1887 |
|
|
if (png_ptr->mode & PNG_HAVE_IDAT) |
1888 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
1889 |
|
|
|
1890 |
|
|
if (length != 7) |
1891 |
|
|
{ |
1892 |
|
|
png_warning(png_ptr, "Incorrect tIME chunk length"); |
1893 |
|
|
png_crc_finish(png_ptr, length); |
1894 |
|
|
return; |
1895 |
|
|
} |
1896 |
|
|
|
1897 |
|
|
png_crc_read(png_ptr, buf, 7); |
1898 |
|
|
if (png_crc_finish(png_ptr, 0)) |
1899 |
|
|
return; |
1900 |
|
|
|
1901 |
|
|
mod_time.second = buf[6]; |
1902 |
|
|
mod_time.minute = buf[5]; |
1903 |
|
|
mod_time.hour = buf[4]; |
1904 |
|
|
mod_time.day = buf[3]; |
1905 |
|
|
mod_time.month = buf[2]; |
1906 |
|
|
mod_time.year = png_get_uint_16(buf); |
1907 |
|
|
|
1908 |
|
|
png_set_tIME(png_ptr, info_ptr, &mod_time); |
1909 |
|
|
} |
1910 |
|
|
#endif |
1911 |
|
|
|
1912 |
|
|
#if defined(PNG_READ_tEXt_SUPPORTED) |
1913 |
|
|
/* Note: this does not properly handle chunks that are > 64K under DOS */ |
1914 |
|
|
void /* PRIVATE */ |
1915 |
|
|
png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
1916 |
|
|
{ |
1917 |
|
|
png_textp text_ptr; |
1918 |
|
|
png_charp key; |
1919 |
|
|
png_charp text; |
1920 |
|
|
png_uint_32 skip = 0; |
1921 |
|
|
png_size_t slength; |
1922 |
|
|
int ret; |
1923 |
|
|
|
1924 |
|
|
png_debug(1, "in png_handle_tEXt"); |
1925 |
|
|
|
1926 |
|
|
|
1927 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
1928 |
|
|
png_error(png_ptr, "Missing IHDR before tEXt"); |
1929 |
|
|
|
1930 |
|
|
if (png_ptr->mode & PNG_HAVE_IDAT) |
1931 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
1932 |
|
|
|
1933 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1934 |
|
|
if (length > (png_uint_32)65535L) |
1935 |
|
|
{ |
1936 |
|
|
png_warning(png_ptr, "tEXt chunk too large to fit in memory"); |
1937 |
|
|
skip = length - (png_uint_32)65535L; |
1938 |
|
|
length = (png_uint_32)65535L; |
1939 |
|
|
} |
1940 |
|
|
#endif |
1941 |
|
|
|
1942 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1943 |
|
|
|
1944 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); |
1945 |
|
|
if (png_ptr->chunkdata == NULL) |
1946 |
|
|
{ |
1947 |
|
|
png_warning(png_ptr, "No memory to process text chunk."); |
1948 |
|
|
return; |
1949 |
|
|
} |
1950 |
|
|
slength = (png_size_t)length; |
1951 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
1952 |
|
|
|
1953 |
|
|
if (png_crc_finish(png_ptr, skip)) |
1954 |
|
|
{ |
1955 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1956 |
|
|
png_ptr->chunkdata = NULL; |
1957 |
|
|
return; |
1958 |
|
|
} |
1959 |
|
|
|
1960 |
|
|
key = png_ptr->chunkdata; |
1961 |
|
|
|
1962 |
|
|
key[slength] = 0x00; |
1963 |
|
|
|
1964 |
|
|
for (text = key; *text; text++) |
1965 |
|
|
/* Empty loop to find end of key */ ; |
1966 |
|
|
|
1967 |
|
|
if (text != key + slength) |
1968 |
|
|
text++; |
1969 |
|
|
|
1970 |
|
|
text_ptr = (png_textp)png_malloc_warn(png_ptr, |
1971 |
|
|
(png_uint_32)png_sizeof(png_text)); |
1972 |
|
|
if (text_ptr == NULL) |
1973 |
|
|
{ |
1974 |
|
|
png_warning(png_ptr, "Not enough memory to process text chunk."); |
1975 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1976 |
|
|
png_ptr->chunkdata = NULL; |
1977 |
|
|
return; |
1978 |
|
|
} |
1979 |
|
|
text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; |
1980 |
|
|
text_ptr->key = key; |
1981 |
|
|
#ifdef PNG_iTXt_SUPPORTED |
1982 |
|
|
text_ptr->lang = NULL; |
1983 |
|
|
text_ptr->lang_key = NULL; |
1984 |
|
|
text_ptr->itxt_length = 0; |
1985 |
|
|
#endif |
1986 |
|
|
text_ptr->text = text; |
1987 |
|
|
text_ptr->text_length = png_strlen(text); |
1988 |
|
|
|
1989 |
|
|
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); |
1990 |
|
|
|
1991 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
1992 |
|
|
png_ptr->chunkdata = NULL; |
1993 |
|
|
png_free(png_ptr, text_ptr); |
1994 |
|
|
if (ret) |
1995 |
|
|
png_warning(png_ptr, "Insufficient memory to process text chunk."); |
1996 |
|
|
} |
1997 |
|
|
#endif |
1998 |
|
|
|
1999 |
|
|
#if defined(PNG_READ_zTXt_SUPPORTED) |
2000 |
|
|
/* Note: this does not correctly handle chunks that are > 64K under DOS */ |
2001 |
|
|
void /* PRIVATE */ |
2002 |
|
|
png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
2003 |
|
|
{ |
2004 |
|
|
png_textp text_ptr; |
2005 |
|
|
png_charp text; |
2006 |
|
|
int comp_type; |
2007 |
|
|
int ret; |
2008 |
|
|
png_size_t slength, prefix_len, data_len; |
2009 |
|
|
|
2010 |
|
|
png_debug(1, "in png_handle_zTXt"); |
2011 |
|
|
|
2012 |
|
|
|
2013 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
2014 |
|
|
png_error(png_ptr, "Missing IHDR before zTXt"); |
2015 |
|
|
|
2016 |
|
|
if (png_ptr->mode & PNG_HAVE_IDAT) |
2017 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
2018 |
|
|
|
2019 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
2020 |
|
|
/* We will no doubt have problems with chunks even half this size, but |
2021 |
|
|
there is no hard and fast rule to tell us where to stop. */ |
2022 |
|
|
if (length > (png_uint_32)65535L) |
2023 |
|
|
{ |
2024 |
|
|
png_warning(png_ptr, "zTXt chunk too large to fit in memory"); |
2025 |
|
|
png_crc_finish(png_ptr, length); |
2026 |
|
|
return; |
2027 |
|
|
} |
2028 |
|
|
#endif |
2029 |
|
|
|
2030 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2031 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); |
2032 |
|
|
if (png_ptr->chunkdata == NULL) |
2033 |
|
|
{ |
2034 |
|
|
png_warning(png_ptr, "Out of memory processing zTXt chunk."); |
2035 |
|
|
return; |
2036 |
|
|
} |
2037 |
|
|
slength = (png_size_t)length; |
2038 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
2039 |
|
|
if (png_crc_finish(png_ptr, 0)) |
2040 |
|
|
{ |
2041 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2042 |
|
|
png_ptr->chunkdata = NULL; |
2043 |
|
|
return; |
2044 |
|
|
} |
2045 |
|
|
|
2046 |
|
|
png_ptr->chunkdata[slength] = 0x00; |
2047 |
|
|
|
2048 |
|
|
for (text = png_ptr->chunkdata; *text; text++) |
2049 |
|
|
/* Empty loop */ ; |
2050 |
|
|
|
2051 |
|
|
/* zTXt must have some text after the chunkdataword */ |
2052 |
|
|
if (text >= png_ptr->chunkdata + slength - 2) |
2053 |
|
|
{ |
2054 |
|
|
png_warning(png_ptr, "Truncated zTXt chunk"); |
2055 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2056 |
|
|
png_ptr->chunkdata = NULL; |
2057 |
|
|
return; |
2058 |
|
|
} |
2059 |
|
|
else |
2060 |
|
|
{ |
2061 |
|
|
comp_type = *(++text); |
2062 |
|
|
if (comp_type != PNG_TEXT_COMPRESSION_zTXt) |
2063 |
|
|
{ |
2064 |
|
|
png_warning(png_ptr, "Unknown compression type in zTXt chunk"); |
2065 |
|
|
comp_type = PNG_TEXT_COMPRESSION_zTXt; |
2066 |
|
|
} |
2067 |
|
|
text++; /* Skip the compression_method byte */ |
2068 |
|
|
} |
2069 |
|
|
prefix_len = text - png_ptr->chunkdata; |
2070 |
|
|
|
2071 |
|
|
png_decompress_chunk(png_ptr, comp_type, |
2072 |
|
|
(png_size_t)length, prefix_len, &data_len); |
2073 |
|
|
|
2074 |
|
|
text_ptr = (png_textp)png_malloc_warn(png_ptr, |
2075 |
|
|
(png_uint_32)png_sizeof(png_text)); |
2076 |
|
|
if (text_ptr == NULL) |
2077 |
|
|
{ |
2078 |
|
|
png_warning(png_ptr, "Not enough memory to process zTXt chunk."); |
2079 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2080 |
|
|
png_ptr->chunkdata = NULL; |
2081 |
|
|
return; |
2082 |
|
|
} |
2083 |
|
|
text_ptr->compression = comp_type; |
2084 |
|
|
text_ptr->key = png_ptr->chunkdata; |
2085 |
|
|
#ifdef PNG_iTXt_SUPPORTED |
2086 |
|
|
text_ptr->lang = NULL; |
2087 |
|
|
text_ptr->lang_key = NULL; |
2088 |
|
|
text_ptr->itxt_length = 0; |
2089 |
|
|
#endif |
2090 |
|
|
text_ptr->text = png_ptr->chunkdata + prefix_len; |
2091 |
|
|
text_ptr->text_length = data_len; |
2092 |
|
|
|
2093 |
|
|
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); |
2094 |
|
|
|
2095 |
|
|
png_free(png_ptr, text_ptr); |
2096 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2097 |
|
|
png_ptr->chunkdata = NULL; |
2098 |
|
|
if (ret) |
2099 |
|
|
png_error(png_ptr, "Insufficient memory to store zTXt chunk."); |
2100 |
|
|
} |
2101 |
|
|
#endif |
2102 |
|
|
|
2103 |
|
|
#if defined(PNG_READ_iTXt_SUPPORTED) |
2104 |
|
|
/* Note: this does not correctly handle chunks that are > 64K under DOS */ |
2105 |
|
|
void /* PRIVATE */ |
2106 |
|
|
png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
2107 |
|
|
{ |
2108 |
|
|
png_textp text_ptr; |
2109 |
|
|
png_charp key, lang, text, lang_key; |
2110 |
|
|
int comp_flag; |
2111 |
|
|
int comp_type = 0; |
2112 |
|
|
int ret; |
2113 |
|
|
png_size_t slength, prefix_len, data_len; |
2114 |
|
|
|
2115 |
|
|
png_debug(1, "in png_handle_iTXt"); |
2116 |
|
|
|
2117 |
|
|
|
2118 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
2119 |
|
|
png_error(png_ptr, "Missing IHDR before iTXt"); |
2120 |
|
|
|
2121 |
|
|
if (png_ptr->mode & PNG_HAVE_IDAT) |
2122 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
2123 |
|
|
|
2124 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
2125 |
|
|
/* We will no doubt have problems with chunks even half this size, but |
2126 |
|
|
there is no hard and fast rule to tell us where to stop. */ |
2127 |
|
|
if (length > (png_uint_32)65535L) |
2128 |
|
|
{ |
2129 |
|
|
png_warning(png_ptr, "iTXt chunk too large to fit in memory"); |
2130 |
|
|
png_crc_finish(png_ptr, length); |
2131 |
|
|
return; |
2132 |
|
|
} |
2133 |
|
|
#endif |
2134 |
|
|
|
2135 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2136 |
|
|
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); |
2137 |
|
|
if (png_ptr->chunkdata == NULL) |
2138 |
|
|
{ |
2139 |
|
|
png_warning(png_ptr, "No memory to process iTXt chunk."); |
2140 |
|
|
return; |
2141 |
|
|
} |
2142 |
|
|
slength = (png_size_t)length; |
2143 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); |
2144 |
|
|
if (png_crc_finish(png_ptr, 0)) |
2145 |
|
|
{ |
2146 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2147 |
|
|
png_ptr->chunkdata = NULL; |
2148 |
|
|
return; |
2149 |
|
|
} |
2150 |
|
|
|
2151 |
|
|
png_ptr->chunkdata[slength] = 0x00; |
2152 |
|
|
|
2153 |
|
|
for (lang = png_ptr->chunkdata; *lang; lang++) |
2154 |
|
|
/* Empty loop */ ; |
2155 |
|
|
lang++; /* Skip NUL separator */ |
2156 |
|
|
|
2157 |
|
|
/* iTXt must have a language tag (possibly empty), two compression bytes, |
2158 |
|
|
* translated keyword (possibly empty), and possibly some text after the |
2159 |
|
|
* keyword |
2160 |
|
|
*/ |
2161 |
|
|
|
2162 |
|
|
if (lang >= png_ptr->chunkdata + slength - 3) |
2163 |
|
|
{ |
2164 |
|
|
png_warning(png_ptr, "Truncated iTXt chunk"); |
2165 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2166 |
|
|
png_ptr->chunkdata = NULL; |
2167 |
|
|
return; |
2168 |
|
|
} |
2169 |
|
|
else |
2170 |
|
|
{ |
2171 |
|
|
comp_flag = *lang++; |
2172 |
|
|
comp_type = *lang++; |
2173 |
|
|
} |
2174 |
|
|
|
2175 |
|
|
for (lang_key = lang; *lang_key; lang_key++) |
2176 |
|
|
/* Empty loop */ ; |
2177 |
|
|
lang_key++; /* Skip NUL separator */ |
2178 |
|
|
|
2179 |
|
|
if (lang_key >= png_ptr->chunkdata + slength) |
2180 |
|
|
{ |
2181 |
|
|
png_warning(png_ptr, "Truncated iTXt chunk"); |
2182 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2183 |
|
|
png_ptr->chunkdata = NULL; |
2184 |
|
|
return; |
2185 |
|
|
} |
2186 |
|
|
|
2187 |
|
|
for (text = lang_key; *text; text++) |
2188 |
|
|
/* Empty loop */ ; |
2189 |
|
|
text++; /* Skip NUL separator */ |
2190 |
|
|
if (text >= png_ptr->chunkdata + slength) |
2191 |
|
|
{ |
2192 |
|
|
png_warning(png_ptr, "Malformed iTXt chunk"); |
2193 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2194 |
|
|
png_ptr->chunkdata = NULL; |
2195 |
|
|
return; |
2196 |
|
|
} |
2197 |
|
|
|
2198 |
|
|
prefix_len = text - png_ptr->chunkdata; |
2199 |
|
|
|
2200 |
|
|
key=png_ptr->chunkdata; |
2201 |
|
|
if (comp_flag) |
2202 |
|
|
png_decompress_chunk(png_ptr, comp_type, |
2203 |
|
|
(size_t)length, prefix_len, &data_len); |
2204 |
|
|
else |
2205 |
|
|
data_len = png_strlen(png_ptr->chunkdata + prefix_len); |
2206 |
|
|
text_ptr = (png_textp)png_malloc_warn(png_ptr, |
2207 |
|
|
(png_uint_32)png_sizeof(png_text)); |
2208 |
|
|
if (text_ptr == NULL) |
2209 |
|
|
{ |
2210 |
|
|
png_warning(png_ptr, "Not enough memory to process iTXt chunk."); |
2211 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2212 |
|
|
png_ptr->chunkdata = NULL; |
2213 |
|
|
return; |
2214 |
|
|
} |
2215 |
|
|
text_ptr->compression = (int)comp_flag + 1; |
2216 |
|
|
text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); |
2217 |
|
|
text_ptr->lang = png_ptr->chunkdata + (lang - key); |
2218 |
|
|
text_ptr->itxt_length = data_len; |
2219 |
|
|
text_ptr->text_length = 0; |
2220 |
|
|
text_ptr->key = png_ptr->chunkdata; |
2221 |
|
|
text_ptr->text = png_ptr->chunkdata + prefix_len; |
2222 |
|
|
|
2223 |
|
|
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); |
2224 |
|
|
|
2225 |
|
|
png_free(png_ptr, text_ptr); |
2226 |
|
|
png_free(png_ptr, png_ptr->chunkdata); |
2227 |
|
|
png_ptr->chunkdata = NULL; |
2228 |
|
|
if (ret) |
2229 |
|
|
png_error(png_ptr, "Insufficient memory to store iTXt chunk."); |
2230 |
|
|
} |
2231 |
|
|
#endif |
2232 |
|
|
|
2233 |
|
|
/* This function is called when we haven't found a handler for a |
2234 |
|
|
chunk. If there isn't a problem with the chunk itself (ie bad |
2235 |
|
|
chunk name, CRC, or a critical chunk), the chunk is silently ignored |
2236 |
|
|
-- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which |
2237 |
|
|
case it will be saved away to be written out later. */ |
2238 |
|
|
void /* PRIVATE */ |
2239 |
|
|
png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) |
2240 |
|
|
{ |
2241 |
|
|
png_uint_32 skip = 0; |
2242 |
|
|
|
2243 |
|
|
png_debug(1, "in png_handle_unknown"); |
2244 |
|
|
|
2245 |
|
|
|
2246 |
|
|
if (png_ptr->mode & PNG_HAVE_IDAT) |
2247 |
|
|
{ |
2248 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
2249 |
|
|
PNG_CONST PNG_IDAT; |
2250 |
|
|
#endif |
2251 |
|
|
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ |
2252 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
2253 |
|
|
} |
2254 |
|
|
|
2255 |
|
|
if (!(png_ptr->chunk_name[0] & 0x20)) |
2256 |
|
|
{ |
2257 |
|
|
#if defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) |
2258 |
|
|
if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != |
2259 |
|
|
PNG_HANDLE_CHUNK_ALWAYS |
2260 |
|
|
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) |
2261 |
|
|
&& png_ptr->read_user_chunk_fn == NULL |
2262 |
|
|
#endif |
2263 |
|
|
) |
2264 |
|
|
#endif |
2265 |
|
|
png_chunk_error(png_ptr, "unknown critical chunk"); |
2266 |
|
|
} |
2267 |
|
|
|
2268 |
|
|
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) |
2269 |
|
|
if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) |
2270 |
|
|
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) |
2271 |
|
|
|| (png_ptr->read_user_chunk_fn != NULL) |
2272 |
|
|
#endif |
2273 |
|
|
) |
2274 |
|
|
{ |
2275 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
2276 |
|
|
if (length > (png_uint_32)65535L) |
2277 |
|
|
{ |
2278 |
|
|
png_warning(png_ptr, "unknown chunk too large to fit in memory"); |
2279 |
|
|
skip = length - (png_uint_32)65535L; |
2280 |
|
|
length = (png_uint_32)65535L; |
2281 |
|
|
} |
2282 |
|
|
#endif |
2283 |
|
|
png_memcpy((png_charp)png_ptr->unknown_chunk.name, |
2284 |
|
|
(png_charp)png_ptr->chunk_name, |
2285 |
|
|
png_sizeof(png_ptr->unknown_chunk.name)); |
2286 |
|
|
png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0'; |
2287 |
|
|
png_ptr->unknown_chunk.size = (png_size_t)length; |
2288 |
|
|
if (length == 0) |
2289 |
|
|
png_ptr->unknown_chunk.data = NULL; |
2290 |
|
|
else |
2291 |
|
|
{ |
2292 |
|
|
png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); |
2293 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); |
2294 |
|
|
} |
2295 |
|
|
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) |
2296 |
|
|
if (png_ptr->read_user_chunk_fn != NULL) |
2297 |
|
|
{ |
2298 |
|
|
/* Callback to user unknown chunk handler */ |
2299 |
|
|
int ret; |
2300 |
|
|
ret = (*(png_ptr->read_user_chunk_fn)) |
2301 |
|
|
(png_ptr, &png_ptr->unknown_chunk); |
2302 |
|
|
if (ret < 0) |
2303 |
|
|
png_chunk_error(png_ptr, "error in user chunk"); |
2304 |
|
|
if (ret == 0) |
2305 |
|
|
{ |
2306 |
|
|
if (!(png_ptr->chunk_name[0] & 0x20)) |
2307 |
|
|
#if defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) |
2308 |
|
|
if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != |
2309 |
|
|
PNG_HANDLE_CHUNK_ALWAYS) |
2310 |
|
|
#endif |
2311 |
|
|
png_chunk_error(png_ptr, "unknown critical chunk"); |
2312 |
|
|
png_set_unknown_chunks(png_ptr, info_ptr, |
2313 |
|
|
&png_ptr->unknown_chunk, 1); |
2314 |
|
|
} |
2315 |
|
|
} |
2316 |
|
|
else |
2317 |
|
|
#endif |
2318 |
|
|
png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); |
2319 |
|
|
png_free(png_ptr, png_ptr->unknown_chunk.data); |
2320 |
|
|
png_ptr->unknown_chunk.data = NULL; |
2321 |
|
|
} |
2322 |
|
|
else |
2323 |
|
|
#endif |
2324 |
|
|
skip = length; |
2325 |
|
|
|
2326 |
|
|
png_crc_finish(png_ptr, skip); |
2327 |
|
|
|
2328 |
|
|
#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) |
2329 |
|
|
info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ |
2330 |
|
|
#endif |
2331 |
|
|
} |
2332 |
|
|
|
2333 |
|
|
/* This function is called to verify that a chunk name is valid. |
2334 |
|
|
This function can't have the "critical chunk check" incorporated |
2335 |
|
|
into it, since in the future we will need to be able to call user |
2336 |
|
|
functions to handle unknown critical chunks after we check that |
2337 |
|
|
the chunk name itself is valid. */ |
2338 |
|
|
|
2339 |
|
|
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) |
2340 |
|
|
|
2341 |
|
|
void /* PRIVATE */ |
2342 |
|
|
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) |
2343 |
|
|
{ |
2344 |
|
|
png_debug(1, "in png_check_chunk_name"); |
2345 |
|
|
if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || |
2346 |
|
|
isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) |
2347 |
|
|
{ |
2348 |
|
|
png_chunk_error(png_ptr, "invalid chunk type"); |
2349 |
|
|
} |
2350 |
|
|
} |
2351 |
|
|
|
2352 |
|
|
/* Combines the row recently read in with the existing pixels in the |
2353 |
|
|
row. This routine takes care of alpha and transparency if requested. |
2354 |
|
|
This routine also handles the two methods of progressive display |
2355 |
|
|
of interlaced images, depending on the mask value. |
2356 |
|
|
The mask value describes which pixels are to be combined with |
2357 |
|
|
the row. The pattern always repeats every 8 pixels, so just 8 |
2358 |
|
|
bits are needed. A one indicates the pixel is to be combined, |
2359 |
|
|
a zero indicates the pixel is to be skipped. This is in addition |
2360 |
|
|
to any alpha or transparency value associated with the pixel. If |
2361 |
|
|
you want all pixels to be combined, pass 0xff (255) in mask. */ |
2362 |
|
|
|
2363 |
|
|
void /* PRIVATE */ |
2364 |
|
|
png_combine_row(png_structp png_ptr, png_bytep row, int mask) |
2365 |
|
|
{ |
2366 |
|
|
png_debug(1, "in png_combine_row"); |
2367 |
|
|
if (mask == 0xff) |
2368 |
|
|
{ |
2369 |
|
|
png_memcpy(row, png_ptr->row_buf + 1, |
2370 |
|
|
PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); |
2371 |
|
|
} |
2372 |
|
|
else |
2373 |
|
|
{ |
2374 |
|
|
switch (png_ptr->row_info.pixel_depth) |
2375 |
|
|
{ |
2376 |
|
|
case 1: |
2377 |
|
|
{ |
2378 |
|
|
png_bytep sp = png_ptr->row_buf + 1; |
2379 |
|
|
png_bytep dp = row; |
2380 |
|
|
int s_inc, s_start, s_end; |
2381 |
|
|
int m = 0x80; |
2382 |
|
|
int shift; |
2383 |
|
|
png_uint_32 i; |
2384 |
|
|
png_uint_32 row_width = png_ptr->width; |
2385 |
|
|
|
2386 |
|
|
#if defined(PNG_READ_PACKSWAP_SUPPORTED) |
2387 |
|
|
if (png_ptr->transformations & PNG_PACKSWAP) |
2388 |
|
|
{ |
2389 |
|
|
s_start = 0; |
2390 |
|
|
s_end = 7; |
2391 |
|
|
s_inc = 1; |
2392 |
|
|
} |
2393 |
|
|
else |
2394 |
|
|
#endif |
2395 |
|
|
{ |
2396 |
|
|
s_start = 7; |
2397 |
|
|
s_end = 0; |
2398 |
|
|
s_inc = -1; |
2399 |
|
|
} |
2400 |
|
|
|
2401 |
|
|
shift = s_start; |
2402 |
|
|
|
2403 |
|
|
for (i = 0; i < row_width; i++) |
2404 |
|
|
{ |
2405 |
|
|
if (m & mask) |
2406 |
|
|
{ |
2407 |
|
|
int value; |
2408 |
|
|
|
2409 |
|
|
value = (*sp >> shift) & 0x01; |
2410 |
|
|
*dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); |
2411 |
|
|
*dp |= (png_byte)(value << shift); |
2412 |
|
|
} |
2413 |
|
|
|
2414 |
|
|
if (shift == s_end) |
2415 |
|
|
{ |
2416 |
|
|
shift = s_start; |
2417 |
|
|
sp++; |
2418 |
|
|
dp++; |
2419 |
|
|
} |
2420 |
|
|
else |
2421 |
|
|
shift += s_inc; |
2422 |
|
|
|
2423 |
|
|
if (m == 1) |
2424 |
|
|
m = 0x80; |
2425 |
|
|
else |
2426 |
|
|
m >>= 1; |
2427 |
|
|
} |
2428 |
|
|
break; |
2429 |
|
|
} |
2430 |
|
|
case 2: |
2431 |
|
|
{ |
2432 |
|
|
png_bytep sp = png_ptr->row_buf + 1; |
2433 |
|
|
png_bytep dp = row; |
2434 |
|
|
int s_start, s_end, s_inc; |
2435 |
|
|
int m = 0x80; |
2436 |
|
|
int shift; |
2437 |
|
|
png_uint_32 i; |
2438 |
|
|
png_uint_32 row_width = png_ptr->width; |
2439 |
|
|
int value; |
2440 |
|
|
|
2441 |
|
|
#if defined(PNG_READ_PACKSWAP_SUPPORTED) |
2442 |
|
|
if (png_ptr->transformations & PNG_PACKSWAP) |
2443 |
|
|
{ |
2444 |
|
|
s_start = 0; |
2445 |
|
|
s_end = 6; |
2446 |
|
|
s_inc = 2; |
2447 |
|
|
} |
2448 |
|
|
else |
2449 |
|
|
#endif |
2450 |
|
|
{ |
2451 |
|
|
s_start = 6; |
2452 |
|
|
s_end = 0; |
2453 |
|
|
s_inc = -2; |
2454 |
|
|
} |
2455 |
|
|
|
2456 |
|
|
shift = s_start; |
2457 |
|
|
|
2458 |
|
|
for (i = 0; i < row_width; i++) |
2459 |
|
|
{ |
2460 |
|
|
if (m & mask) |
2461 |
|
|
{ |
2462 |
|
|
value = (*sp >> shift) & 0x03; |
2463 |
|
|
*dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); |
2464 |
|
|
*dp |= (png_byte)(value << shift); |
2465 |
|
|
} |
2466 |
|
|
|
2467 |
|
|
if (shift == s_end) |
2468 |
|
|
{ |
2469 |
|
|
shift = s_start; |
2470 |
|
|
sp++; |
2471 |
|
|
dp++; |
2472 |
|
|
} |
2473 |
|
|
else |
2474 |
|
|
shift += s_inc; |
2475 |
|
|
if (m == 1) |
2476 |
|
|
m = 0x80; |
2477 |
|
|
else |
2478 |
|
|
m >>= 1; |
2479 |
|
|
} |
2480 |
|
|
break; |
2481 |
|
|
} |
2482 |
|
|
case 4: |
2483 |
|
|
{ |
2484 |
|
|
png_bytep sp = png_ptr->row_buf + 1; |
2485 |
|
|
png_bytep dp = row; |
2486 |
|
|
int s_start, s_end, s_inc; |
2487 |
|
|
int m = 0x80; |
2488 |
|
|
int shift; |
2489 |
|
|
png_uint_32 i; |
2490 |
|
|
png_uint_32 row_width = png_ptr->width; |
2491 |
|
|
int value; |
2492 |
|
|
|
2493 |
|
|
#if defined(PNG_READ_PACKSWAP_SUPPORTED) |
2494 |
|
|
if (png_ptr->transformations & PNG_PACKSWAP) |
2495 |
|
|
{ |
2496 |
|
|
s_start = 0; |
2497 |
|
|
s_end = 4; |
2498 |
|
|
s_inc = 4; |
2499 |
|
|
} |
2500 |
|
|
else |
2501 |
|
|
#endif |
2502 |
|
|
{ |
2503 |
|
|
s_start = 4; |
2504 |
|
|
s_end = 0; |
2505 |
|
|
s_inc = -4; |
2506 |
|
|
} |
2507 |
|
|
shift = s_start; |
2508 |
|
|
|
2509 |
|
|
for (i = 0; i < row_width; i++) |
2510 |
|
|
{ |
2511 |
|
|
if (m & mask) |
2512 |
|
|
{ |
2513 |
|
|
value = (*sp >> shift) & 0xf; |
2514 |
|
|
*dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); |
2515 |
|
|
*dp |= (png_byte)(value << shift); |
2516 |
|
|
} |
2517 |
|
|
|
2518 |
|
|
if (shift == s_end) |
2519 |
|
|
{ |
2520 |
|
|
shift = s_start; |
2521 |
|
|
sp++; |
2522 |
|
|
dp++; |
2523 |
|
|
} |
2524 |
|
|
else |
2525 |
|
|
shift += s_inc; |
2526 |
|
|
if (m == 1) |
2527 |
|
|
m = 0x80; |
2528 |
|
|
else |
2529 |
|
|
m >>= 1; |
2530 |
|
|
} |
2531 |
|
|
break; |
2532 |
|
|
} |
2533 |
|
|
default: |
2534 |
|
|
{ |
2535 |
|
|
png_bytep sp = png_ptr->row_buf + 1; |
2536 |
|
|
png_bytep dp = row; |
2537 |
|
|
png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); |
2538 |
|
|
png_uint_32 i; |
2539 |
|
|
png_uint_32 row_width = png_ptr->width; |
2540 |
|
|
png_byte m = 0x80; |
2541 |
|
|
|
2542 |
|
|
|
2543 |
|
|
for (i = 0; i < row_width; i++) |
2544 |
|
|
{ |
2545 |
|
|
if (m & mask) |
2546 |
|
|
{ |
2547 |
|
|
png_memcpy(dp, sp, pixel_bytes); |
2548 |
|
|
} |
2549 |
|
|
|
2550 |
|
|
sp += pixel_bytes; |
2551 |
|
|
dp += pixel_bytes; |
2552 |
|
|
|
2553 |
|
|
if (m == 1) |
2554 |
|
|
m = 0x80; |
2555 |
|
|
else |
2556 |
|
|
m >>= 1; |
2557 |
|
|
} |
2558 |
|
|
break; |
2559 |
|
|
} |
2560 |
|
|
} |
2561 |
|
|
} |
2562 |
|
|
} |
2563 |
|
|
|
2564 |
|
|
#ifdef PNG_READ_INTERLACING_SUPPORTED |
2565 |
|
|
/* OLD pre-1.0.9 interface: |
2566 |
|
|
void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, |
2567 |
|
|
png_uint_32 transformations) |
2568 |
|
|
*/ |
2569 |
|
|
void /* PRIVATE */ |
2570 |
|
|
png_do_read_interlace(png_structp png_ptr) |
2571 |
|
|
{ |
2572 |
|
|
png_row_infop row_info = &(png_ptr->row_info); |
2573 |
|
|
png_bytep row = png_ptr->row_buf + 1; |
2574 |
|
|
int pass = png_ptr->pass; |
2575 |
|
|
png_uint_32 transformations = png_ptr->transformations; |
2576 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
2577 |
|
|
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
2578 |
|
|
/* Offset to next interlace block */ |
2579 |
|
|
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
2580 |
|
|
#endif |
2581 |
|
|
|
2582 |
|
|
png_debug(1, "in png_do_read_interlace"); |
2583 |
|
|
if (row != NULL && row_info != NULL) |
2584 |
|
|
{ |
2585 |
|
|
png_uint_32 final_width; |
2586 |
|
|
|
2587 |
|
|
final_width = row_info->width * png_pass_inc[pass]; |
2588 |
|
|
|
2589 |
|
|
switch (row_info->pixel_depth) |
2590 |
|
|
{ |
2591 |
|
|
case 1: |
2592 |
|
|
{ |
2593 |
|
|
png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); |
2594 |
|
|
png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); |
2595 |
|
|
int sshift, dshift; |
2596 |
|
|
int s_start, s_end, s_inc; |
2597 |
|
|
int jstop = png_pass_inc[pass]; |
2598 |
|
|
png_byte v; |
2599 |
|
|
png_uint_32 i; |
2600 |
|
|
int j; |
2601 |
|
|
|
2602 |
|
|
#if defined(PNG_READ_PACKSWAP_SUPPORTED) |
2603 |
|
|
if (transformations & PNG_PACKSWAP) |
2604 |
|
|
{ |
2605 |
|
|
sshift = (int)((row_info->width + 7) & 0x07); |
2606 |
|
|
dshift = (int)((final_width + 7) & 0x07); |
2607 |
|
|
s_start = 7; |
2608 |
|
|
s_end = 0; |
2609 |
|
|
s_inc = -1; |
2610 |
|
|
} |
2611 |
|
|
else |
2612 |
|
|
#endif |
2613 |
|
|
{ |
2614 |
|
|
sshift = 7 - (int)((row_info->width + 7) & 0x07); |
2615 |
|
|
dshift = 7 - (int)((final_width + 7) & 0x07); |
2616 |
|
|
s_start = 0; |
2617 |
|
|
s_end = 7; |
2618 |
|
|
s_inc = 1; |
2619 |
|
|
} |
2620 |
|
|
|
2621 |
|
|
for (i = 0; i < row_info->width; i++) |
2622 |
|
|
{ |
2623 |
|
|
v = (png_byte)((*sp >> sshift) & 0x01); |
2624 |
|
|
for (j = 0; j < jstop; j++) |
2625 |
|
|
{ |
2626 |
|
|
*dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); |
2627 |
|
|
*dp |= (png_byte)(v << dshift); |
2628 |
|
|
if (dshift == s_end) |
2629 |
|
|
{ |
2630 |
|
|
dshift = s_start; |
2631 |
|
|
dp--; |
2632 |
|
|
} |
2633 |
|
|
else |
2634 |
|
|
dshift += s_inc; |
2635 |
|
|
} |
2636 |
|
|
if (sshift == s_end) |
2637 |
|
|
{ |
2638 |
|
|
sshift = s_start; |
2639 |
|
|
sp--; |
2640 |
|
|
} |
2641 |
|
|
else |
2642 |
|
|
sshift += s_inc; |
2643 |
|
|
} |
2644 |
|
|
break; |
2645 |
|
|
} |
2646 |
|
|
case 2: |
2647 |
|
|
{ |
2648 |
|
|
png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); |
2649 |
|
|
png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); |
2650 |
|
|
int sshift, dshift; |
2651 |
|
|
int s_start, s_end, s_inc; |
2652 |
|
|
int jstop = png_pass_inc[pass]; |
2653 |
|
|
png_uint_32 i; |
2654 |
|
|
|
2655 |
|
|
#if defined(PNG_READ_PACKSWAP_SUPPORTED) |
2656 |
|
|
if (transformations & PNG_PACKSWAP) |
2657 |
|
|
{ |
2658 |
|
|
sshift = (int)(((row_info->width + 3) & 0x03) << 1); |
2659 |
|
|
dshift = (int)(((final_width + 3) & 0x03) << 1); |
2660 |
|
|
s_start = 6; |
2661 |
|
|
s_end = 0; |
2662 |
|
|
s_inc = -2; |
2663 |
|
|
} |
2664 |
|
|
else |
2665 |
|
|
#endif |
2666 |
|
|
{ |
2667 |
|
|
sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); |
2668 |
|
|
dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); |
2669 |
|
|
s_start = 0; |
2670 |
|
|
s_end = 6; |
2671 |
|
|
s_inc = 2; |
2672 |
|
|
} |
2673 |
|
|
|
2674 |
|
|
for (i = 0; i < row_info->width; i++) |
2675 |
|
|
{ |
2676 |
|
|
png_byte v; |
2677 |
|
|
int j; |
2678 |
|
|
|
2679 |
|
|
v = (png_byte)((*sp >> sshift) & 0x03); |
2680 |
|
|
for (j = 0; j < jstop; j++) |
2681 |
|
|
{ |
2682 |
|
|
*dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); |
2683 |
|
|
*dp |= (png_byte)(v << dshift); |
2684 |
|
|
if (dshift == s_end) |
2685 |
|
|
{ |
2686 |
|
|
dshift = s_start; |
2687 |
|
|
dp--; |
2688 |
|
|
} |
2689 |
|
|
else |
2690 |
|
|
dshift += s_inc; |
2691 |
|
|
} |
2692 |
|
|
if (sshift == s_end) |
2693 |
|
|
{ |
2694 |
|
|
sshift = s_start; |
2695 |
|
|
sp--; |
2696 |
|
|
} |
2697 |
|
|
else |
2698 |
|
|
sshift += s_inc; |
2699 |
|
|
} |
2700 |
|
|
break; |
2701 |
|
|
} |
2702 |
|
|
case 4: |
2703 |
|
|
{ |
2704 |
|
|
png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); |
2705 |
|
|
png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); |
2706 |
|
|
int sshift, dshift; |
2707 |
|
|
int s_start, s_end, s_inc; |
2708 |
|
|
png_uint_32 i; |
2709 |
|
|
int jstop = png_pass_inc[pass]; |
2710 |
|
|
|
2711 |
|
|
#if defined(PNG_READ_PACKSWAP_SUPPORTED) |
2712 |
|
|
if (transformations & PNG_PACKSWAP) |
2713 |
|
|
{ |
2714 |
|
|
sshift = (int)(((row_info->width + 1) & 0x01) << 2); |
2715 |
|
|
dshift = (int)(((final_width + 1) & 0x01) << 2); |
2716 |
|
|
s_start = 4; |
2717 |
|
|
s_end = 0; |
2718 |
|
|
s_inc = -4; |
2719 |
|
|
} |
2720 |
|
|
else |
2721 |
|
|
#endif |
2722 |
|
|
{ |
2723 |
|
|
sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); |
2724 |
|
|
dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); |
2725 |
|
|
s_start = 0; |
2726 |
|
|
s_end = 4; |
2727 |
|
|
s_inc = 4; |
2728 |
|
|
} |
2729 |
|
|
|
2730 |
|
|
for (i = 0; i < row_info->width; i++) |
2731 |
|
|
{ |
2732 |
|
|
png_byte v = (png_byte)((*sp >> sshift) & 0xf); |
2733 |
|
|
int j; |
2734 |
|
|
|
2735 |
|
|
for (j = 0; j < jstop; j++) |
2736 |
|
|
{ |
2737 |
|
|
*dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); |
2738 |
|
|
*dp |= (png_byte)(v << dshift); |
2739 |
|
|
if (dshift == s_end) |
2740 |
|
|
{ |
2741 |
|
|
dshift = s_start; |
2742 |
|
|
dp--; |
2743 |
|
|
} |
2744 |
|
|
else |
2745 |
|
|
dshift += s_inc; |
2746 |
|
|
} |
2747 |
|
|
if (sshift == s_end) |
2748 |
|
|
{ |
2749 |
|
|
sshift = s_start; |
2750 |
|
|
sp--; |
2751 |
|
|
} |
2752 |
|
|
else |
2753 |
|
|
sshift += s_inc; |
2754 |
|
|
} |
2755 |
|
|
break; |
2756 |
|
|
} |
2757 |
|
|
default: |
2758 |
|
|
{ |
2759 |
|
|
png_size_t pixel_bytes = (row_info->pixel_depth >> 3); |
2760 |
|
|
png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; |
2761 |
|
|
png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; |
2762 |
|
|
|
2763 |
|
|
int jstop = png_pass_inc[pass]; |
2764 |
|
|
png_uint_32 i; |
2765 |
|
|
|
2766 |
|
|
for (i = 0; i < row_info->width; i++) |
2767 |
|
|
{ |
2768 |
|
|
png_byte v[8]; |
2769 |
|
|
int j; |
2770 |
|
|
|
2771 |
|
|
png_memcpy(v, sp, pixel_bytes); |
2772 |
|
|
for (j = 0; j < jstop; j++) |
2773 |
|
|
{ |
2774 |
|
|
png_memcpy(dp, v, pixel_bytes); |
2775 |
|
|
dp -= pixel_bytes; |
2776 |
|
|
} |
2777 |
|
|
sp -= pixel_bytes; |
2778 |
|
|
} |
2779 |
|
|
break; |
2780 |
|
|
} |
2781 |
|
|
} |
2782 |
|
|
row_info->width = final_width; |
2783 |
|
|
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); |
2784 |
|
|
} |
2785 |
|
|
#if !defined(PNG_READ_PACKSWAP_SUPPORTED) |
2786 |
|
|
transformations = transformations; /* Silence compiler warning */ |
2787 |
|
|
#endif |
2788 |
|
|
} |
2789 |
|
|
#endif /* PNG_READ_INTERLACING_SUPPORTED */ |
2790 |
|
|
|
2791 |
|
|
void /* PRIVATE */ |
2792 |
|
|
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, |
2793 |
|
|
png_bytep prev_row, int filter) |
2794 |
|
|
{ |
2795 |
|
|
png_debug(1, "in png_read_filter_row"); |
2796 |
|
|
png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter); |
2797 |
|
|
switch (filter) |
2798 |
|
|
{ |
2799 |
|
|
case PNG_FILTER_VALUE_NONE: |
2800 |
|
|
break; |
2801 |
|
|
case PNG_FILTER_VALUE_SUB: |
2802 |
|
|
{ |
2803 |
|
|
png_uint_32 i; |
2804 |
|
|
png_uint_32 istop = row_info->rowbytes; |
2805 |
|
|
png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; |
2806 |
|
|
png_bytep rp = row + bpp; |
2807 |
|
|
png_bytep lp = row; |
2808 |
|
|
|
2809 |
|
|
for (i = bpp; i < istop; i++) |
2810 |
|
|
{ |
2811 |
|
|
*rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); |
2812 |
|
|
rp++; |
2813 |
|
|
} |
2814 |
|
|
break; |
2815 |
|
|
} |
2816 |
|
|
case PNG_FILTER_VALUE_UP: |
2817 |
|
|
{ |
2818 |
|
|
png_uint_32 i; |
2819 |
|
|
png_uint_32 istop = row_info->rowbytes; |
2820 |
|
|
png_bytep rp = row; |
2821 |
|
|
png_bytep pp = prev_row; |
2822 |
|
|
|
2823 |
|
|
for (i = 0; i < istop; i++) |
2824 |
|
|
{ |
2825 |
|
|
*rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); |
2826 |
|
|
rp++; |
2827 |
|
|
} |
2828 |
|
|
break; |
2829 |
|
|
} |
2830 |
|
|
case PNG_FILTER_VALUE_AVG: |
2831 |
|
|
{ |
2832 |
|
|
png_uint_32 i; |
2833 |
|
|
png_bytep rp = row; |
2834 |
|
|
png_bytep pp = prev_row; |
2835 |
|
|
png_bytep lp = row; |
2836 |
|
|
png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; |
2837 |
|
|
png_uint_32 istop = row_info->rowbytes - bpp; |
2838 |
|
|
|
2839 |
|
|
for (i = 0; i < bpp; i++) |
2840 |
|
|
{ |
2841 |
|
|
*rp = (png_byte)(((int)(*rp) + |
2842 |
|
|
((int)(*pp++) / 2 )) & 0xff); |
2843 |
|
|
rp++; |
2844 |
|
|
} |
2845 |
|
|
|
2846 |
|
|
for (i = 0; i < istop; i++) |
2847 |
|
|
{ |
2848 |
|
|
*rp = (png_byte)(((int)(*rp) + |
2849 |
|
|
(int)(*pp++ + *lp++) / 2 ) & 0xff); |
2850 |
|
|
rp++; |
2851 |
|
|
} |
2852 |
|
|
break; |
2853 |
|
|
} |
2854 |
|
|
case PNG_FILTER_VALUE_PAETH: |
2855 |
|
|
{ |
2856 |
|
|
png_uint_32 i; |
2857 |
|
|
png_bytep rp = row; |
2858 |
|
|
png_bytep pp = prev_row; |
2859 |
|
|
png_bytep lp = row; |
2860 |
|
|
png_bytep cp = prev_row; |
2861 |
|
|
png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; |
2862 |
|
|
png_uint_32 istop=row_info->rowbytes - bpp; |
2863 |
|
|
|
2864 |
|
|
for (i = 0; i < bpp; i++) |
2865 |
|
|
{ |
2866 |
|
|
*rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); |
2867 |
|
|
rp++; |
2868 |
|
|
} |
2869 |
|
|
|
2870 |
|
|
for (i = 0; i < istop; i++) /* Use leftover rp,pp */ |
2871 |
|
|
{ |
2872 |
|
|
int a, b, c, pa, pb, pc, p; |
2873 |
|
|
|
2874 |
|
|
a = *lp++; |
2875 |
|
|
b = *pp++; |
2876 |
|
|
c = *cp++; |
2877 |
|
|
|
2878 |
|
|
p = b - c; |
2879 |
|
|
pc = a - c; |
2880 |
|
|
|
2881 |
|
|
#ifdef PNG_USE_ABS |
2882 |
|
|
pa = abs(p); |
2883 |
|
|
pb = abs(pc); |
2884 |
|
|
pc = abs(p + pc); |
2885 |
|
|
#else |
2886 |
|
|
pa = p < 0 ? -p : p; |
2887 |
|
|
pb = pc < 0 ? -pc : pc; |
2888 |
|
|
pc = (p + pc) < 0 ? -(p + pc) : p + pc; |
2889 |
|
|
#endif |
2890 |
|
|
|
2891 |
|
|
/* |
2892 |
|
|
if (pa <= pb && pa <= pc) |
2893 |
|
|
p = a; |
2894 |
|
|
else if (pb <= pc) |
2895 |
|
|
p = b; |
2896 |
|
|
else |
2897 |
|
|
p = c; |
2898 |
|
|
*/ |
2899 |
|
|
|
2900 |
|
|
p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; |
2901 |
|
|
|
2902 |
|
|
*rp = (png_byte)(((int)(*rp) + p) & 0xff); |
2903 |
|
|
rp++; |
2904 |
|
|
} |
2905 |
|
|
break; |
2906 |
|
|
} |
2907 |
|
|
default: |
2908 |
|
|
png_warning(png_ptr, "Ignoring bad adaptive filter type"); |
2909 |
|
|
*row = 0; |
2910 |
|
|
break; |
2911 |
|
|
} |
2912 |
|
|
} |
2913 |
|
|
|
2914 |
|
|
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED |
2915 |
|
|
void /* PRIVATE */ |
2916 |
|
|
png_read_finish_row(png_structp png_ptr) |
2917 |
|
|
{ |
2918 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
2919 |
|
|
#ifdef PNG_READ_INTERLACING_SUPPORTED |
2920 |
|
|
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
2921 |
|
|
|
2922 |
|
|
/* Start of interlace block */ |
2923 |
|
|
PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
2924 |
|
|
|
2925 |
|
|
/* Offset to next interlace block */ |
2926 |
|
|
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
2927 |
|
|
|
2928 |
|
|
/* Start of interlace block in the y direction */ |
2929 |
|
|
PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
2930 |
|
|
|
2931 |
|
|
/* Offset to next interlace block in the y direction */ |
2932 |
|
|
PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
2933 |
|
|
#endif /* PNG_READ_INTERLACING_SUPPORTED */ |
2934 |
|
|
#endif |
2935 |
|
|
|
2936 |
|
|
png_debug(1, "in png_read_finish_row"); |
2937 |
|
|
png_ptr->row_number++; |
2938 |
|
|
if (png_ptr->row_number < png_ptr->num_rows) |
2939 |
|
|
return; |
2940 |
|
|
|
2941 |
|
|
#ifdef PNG_READ_INTERLACING_SUPPORTED |
2942 |
|
|
if (png_ptr->interlaced) |
2943 |
|
|
{ |
2944 |
|
|
png_ptr->row_number = 0; |
2945 |
|
|
png_memset_check(png_ptr, png_ptr->prev_row, 0, |
2946 |
|
|
png_ptr->rowbytes + 1); |
2947 |
|
|
do |
2948 |
|
|
{ |
2949 |
|
|
png_ptr->pass++; |
2950 |
|
|
if (png_ptr->pass >= 7) |
2951 |
|
|
break; |
2952 |
|
|
png_ptr->iwidth = (png_ptr->width + |
2953 |
|
|
png_pass_inc[png_ptr->pass] - 1 - |
2954 |
|
|
png_pass_start[png_ptr->pass]) / |
2955 |
|
|
png_pass_inc[png_ptr->pass]; |
2956 |
|
|
|
2957 |
|
|
png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, |
2958 |
|
|
png_ptr->iwidth) + 1; |
2959 |
|
|
|
2960 |
|
|
if (!(png_ptr->transformations & PNG_INTERLACE)) |
2961 |
|
|
{ |
2962 |
|
|
png_ptr->num_rows = (png_ptr->height + |
2963 |
|
|
png_pass_yinc[png_ptr->pass] - 1 - |
2964 |
|
|
png_pass_ystart[png_ptr->pass]) / |
2965 |
|
|
png_pass_yinc[png_ptr->pass]; |
2966 |
|
|
if (!(png_ptr->num_rows)) |
2967 |
|
|
continue; |
2968 |
|
|
} |
2969 |
|
|
else /* if (png_ptr->transformations & PNG_INTERLACE) */ |
2970 |
|
|
break; |
2971 |
|
|
} while (png_ptr->iwidth == 0); |
2972 |
|
|
|
2973 |
|
|
if (png_ptr->pass < 7) |
2974 |
|
|
return; |
2975 |
|
|
} |
2976 |
|
|
#endif /* PNG_READ_INTERLACING_SUPPORTED */ |
2977 |
|
|
|
2978 |
|
|
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) |
2979 |
|
|
{ |
2980 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
2981 |
|
|
PNG_CONST PNG_IDAT; |
2982 |
|
|
#endif |
2983 |
|
|
char extra; |
2984 |
|
|
int ret; |
2985 |
|
|
|
2986 |
|
|
png_ptr->zstream.next_out = (Byte *)&extra; |
2987 |
|
|
png_ptr->zstream.avail_out = (uInt)1; |
2988 |
|
|
for (;;) |
2989 |
|
|
{ |
2990 |
|
|
if (!(png_ptr->zstream.avail_in)) |
2991 |
|
|
{ |
2992 |
|
|
while (!png_ptr->idat_size) |
2993 |
|
|
{ |
2994 |
|
|
png_byte chunk_length[4]; |
2995 |
|
|
|
2996 |
|
|
png_crc_finish(png_ptr, 0); |
2997 |
|
|
|
2998 |
|
|
png_read_data(png_ptr, chunk_length, 4); |
2999 |
|
|
png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); |
3000 |
|
|
png_reset_crc(png_ptr); |
3001 |
|
|
png_crc_read(png_ptr, png_ptr->chunk_name, 4); |
3002 |
|
|
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) |
3003 |
|
|
png_error(png_ptr, "Not enough image data"); |
3004 |
|
|
|
3005 |
|
|
} |
3006 |
|
|
png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; |
3007 |
|
|
png_ptr->zstream.next_in = png_ptr->zbuf; |
3008 |
|
|
if (png_ptr->zbuf_size > png_ptr->idat_size) |
3009 |
|
|
png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; |
3010 |
|
|
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); |
3011 |
|
|
png_ptr->idat_size -= png_ptr->zstream.avail_in; |
3012 |
|
|
} |
3013 |
|
|
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); |
3014 |
|
|
if (ret == Z_STREAM_END) |
3015 |
|
|
{ |
3016 |
|
|
if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || |
3017 |
|
|
png_ptr->idat_size) |
3018 |
|
|
png_warning(png_ptr, "Extra compressed data"); |
3019 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
3020 |
|
|
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; |
3021 |
|
|
break; |
3022 |
|
|
} |
3023 |
|
|
if (ret != Z_OK) |
3024 |
|
|
png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : |
3025 |
|
|
"Decompression Error"); |
3026 |
|
|
|
3027 |
|
|
if (!(png_ptr->zstream.avail_out)) |
3028 |
|
|
{ |
3029 |
|
|
png_warning(png_ptr, "Extra compressed data."); |
3030 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
3031 |
|
|
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; |
3032 |
|
|
break; |
3033 |
|
|
} |
3034 |
|
|
|
3035 |
|
|
} |
3036 |
|
|
png_ptr->zstream.avail_out = 0; |
3037 |
|
|
} |
3038 |
|
|
|
3039 |
|
|
if (png_ptr->idat_size || png_ptr->zstream.avail_in) |
3040 |
|
|
png_warning(png_ptr, "Extra compression data"); |
3041 |
|
|
|
3042 |
|
|
inflateReset(&png_ptr->zstream); |
3043 |
|
|
|
3044 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
3045 |
|
|
} |
3046 |
|
|
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ |
3047 |
|
|
|
3048 |
|
|
void /* PRIVATE */ |
3049 |
|
|
png_read_start_row(png_structp png_ptr) |
3050 |
|
|
{ |
3051 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
3052 |
|
|
#ifdef PNG_READ_INTERLACING_SUPPORTED |
3053 |
|
|
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
3054 |
|
|
|
3055 |
|
|
/* Start of interlace block */ |
3056 |
|
|
PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
3057 |
|
|
|
3058 |
|
|
/* Offset to next interlace block */ |
3059 |
|
|
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
3060 |
|
|
|
3061 |
|
|
/* Start of interlace block in the y direction */ |
3062 |
|
|
PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
3063 |
|
|
|
3064 |
|
|
/* Offset to next interlace block in the y direction */ |
3065 |
|
|
PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
3066 |
|
|
#endif |
3067 |
|
|
#endif |
3068 |
|
|
|
3069 |
|
|
int max_pixel_depth; |
3070 |
|
|
png_size_t row_bytes; |
3071 |
|
|
|
3072 |
|
|
png_debug(1, "in png_read_start_row"); |
3073 |
|
|
png_ptr->zstream.avail_in = 0; |
3074 |
|
|
png_init_read_transformations(png_ptr); |
3075 |
|
|
#ifdef PNG_READ_INTERLACING_SUPPORTED |
3076 |
|
|
if (png_ptr->interlaced) |
3077 |
|
|
{ |
3078 |
|
|
if (!(png_ptr->transformations & PNG_INTERLACE)) |
3079 |
|
|
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - |
3080 |
|
|
png_pass_ystart[0]) / png_pass_yinc[0]; |
3081 |
|
|
else |
3082 |
|
|
png_ptr->num_rows = png_ptr->height; |
3083 |
|
|
|
3084 |
|
|
png_ptr->iwidth = (png_ptr->width + |
3085 |
|
|
png_pass_inc[png_ptr->pass] - 1 - |
3086 |
|
|
png_pass_start[png_ptr->pass]) / |
3087 |
|
|
png_pass_inc[png_ptr->pass]; |
3088 |
|
|
|
3089 |
|
|
png_ptr->irowbytes = |
3090 |
|
|
PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; |
3091 |
|
|
} |
3092 |
|
|
else |
3093 |
|
|
#endif /* PNG_READ_INTERLACING_SUPPORTED */ |
3094 |
|
|
{ |
3095 |
|
|
png_ptr->num_rows = png_ptr->height; |
3096 |
|
|
png_ptr->iwidth = png_ptr->width; |
3097 |
|
|
png_ptr->irowbytes = png_ptr->rowbytes + 1; |
3098 |
|
|
} |
3099 |
|
|
max_pixel_depth = png_ptr->pixel_depth; |
3100 |
|
|
|
3101 |
|
|
#if defined(PNG_READ_PACK_SUPPORTED) |
3102 |
|
|
if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) |
3103 |
|
|
max_pixel_depth = 8; |
3104 |
|
|
#endif |
3105 |
|
|
|
3106 |
|
|
#if defined(PNG_READ_EXPAND_SUPPORTED) |
3107 |
|
|
if (png_ptr->transformations & PNG_EXPAND) |
3108 |
|
|
{ |
3109 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
3110 |
|
|
{ |
3111 |
|
|
if (png_ptr->num_trans) |
3112 |
|
|
max_pixel_depth = 32; |
3113 |
|
|
else |
3114 |
|
|
max_pixel_depth = 24; |
3115 |
|
|
} |
3116 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) |
3117 |
|
|
{ |
3118 |
|
|
if (max_pixel_depth < 8) |
3119 |
|
|
max_pixel_depth = 8; |
3120 |
|
|
if (png_ptr->num_trans) |
3121 |
|
|
max_pixel_depth *= 2; |
3122 |
|
|
} |
3123 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) |
3124 |
|
|
{ |
3125 |
|
|
if (png_ptr->num_trans) |
3126 |
|
|
{ |
3127 |
|
|
max_pixel_depth *= 4; |
3128 |
|
|
max_pixel_depth /= 3; |
3129 |
|
|
} |
3130 |
|
|
} |
3131 |
|
|
} |
3132 |
|
|
#endif |
3133 |
|
|
|
3134 |
|
|
#if defined(PNG_READ_FILLER_SUPPORTED) |
3135 |
|
|
if (png_ptr->transformations & (PNG_FILLER)) |
3136 |
|
|
{ |
3137 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
3138 |
|
|
max_pixel_depth = 32; |
3139 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) |
3140 |
|
|
{ |
3141 |
|
|
if (max_pixel_depth <= 8) |
3142 |
|
|
max_pixel_depth = 16; |
3143 |
|
|
else |
3144 |
|
|
max_pixel_depth = 32; |
3145 |
|
|
} |
3146 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) |
3147 |
|
|
{ |
3148 |
|
|
if (max_pixel_depth <= 32) |
3149 |
|
|
max_pixel_depth = 32; |
3150 |
|
|
else |
3151 |
|
|
max_pixel_depth = 64; |
3152 |
|
|
} |
3153 |
|
|
} |
3154 |
|
|
#endif |
3155 |
|
|
|
3156 |
|
|
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) |
3157 |
|
|
if (png_ptr->transformations & PNG_GRAY_TO_RGB) |
3158 |
|
|
{ |
3159 |
|
|
if ( |
3160 |
|
|
#if defined(PNG_READ_EXPAND_SUPPORTED) |
3161 |
|
|
(png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || |
3162 |
|
|
#endif |
3163 |
|
|
#if defined(PNG_READ_FILLER_SUPPORTED) |
3164 |
|
|
(png_ptr->transformations & (PNG_FILLER)) || |
3165 |
|
|
#endif |
3166 |
|
|
png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) |
3167 |
|
|
{ |
3168 |
|
|
if (max_pixel_depth <= 16) |
3169 |
|
|
max_pixel_depth = 32; |
3170 |
|
|
else |
3171 |
|
|
max_pixel_depth = 64; |
3172 |
|
|
} |
3173 |
|
|
else |
3174 |
|
|
{ |
3175 |
|
|
if (max_pixel_depth <= 8) |
3176 |
|
|
{ |
3177 |
|
|
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) |
3178 |
|
|
max_pixel_depth = 32; |
3179 |
|
|
else |
3180 |
|
|
max_pixel_depth = 24; |
3181 |
|
|
} |
3182 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) |
3183 |
|
|
max_pixel_depth = 64; |
3184 |
|
|
else |
3185 |
|
|
max_pixel_depth = 48; |
3186 |
|
|
} |
3187 |
|
|
} |
3188 |
|
|
#endif |
3189 |
|
|
|
3190 |
|
|
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ |
3191 |
|
|
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) |
3192 |
|
|
if (png_ptr->transformations & PNG_USER_TRANSFORM) |
3193 |
|
|
{ |
3194 |
|
|
int user_pixel_depth = png_ptr->user_transform_depth* |
3195 |
|
|
png_ptr->user_transform_channels; |
3196 |
|
|
if (user_pixel_depth > max_pixel_depth) |
3197 |
|
|
max_pixel_depth=user_pixel_depth; |
3198 |
|
|
} |
3199 |
|
|
#endif |
3200 |
|
|
|
3201 |
|
|
/* Align the width on the next larger 8 pixels. Mainly used |
3202 |
|
|
* for interlacing |
3203 |
|
|
*/ |
3204 |
|
|
row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); |
3205 |
|
|
/* Calculate the maximum bytes needed, adding a byte and a pixel |
3206 |
|
|
* for safety's sake |
3207 |
|
|
*/ |
3208 |
|
|
row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + |
3209 |
|
|
1 + ((max_pixel_depth + 7) >> 3); |
3210 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
3211 |
|
|
if (row_bytes > (png_uint_32)65536L) |
3212 |
|
|
png_error(png_ptr, "This image requires a row greater than 64KB"); |
3213 |
|
|
#endif |
3214 |
|
|
|
3215 |
|
|
if (row_bytes + 64 > png_ptr->old_big_row_buf_size) |
3216 |
|
|
{ |
3217 |
|
|
png_free(png_ptr, png_ptr->big_row_buf); |
3218 |
|
|
png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 64); |
3219 |
|
|
if (png_ptr->interlaced) |
3220 |
|
|
png_memset(png_ptr->big_row_buf, 0, row_bytes + 64); |
3221 |
|
|
png_ptr->row_buf = png_ptr->big_row_buf + 32; |
3222 |
|
|
png_ptr->old_big_row_buf_size = row_bytes + 64; |
3223 |
|
|
} |
3224 |
|
|
|
3225 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
3226 |
|
|
if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L) |
3227 |
|
|
png_error(png_ptr, "This image requires a row greater than 64KB"); |
3228 |
|
|
#endif |
3229 |
|
|
if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1)) |
3230 |
|
|
png_error(png_ptr, "Row has too many bytes to allocate in memory."); |
3231 |
|
|
|
3232 |
|
|
if (row_bytes + 1 > png_ptr->old_prev_row_size) |
3233 |
|
|
{ |
3234 |
|
|
png_free(png_ptr, png_ptr->prev_row); |
3235 |
|
|
png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( |
3236 |
|
|
row_bytes + 1)); |
3237 |
|
|
png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1); |
3238 |
|
|
png_ptr->old_prev_row_size = row_bytes + 1; |
3239 |
|
|
} |
3240 |
|
|
|
3241 |
|
|
png_ptr->rowbytes = row_bytes; |
3242 |
|
|
|
3243 |
|
|
png_debug1(3, "width = %lu,", png_ptr->width); |
3244 |
|
|
png_debug1(3, "height = %lu,", png_ptr->height); |
3245 |
|
|
png_debug1(3, "iwidth = %lu,", png_ptr->iwidth); |
3246 |
|
|
png_debug1(3, "num_rows = %lu,", png_ptr->num_rows); |
3247 |
|
|
png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes); |
3248 |
|
|
png_debug1(3, "irowbytes = %lu", png_ptr->irowbytes); |
3249 |
|
|
|
3250 |
|
|
png_ptr->flags |= PNG_FLAG_ROW_INIT; |
3251 |
|
|
} |
3252 |
|
|
#endif /* PNG_READ_SUPPORTED */ |