blob: d67af58771acf347ab16a65691dd66da1df96ec8 [file] [log] [blame]
The Android Open Source Project893912b2009-03-03 19:30:05 -08001
2/* pngrutil.c - utilities to read a PNG file
3 *
Eric Vannier66dce0d2011-07-20 17:03:29 -07004 * Last changed in libpng 1.2.45 [July 7, 2011]
5 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
The Android Open Source Project893912b2009-03-03 19:30:05 -08006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8 *
Patrick Scotta0bb96c2009-07-22 11:50:02 -04009 * 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 *
The Android Open Source Project893912b2009-03-03 19:30:05 -080013 * 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
Patrick Scott5f6bd842010-06-28 16:55:16 -040018#define PNG_NO_PEDANTIC_WARNINGS
The Android Open Source Project893912b2009-03-03 19:30:05 -080019#include "png.h"
Patrick Scott5f6bd842010-06-28 16:55:16 -040020#ifdef PNG_READ_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -080021
22#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
23# define WIN32_WCE_OLD
24#endif
25
26#ifdef PNG_FLOATING_POINT_SUPPORTED
Patrick Scott5f6bd842010-06-28 16:55:16 -040027# ifdef WIN32_WCE_OLD
Patrick Scotta0bb96c2009-07-22 11:50:02 -040028/* The strtod() function is not supported on WindowsCE */
Patrick Scott5f6bd842010-06-28 16:55:16 -040029__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr,
30 char **endptr)
The Android Open Source Project893912b2009-03-03 19:30:05 -080031{
32 double result = 0;
33 int len;
34 wchar_t *str, *end;
35
36 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
The Android Open Source Project4215dd12009-03-09 11:52:12 -070037 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
The Android Open Source Project893912b2009-03-03 19:30:05 -080038 if ( NULL != str )
39 {
40 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
41 result = wcstod(str, &end);
42 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
43 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
44 png_free(png_ptr, str);
45 }
46 return result;
47}
48# else
49# define png_strtod(p,a,b) strtod(a,b)
50# endif
51#endif
52
53png_uint_32 PNGAPI
54png_get_uint_31(png_structp png_ptr, png_bytep buf)
55{
The Android Open Source Project4215dd12009-03-09 11:52:12 -070056#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -080057 png_uint_32 i = png_get_uint_32(buf);
The Android Open Source Project4215dd12009-03-09 11:52:12 -070058#else
59 /* Avoid an extra function call by inlining the result. */
60 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
61 ((png_uint_32)(*(buf + 1)) << 16) +
62 ((png_uint_32)(*(buf + 2)) << 8) +
63 (png_uint_32)(*(buf + 3));
64#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -080065 if (i > PNG_UINT_31_MAX)
66 png_error(png_ptr, "PNG unsigned integer out of range.");
67 return (i);
68}
69#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
70/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
71png_uint_32 PNGAPI
72png_get_uint_32(png_bytep buf)
73{
74 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
75 ((png_uint_32)(*(buf + 1)) << 16) +
76 ((png_uint_32)(*(buf + 2)) << 8) +
77 (png_uint_32)(*(buf + 3));
78
79 return (i);
80}
81
82/* Grab a signed 32-bit integer from a buffer in big-endian format. The
83 * data is stored in the PNG file in two's complement format, and it is
Patrick Scotta0bb96c2009-07-22 11:50:02 -040084 * assumed that the machine format for signed integers is the same.
85 */
The Android Open Source Project893912b2009-03-03 19:30:05 -080086png_int_32 PNGAPI
87png_get_int_32(png_bytep buf)
88{
89 png_int_32 i = ((png_int_32)(*buf) << 24) +
90 ((png_int_32)(*(buf + 1)) << 16) +
91 ((png_int_32)(*(buf + 2)) << 8) +
92 (png_int_32)(*(buf + 3));
93
94 return (i);
95}
96
97/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
98png_uint_16 PNGAPI
99png_get_uint_16(png_bytep buf)
100{
101 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
102 (png_uint_16)(*(buf + 1)));
103
104 return (i);
105}
106#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
107
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700108/* Read the chunk header (length + type name).
109 * Put the type name into png_ptr->chunk_name, and return the length.
110 */
111png_uint_32 /* PRIVATE */
112png_read_chunk_header(png_structp png_ptr)
113{
114 png_byte buf[8];
115 png_uint_32 length;
116
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400117 /* Read the length and the chunk name */
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700118 png_read_data(png_ptr, buf, 8);
119 length = png_get_uint_31(png_ptr, buf);
120
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400121 /* Put the chunk name into png_ptr->chunk_name */
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700122 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
123
124 png_debug2(0, "Reading %s chunk, length = %lu",
125 png_ptr->chunk_name, length);
126
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400127 /* Reset the crc and run it over the chunk name */
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700128 png_reset_crc(png_ptr);
129 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
130
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400131 /* Check to see if chunk name is valid */
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700132 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
133
134 return length;
135}
136
The Android Open Source Project893912b2009-03-03 19:30:05 -0800137/* Read data, and (optionally) run it through the CRC. */
138void /* PRIVATE */
139png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
140{
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400141 if (png_ptr == NULL)
142 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -0800143 png_read_data(png_ptr, buf, length);
144 png_calculate_crc(png_ptr, buf, length);
145}
146
Joseph Wen4ce0ee12010-08-20 10:42:22 +0800147#ifdef PNG_INDEX_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800148/* Optionally skip data and then check the CRC. Depending on whether we
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400149 * are reading a ancillary or critical chunk, and how the program has set
150 * things up, we may calculate the CRC on the data and print a message.
151 * Returns '1' if there was a CRC error, '0' otherwise.
152 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800153int /* PRIVATE */
Joseph Wen4ce0ee12010-08-20 10:42:22 +0800154png_opt_crc_finish(png_structp png_ptr, png_uint_32 skip, int check_crc)
The Android Open Source Project893912b2009-03-03 19:30:05 -0800155{
156 png_size_t i;
157 png_size_t istop = png_ptr->zbuf_size;
158
159 for (i = (png_size_t)skip; i > istop; i -= istop)
160 {
161 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
162 }
163 if (i)
164 {
165 png_crc_read(png_ptr, png_ptr->zbuf, i);
166 }
167
168 if (png_crc_error(png_ptr))
169 {
Joseph Wen4ce0ee12010-08-20 10:42:22 +0800170 if (!check_crc) {
171 png_chunk_warning(png_ptr, "CRC error");
172 return (1);
173 }
The Android Open Source Project893912b2009-03-03 19:30:05 -0800174 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400175 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
The Android Open Source Project893912b2009-03-03 19:30:05 -0800176 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
177 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
178 {
179 png_chunk_warning(png_ptr, "CRC error");
180 }
181 else
182 {
183 png_chunk_error(png_ptr, "CRC error");
184 }
185 return (1);
186 }
187
188 return (0);
189}
Joseph Wen4ce0ee12010-08-20 10:42:22 +0800190#endif
191
192/* Optionally skip data and then check the CRC. Depending on whether we
193 * are reading a ancillary or critical chunk, and how the program has set
194 * things up, we may calculate the CRC on the data and print a message.
195 * Returns '1' if there was a CRC error, '0' otherwise.
196 */
197int /* PRIVATE */
198png_crc_finish(png_structp png_ptr, png_uint_32 skip)
199{
200 return png_opt_crc_finish(png_ptr, skip, 1);
201}
The Android Open Source Project893912b2009-03-03 19:30:05 -0800202
203/* Compare the CRC stored in the PNG file with that calculated by libpng from
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400204 * the data it has read thus far.
205 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800206int /* PRIVATE */
207png_crc_error(png_structp png_ptr)
208{
209 png_byte crc_bytes[4];
210 png_uint_32 crc;
211 int need_crc = 1;
212
213 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
214 {
215 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
216 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
217 need_crc = 0;
218 }
219 else /* critical */
220 {
221 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
222 need_crc = 0;
223 }
224
225 png_read_data(png_ptr, crc_bytes, 4);
226
227 if (need_crc)
228 {
229 crc = png_get_uint_32(crc_bytes);
230 return ((int)(crc != png_ptr->crc));
231 }
232 else
233 return (0);
234}
235
236#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
237 defined(PNG_READ_iCCP_SUPPORTED)
Patrick Scott5f6bd842010-06-28 16:55:16 -0400238static png_size_t
239png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
240 png_bytep output, png_size_t output_size)
241{
242 png_size_t count = 0;
243
244 png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
245 png_ptr->zstream.avail_in = size;
246
247 while (1)
248 {
249 int ret, avail;
250
251 /* Reset the output buffer each time round - we empty it
252 * after every inflate call.
253 */
254 png_ptr->zstream.next_out = png_ptr->zbuf;
255 png_ptr->zstream.avail_out = png_ptr->zbuf_size;
256
257 ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
258 avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
259
260 /* First copy/count any new output - but only if we didn't
261 * get an error code.
262 */
263 if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
264 {
265 if (output != 0 && output_size > count)
266 {
267 int copy = output_size - count;
268 if (avail < copy) copy = avail;
269 png_memcpy(output + count, png_ptr->zbuf, copy);
270 }
271 count += avail;
272 }
273
274 if (ret == Z_OK)
275 continue;
276
277 /* Termination conditions - always reset the zstream, it
278 * must be left in inflateInit state.
279 */
280 png_ptr->zstream.avail_in = 0;
281 inflateReset(&png_ptr->zstream);
282
283 if (ret == Z_STREAM_END)
284 return count; /* NOTE: may be zero. */
285
286 /* Now handle the error codes - the API always returns 0
287 * and the error message is dumped into the uncompressed
288 * buffer if available.
289 */
290 {
291 PNG_CONST char *msg;
292 if (png_ptr->zstream.msg != 0)
293 msg = png_ptr->zstream.msg;
294 else
295 {
296#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
297 char umsg[52];
298
299 switch (ret)
300 {
301 case Z_BUF_ERROR:
302 msg = "Buffer error in compressed datastream in %s chunk";
303 break;
304 case Z_DATA_ERROR:
305 msg = "Data error in compressed datastream in %s chunk";
306 break;
307 default:
308 msg = "Incomplete compressed datastream in %s chunk";
309 break;
310 }
311
312 png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
313 msg = umsg;
314#else
315 msg = "Damaged compressed datastream in chunk other than IDAT";
316#endif
317 }
318
319 png_warning(png_ptr, msg);
320 }
321
322 /* 0 means an error - notice that this code simple ignores
323 * zero length compressed chunks as a result.
324 */
325 return 0;
326 }
327}
328
The Android Open Source Project893912b2009-03-03 19:30:05 -0800329/*
330 * Decompress trailing data in a chunk. The assumption is that chunkdata
331 * points at an allocated area holding the contents of a chunk with a
332 * trailing compressed part. What we get back is an allocated area
333 * holding the original prefix part and an uncompressed version of the
334 * trailing part (the malloc area passed in is freed).
335 */
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700336void /* PRIVATE */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800337png_decompress_chunk(png_structp png_ptr, int comp_type,
Patrick Scott5f6bd842010-06-28 16:55:16 -0400338 png_size_t chunklength,
339 png_size_t prefix_size, png_size_t *newlength)
The Android Open Source Project893912b2009-03-03 19:30:05 -0800340{
Patrick Scott5f6bd842010-06-28 16:55:16 -0400341 /* The caller should guarantee this */
342 if (prefix_size > chunklength)
The Android Open Source Project893912b2009-03-03 19:30:05 -0800343 {
Patrick Scott5f6bd842010-06-28 16:55:16 -0400344 /* The recovery is to delete the chunk. */
345 png_warning(png_ptr, "invalid chunklength");
346 prefix_size = 0; /* To delete everything */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800347 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400348
349 else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
350 {
351 png_size_t expanded_size = png_inflate(png_ptr,
352 (png_bytep)(png_ptr->chunkdata + prefix_size),
353 chunklength - prefix_size,
354 0/*output*/, 0/*output size*/);
355
356 /* Now check the limits on this chunk - if the limit fails the
357 * compressed data will be removed, the prefix will remain.
358 */
359#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
360 if (png_ptr->user_chunk_malloc_max &&
361 (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
362#else
363# ifdef PNG_USER_CHUNK_MALLOC_MAX
364 if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
365 prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
366# endif
367#endif
368 png_warning(png_ptr, "Exceeded size limit while expanding chunk");
369
370 /* If the size is zero either there was an error and a message
371 * has already been output (warning) or the size really is zero
372 * and we have nothing to do - the code will exit through the
373 * error case below.
374 */
375#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
376 defined(PNG_USER_CHUNK_MALLOC_MAX)
377 else
378#endif
379 if (expanded_size > 0)
380 {
381 /* Success (maybe) - really uncompress the chunk. */
382 png_size_t new_size = 0;
Dave Burkeccee1212012-03-05 22:36:13 -0800383 png_charp text = NULL;
384
385 /* Need to check for both truncation (64-bit) and integer overflow. */
386 if (prefix_size + expanded_size > prefix_size &&
387 prefix_size + expanded_size < 0xffffffffU)
388 {
389 text = png_malloc_warn(png_ptr, prefix_size + expanded_size + 1);
390 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400391
392 if (text != NULL)
393 {
394 png_memcpy(text, png_ptr->chunkdata, prefix_size);
395 new_size = png_inflate(png_ptr,
396 (png_bytep)(png_ptr->chunkdata + prefix_size),
397 chunklength - prefix_size,
398 (png_bytep)(text + prefix_size), expanded_size);
399 text[prefix_size + expanded_size] = 0; /* just in case */
400
401 if (new_size == expanded_size)
402 {
403 png_free(png_ptr, png_ptr->chunkdata);
404 png_ptr->chunkdata = text;
405 *newlength = prefix_size + expanded_size;
406 return; /* The success return! */
407 }
408
409 png_warning(png_ptr, "png_inflate logic error");
410 png_free(png_ptr, text);
411 }
412 else
413 png_warning(png_ptr, "Not enough memory to decompress chunk.");
414 }
415 }
416
The Android Open Source Project893912b2009-03-03 19:30:05 -0800417 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
418 {
Patrick Scott5f6bd842010-06-28 16:55:16 -0400419#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
The Android Open Source Project893912b2009-03-03 19:30:05 -0800420 char umsg[50];
421
Patrick Scott5f6bd842010-06-28 16:55:16 -0400422 png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
423 comp_type);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800424 png_warning(png_ptr, umsg);
425#else
426 png_warning(png_ptr, "Unknown zTXt compression type");
427#endif
428
Patrick Scott5f6bd842010-06-28 16:55:16 -0400429 /* The recovery is to simply drop the data. */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800430 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400431
432 /* Generic error return - leave the prefix, delete the compressed
433 * data, reallocate the chunkdata to remove the potentially large
434 * amount of compressed data.
435 */
436 {
437 png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
438 if (text != NULL)
439 {
440 if (prefix_size > 0)
441 png_memcpy(text, png_ptr->chunkdata, prefix_size);
442 png_free(png_ptr, png_ptr->chunkdata);
443 png_ptr->chunkdata = text;
444
445 /* This is an extra zero in the 'uncompressed' part. */
446 *(png_ptr->chunkdata + prefix_size) = 0x00;
447 }
448 /* Ignore a malloc error here - it is safe. */
449 }
450
451 *newlength = prefix_size;
The Android Open Source Project893912b2009-03-03 19:30:05 -0800452}
453#endif
454
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400455/* Read and check the IDHR chunk */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800456void /* PRIVATE */
457png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
458{
459 png_byte buf[13];
460 png_uint_32 width, height;
461 int bit_depth, color_type, compression_type, filter_type;
462 int interlace_type;
463
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700464 png_debug(1, "in png_handle_IHDR");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800465
466 if (png_ptr->mode & PNG_HAVE_IHDR)
467 png_error(png_ptr, "Out of place IHDR");
468
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400469 /* Check the length */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800470 if (length != 13)
471 png_error(png_ptr, "Invalid IHDR chunk");
472
473 png_ptr->mode |= PNG_HAVE_IHDR;
474
475 png_crc_read(png_ptr, buf, 13);
476 png_crc_finish(png_ptr, 0);
477
478 width = png_get_uint_31(png_ptr, buf);
479 height = png_get_uint_31(png_ptr, buf + 4);
480 bit_depth = buf[8];
481 color_type = buf[9];
482 compression_type = buf[10];
483 filter_type = buf[11];
484 interlace_type = buf[12];
485
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400486 /* Set internal variables */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800487 png_ptr->width = width;
488 png_ptr->height = height;
489 png_ptr->bit_depth = (png_byte)bit_depth;
490 png_ptr->interlaced = (png_byte)interlace_type;
491 png_ptr->color_type = (png_byte)color_type;
Patrick Scott5f6bd842010-06-28 16:55:16 -0400492#ifdef PNG_MNG_FEATURES_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800493 png_ptr->filter_type = (png_byte)filter_type;
494#endif
495 png_ptr->compression_type = (png_byte)compression_type;
496
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400497 /* Find number of channels */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800498 switch (png_ptr->color_type)
499 {
500 case PNG_COLOR_TYPE_GRAY:
501 case PNG_COLOR_TYPE_PALETTE:
502 png_ptr->channels = 1;
503 break;
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400504
The Android Open Source Project893912b2009-03-03 19:30:05 -0800505 case PNG_COLOR_TYPE_RGB:
506 png_ptr->channels = 3;
507 break;
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400508
The Android Open Source Project893912b2009-03-03 19:30:05 -0800509 case PNG_COLOR_TYPE_GRAY_ALPHA:
510 png_ptr->channels = 2;
511 break;
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400512
The Android Open Source Project893912b2009-03-03 19:30:05 -0800513 case PNG_COLOR_TYPE_RGB_ALPHA:
514 png_ptr->channels = 4;
515 break;
516 }
517
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400518 /* Set up other useful info */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800519 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
520 png_ptr->channels);
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700521 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
522 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
523 png_debug1(3, "channels = %d", png_ptr->channels);
524 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800525 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
526 color_type, interlace_type, compression_type, filter_type);
527}
528
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400529/* Read and check the palette */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800530void /* PRIVATE */
531png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
532{
533 png_color palette[PNG_MAX_PALETTE_LENGTH];
534 int num, i;
Patrick Scott5f6bd842010-06-28 16:55:16 -0400535#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800536 png_colorp pal_ptr;
537#endif
538
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700539 png_debug(1, "in png_handle_PLTE");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800540
541 if (!(png_ptr->mode & PNG_HAVE_IHDR))
542 png_error(png_ptr, "Missing IHDR before PLTE");
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400543
The Android Open Source Project893912b2009-03-03 19:30:05 -0800544 else if (png_ptr->mode & PNG_HAVE_IDAT)
545 {
546 png_warning(png_ptr, "Invalid PLTE after IDAT");
547 png_crc_finish(png_ptr, length);
548 return;
549 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400550
The Android Open Source Project893912b2009-03-03 19:30:05 -0800551 else if (png_ptr->mode & PNG_HAVE_PLTE)
552 png_error(png_ptr, "Duplicate PLTE chunk");
553
554 png_ptr->mode |= PNG_HAVE_PLTE;
555
556 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
557 {
558 png_warning(png_ptr,
559 "Ignoring PLTE chunk in grayscale PNG");
560 png_crc_finish(png_ptr, length);
561 return;
562 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400563#ifndef PNG_READ_OPT_PLTE_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800564 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
565 {
566 png_crc_finish(png_ptr, length);
567 return;
568 }
569#endif
570
571 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
572 {
573 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
574 {
575 png_warning(png_ptr, "Invalid palette chunk");
576 png_crc_finish(png_ptr, length);
577 return;
578 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400579
The Android Open Source Project893912b2009-03-03 19:30:05 -0800580 else
581 {
582 png_error(png_ptr, "Invalid palette chunk");
583 }
584 }
585
586 num = (int)length / 3;
587
Patrick Scott5f6bd842010-06-28 16:55:16 -0400588#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800589 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
590 {
591 png_byte buf[3];
592
593 png_crc_read(png_ptr, buf, 3);
594 pal_ptr->red = buf[0];
595 pal_ptr->green = buf[1];
596 pal_ptr->blue = buf[2];
597 }
598#else
599 for (i = 0; i < num; i++)
600 {
601 png_byte buf[3];
602
603 png_crc_read(png_ptr, buf, 3);
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400604 /* Don't depend upon png_color being any order */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800605 palette[i].red = buf[0];
606 palette[i].green = buf[1];
607 palette[i].blue = buf[2];
608 }
609#endif
610
611 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400612 * whatever the normal CRC configuration tells us. However, if we
613 * have an RGB image, the PLTE can be considered ancillary, so
614 * we will act as though it is.
615 */
Patrick Scott5f6bd842010-06-28 16:55:16 -0400616#ifndef PNG_READ_OPT_PLTE_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800617 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
618#endif
619 {
620 png_crc_finish(png_ptr, 0);
621 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400622#ifndef PNG_READ_OPT_PLTE_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800623 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
624 {
625 /* If we don't want to use the data from an ancillary chunk,
626 we have two options: an error abort, or a warning and we
627 ignore the data in this chunk (which should be OK, since
628 it's considered ancillary for a RGB or RGBA image). */
629 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
630 {
631 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
632 {
633 png_chunk_error(png_ptr, "CRC error");
634 }
635 else
636 {
637 png_chunk_warning(png_ptr, "CRC error");
638 return;
639 }
640 }
641 /* Otherwise, we (optionally) emit a warning and use the chunk. */
642 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
643 {
644 png_chunk_warning(png_ptr, "CRC error");
645 }
646 }
647#endif
648
649 png_set_PLTE(png_ptr, info_ptr, palette, num);
650
Patrick Scott5f6bd842010-06-28 16:55:16 -0400651#ifdef PNG_READ_tRNS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800652 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
653 {
654 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
655 {
656 if (png_ptr->num_trans > (png_uint_16)num)
657 {
658 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
659 png_ptr->num_trans = (png_uint_16)num;
660 }
661 if (info_ptr->num_trans > (png_uint_16)num)
662 {
663 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
664 info_ptr->num_trans = (png_uint_16)num;
665 }
666 }
667 }
668#endif
669
670}
671
672void /* PRIVATE */
673png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
674{
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700675 png_debug(1, "in png_handle_IEND");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800676
677 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
678 {
679 png_error(png_ptr, "No image in file");
680 }
681
682 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
683
684 if (length != 0)
685 {
686 png_warning(png_ptr, "Incorrect IEND chunk length");
687 }
688 png_crc_finish(png_ptr, length);
689
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400690 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800691}
692
Patrick Scott5f6bd842010-06-28 16:55:16 -0400693#ifdef PNG_READ_gAMA_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800694void /* PRIVATE */
695png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
696{
697 png_fixed_point igamma;
698#ifdef PNG_FLOATING_POINT_SUPPORTED
699 float file_gamma;
700#endif
701 png_byte buf[4];
702
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700703 png_debug(1, "in png_handle_gAMA");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800704
705 if (!(png_ptr->mode & PNG_HAVE_IHDR))
706 png_error(png_ptr, "Missing IHDR before gAMA");
707 else if (png_ptr->mode & PNG_HAVE_IDAT)
708 {
709 png_warning(png_ptr, "Invalid gAMA after IDAT");
710 png_crc_finish(png_ptr, length);
711 return;
712 }
713 else if (png_ptr->mode & PNG_HAVE_PLTE)
714 /* Should be an error, but we can cope with it */
715 png_warning(png_ptr, "Out of place gAMA chunk");
716
717 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Patrick Scott5f6bd842010-06-28 16:55:16 -0400718#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800719 && !(info_ptr->valid & PNG_INFO_sRGB)
720#endif
721 )
722 {
723 png_warning(png_ptr, "Duplicate gAMA chunk");
724 png_crc_finish(png_ptr, length);
725 return;
726 }
727
728 if (length != 4)
729 {
730 png_warning(png_ptr, "Incorrect gAMA chunk length");
731 png_crc_finish(png_ptr, length);
732 return;
733 }
734
735 png_crc_read(png_ptr, buf, 4);
736 if (png_crc_finish(png_ptr, 0))
737 return;
738
739 igamma = (png_fixed_point)png_get_uint_32(buf);
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400740 /* Check for zero gamma */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800741 if (igamma == 0)
742 {
743 png_warning(png_ptr,
744 "Ignoring gAMA chunk with gamma=0");
745 return;
746 }
747
Patrick Scott5f6bd842010-06-28 16:55:16 -0400748#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800749 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
750 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
751 {
752 png_warning(png_ptr,
753 "Ignoring incorrect gAMA value when sRGB is also present");
Patrick Scott5f6bd842010-06-28 16:55:16 -0400754#ifdef PNG_CONSOLE_IO_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700755 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800756#endif
757 return;
758 }
759#endif /* PNG_READ_sRGB_SUPPORTED */
760
761#ifdef PNG_FLOATING_POINT_SUPPORTED
762 file_gamma = (float)igamma / (float)100000.0;
763# ifdef PNG_READ_GAMMA_SUPPORTED
764 png_ptr->gamma = file_gamma;
765# endif
766 png_set_gAMA(png_ptr, info_ptr, file_gamma);
767#endif
768#ifdef PNG_FIXED_POINT_SUPPORTED
769 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
770#endif
771}
772#endif
773
Patrick Scott5f6bd842010-06-28 16:55:16 -0400774#ifdef PNG_READ_sBIT_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800775void /* PRIVATE */
776png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
777{
778 png_size_t truelen;
779 png_byte buf[4];
780
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700781 png_debug(1, "in png_handle_sBIT");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800782
783 buf[0] = buf[1] = buf[2] = buf[3] = 0;
784
785 if (!(png_ptr->mode & PNG_HAVE_IHDR))
786 png_error(png_ptr, "Missing IHDR before sBIT");
787 else if (png_ptr->mode & PNG_HAVE_IDAT)
788 {
789 png_warning(png_ptr, "Invalid sBIT after IDAT");
790 png_crc_finish(png_ptr, length);
791 return;
792 }
793 else if (png_ptr->mode & PNG_HAVE_PLTE)
794 {
795 /* Should be an error, but we can cope with it */
796 png_warning(png_ptr, "Out of place sBIT chunk");
797 }
798 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
799 {
800 png_warning(png_ptr, "Duplicate sBIT chunk");
801 png_crc_finish(png_ptr, length);
802 return;
803 }
804
805 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
806 truelen = 3;
807 else
808 truelen = (png_size_t)png_ptr->channels;
809
810 if (length != truelen || length > 4)
811 {
812 png_warning(png_ptr, "Incorrect sBIT chunk length");
813 png_crc_finish(png_ptr, length);
814 return;
815 }
816
817 png_crc_read(png_ptr, buf, truelen);
818 if (png_crc_finish(png_ptr, 0))
819 return;
820
821 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
822 {
823 png_ptr->sig_bit.red = buf[0];
824 png_ptr->sig_bit.green = buf[1];
825 png_ptr->sig_bit.blue = buf[2];
826 png_ptr->sig_bit.alpha = buf[3];
827 }
828 else
829 {
830 png_ptr->sig_bit.gray = buf[0];
831 png_ptr->sig_bit.red = buf[0];
832 png_ptr->sig_bit.green = buf[0];
833 png_ptr->sig_bit.blue = buf[0];
834 png_ptr->sig_bit.alpha = buf[1];
835 }
836 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
837}
838#endif
839
Patrick Scott5f6bd842010-06-28 16:55:16 -0400840#ifdef PNG_READ_cHRM_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800841void /* PRIVATE */
842png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
843{
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700844 png_byte buf[32];
The Android Open Source Project893912b2009-03-03 19:30:05 -0800845#ifdef PNG_FLOATING_POINT_SUPPORTED
846 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
847#endif
848 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
849 int_y_green, int_x_blue, int_y_blue;
850
851 png_uint_32 uint_x, uint_y;
852
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700853 png_debug(1, "in png_handle_cHRM");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800854
855 if (!(png_ptr->mode & PNG_HAVE_IHDR))
856 png_error(png_ptr, "Missing IHDR before cHRM");
857 else if (png_ptr->mode & PNG_HAVE_IDAT)
858 {
859 png_warning(png_ptr, "Invalid cHRM after IDAT");
860 png_crc_finish(png_ptr, length);
861 return;
862 }
863 else if (png_ptr->mode & PNG_HAVE_PLTE)
864 /* Should be an error, but we can cope with it */
865 png_warning(png_ptr, "Missing PLTE before cHRM");
866
867 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Patrick Scott5f6bd842010-06-28 16:55:16 -0400868#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800869 && !(info_ptr->valid & PNG_INFO_sRGB)
870#endif
871 )
872 {
873 png_warning(png_ptr, "Duplicate cHRM chunk");
874 png_crc_finish(png_ptr, length);
875 return;
876 }
877
878 if (length != 32)
879 {
880 png_warning(png_ptr, "Incorrect cHRM chunk length");
881 png_crc_finish(png_ptr, length);
882 return;
883 }
884
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700885 png_crc_read(png_ptr, buf, 32);
886 if (png_crc_finish(png_ptr, 0))
The Android Open Source Project893912b2009-03-03 19:30:05 -0800887 return;
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700888
889 uint_x = png_get_uint_32(buf);
890 uint_y = png_get_uint_32(buf + 4);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800891 int_x_white = (png_fixed_point)uint_x;
892 int_y_white = (png_fixed_point)uint_y;
893
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700894 uint_x = png_get_uint_32(buf + 8);
895 uint_y = png_get_uint_32(buf + 12);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800896 int_x_red = (png_fixed_point)uint_x;
897 int_y_red = (png_fixed_point)uint_y;
898
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700899 uint_x = png_get_uint_32(buf + 16);
900 uint_y = png_get_uint_32(buf + 20);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800901 int_x_green = (png_fixed_point)uint_x;
902 int_y_green = (png_fixed_point)uint_y;
903
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700904 uint_x = png_get_uint_32(buf + 24);
905 uint_y = png_get_uint_32(buf + 28);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800906 int_x_blue = (png_fixed_point)uint_x;
907 int_y_blue = (png_fixed_point)uint_y;
908
909#ifdef PNG_FLOATING_POINT_SUPPORTED
910 white_x = (float)int_x_white / (float)100000.0;
911 white_y = (float)int_y_white / (float)100000.0;
912 red_x = (float)int_x_red / (float)100000.0;
913 red_y = (float)int_y_red / (float)100000.0;
914 green_x = (float)int_x_green / (float)100000.0;
915 green_y = (float)int_y_green / (float)100000.0;
916 blue_x = (float)int_x_blue / (float)100000.0;
917 blue_y = (float)int_y_blue / (float)100000.0;
918#endif
919
Patrick Scott5f6bd842010-06-28 16:55:16 -0400920#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800921 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
922 {
923 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
924 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
925 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
926 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
927 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
928 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
929 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
930 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
931 {
932 png_warning(png_ptr,
933 "Ignoring incorrect cHRM value when sRGB is also present");
Patrick Scott5f6bd842010-06-28 16:55:16 -0400934#ifdef PNG_CONSOLE_IO_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800935#ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700936 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
The Android Open Source Project893912b2009-03-03 19:30:05 -0800937 white_x, white_y, red_x, red_y);
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700938 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
The Android Open Source Project893912b2009-03-03 19:30:05 -0800939 green_x, green_y, blue_x, blue_y);
940#else
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700941 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Patrick Scott5f6bd842010-06-28 16:55:16 -0400942 (long)int_x_white, (long)int_y_white,
943 (long)int_x_red, (long)int_y_red);
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700944 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Patrick Scott5f6bd842010-06-28 16:55:16 -0400945 (long)int_x_green, (long)int_y_green,
946 (long)int_x_blue, (long)int_y_blue);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800947#endif
Patrick Scott5f6bd842010-06-28 16:55:16 -0400948#endif /* PNG_CONSOLE_IO_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800949 }
The Android Open Source Project893912b2009-03-03 19:30:05 -0800950 return;
951 }
952#endif /* PNG_READ_sRGB_SUPPORTED */
953
954#ifdef PNG_FLOATING_POINT_SUPPORTED
955 png_set_cHRM(png_ptr, info_ptr,
956 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
957#endif
958#ifdef PNG_FIXED_POINT_SUPPORTED
959 png_set_cHRM_fixed(png_ptr, info_ptr,
960 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
961 int_y_green, int_x_blue, int_y_blue);
962#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -0800963}
964#endif
965
Patrick Scott5f6bd842010-06-28 16:55:16 -0400966#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800967void /* PRIVATE */
968png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
969{
970 int intent;
971 png_byte buf[1];
972
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700973 png_debug(1, "in png_handle_sRGB");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800974
975 if (!(png_ptr->mode & PNG_HAVE_IHDR))
976 png_error(png_ptr, "Missing IHDR before sRGB");
977 else if (png_ptr->mode & PNG_HAVE_IDAT)
978 {
979 png_warning(png_ptr, "Invalid sRGB after IDAT");
980 png_crc_finish(png_ptr, length);
981 return;
982 }
983 else if (png_ptr->mode & PNG_HAVE_PLTE)
984 /* Should be an error, but we can cope with it */
985 png_warning(png_ptr, "Out of place sRGB chunk");
986
987 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
988 {
989 png_warning(png_ptr, "Duplicate sRGB chunk");
990 png_crc_finish(png_ptr, length);
991 return;
992 }
993
994 if (length != 1)
995 {
996 png_warning(png_ptr, "Incorrect sRGB chunk length");
997 png_crc_finish(png_ptr, length);
998 return;
999 }
1000
1001 png_crc_read(png_ptr, buf, 1);
1002 if (png_crc_finish(png_ptr, 0))
1003 return;
1004
1005 intent = buf[0];
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001006 /* Check for bad intent */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001007 if (intent >= PNG_sRGB_INTENT_LAST)
1008 {
1009 png_warning(png_ptr, "Unknown sRGB intent");
1010 return;
1011 }
1012
1013#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
1014 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
1015 {
1016 png_fixed_point igamma;
1017#ifdef PNG_FIXED_POINT_SUPPORTED
1018 igamma=info_ptr->int_gamma;
1019#else
1020# ifdef PNG_FLOATING_POINT_SUPPORTED
1021 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
1022# endif
1023#endif
1024 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
1025 {
1026 png_warning(png_ptr,
1027 "Ignoring incorrect gAMA value when sRGB is also present");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001028#ifdef PNG_CONSOLE_IO_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001029# ifdef PNG_FIXED_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001030 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
1031 (int)png_ptr->int_gamma);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001032# else
1033# ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001034 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001035# endif
1036# endif
1037#endif
1038 }
1039 }
1040#endif /* PNG_READ_gAMA_SUPPORTED */
1041
1042#ifdef PNG_READ_cHRM_SUPPORTED
1043#ifdef PNG_FIXED_POINT_SUPPORTED
1044 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
1045 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
1046 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
1047 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
1048 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
1049 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
1050 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
1051 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
1052 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
1053 {
1054 png_warning(png_ptr,
1055 "Ignoring incorrect cHRM value when sRGB is also present");
1056 }
1057#endif /* PNG_FIXED_POINT_SUPPORTED */
1058#endif /* PNG_READ_cHRM_SUPPORTED */
1059
1060 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1061}
1062#endif /* PNG_READ_sRGB_SUPPORTED */
1063
Patrick Scott5f6bd842010-06-28 16:55:16 -04001064#ifdef PNG_READ_iCCP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001065void /* PRIVATE */
1066png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1067/* Note: this does not properly handle chunks that are > 64K under DOS */
1068{
The Android Open Source Project893912b2009-03-03 19:30:05 -08001069 png_byte compression_type;
1070 png_bytep pC;
1071 png_charp profile;
1072 png_uint_32 skip = 0;
1073 png_uint_32 profile_size, profile_length;
1074 png_size_t slength, prefix_length, data_length;
1075
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001076 png_debug(1, "in png_handle_iCCP");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001077
1078 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1079 png_error(png_ptr, "Missing IHDR before iCCP");
1080 else if (png_ptr->mode & PNG_HAVE_IDAT)
1081 {
1082 png_warning(png_ptr, "Invalid iCCP after IDAT");
1083 png_crc_finish(png_ptr, length);
1084 return;
1085 }
1086 else if (png_ptr->mode & PNG_HAVE_PLTE)
1087 /* Should be an error, but we can cope with it */
1088 png_warning(png_ptr, "Out of place iCCP chunk");
1089
1090 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1091 {
1092 png_warning(png_ptr, "Duplicate iCCP chunk");
1093 png_crc_finish(png_ptr, length);
1094 return;
1095 }
1096
1097#ifdef PNG_MAX_MALLOC_64K
1098 if (length > (png_uint_32)65535L)
1099 {
1100 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1101 skip = length - (png_uint_32)65535L;
1102 length = (png_uint_32)65535L;
1103 }
1104#endif
1105
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001106 png_free(png_ptr, png_ptr->chunkdata);
1107 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001108 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001109 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001110
1111 if (png_crc_finish(png_ptr, skip))
1112 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001113 png_free(png_ptr, png_ptr->chunkdata);
1114 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001115 return;
1116 }
1117
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001118 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001119
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001120 for (profile = png_ptr->chunkdata; *profile; profile++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001121 /* Empty loop to find end of name */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001122
1123 ++profile;
1124
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001125 /* There should be at least one zero (the compression type byte)
1126 * following the separator, and we should be on it
1127 */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001128 if ( profile >= png_ptr->chunkdata + slength - 1)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001129 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001130 png_free(png_ptr, png_ptr->chunkdata);
1131 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001132 png_warning(png_ptr, "Malformed iCCP chunk");
1133 return;
1134 }
1135
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001136 /* Compression_type should always be zero */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001137 compression_type = *profile++;
1138 if (compression_type)
1139 {
1140 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001141 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
The Android Open Source Project893912b2009-03-03 19:30:05 -08001142 wrote nonzero) */
1143 }
1144
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001145 prefix_length = profile - png_ptr->chunkdata;
1146 png_decompress_chunk(png_ptr, compression_type,
1147 slength, prefix_length, &data_length);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001148
1149 profile_length = data_length - prefix_length;
1150
1151 if ( prefix_length > data_length || profile_length < 4)
1152 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001153 png_free(png_ptr, png_ptr->chunkdata);
1154 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001155 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1156 return;
1157 }
1158
1159 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001160 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1161 profile_size = ((*(pC ))<<24) |
1162 ((*(pC + 1))<<16) |
1163 ((*(pC + 2))<< 8) |
1164 ((*(pC + 3)) );
The Android Open Source Project893912b2009-03-03 19:30:05 -08001165
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001166 if (profile_size < profile_length)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001167 profile_length = profile_size;
1168
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001169 if (profile_size > profile_length)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001170 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001171 png_free(png_ptr, png_ptr->chunkdata);
1172 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001173 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1174 return;
1175 }
1176
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001177 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1178 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1179 png_free(png_ptr, png_ptr->chunkdata);
1180 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001181}
1182#endif /* PNG_READ_iCCP_SUPPORTED */
1183
Patrick Scott5f6bd842010-06-28 16:55:16 -04001184#ifdef PNG_READ_sPLT_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001185void /* PRIVATE */
1186png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1187/* Note: this does not properly handle chunks that are > 64K under DOS */
1188{
The Android Open Source Project893912b2009-03-03 19:30:05 -08001189 png_bytep entry_start;
1190 png_sPLT_t new_palette;
Patrick Scott5f6bd842010-06-28 16:55:16 -04001191#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001192 png_sPLT_entryp pp;
1193#endif
1194 int data_length, entry_size, i;
1195 png_uint_32 skip = 0;
1196 png_size_t slength;
1197
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001198 png_debug(1, "in png_handle_sPLT");
1199
Patrick Scott5f6bd842010-06-28 16:55:16 -04001200#ifdef PNG_USER_LIMITS_SUPPORTED
1201
1202 if (png_ptr->user_chunk_cache_max != 0)
1203 {
1204 if (png_ptr->user_chunk_cache_max == 1)
1205 {
1206 png_crc_finish(png_ptr, length);
1207 return;
1208 }
1209 if (--png_ptr->user_chunk_cache_max == 1)
1210 {
1211 png_warning(png_ptr, "No space in chunk cache for sPLT");
1212 png_crc_finish(png_ptr, length);
1213 return;
1214 }
1215 }
1216#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08001217
1218 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1219 png_error(png_ptr, "Missing IHDR before sPLT");
1220 else if (png_ptr->mode & PNG_HAVE_IDAT)
1221 {
1222 png_warning(png_ptr, "Invalid sPLT after IDAT");
1223 png_crc_finish(png_ptr, length);
1224 return;
1225 }
1226
1227#ifdef PNG_MAX_MALLOC_64K
1228 if (length > (png_uint_32)65535L)
1229 {
1230 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1231 skip = length - (png_uint_32)65535L;
1232 length = (png_uint_32)65535L;
1233 }
1234#endif
1235
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001236 png_free(png_ptr, png_ptr->chunkdata);
1237 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001238 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001239 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001240
1241 if (png_crc_finish(png_ptr, skip))
1242 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001243 png_free(png_ptr, png_ptr->chunkdata);
1244 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001245 return;
1246 }
1247
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001248 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001249
Patrick Scott5f6bd842010-06-28 16:55:16 -04001250 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1251 entry_start++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001252 /* Empty loop to find end of name */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001253 ++entry_start;
1254
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001255 /* A sample depth should follow the separator, and we should be on it */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001256 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001257 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001258 png_free(png_ptr, png_ptr->chunkdata);
1259 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001260 png_warning(png_ptr, "malformed sPLT chunk");
1261 return;
1262 }
1263
1264 new_palette.depth = *entry_start++;
1265 entry_size = (new_palette.depth == 8 ? 6 : 10);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001266 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
The Android Open Source Project893912b2009-03-03 19:30:05 -08001267
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001268 /* Integrity-check the data length */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001269 if (data_length % entry_size)
1270 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001271 png_free(png_ptr, png_ptr->chunkdata);
1272 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001273 png_warning(png_ptr, "sPLT chunk has bad length");
1274 return;
1275 }
1276
1277 new_palette.nentries = (png_int_32) ( data_length / entry_size);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001278 if ((png_uint_32) new_palette.nentries >
1279 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
The Android Open Source Project893912b2009-03-03 19:30:05 -08001280 {
1281 png_warning(png_ptr, "sPLT chunk too long");
1282 return;
1283 }
1284 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1285 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1286 if (new_palette.entries == NULL)
1287 {
1288 png_warning(png_ptr, "sPLT chunk requires too much memory");
1289 return;
1290 }
1291
Patrick Scott5f6bd842010-06-28 16:55:16 -04001292#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001293 for (i = 0; i < new_palette.nentries; i++)
1294 {
Patrick Scott5f6bd842010-06-28 16:55:16 -04001295 pp = new_palette.entries + i;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001296
1297 if (new_palette.depth == 8)
1298 {
1299 pp->red = *entry_start++;
1300 pp->green = *entry_start++;
1301 pp->blue = *entry_start++;
1302 pp->alpha = *entry_start++;
1303 }
1304 else
1305 {
1306 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1307 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1308 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1309 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1310 }
1311 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1312 }
1313#else
1314 pp = new_palette.entries;
1315 for (i = 0; i < new_palette.nentries; i++)
1316 {
1317
1318 if (new_palette.depth == 8)
1319 {
1320 pp[i].red = *entry_start++;
1321 pp[i].green = *entry_start++;
1322 pp[i].blue = *entry_start++;
1323 pp[i].alpha = *entry_start++;
1324 }
1325 else
1326 {
1327 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1328 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1329 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1330 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1331 }
1332 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1333 }
1334#endif
1335
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001336 /* Discard all chunk data except the name and stash that */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001337 new_palette.name = png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001338
1339 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1340
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001341 png_free(png_ptr, png_ptr->chunkdata);
1342 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001343 png_free(png_ptr, new_palette.entries);
1344}
1345#endif /* PNG_READ_sPLT_SUPPORTED */
1346
Patrick Scott5f6bd842010-06-28 16:55:16 -04001347#ifdef PNG_READ_tRNS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001348void /* PRIVATE */
1349png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1350{
1351 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1352
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001353 png_debug(1, "in png_handle_tRNS");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001354
1355 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1356 png_error(png_ptr, "Missing IHDR before tRNS");
1357 else if (png_ptr->mode & PNG_HAVE_IDAT)
1358 {
1359 png_warning(png_ptr, "Invalid tRNS after IDAT");
1360 png_crc_finish(png_ptr, length);
1361 return;
1362 }
1363 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1364 {
1365 png_warning(png_ptr, "Duplicate tRNS chunk");
1366 png_crc_finish(png_ptr, length);
1367 return;
1368 }
1369
1370 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1371 {
1372 png_byte buf[2];
1373
1374 if (length != 2)
1375 {
1376 png_warning(png_ptr, "Incorrect tRNS chunk length");
1377 png_crc_finish(png_ptr, length);
1378 return;
1379 }
1380
1381 png_crc_read(png_ptr, buf, 2);
1382 png_ptr->num_trans = 1;
1383 png_ptr->trans_values.gray = png_get_uint_16(buf);
1384 }
1385 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1386 {
1387 png_byte buf[6];
1388
1389 if (length != 6)
1390 {
1391 png_warning(png_ptr, "Incorrect tRNS chunk length");
1392 png_crc_finish(png_ptr, length);
1393 return;
1394 }
1395 png_crc_read(png_ptr, buf, (png_size_t)length);
1396 png_ptr->num_trans = 1;
1397 png_ptr->trans_values.red = png_get_uint_16(buf);
1398 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1399 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1400 }
1401 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1402 {
1403 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1404 {
1405 /* Should be an error, but we can cope with it. */
1406 png_warning(png_ptr, "Missing PLTE before tRNS");
1407 }
1408 if (length > (png_uint_32)png_ptr->num_palette ||
1409 length > PNG_MAX_PALETTE_LENGTH)
1410 {
1411 png_warning(png_ptr, "Incorrect tRNS chunk length");
1412 png_crc_finish(png_ptr, length);
1413 return;
1414 }
1415 if (length == 0)
1416 {
1417 png_warning(png_ptr, "Zero length tRNS chunk");
1418 png_crc_finish(png_ptr, length);
1419 return;
1420 }
1421 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1422 png_ptr->num_trans = (png_uint_16)length;
1423 }
1424 else
1425 {
1426 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1427 png_crc_finish(png_ptr, length);
1428 return;
1429 }
1430
1431 if (png_crc_finish(png_ptr, 0))
1432 {
1433 png_ptr->num_trans = 0;
1434 return;
1435 }
1436
1437 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1438 &(png_ptr->trans_values));
1439}
1440#endif
1441
Patrick Scott5f6bd842010-06-28 16:55:16 -04001442#ifdef PNG_READ_bKGD_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001443void /* PRIVATE */
1444png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1445{
1446 png_size_t truelen;
1447 png_byte buf[6];
1448
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001449 png_debug(1, "in png_handle_bKGD");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001450
1451 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1452 png_error(png_ptr, "Missing IHDR before bKGD");
1453 else if (png_ptr->mode & PNG_HAVE_IDAT)
1454 {
1455 png_warning(png_ptr, "Invalid bKGD after IDAT");
1456 png_crc_finish(png_ptr, length);
1457 return;
1458 }
1459 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1460 !(png_ptr->mode & PNG_HAVE_PLTE))
1461 {
1462 png_warning(png_ptr, "Missing PLTE before bKGD");
1463 png_crc_finish(png_ptr, length);
1464 return;
1465 }
1466 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1467 {
1468 png_warning(png_ptr, "Duplicate bKGD chunk");
1469 png_crc_finish(png_ptr, length);
1470 return;
1471 }
1472
1473 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1474 truelen = 1;
1475 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1476 truelen = 6;
1477 else
1478 truelen = 2;
1479
1480 if (length != truelen)
1481 {
1482 png_warning(png_ptr, "Incorrect bKGD chunk length");
1483 png_crc_finish(png_ptr, length);
1484 return;
1485 }
1486
1487 png_crc_read(png_ptr, buf, truelen);
1488 if (png_crc_finish(png_ptr, 0))
1489 return;
1490
1491 /* We convert the index value into RGB components so that we can allow
1492 * arbitrary RGB values for background when we have transparency, and
1493 * so it is easy to determine the RGB values of the background color
1494 * from the info_ptr struct. */
1495 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1496 {
1497 png_ptr->background.index = buf[0];
1498 if (info_ptr && info_ptr->num_palette)
1499 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001500 if (buf[0] >= info_ptr->num_palette)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001501 {
1502 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1503 return;
1504 }
1505 png_ptr->background.red =
1506 (png_uint_16)png_ptr->palette[buf[0]].red;
1507 png_ptr->background.green =
1508 (png_uint_16)png_ptr->palette[buf[0]].green;
1509 png_ptr->background.blue =
1510 (png_uint_16)png_ptr->palette[buf[0]].blue;
1511 }
1512 }
1513 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1514 {
1515 png_ptr->background.red =
1516 png_ptr->background.green =
1517 png_ptr->background.blue =
1518 png_ptr->background.gray = png_get_uint_16(buf);
1519 }
1520 else
1521 {
1522 png_ptr->background.red = png_get_uint_16(buf);
1523 png_ptr->background.green = png_get_uint_16(buf + 2);
1524 png_ptr->background.blue = png_get_uint_16(buf + 4);
1525 }
1526
1527 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1528}
1529#endif
1530
Patrick Scott5f6bd842010-06-28 16:55:16 -04001531#ifdef PNG_READ_hIST_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001532void /* PRIVATE */
1533png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1534{
1535 unsigned int num, i;
1536 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1537
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001538 png_debug(1, "in png_handle_hIST");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001539
1540 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1541 png_error(png_ptr, "Missing IHDR before hIST");
1542 else if (png_ptr->mode & PNG_HAVE_IDAT)
1543 {
1544 png_warning(png_ptr, "Invalid hIST after IDAT");
1545 png_crc_finish(png_ptr, length);
1546 return;
1547 }
1548 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1549 {
1550 png_warning(png_ptr, "Missing PLTE before hIST");
1551 png_crc_finish(png_ptr, length);
1552 return;
1553 }
1554 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1555 {
1556 png_warning(png_ptr, "Duplicate hIST chunk");
1557 png_crc_finish(png_ptr, length);
1558 return;
1559 }
1560
1561 num = length / 2 ;
1562 if (num != (unsigned int) png_ptr->num_palette || num >
1563 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1564 {
1565 png_warning(png_ptr, "Incorrect hIST chunk length");
1566 png_crc_finish(png_ptr, length);
1567 return;
1568 }
1569
1570 for (i = 0; i < num; i++)
1571 {
1572 png_byte buf[2];
1573
1574 png_crc_read(png_ptr, buf, 2);
1575 readbuf[i] = png_get_uint_16(buf);
1576 }
1577
1578 if (png_crc_finish(png_ptr, 0))
1579 return;
1580
1581 png_set_hIST(png_ptr, info_ptr, readbuf);
1582}
1583#endif
1584
Patrick Scott5f6bd842010-06-28 16:55:16 -04001585#ifdef PNG_READ_pHYs_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001586void /* PRIVATE */
1587png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1588{
1589 png_byte buf[9];
1590 png_uint_32 res_x, res_y;
1591 int unit_type;
1592
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001593 png_debug(1, "in png_handle_pHYs");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001594
1595 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1596 png_error(png_ptr, "Missing IHDR before pHYs");
1597 else if (png_ptr->mode & PNG_HAVE_IDAT)
1598 {
1599 png_warning(png_ptr, "Invalid pHYs after IDAT");
1600 png_crc_finish(png_ptr, length);
1601 return;
1602 }
1603 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1604 {
1605 png_warning(png_ptr, "Duplicate pHYs chunk");
1606 png_crc_finish(png_ptr, length);
1607 return;
1608 }
1609
1610 if (length != 9)
1611 {
1612 png_warning(png_ptr, "Incorrect pHYs chunk length");
1613 png_crc_finish(png_ptr, length);
1614 return;
1615 }
1616
1617 png_crc_read(png_ptr, buf, 9);
1618 if (png_crc_finish(png_ptr, 0))
1619 return;
1620
1621 res_x = png_get_uint_32(buf);
1622 res_y = png_get_uint_32(buf + 4);
1623 unit_type = buf[8];
1624 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1625}
1626#endif
1627
Patrick Scott5f6bd842010-06-28 16:55:16 -04001628#ifdef PNG_READ_oFFs_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001629void /* PRIVATE */
1630png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1631{
1632 png_byte buf[9];
1633 png_int_32 offset_x, offset_y;
1634 int unit_type;
1635
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001636 png_debug(1, "in png_handle_oFFs");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001637
1638 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1639 png_error(png_ptr, "Missing IHDR before oFFs");
1640 else if (png_ptr->mode & PNG_HAVE_IDAT)
1641 {
1642 png_warning(png_ptr, "Invalid oFFs after IDAT");
1643 png_crc_finish(png_ptr, length);
1644 return;
1645 }
1646 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1647 {
1648 png_warning(png_ptr, "Duplicate oFFs chunk");
1649 png_crc_finish(png_ptr, length);
1650 return;
1651 }
1652
1653 if (length != 9)
1654 {
1655 png_warning(png_ptr, "Incorrect oFFs chunk length");
1656 png_crc_finish(png_ptr, length);
1657 return;
1658 }
1659
1660 png_crc_read(png_ptr, buf, 9);
1661 if (png_crc_finish(png_ptr, 0))
1662 return;
1663
1664 offset_x = png_get_int_32(buf);
1665 offset_y = png_get_int_32(buf + 4);
1666 unit_type = buf[8];
1667 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1668}
1669#endif
1670
Patrick Scott5f6bd842010-06-28 16:55:16 -04001671#ifdef PNG_READ_pCAL_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001672/* Read the pCAL chunk (described in the PNG Extensions document) */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001673void /* PRIVATE */
1674png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1675{
The Android Open Source Project893912b2009-03-03 19:30:05 -08001676 png_int_32 X0, X1;
1677 png_byte type, nparams;
1678 png_charp buf, units, endptr;
1679 png_charpp params;
1680 png_size_t slength;
1681 int i;
1682
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001683 png_debug(1, "in png_handle_pCAL");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001684
1685 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1686 png_error(png_ptr, "Missing IHDR before pCAL");
1687 else if (png_ptr->mode & PNG_HAVE_IDAT)
1688 {
1689 png_warning(png_ptr, "Invalid pCAL after IDAT");
1690 png_crc_finish(png_ptr, length);
1691 return;
1692 }
1693 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1694 {
1695 png_warning(png_ptr, "Duplicate pCAL chunk");
1696 png_crc_finish(png_ptr, length);
1697 return;
1698 }
1699
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001700 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
The Android Open Source Project893912b2009-03-03 19:30:05 -08001701 length + 1);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001702 png_free(png_ptr, png_ptr->chunkdata);
1703 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1704 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001705 {
1706 png_warning(png_ptr, "No memory for pCAL purpose.");
1707 return;
1708 }
1709 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001710 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001711
1712 if (png_crc_finish(png_ptr, 0))
1713 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001714 png_free(png_ptr, png_ptr->chunkdata);
1715 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001716 return;
1717 }
1718
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001719 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001720
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001721 png_debug(3, "Finding end of pCAL purpose string");
1722 for (buf = png_ptr->chunkdata; *buf; buf++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001723 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001724
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001725 endptr = png_ptr->chunkdata + slength;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001726
1727 /* We need to have at least 12 bytes after the purpose string
1728 in order to get the parameter information. */
1729 if (endptr <= buf + 12)
1730 {
1731 png_warning(png_ptr, "Invalid pCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001732 png_free(png_ptr, png_ptr->chunkdata);
1733 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001734 return;
1735 }
1736
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001737 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001738 X0 = png_get_int_32((png_bytep)buf+1);
1739 X1 = png_get_int_32((png_bytep)buf+5);
1740 type = buf[9];
1741 nparams = buf[10];
1742 units = buf + 11;
1743
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001744 png_debug(3, "Checking pCAL equation type and number of parameters");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001745 /* Check that we have the right number of parameters for known
1746 equation types. */
1747 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1748 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1749 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1750 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1751 {
1752 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001753 png_free(png_ptr, png_ptr->chunkdata);
1754 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001755 return;
1756 }
1757 else if (type >= PNG_EQUATION_LAST)
1758 {
1759 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1760 }
1761
1762 for (buf = units; *buf; buf++)
1763 /* Empty loop to move past the units string. */ ;
1764
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001765 png_debug(3, "Allocating pCAL parameters array");
1766 params = (png_charpp)png_malloc_warn(png_ptr,
1767 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001768 if (params == NULL)
1769 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001770 png_free(png_ptr, png_ptr->chunkdata);
1771 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001772 png_warning(png_ptr, "No memory for pCAL params.");
1773 return;
1774 }
1775
1776 /* Get pointers to the start of each parameter string. */
1777 for (i = 0; i < (int)nparams; i++)
1778 {
1779 buf++; /* Skip the null string terminator from previous parameter. */
1780
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001781 png_debug1(3, "Reading pCAL parameter %d", i);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001782 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1783 /* Empty loop to move past each parameter string */ ;
1784
1785 /* Make sure we haven't run out of data yet */
1786 if (buf > endptr)
1787 {
1788 png_warning(png_ptr, "Invalid pCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001789 png_free(png_ptr, png_ptr->chunkdata);
1790 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001791 png_free(png_ptr, params);
1792 return;
1793 }
1794 }
1795
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001796 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
The Android Open Source Project893912b2009-03-03 19:30:05 -08001797 units, params);
1798
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001799 png_free(png_ptr, png_ptr->chunkdata);
1800 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001801 png_free(png_ptr, params);
1802}
1803#endif
1804
Patrick Scott5f6bd842010-06-28 16:55:16 -04001805#ifdef PNG_READ_sCAL_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001806/* Read the sCAL chunk */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001807void /* PRIVATE */
1808png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1809{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001810 png_charp ep;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001811#ifdef PNG_FLOATING_POINT_SUPPORTED
1812 double width, height;
1813 png_charp vp;
1814#else
1815#ifdef PNG_FIXED_POINT_SUPPORTED
1816 png_charp swidth, sheight;
1817#endif
1818#endif
1819 png_size_t slength;
1820
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001821 png_debug(1, "in png_handle_sCAL");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001822
1823 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1824 png_error(png_ptr, "Missing IHDR before sCAL");
1825 else if (png_ptr->mode & PNG_HAVE_IDAT)
1826 {
1827 png_warning(png_ptr, "Invalid sCAL after IDAT");
1828 png_crc_finish(png_ptr, length);
1829 return;
1830 }
1831 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1832 {
1833 png_warning(png_ptr, "Duplicate sCAL chunk");
1834 png_crc_finish(png_ptr, length);
1835 return;
1836 }
1837
Eric Vannier66dce0d2011-07-20 17:03:29 -07001838 /* Need unit type, width, \0, height: minimum 4 bytes */
1839 else if (length < 4)
1840 {
1841 png_warning(png_ptr, "sCAL chunk too short");
1842 png_crc_finish(png_ptr, length);
1843 return;
1844 }
1845
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001846 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
The Android Open Source Project893912b2009-03-03 19:30:05 -08001847 length + 1);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001848 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1849 if (png_ptr->chunkdata == NULL)
1850 {
1851 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001852 png_crc_finish(png_ptr, length);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001853 return;
1854 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001855 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001856 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001857
1858 if (png_crc_finish(png_ptr, 0))
1859 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001860 png_free(png_ptr, png_ptr->chunkdata);
1861 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001862 return;
1863 }
1864
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001865 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001866
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001867 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001868
1869#ifdef PNG_FLOATING_POINT_SUPPORTED
1870 width = png_strtod(png_ptr, ep, &vp);
1871 if (*vp)
1872 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001873 png_warning(png_ptr, "malformed width string in sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001874 png_free(png_ptr, png_ptr->chunkdata);
1875 png_ptr->chunkdata = NULL;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001876 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001877 }
1878#else
1879#ifdef PNG_FIXED_POINT_SUPPORTED
1880 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1881 if (swidth == NULL)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001882 {
1883 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001884 png_free(png_ptr, png_ptr->chunkdata);
1885 png_ptr->chunkdata = NULL;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001886 return;
1887 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001888 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1889#endif
1890#endif
1891
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001892 for (ep = png_ptr->chunkdata; *ep; ep++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001893 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001894 ep++;
1895
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001896 if (png_ptr->chunkdata + slength < ep)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001897 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001898 png_warning(png_ptr, "Truncated sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001899#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001900 png_free(png_ptr, swidth);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001901#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001902 png_free(png_ptr, png_ptr->chunkdata);
1903 png_ptr->chunkdata = NULL;
1904 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001905 }
1906
1907#ifdef PNG_FLOATING_POINT_SUPPORTED
1908 height = png_strtod(png_ptr, ep, &vp);
1909 if (*vp)
1910 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001911 png_warning(png_ptr, "malformed height string in sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001912 png_free(png_ptr, png_ptr->chunkdata);
1913 png_ptr->chunkdata = NULL;
1914#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1915 png_free(png_ptr, swidth);
1916#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001917 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001918 }
1919#else
1920#ifdef PNG_FIXED_POINT_SUPPORTED
1921 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1922 if (sheight == NULL)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001923 {
1924 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001925 png_free(png_ptr, png_ptr->chunkdata);
1926 png_ptr->chunkdata = NULL;
1927#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1928 png_free(png_ptr, swidth);
1929#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001930 return;
1931 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001932 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1933#endif
1934#endif
1935
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001936 if (png_ptr->chunkdata + slength < ep
The Android Open Source Project893912b2009-03-03 19:30:05 -08001937#ifdef PNG_FLOATING_POINT_SUPPORTED
1938 || width <= 0. || height <= 0.
1939#endif
1940 )
1941 {
1942 png_warning(png_ptr, "Invalid sCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001943 png_free(png_ptr, png_ptr->chunkdata);
1944 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001945#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1946 png_free(png_ptr, swidth);
1947 png_free(png_ptr, sheight);
1948#endif
1949 return;
1950 }
1951
1952
1953#ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001954 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001955#else
1956#ifdef PNG_FIXED_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001957 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001958#endif
1959#endif
1960
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001961 png_free(png_ptr, png_ptr->chunkdata);
1962 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001963#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1964 png_free(png_ptr, swidth);
1965 png_free(png_ptr, sheight);
1966#endif
1967}
1968#endif
1969
Patrick Scott5f6bd842010-06-28 16:55:16 -04001970#ifdef PNG_READ_tIME_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001971void /* PRIVATE */
1972png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1973{
1974 png_byte buf[7];
1975 png_time mod_time;
1976
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001977 png_debug(1, "in png_handle_tIME");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001978
1979 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1980 png_error(png_ptr, "Out of place tIME chunk");
1981 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1982 {
1983 png_warning(png_ptr, "Duplicate tIME chunk");
1984 png_crc_finish(png_ptr, length);
1985 return;
1986 }
1987
1988 if (png_ptr->mode & PNG_HAVE_IDAT)
1989 png_ptr->mode |= PNG_AFTER_IDAT;
1990
1991 if (length != 7)
1992 {
1993 png_warning(png_ptr, "Incorrect tIME chunk length");
1994 png_crc_finish(png_ptr, length);
1995 return;
1996 }
1997
1998 png_crc_read(png_ptr, buf, 7);
1999 if (png_crc_finish(png_ptr, 0))
2000 return;
2001
2002 mod_time.second = buf[6];
2003 mod_time.minute = buf[5];
2004 mod_time.hour = buf[4];
2005 mod_time.day = buf[3];
2006 mod_time.month = buf[2];
2007 mod_time.year = png_get_uint_16(buf);
2008
2009 png_set_tIME(png_ptr, info_ptr, &mod_time);
2010}
2011#endif
2012
Patrick Scott5f6bd842010-06-28 16:55:16 -04002013#ifdef PNG_READ_tEXt_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002014/* Note: this does not properly handle chunks that are > 64K under DOS */
2015void /* PRIVATE */
2016png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2017{
2018 png_textp text_ptr;
2019 png_charp key;
2020 png_charp text;
2021 png_uint_32 skip = 0;
2022 png_size_t slength;
2023 int ret;
2024
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002025 png_debug(1, "in png_handle_tEXt");
2026
Patrick Scott5f6bd842010-06-28 16:55:16 -04002027#ifdef PNG_USER_LIMITS_SUPPORTED
2028 if (png_ptr->user_chunk_cache_max != 0)
2029 {
2030 if (png_ptr->user_chunk_cache_max == 1)
2031 {
2032 png_crc_finish(png_ptr, length);
2033 return;
2034 }
2035 if (--png_ptr->user_chunk_cache_max == 1)
2036 {
2037 png_warning(png_ptr, "No space in chunk cache for tEXt");
2038 png_crc_finish(png_ptr, length);
2039 return;
2040 }
2041 }
2042#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002043
2044 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2045 png_error(png_ptr, "Missing IHDR before tEXt");
2046
2047 if (png_ptr->mode & PNG_HAVE_IDAT)
2048 png_ptr->mode |= PNG_AFTER_IDAT;
2049
2050#ifdef PNG_MAX_MALLOC_64K
2051 if (length > (png_uint_32)65535L)
2052 {
2053 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
2054 skip = length - (png_uint_32)65535L;
2055 length = (png_uint_32)65535L;
2056 }
2057#endif
2058
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002059 png_free(png_ptr, png_ptr->chunkdata);
2060
2061 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2062 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002063 {
2064 png_warning(png_ptr, "No memory to process text chunk.");
2065 return;
2066 }
2067 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002068 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002069
2070 if (png_crc_finish(png_ptr, skip))
2071 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002072 png_free(png_ptr, png_ptr->chunkdata);
2073 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002074 return;
2075 }
2076
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002077 key = png_ptr->chunkdata;
2078
The Android Open Source Project893912b2009-03-03 19:30:05 -08002079 key[slength] = 0x00;
2080
2081 for (text = key; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002082 /* Empty loop to find end of key */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002083
2084 if (text != key + slength)
2085 text++;
2086
2087 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2088 (png_uint_32)png_sizeof(png_text));
2089 if (text_ptr == NULL)
2090 {
2091 png_warning(png_ptr, "Not enough memory to process text chunk.");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002092 png_free(png_ptr, png_ptr->chunkdata);
2093 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002094 return;
2095 }
2096 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2097 text_ptr->key = key;
2098#ifdef PNG_iTXt_SUPPORTED
2099 text_ptr->lang = NULL;
2100 text_ptr->lang_key = NULL;
2101 text_ptr->itxt_length = 0;
2102#endif
2103 text_ptr->text = text;
2104 text_ptr->text_length = png_strlen(text);
2105
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002106 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002107
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002108 png_free(png_ptr, png_ptr->chunkdata);
2109 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002110 png_free(png_ptr, text_ptr);
2111 if (ret)
2112 png_warning(png_ptr, "Insufficient memory to process text chunk.");
2113}
2114#endif
2115
Patrick Scott5f6bd842010-06-28 16:55:16 -04002116#ifdef PNG_READ_zTXt_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002117/* Note: this does not correctly handle chunks that are > 64K under DOS */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002118void /* PRIVATE */
2119png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2120{
2121 png_textp text_ptr;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002122 png_charp text;
2123 int comp_type;
2124 int ret;
2125 png_size_t slength, prefix_len, data_len;
2126
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002127 png_debug(1, "in png_handle_zTXt");
2128
Patrick Scott5f6bd842010-06-28 16:55:16 -04002129#ifdef PNG_USER_LIMITS_SUPPORTED
2130 if (png_ptr->user_chunk_cache_max != 0)
2131 {
2132 if (png_ptr->user_chunk_cache_max == 1)
2133 {
2134 png_crc_finish(png_ptr, length);
2135 return;
2136 }
2137 if (--png_ptr->user_chunk_cache_max == 1)
2138 {
2139 png_warning(png_ptr, "No space in chunk cache for zTXt");
2140 png_crc_finish(png_ptr, length);
2141 return;
2142 }
2143 }
2144#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002145
The Android Open Source Project893912b2009-03-03 19:30:05 -08002146 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2147 png_error(png_ptr, "Missing IHDR before zTXt");
2148
2149 if (png_ptr->mode & PNG_HAVE_IDAT)
2150 png_ptr->mode |= PNG_AFTER_IDAT;
2151
2152#ifdef PNG_MAX_MALLOC_64K
2153 /* We will no doubt have problems with chunks even half this size, but
2154 there is no hard and fast rule to tell us where to stop. */
2155 if (length > (png_uint_32)65535L)
2156 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002157 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002158 png_crc_finish(png_ptr, length);
2159 return;
2160 }
2161#endif
2162
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002163 png_free(png_ptr, png_ptr->chunkdata);
2164 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2165 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002166 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002167 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002168 return;
2169 }
2170 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002171 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002172 if (png_crc_finish(png_ptr, 0))
2173 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002174 png_free(png_ptr, png_ptr->chunkdata);
2175 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002176 return;
2177 }
2178
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002179 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002180
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002181 for (text = png_ptr->chunkdata; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002182 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002183
2184 /* zTXt must have some text after the chunkdataword */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002185 if (text >= png_ptr->chunkdata + slength - 2)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002186 {
2187 png_warning(png_ptr, "Truncated zTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002188 png_free(png_ptr, png_ptr->chunkdata);
2189 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002190 return;
2191 }
2192 else
2193 {
2194 comp_type = *(++text);
2195 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2196 {
2197 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2198 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2199 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002200 text++; /* Skip the compression_method byte */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002201 }
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002202 prefix_len = text - png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002203
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002204 png_decompress_chunk(png_ptr, comp_type,
2205 (png_size_t)length, prefix_len, &data_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002206
2207 text_ptr = (png_textp)png_malloc_warn(png_ptr,
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002208 (png_uint_32)png_sizeof(png_text));
The Android Open Source Project893912b2009-03-03 19:30:05 -08002209 if (text_ptr == NULL)
2210 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002211 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
2212 png_free(png_ptr, png_ptr->chunkdata);
2213 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002214 return;
2215 }
2216 text_ptr->compression = comp_type;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002217 text_ptr->key = png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002218#ifdef PNG_iTXt_SUPPORTED
2219 text_ptr->lang = NULL;
2220 text_ptr->lang_key = NULL;
2221 text_ptr->itxt_length = 0;
2222#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002223 text_ptr->text = png_ptr->chunkdata + prefix_len;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002224 text_ptr->text_length = data_len;
2225
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002226 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002227
2228 png_free(png_ptr, text_ptr);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002229 png_free(png_ptr, png_ptr->chunkdata);
2230 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002231 if (ret)
2232 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2233}
2234#endif
2235
Patrick Scott5f6bd842010-06-28 16:55:16 -04002236#ifdef PNG_READ_iTXt_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002237/* Note: this does not correctly handle chunks that are > 64K under DOS */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002238void /* PRIVATE */
2239png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2240{
2241 png_textp text_ptr;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002242 png_charp key, lang, text, lang_key;
2243 int comp_flag;
2244 int comp_type = 0;
2245 int ret;
2246 png_size_t slength, prefix_len, data_len;
2247
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002248 png_debug(1, "in png_handle_iTXt");
2249
Patrick Scott5f6bd842010-06-28 16:55:16 -04002250#ifdef PNG_USER_LIMITS_SUPPORTED
2251 if (png_ptr->user_chunk_cache_max != 0)
2252 {
2253 if (png_ptr->user_chunk_cache_max == 1)
2254 {
2255 png_crc_finish(png_ptr, length);
2256 return;
2257 }
2258 if (--png_ptr->user_chunk_cache_max == 1)
2259 {
2260 png_warning(png_ptr, "No space in chunk cache for iTXt");
2261 png_crc_finish(png_ptr, length);
2262 return;
2263 }
2264 }
2265#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002266
2267 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2268 png_error(png_ptr, "Missing IHDR before iTXt");
2269
2270 if (png_ptr->mode & PNG_HAVE_IDAT)
2271 png_ptr->mode |= PNG_AFTER_IDAT;
2272
2273#ifdef PNG_MAX_MALLOC_64K
2274 /* We will no doubt have problems with chunks even half this size, but
2275 there is no hard and fast rule to tell us where to stop. */
2276 if (length > (png_uint_32)65535L)
2277 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002278 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002279 png_crc_finish(png_ptr, length);
2280 return;
2281 }
2282#endif
2283
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002284 png_free(png_ptr, png_ptr->chunkdata);
2285 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2286 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002287 {
2288 png_warning(png_ptr, "No memory to process iTXt chunk.");
2289 return;
2290 }
2291 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002292 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002293 if (png_crc_finish(png_ptr, 0))
2294 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002295 png_free(png_ptr, png_ptr->chunkdata);
2296 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002297 return;
2298 }
2299
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002300 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002301
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002302 for (lang = png_ptr->chunkdata; *lang; lang++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002303 /* Empty loop */ ;
2304 lang++; /* Skip NUL separator */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002305
2306 /* iTXt must have a language tag (possibly empty), two compression bytes,
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002307 * translated keyword (possibly empty), and possibly some text after the
2308 * keyword
2309 */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002310
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002311 if (lang >= png_ptr->chunkdata + slength - 3)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002312 {
2313 png_warning(png_ptr, "Truncated iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002314 png_free(png_ptr, png_ptr->chunkdata);
2315 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002316 return;
2317 }
2318 else
2319 {
2320 comp_flag = *lang++;
2321 comp_type = *lang++;
2322 }
2323
2324 for (lang_key = lang; *lang_key; lang_key++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002325 /* Empty loop */ ;
2326 lang_key++; /* Skip NUL separator */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002327
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002328 if (lang_key >= png_ptr->chunkdata + slength)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002329 {
2330 png_warning(png_ptr, "Truncated iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002331 png_free(png_ptr, png_ptr->chunkdata);
2332 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002333 return;
2334 }
2335
2336 for (text = lang_key; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002337 /* Empty loop */ ;
2338 text++; /* Skip NUL separator */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002339 if (text >= png_ptr->chunkdata + slength)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002340 {
2341 png_warning(png_ptr, "Malformed iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002342 png_free(png_ptr, png_ptr->chunkdata);
2343 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002344 return;
2345 }
2346
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002347 prefix_len = text - png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002348
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002349 key=png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002350 if (comp_flag)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002351 png_decompress_chunk(png_ptr, comp_type,
2352 (size_t)length, prefix_len, &data_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002353 else
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002354 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002355 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2356 (png_uint_32)png_sizeof(png_text));
2357 if (text_ptr == NULL)
2358 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002359 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2360 png_free(png_ptr, png_ptr->chunkdata);
2361 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002362 return;
2363 }
2364 text_ptr->compression = (int)comp_flag + 1;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002365 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2366 text_ptr->lang = png_ptr->chunkdata + (lang - key);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002367 text_ptr->itxt_length = data_len;
2368 text_ptr->text_length = 0;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002369 text_ptr->key = png_ptr->chunkdata;
2370 text_ptr->text = png_ptr->chunkdata + prefix_len;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002371
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002372 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002373
2374 png_free(png_ptr, text_ptr);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002375 png_free(png_ptr, png_ptr->chunkdata);
2376 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002377 if (ret)
2378 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2379}
2380#endif
2381
2382/* This function is called when we haven't found a handler for a
2383 chunk. If there isn't a problem with the chunk itself (ie bad
2384 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2385 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2386 case it will be saved away to be written out later. */
2387void /* PRIVATE */
2388png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2389{
2390 png_uint_32 skip = 0;
2391
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002392 png_debug(1, "in png_handle_unknown");
2393
Patrick Scott5f6bd842010-06-28 16:55:16 -04002394#ifdef PNG_USER_LIMITS_SUPPORTED
2395 if (png_ptr->user_chunk_cache_max != 0)
2396 {
2397 if (png_ptr->user_chunk_cache_max == 1)
2398 {
2399 png_crc_finish(png_ptr, length);
2400 return;
2401 }
2402 if (--png_ptr->user_chunk_cache_max == 1)
2403 {
2404 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2405 png_crc_finish(png_ptr, length);
2406 return;
2407 }
2408 }
2409#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002410
2411 if (png_ptr->mode & PNG_HAVE_IDAT)
2412 {
2413#ifdef PNG_USE_LOCAL_ARRAYS
2414 PNG_CONST PNG_IDAT;
2415#endif
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002416 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002417 png_ptr->mode |= PNG_AFTER_IDAT;
2418 }
2419
The Android Open Source Project893912b2009-03-03 19:30:05 -08002420 if (!(png_ptr->chunk_name[0] & 0x20))
2421 {
Patrick Scott5f6bd842010-06-28 16:55:16 -04002422#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002423 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
The Android Open Source Project893912b2009-03-03 19:30:05 -08002424 PNG_HANDLE_CHUNK_ALWAYS
Patrick Scott5f6bd842010-06-28 16:55:16 -04002425#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002426 && png_ptr->read_user_chunk_fn == NULL
2427#endif
2428 )
2429#endif
2430 png_chunk_error(png_ptr, "unknown critical chunk");
2431 }
2432
Patrick Scott5f6bd842010-06-28 16:55:16 -04002433#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002434 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
Patrick Scott5f6bd842010-06-28 16:55:16 -04002435#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002436 || (png_ptr->read_user_chunk_fn != NULL)
2437#endif
2438 )
The Android Open Source Project893912b2009-03-03 19:30:05 -08002439 {
2440#ifdef PNG_MAX_MALLOC_64K
2441 if (length > (png_uint_32)65535L)
2442 {
2443 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2444 skip = length - (png_uint_32)65535L;
2445 length = (png_uint_32)65535L;
2446 }
2447#endif
2448 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002449 (png_charp)png_ptr->chunk_name,
The Android Open Source Project893912b2009-03-03 19:30:05 -08002450 png_sizeof(png_ptr->unknown_chunk.name));
Patrick Scott5f6bd842010-06-28 16:55:16 -04002451 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2452 = '\0';
The Android Open Source Project893912b2009-03-03 19:30:05 -08002453 png_ptr->unknown_chunk.size = (png_size_t)length;
2454 if (length == 0)
2455 png_ptr->unknown_chunk.data = NULL;
2456 else
2457 {
2458 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2459 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2460 }
Patrick Scott5f6bd842010-06-28 16:55:16 -04002461#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002462 if (png_ptr->read_user_chunk_fn != NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002463 {
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002464 /* Callback to user unknown chunk handler */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002465 int ret;
2466 ret = (*(png_ptr->read_user_chunk_fn))
2467 (png_ptr, &png_ptr->unknown_chunk);
2468 if (ret < 0)
2469 png_chunk_error(png_ptr, "error in user chunk");
2470 if (ret == 0)
2471 {
2472 if (!(png_ptr->chunk_name[0] & 0x20))
Patrick Scott5f6bd842010-06-28 16:55:16 -04002473#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002474 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
The Android Open Source Project893912b2009-03-03 19:30:05 -08002475 PNG_HANDLE_CHUNK_ALWAYS)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002476#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002477 png_chunk_error(png_ptr, "unknown critical chunk");
2478 png_set_unknown_chunks(png_ptr, info_ptr,
2479 &png_ptr->unknown_chunk, 1);
2480 }
2481 }
2482 else
2483#endif
2484 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2485 png_free(png_ptr, png_ptr->unknown_chunk.data);
2486 png_ptr->unknown_chunk.data = NULL;
2487 }
2488 else
2489#endif
2490 skip = length;
2491
2492 png_crc_finish(png_ptr, skip);
2493
Patrick Scott5f6bd842010-06-28 16:55:16 -04002494#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002495 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002496#endif
2497}
2498
2499/* This function is called to verify that a chunk name is valid.
2500 This function can't have the "critical chunk check" incorporated
2501 into it, since in the future we will need to be able to call user
2502 functions to handle unknown critical chunks after we check that
2503 the chunk name itself is valid. */
2504
2505#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2506
2507void /* PRIVATE */
2508png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2509{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002510 png_debug(1, "in png_check_chunk_name");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002511 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2512 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2513 {
2514 png_chunk_error(png_ptr, "invalid chunk type");
2515 }
2516}
2517
2518/* Combines the row recently read in with the existing pixels in the
2519 row. This routine takes care of alpha and transparency if requested.
2520 This routine also handles the two methods of progressive display
2521 of interlaced images, depending on the mask value.
2522 The mask value describes which pixels are to be combined with
2523 the row. The pattern always repeats every 8 pixels, so just 8
2524 bits are needed. A one indicates the pixel is to be combined,
2525 a zero indicates the pixel is to be skipped. This is in addition
2526 to any alpha or transparency value associated with the pixel. If
2527 you want all pixels to be combined, pass 0xff (255) in mask. */
2528
2529void /* PRIVATE */
2530png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2531{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002532 png_debug(1, "in png_combine_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002533 if (mask == 0xff)
2534 {
2535 png_memcpy(row, png_ptr->row_buf + 1,
2536 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2537 }
2538 else
2539 {
2540 switch (png_ptr->row_info.pixel_depth)
2541 {
2542 case 1:
2543 {
2544 png_bytep sp = png_ptr->row_buf + 1;
2545 png_bytep dp = row;
2546 int s_inc, s_start, s_end;
2547 int m = 0x80;
2548 int shift;
2549 png_uint_32 i;
2550 png_uint_32 row_width = png_ptr->width;
2551
Patrick Scott5f6bd842010-06-28 16:55:16 -04002552#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002553 if (png_ptr->transformations & PNG_PACKSWAP)
2554 {
2555 s_start = 0;
2556 s_end = 7;
2557 s_inc = 1;
2558 }
2559 else
2560#endif
2561 {
2562 s_start = 7;
2563 s_end = 0;
2564 s_inc = -1;
2565 }
2566
2567 shift = s_start;
2568
2569 for (i = 0; i < row_width; i++)
2570 {
2571 if (m & mask)
2572 {
2573 int value;
2574
2575 value = (*sp >> shift) & 0x01;
2576 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2577 *dp |= (png_byte)(value << shift);
2578 }
2579
2580 if (shift == s_end)
2581 {
2582 shift = s_start;
2583 sp++;
2584 dp++;
2585 }
2586 else
2587 shift += s_inc;
2588
2589 if (m == 1)
2590 m = 0x80;
2591 else
2592 m >>= 1;
2593 }
2594 break;
2595 }
2596 case 2:
2597 {
2598 png_bytep sp = png_ptr->row_buf + 1;
2599 png_bytep dp = row;
2600 int s_start, s_end, s_inc;
2601 int m = 0x80;
2602 int shift;
2603 png_uint_32 i;
2604 png_uint_32 row_width = png_ptr->width;
2605 int value;
2606
Patrick Scott5f6bd842010-06-28 16:55:16 -04002607#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002608 if (png_ptr->transformations & PNG_PACKSWAP)
2609 {
2610 s_start = 0;
2611 s_end = 6;
2612 s_inc = 2;
2613 }
2614 else
2615#endif
2616 {
2617 s_start = 6;
2618 s_end = 0;
2619 s_inc = -2;
2620 }
2621
2622 shift = s_start;
2623
2624 for (i = 0; i < row_width; i++)
2625 {
2626 if (m & mask)
2627 {
2628 value = (*sp >> shift) & 0x03;
2629 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2630 *dp |= (png_byte)(value << shift);
2631 }
2632
2633 if (shift == s_end)
2634 {
2635 shift = s_start;
2636 sp++;
2637 dp++;
2638 }
2639 else
2640 shift += s_inc;
2641 if (m == 1)
2642 m = 0x80;
2643 else
2644 m >>= 1;
2645 }
2646 break;
2647 }
2648 case 4:
2649 {
2650 png_bytep sp = png_ptr->row_buf + 1;
2651 png_bytep dp = row;
2652 int s_start, s_end, s_inc;
2653 int m = 0x80;
2654 int shift;
2655 png_uint_32 i;
2656 png_uint_32 row_width = png_ptr->width;
2657 int value;
2658
Patrick Scott5f6bd842010-06-28 16:55:16 -04002659#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002660 if (png_ptr->transformations & PNG_PACKSWAP)
2661 {
2662 s_start = 0;
2663 s_end = 4;
2664 s_inc = 4;
2665 }
2666 else
2667#endif
2668 {
2669 s_start = 4;
2670 s_end = 0;
2671 s_inc = -4;
2672 }
2673 shift = s_start;
2674
2675 for (i = 0; i < row_width; i++)
2676 {
2677 if (m & mask)
2678 {
2679 value = (*sp >> shift) & 0xf;
2680 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2681 *dp |= (png_byte)(value << shift);
2682 }
2683
2684 if (shift == s_end)
2685 {
2686 shift = s_start;
2687 sp++;
2688 dp++;
2689 }
2690 else
2691 shift += s_inc;
2692 if (m == 1)
2693 m = 0x80;
2694 else
2695 m >>= 1;
2696 }
2697 break;
2698 }
2699 default:
2700 {
2701 png_bytep sp = png_ptr->row_buf + 1;
2702 png_bytep dp = row;
2703 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2704 png_uint_32 i;
2705 png_uint_32 row_width = png_ptr->width;
2706 png_byte m = 0x80;
2707
2708
2709 for (i = 0; i < row_width; i++)
2710 {
2711 if (m & mask)
2712 {
2713 png_memcpy(dp, sp, pixel_bytes);
2714 }
2715
2716 sp += pixel_bytes;
2717 dp += pixel_bytes;
2718
2719 if (m == 1)
2720 m = 0x80;
2721 else
2722 m >>= 1;
2723 }
2724 break;
2725 }
2726 }
2727 }
2728}
2729
2730#ifdef PNG_READ_INTERLACING_SUPPORTED
2731/* OLD pre-1.0.9 interface:
2732void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2733 png_uint_32 transformations)
2734 */
2735void /* PRIVATE */
2736png_do_read_interlace(png_structp png_ptr)
2737{
2738 png_row_infop row_info = &(png_ptr->row_info);
2739 png_bytep row = png_ptr->row_buf + 1;
2740 int pass = png_ptr->pass;
2741 png_uint_32 transformations = png_ptr->transformations;
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002742 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2743 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002744 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
The Android Open Source Project893912b2009-03-03 19:30:05 -08002745
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002746 png_debug(1, "in png_do_read_interlace");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002747 if (row != NULL && row_info != NULL)
2748 {
2749 png_uint_32 final_width;
2750
2751 final_width = row_info->width * png_pass_inc[pass];
2752
2753 switch (row_info->pixel_depth)
2754 {
2755 case 1:
2756 {
2757 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2758 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2759 int sshift, dshift;
2760 int s_start, s_end, s_inc;
2761 int jstop = png_pass_inc[pass];
2762 png_byte v;
2763 png_uint_32 i;
2764 int j;
2765
Patrick Scott5f6bd842010-06-28 16:55:16 -04002766#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002767 if (transformations & PNG_PACKSWAP)
2768 {
2769 sshift = (int)((row_info->width + 7) & 0x07);
2770 dshift = (int)((final_width + 7) & 0x07);
2771 s_start = 7;
2772 s_end = 0;
2773 s_inc = -1;
2774 }
2775 else
2776#endif
2777 {
2778 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2779 dshift = 7 - (int)((final_width + 7) & 0x07);
2780 s_start = 0;
2781 s_end = 7;
2782 s_inc = 1;
2783 }
2784
2785 for (i = 0; i < row_info->width; i++)
2786 {
2787 v = (png_byte)((*sp >> sshift) & 0x01);
2788 for (j = 0; j < jstop; j++)
2789 {
2790 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2791 *dp |= (png_byte)(v << dshift);
2792 if (dshift == s_end)
2793 {
2794 dshift = s_start;
2795 dp--;
2796 }
2797 else
2798 dshift += s_inc;
2799 }
2800 if (sshift == s_end)
2801 {
2802 sshift = s_start;
2803 sp--;
2804 }
2805 else
2806 sshift += s_inc;
2807 }
2808 break;
2809 }
2810 case 2:
2811 {
2812 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2813 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2814 int sshift, dshift;
2815 int s_start, s_end, s_inc;
2816 int jstop = png_pass_inc[pass];
2817 png_uint_32 i;
2818
Patrick Scott5f6bd842010-06-28 16:55:16 -04002819#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002820 if (transformations & PNG_PACKSWAP)
2821 {
2822 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2823 dshift = (int)(((final_width + 3) & 0x03) << 1);
2824 s_start = 6;
2825 s_end = 0;
2826 s_inc = -2;
2827 }
2828 else
2829#endif
2830 {
2831 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2832 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2833 s_start = 0;
2834 s_end = 6;
2835 s_inc = 2;
2836 }
2837
2838 for (i = 0; i < row_info->width; i++)
2839 {
2840 png_byte v;
2841 int j;
2842
2843 v = (png_byte)((*sp >> sshift) & 0x03);
2844 for (j = 0; j < jstop; j++)
2845 {
2846 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2847 *dp |= (png_byte)(v << dshift);
2848 if (dshift == s_end)
2849 {
2850 dshift = s_start;
2851 dp--;
2852 }
2853 else
2854 dshift += s_inc;
2855 }
2856 if (sshift == s_end)
2857 {
2858 sshift = s_start;
2859 sp--;
2860 }
2861 else
2862 sshift += s_inc;
2863 }
2864 break;
2865 }
2866 case 4:
2867 {
2868 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2869 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2870 int sshift, dshift;
2871 int s_start, s_end, s_inc;
2872 png_uint_32 i;
2873 int jstop = png_pass_inc[pass];
2874
Patrick Scott5f6bd842010-06-28 16:55:16 -04002875#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002876 if (transformations & PNG_PACKSWAP)
2877 {
2878 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2879 dshift = (int)(((final_width + 1) & 0x01) << 2);
2880 s_start = 4;
2881 s_end = 0;
2882 s_inc = -4;
2883 }
2884 else
2885#endif
2886 {
2887 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2888 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2889 s_start = 0;
2890 s_end = 4;
2891 s_inc = 4;
2892 }
2893
2894 for (i = 0; i < row_info->width; i++)
2895 {
2896 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2897 int j;
2898
2899 for (j = 0; j < jstop; j++)
2900 {
2901 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2902 *dp |= (png_byte)(v << dshift);
2903 if (dshift == s_end)
2904 {
2905 dshift = s_start;
2906 dp--;
2907 }
2908 else
2909 dshift += s_inc;
2910 }
2911 if (sshift == s_end)
2912 {
2913 sshift = s_start;
2914 sp--;
2915 }
2916 else
2917 sshift += s_inc;
2918 }
2919 break;
2920 }
2921 default:
2922 {
2923 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
Patrick Scott5f6bd842010-06-28 16:55:16 -04002924 png_bytep sp = row + (png_size_t)(row_info->width - 1)
2925 * pixel_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002926 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2927
2928 int jstop = png_pass_inc[pass];
2929 png_uint_32 i;
2930
2931 for (i = 0; i < row_info->width; i++)
2932 {
2933 png_byte v[8];
2934 int j;
2935
2936 png_memcpy(v, sp, pixel_bytes);
2937 for (j = 0; j < jstop; j++)
2938 {
2939 png_memcpy(dp, v, pixel_bytes);
2940 dp -= pixel_bytes;
2941 }
2942 sp -= pixel_bytes;
2943 }
2944 break;
2945 }
2946 }
2947 row_info->width = final_width;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002948 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002949 }
Patrick Scott5f6bd842010-06-28 16:55:16 -04002950#ifndef PNG_READ_PACKSWAP_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002951 transformations = transformations; /* Silence compiler warning */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002952#endif
2953}
2954#endif /* PNG_READ_INTERLACING_SUPPORTED */
2955
2956void /* PRIVATE */
2957png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2958 png_bytep prev_row, int filter)
2959{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002960 png_debug(1, "in png_read_filter_row");
2961 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002962 switch (filter)
2963 {
2964 case PNG_FILTER_VALUE_NONE:
2965 break;
2966 case PNG_FILTER_VALUE_SUB:
2967 {
2968 png_uint_32 i;
2969 png_uint_32 istop = row_info->rowbytes;
2970 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2971 png_bytep rp = row + bpp;
2972 png_bytep lp = row;
2973
2974 for (i = bpp; i < istop; i++)
2975 {
2976 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2977 rp++;
2978 }
2979 break;
2980 }
2981 case PNG_FILTER_VALUE_UP:
2982 {
2983 png_uint_32 i;
2984 png_uint_32 istop = row_info->rowbytes;
2985 png_bytep rp = row;
2986 png_bytep pp = prev_row;
2987
2988 for (i = 0; i < istop; i++)
2989 {
2990 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2991 rp++;
2992 }
2993 break;
2994 }
2995 case PNG_FILTER_VALUE_AVG:
2996 {
2997 png_uint_32 i;
2998 png_bytep rp = row;
2999 png_bytep pp = prev_row;
3000 png_bytep lp = row;
3001 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3002 png_uint_32 istop = row_info->rowbytes - bpp;
3003
3004 for (i = 0; i < bpp; i++)
3005 {
3006 *rp = (png_byte)(((int)(*rp) +
3007 ((int)(*pp++) / 2 )) & 0xff);
3008 rp++;
3009 }
3010
3011 for (i = 0; i < istop; i++)
3012 {
3013 *rp = (png_byte)(((int)(*rp) +
3014 (int)(*pp++ + *lp++) / 2 ) & 0xff);
3015 rp++;
3016 }
3017 break;
3018 }
3019 case PNG_FILTER_VALUE_PAETH:
3020 {
3021 png_uint_32 i;
3022 png_bytep rp = row;
3023 png_bytep pp = prev_row;
3024 png_bytep lp = row;
3025 png_bytep cp = prev_row;
3026 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3027 png_uint_32 istop=row_info->rowbytes - bpp;
3028
3029 for (i = 0; i < bpp; i++)
3030 {
3031 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3032 rp++;
3033 }
3034
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003035 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003036 {
3037 int a, b, c, pa, pb, pc, p;
3038
3039 a = *lp++;
3040 b = *pp++;
3041 c = *cp++;
3042
3043 p = b - c;
3044 pc = a - c;
3045
3046#ifdef PNG_USE_ABS
3047 pa = abs(p);
3048 pb = abs(pc);
3049 pc = abs(p + pc);
3050#else
3051 pa = p < 0 ? -p : p;
3052 pb = pc < 0 ? -pc : pc;
3053 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3054#endif
3055
3056 /*
3057 if (pa <= pb && pa <= pc)
3058 p = a;
3059 else if (pb <= pc)
3060 p = b;
3061 else
3062 p = c;
3063 */
3064
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003065 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003066
3067 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3068 rp++;
3069 }
3070 break;
3071 }
3072 default:
3073 png_warning(png_ptr, "Ignoring bad adaptive filter type");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003074 *row = 0;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003075 break;
3076 }
3077}
3078
Joseph Wen4ce0ee12010-08-20 10:42:22 +08003079#ifdef PNG_INDEX_SUPPORTED
3080void /* PRIVATE */
3081png_set_interlaced_pass(png_structp png_ptr, int pass)
3082{
3083 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3084
3085 /* Start of interlace block */
3086 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3087
3088 /* Offset to next interlace block */
3089 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3090
3091 /* Start of interlace block in the y direction */
3092 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3093
3094 /* Offset to next interlace block in the y direction */
3095 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3096
3097 png_ptr->pass = pass;
3098 png_ptr->iwidth = (png_ptr->width +
3099 png_pass_inc[png_ptr->pass] - 1 -
3100 png_pass_start[png_ptr->pass]) /
3101 png_pass_inc[png_ptr->pass];
3102}
3103#endif
3104
Patrick Scott5f6bd842010-06-28 16:55:16 -04003105#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003106void /* PRIVATE */
3107png_read_finish_row(png_structp png_ptr)
3108{
The Android Open Source Project893912b2009-03-03 19:30:05 -08003109#ifdef PNG_READ_INTERLACING_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003110 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003111
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003112 /* Start of interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003113 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3114
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003115 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003116 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3117
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003118 /* Start of interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003119 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3120
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003121 /* Offset to next interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003122 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3123#endif /* PNG_READ_INTERLACING_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003124
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003125 png_debug(1, "in png_read_finish_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003126 png_ptr->row_number++;
3127 if (png_ptr->row_number < png_ptr->num_rows)
3128 return;
3129
3130#ifdef PNG_READ_INTERLACING_SUPPORTED
3131 if (png_ptr->interlaced)
3132 {
3133 png_ptr->row_number = 0;
3134 png_memset_check(png_ptr, png_ptr->prev_row, 0,
3135 png_ptr->rowbytes + 1);
3136 do
3137 {
3138 png_ptr->pass++;
3139 if (png_ptr->pass >= 7)
3140 break;
3141 png_ptr->iwidth = (png_ptr->width +
3142 png_pass_inc[png_ptr->pass] - 1 -
3143 png_pass_start[png_ptr->pass]) /
3144 png_pass_inc[png_ptr->pass];
3145
The Android Open Source Project893912b2009-03-03 19:30:05 -08003146 if (!(png_ptr->transformations & PNG_INTERLACE))
3147 {
3148 png_ptr->num_rows = (png_ptr->height +
3149 png_pass_yinc[png_ptr->pass] - 1 -
3150 png_pass_ystart[png_ptr->pass]) /
3151 png_pass_yinc[png_ptr->pass];
3152 if (!(png_ptr->num_rows))
3153 continue;
3154 }
3155 else /* if (png_ptr->transformations & PNG_INTERLACE) */
3156 break;
3157 } while (png_ptr->iwidth == 0);
3158
3159 if (png_ptr->pass < 7)
3160 return;
3161 }
3162#endif /* PNG_READ_INTERLACING_SUPPORTED */
3163
3164 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
3165 {
3166#ifdef PNG_USE_LOCAL_ARRAYS
3167 PNG_CONST PNG_IDAT;
3168#endif
3169 char extra;
3170 int ret;
3171
3172 png_ptr->zstream.next_out = (Byte *)&extra;
3173 png_ptr->zstream.avail_out = (uInt)1;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003174 for (;;)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003175 {
3176 if (!(png_ptr->zstream.avail_in))
3177 {
3178 while (!png_ptr->idat_size)
3179 {
3180 png_byte chunk_length[4];
3181
3182 png_crc_finish(png_ptr, 0);
3183
3184 png_read_data(png_ptr, chunk_length, 4);
3185 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
3186 png_reset_crc(png_ptr);
3187 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
3188 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
3189 png_error(png_ptr, "Not enough image data");
3190
3191 }
3192 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3193 png_ptr->zstream.next_in = png_ptr->zbuf;
3194 if (png_ptr->zbuf_size > png_ptr->idat_size)
3195 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3196 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3197 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3198 }
3199 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3200 if (ret == Z_STREAM_END)
3201 {
3202 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3203 png_ptr->idat_size)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003204 png_warning(png_ptr, "Extra compressed data.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003205 png_ptr->mode |= PNG_AFTER_IDAT;
3206 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3207 break;
3208 }
3209 if (ret != Z_OK)
3210 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3211 "Decompression Error");
3212
3213 if (!(png_ptr->zstream.avail_out))
3214 {
3215 png_warning(png_ptr, "Extra compressed data.");
3216 png_ptr->mode |= PNG_AFTER_IDAT;
3217 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3218 break;
3219 }
3220
3221 }
3222 png_ptr->zstream.avail_out = 0;
3223 }
3224
3225 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003226 png_warning(png_ptr, "Extra compression data.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003227
3228 inflateReset(&png_ptr->zstream);
3229
3230 png_ptr->mode |= PNG_AFTER_IDAT;
3231}
Patrick Scott5f6bd842010-06-28 16:55:16 -04003232#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003233
3234void /* PRIVATE */
3235png_read_start_row(png_structp png_ptr)
3236{
The Android Open Source Project893912b2009-03-03 19:30:05 -08003237#ifdef PNG_READ_INTERLACING_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003238 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003239
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003240 /* Start of interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003241 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3242
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003243 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003244 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3245
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003246 /* Start of interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003247 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3248
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003249 /* Offset to next interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003250 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3251#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08003252
3253 int max_pixel_depth;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003254 png_size_t row_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003255
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003256 png_debug(1, "in png_read_start_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003257 png_ptr->zstream.avail_in = 0;
3258 png_init_read_transformations(png_ptr);
3259#ifdef PNG_READ_INTERLACING_SUPPORTED
3260 if (png_ptr->interlaced)
3261 {
3262 if (!(png_ptr->transformations & PNG_INTERLACE))
3263 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3264 png_pass_ystart[0]) / png_pass_yinc[0];
3265 else
3266 png_ptr->num_rows = png_ptr->height;
3267
3268 png_ptr->iwidth = (png_ptr->width +
3269 png_pass_inc[png_ptr->pass] - 1 -
3270 png_pass_start[png_ptr->pass]) /
3271 png_pass_inc[png_ptr->pass];
The Android Open Source Project893912b2009-03-03 19:30:05 -08003272 }
3273 else
3274#endif /* PNG_READ_INTERLACING_SUPPORTED */
3275 {
3276 png_ptr->num_rows = png_ptr->height;
3277 png_ptr->iwidth = png_ptr->width;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003278 }
3279 max_pixel_depth = png_ptr->pixel_depth;
3280
Patrick Scott5f6bd842010-06-28 16:55:16 -04003281#ifdef PNG_READ_PACK_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003282 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3283 max_pixel_depth = 8;
3284#endif
3285
Patrick Scott5f6bd842010-06-28 16:55:16 -04003286#ifdef PNG_READ_EXPAND_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003287 if (png_ptr->transformations & PNG_EXPAND)
3288 {
3289 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3290 {
3291 if (png_ptr->num_trans)
3292 max_pixel_depth = 32;
3293 else
3294 max_pixel_depth = 24;
3295 }
3296 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3297 {
3298 if (max_pixel_depth < 8)
3299 max_pixel_depth = 8;
3300 if (png_ptr->num_trans)
3301 max_pixel_depth *= 2;
3302 }
3303 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3304 {
3305 if (png_ptr->num_trans)
3306 {
3307 max_pixel_depth *= 4;
3308 max_pixel_depth /= 3;
3309 }
3310 }
3311 }
3312#endif
3313
Patrick Scott5f6bd842010-06-28 16:55:16 -04003314#ifdef PNG_READ_FILLER_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003315 if (png_ptr->transformations & (PNG_FILLER))
3316 {
3317 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3318 max_pixel_depth = 32;
3319 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3320 {
3321 if (max_pixel_depth <= 8)
3322 max_pixel_depth = 16;
3323 else
3324 max_pixel_depth = 32;
3325 }
3326 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3327 {
3328 if (max_pixel_depth <= 32)
3329 max_pixel_depth = 32;
3330 else
3331 max_pixel_depth = 64;
3332 }
3333 }
3334#endif
3335
Patrick Scott5f6bd842010-06-28 16:55:16 -04003336#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003337 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3338 {
3339 if (
Patrick Scott5f6bd842010-06-28 16:55:16 -04003340#ifdef PNG_READ_EXPAND_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003341 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3342#endif
Patrick Scott5f6bd842010-06-28 16:55:16 -04003343#ifdef PNG_READ_FILLER_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003344 (png_ptr->transformations & (PNG_FILLER)) ||
3345#endif
3346 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3347 {
3348 if (max_pixel_depth <= 16)
3349 max_pixel_depth = 32;
3350 else
3351 max_pixel_depth = 64;
3352 }
3353 else
3354 {
3355 if (max_pixel_depth <= 8)
3356 {
3357 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3358 max_pixel_depth = 32;
3359 else
3360 max_pixel_depth = 24;
3361 }
3362 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3363 max_pixel_depth = 64;
3364 else
3365 max_pixel_depth = 48;
3366 }
3367 }
3368#endif
3369
3370#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3371defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003372 if (png_ptr->transformations & PNG_USER_TRANSFORM)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003373 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003374 int user_pixel_depth = png_ptr->user_transform_depth*
The Android Open Source Project893912b2009-03-03 19:30:05 -08003375 png_ptr->user_transform_channels;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003376 if (user_pixel_depth > max_pixel_depth)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003377 max_pixel_depth=user_pixel_depth;
3378 }
3379#endif
3380
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003381 /* Align the width on the next larger 8 pixels. Mainly used
3382 * for interlacing
3383 */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003384 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003385 /* Calculate the maximum bytes needed, adding a byte and a pixel
3386 * for safety's sake
3387 */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003388 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
The Android Open Source Project893912b2009-03-03 19:30:05 -08003389 1 + ((max_pixel_depth + 7) >> 3);
3390#ifdef PNG_MAX_MALLOC_64K
3391 if (row_bytes > (png_uint_32)65536L)
3392 png_error(png_ptr, "This image requires a row greater than 64KB");
3393#endif
3394
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003395 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003396 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003397 png_free(png_ptr, png_ptr->big_row_buf);
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003398 if (png_ptr->interlaced)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003399 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3400 row_bytes + 64);
3401 else
3402 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3403 row_bytes + 64);
3404 png_ptr->old_big_row_buf_size = row_bytes + 64;
3405
3406 /* Use 32 bytes of padding before and after row_buf. */
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003407 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3408 png_ptr->old_big_row_buf_size = row_bytes + 64;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003409 }
3410
3411#ifdef PNG_MAX_MALLOC_64K
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003412 if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003413 png_error(png_ptr, "This image requires a row greater than 64KB");
3414#endif
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003415 if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
The Android Open Source Project893912b2009-03-03 19:30:05 -08003416 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3417
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003418 if (row_bytes + 1 > png_ptr->old_prev_row_size)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003419 {
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003420 png_free(png_ptr, png_ptr->prev_row);
3421 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3422 row_bytes + 1));
3423 png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
3424 png_ptr->old_prev_row_size = row_bytes + 1;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003425 }
3426
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003427 png_ptr->rowbytes = row_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003428
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003429 png_debug1(3, "width = %lu,", png_ptr->width);
3430 png_debug1(3, "height = %lu,", png_ptr->height);
3431 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3432 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
3433 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
Patrick Scott5f6bd842010-06-28 16:55:16 -04003434 png_debug1(3, "irowbytes = %lu",
3435 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08003436
3437 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3438}
3439#endif /* PNG_READ_SUPPORTED */