blob: dfa2c03b6f578427db94f951fdab5b2c36223d44 [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;
383 png_charp text = png_malloc_warn(png_ptr,
384 prefix_size + expanded_size + 1);
385
386 if (text != NULL)
387 {
388 png_memcpy(text, png_ptr->chunkdata, prefix_size);
389 new_size = png_inflate(png_ptr,
390 (png_bytep)(png_ptr->chunkdata + prefix_size),
391 chunklength - prefix_size,
392 (png_bytep)(text + prefix_size), expanded_size);
393 text[prefix_size + expanded_size] = 0; /* just in case */
394
395 if (new_size == expanded_size)
396 {
397 png_free(png_ptr, png_ptr->chunkdata);
398 png_ptr->chunkdata = text;
399 *newlength = prefix_size + expanded_size;
400 return; /* The success return! */
401 }
402
403 png_warning(png_ptr, "png_inflate logic error");
404 png_free(png_ptr, text);
405 }
406 else
407 png_warning(png_ptr, "Not enough memory to decompress chunk.");
408 }
409 }
410
The Android Open Source Project893912b2009-03-03 19:30:05 -0800411 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
412 {
Patrick Scott5f6bd842010-06-28 16:55:16 -0400413#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
The Android Open Source Project893912b2009-03-03 19:30:05 -0800414 char umsg[50];
415
Patrick Scott5f6bd842010-06-28 16:55:16 -0400416 png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
417 comp_type);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800418 png_warning(png_ptr, umsg);
419#else
420 png_warning(png_ptr, "Unknown zTXt compression type");
421#endif
422
Patrick Scott5f6bd842010-06-28 16:55:16 -0400423 /* The recovery is to simply drop the data. */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800424 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400425
426 /* Generic error return - leave the prefix, delete the compressed
427 * data, reallocate the chunkdata to remove the potentially large
428 * amount of compressed data.
429 */
430 {
431 png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
432 if (text != NULL)
433 {
434 if (prefix_size > 0)
435 png_memcpy(text, png_ptr->chunkdata, prefix_size);
436 png_free(png_ptr, png_ptr->chunkdata);
437 png_ptr->chunkdata = text;
438
439 /* This is an extra zero in the 'uncompressed' part. */
440 *(png_ptr->chunkdata + prefix_size) = 0x00;
441 }
442 /* Ignore a malloc error here - it is safe. */
443 }
444
445 *newlength = prefix_size;
The Android Open Source Project893912b2009-03-03 19:30:05 -0800446}
447#endif
448
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400449/* Read and check the IDHR chunk */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800450void /* PRIVATE */
451png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
452{
453 png_byte buf[13];
454 png_uint_32 width, height;
455 int bit_depth, color_type, compression_type, filter_type;
456 int interlace_type;
457
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700458 png_debug(1, "in png_handle_IHDR");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800459
460 if (png_ptr->mode & PNG_HAVE_IHDR)
461 png_error(png_ptr, "Out of place IHDR");
462
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400463 /* Check the length */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800464 if (length != 13)
465 png_error(png_ptr, "Invalid IHDR chunk");
466
467 png_ptr->mode |= PNG_HAVE_IHDR;
468
469 png_crc_read(png_ptr, buf, 13);
470 png_crc_finish(png_ptr, 0);
471
472 width = png_get_uint_31(png_ptr, buf);
473 height = png_get_uint_31(png_ptr, buf + 4);
474 bit_depth = buf[8];
475 color_type = buf[9];
476 compression_type = buf[10];
477 filter_type = buf[11];
478 interlace_type = buf[12];
479
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400480 /* Set internal variables */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800481 png_ptr->width = width;
482 png_ptr->height = height;
483 png_ptr->bit_depth = (png_byte)bit_depth;
484 png_ptr->interlaced = (png_byte)interlace_type;
485 png_ptr->color_type = (png_byte)color_type;
Patrick Scott5f6bd842010-06-28 16:55:16 -0400486#ifdef PNG_MNG_FEATURES_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800487 png_ptr->filter_type = (png_byte)filter_type;
488#endif
489 png_ptr->compression_type = (png_byte)compression_type;
490
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400491 /* Find number of channels */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800492 switch (png_ptr->color_type)
493 {
494 case PNG_COLOR_TYPE_GRAY:
495 case PNG_COLOR_TYPE_PALETTE:
496 png_ptr->channels = 1;
497 break;
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400498
The Android Open Source Project893912b2009-03-03 19:30:05 -0800499 case PNG_COLOR_TYPE_RGB:
500 png_ptr->channels = 3;
501 break;
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400502
The Android Open Source Project893912b2009-03-03 19:30:05 -0800503 case PNG_COLOR_TYPE_GRAY_ALPHA:
504 png_ptr->channels = 2;
505 break;
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400506
The Android Open Source Project893912b2009-03-03 19:30:05 -0800507 case PNG_COLOR_TYPE_RGB_ALPHA:
508 png_ptr->channels = 4;
509 break;
510 }
511
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400512 /* Set up other useful info */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800513 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
514 png_ptr->channels);
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700515 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
516 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
517 png_debug1(3, "channels = %d", png_ptr->channels);
518 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800519 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
520 color_type, interlace_type, compression_type, filter_type);
521}
522
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400523/* Read and check the palette */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800524void /* PRIVATE */
525png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
526{
527 png_color palette[PNG_MAX_PALETTE_LENGTH];
528 int num, i;
Patrick Scott5f6bd842010-06-28 16:55:16 -0400529#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800530 png_colorp pal_ptr;
531#endif
532
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700533 png_debug(1, "in png_handle_PLTE");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800534
535 if (!(png_ptr->mode & PNG_HAVE_IHDR))
536 png_error(png_ptr, "Missing IHDR before PLTE");
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400537
The Android Open Source Project893912b2009-03-03 19:30:05 -0800538 else if (png_ptr->mode & PNG_HAVE_IDAT)
539 {
540 png_warning(png_ptr, "Invalid PLTE after IDAT");
541 png_crc_finish(png_ptr, length);
542 return;
543 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400544
The Android Open Source Project893912b2009-03-03 19:30:05 -0800545 else if (png_ptr->mode & PNG_HAVE_PLTE)
546 png_error(png_ptr, "Duplicate PLTE chunk");
547
548 png_ptr->mode |= PNG_HAVE_PLTE;
549
550 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
551 {
552 png_warning(png_ptr,
553 "Ignoring PLTE chunk in grayscale PNG");
554 png_crc_finish(png_ptr, length);
555 return;
556 }
Patrick Scott5f6bd842010-06-28 16:55:16 -0400557#ifndef PNG_READ_OPT_PLTE_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800558 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
559 {
560 png_crc_finish(png_ptr, length);
561 return;
562 }
563#endif
564
565 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
566 {
567 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
568 {
569 png_warning(png_ptr, "Invalid palette chunk");
570 png_crc_finish(png_ptr, length);
571 return;
572 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400573
The Android Open Source Project893912b2009-03-03 19:30:05 -0800574 else
575 {
576 png_error(png_ptr, "Invalid palette chunk");
577 }
578 }
579
580 num = (int)length / 3;
581
Patrick Scott5f6bd842010-06-28 16:55:16 -0400582#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800583 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
584 {
585 png_byte buf[3];
586
587 png_crc_read(png_ptr, buf, 3);
588 pal_ptr->red = buf[0];
589 pal_ptr->green = buf[1];
590 pal_ptr->blue = buf[2];
591 }
592#else
593 for (i = 0; i < num; i++)
594 {
595 png_byte buf[3];
596
597 png_crc_read(png_ptr, buf, 3);
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400598 /* Don't depend upon png_color being any order */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800599 palette[i].red = buf[0];
600 palette[i].green = buf[1];
601 palette[i].blue = buf[2];
602 }
603#endif
604
605 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400606 * whatever the normal CRC configuration tells us. However, if we
607 * have an RGB image, the PLTE can be considered ancillary, so
608 * we will act as though it is.
609 */
Patrick Scott5f6bd842010-06-28 16:55:16 -0400610#ifndef PNG_READ_OPT_PLTE_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800611 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
612#endif
613 {
614 png_crc_finish(png_ptr, 0);
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 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
618 {
619 /* If we don't want to use the data from an ancillary chunk,
620 we have two options: an error abort, or a warning and we
621 ignore the data in this chunk (which should be OK, since
622 it's considered ancillary for a RGB or RGBA image). */
623 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
624 {
625 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
626 {
627 png_chunk_error(png_ptr, "CRC error");
628 }
629 else
630 {
631 png_chunk_warning(png_ptr, "CRC error");
632 return;
633 }
634 }
635 /* Otherwise, we (optionally) emit a warning and use the chunk. */
636 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
637 {
638 png_chunk_warning(png_ptr, "CRC error");
639 }
640 }
641#endif
642
643 png_set_PLTE(png_ptr, info_ptr, palette, num);
644
Patrick Scott5f6bd842010-06-28 16:55:16 -0400645#ifdef PNG_READ_tRNS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800646 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
647 {
648 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
649 {
650 if (png_ptr->num_trans > (png_uint_16)num)
651 {
652 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
653 png_ptr->num_trans = (png_uint_16)num;
654 }
655 if (info_ptr->num_trans > (png_uint_16)num)
656 {
657 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
658 info_ptr->num_trans = (png_uint_16)num;
659 }
660 }
661 }
662#endif
663
664}
665
666void /* PRIVATE */
667png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
668{
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700669 png_debug(1, "in png_handle_IEND");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800670
671 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
672 {
673 png_error(png_ptr, "No image in file");
674 }
675
676 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
677
678 if (length != 0)
679 {
680 png_warning(png_ptr, "Incorrect IEND chunk length");
681 }
682 png_crc_finish(png_ptr, length);
683
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400684 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800685}
686
Patrick Scott5f6bd842010-06-28 16:55:16 -0400687#ifdef PNG_READ_gAMA_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800688void /* PRIVATE */
689png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
690{
691 png_fixed_point igamma;
692#ifdef PNG_FLOATING_POINT_SUPPORTED
693 float file_gamma;
694#endif
695 png_byte buf[4];
696
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700697 png_debug(1, "in png_handle_gAMA");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800698
699 if (!(png_ptr->mode & PNG_HAVE_IHDR))
700 png_error(png_ptr, "Missing IHDR before gAMA");
701 else if (png_ptr->mode & PNG_HAVE_IDAT)
702 {
703 png_warning(png_ptr, "Invalid gAMA after IDAT");
704 png_crc_finish(png_ptr, length);
705 return;
706 }
707 else if (png_ptr->mode & PNG_HAVE_PLTE)
708 /* Should be an error, but we can cope with it */
709 png_warning(png_ptr, "Out of place gAMA chunk");
710
711 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Patrick Scott5f6bd842010-06-28 16:55:16 -0400712#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800713 && !(info_ptr->valid & PNG_INFO_sRGB)
714#endif
715 )
716 {
717 png_warning(png_ptr, "Duplicate gAMA chunk");
718 png_crc_finish(png_ptr, length);
719 return;
720 }
721
722 if (length != 4)
723 {
724 png_warning(png_ptr, "Incorrect gAMA chunk length");
725 png_crc_finish(png_ptr, length);
726 return;
727 }
728
729 png_crc_read(png_ptr, buf, 4);
730 if (png_crc_finish(png_ptr, 0))
731 return;
732
733 igamma = (png_fixed_point)png_get_uint_32(buf);
Patrick Scotta0bb96c2009-07-22 11:50:02 -0400734 /* Check for zero gamma */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800735 if (igamma == 0)
736 {
737 png_warning(png_ptr,
738 "Ignoring gAMA chunk with gamma=0");
739 return;
740 }
741
Patrick Scott5f6bd842010-06-28 16:55:16 -0400742#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800743 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
744 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
745 {
746 png_warning(png_ptr,
747 "Ignoring incorrect gAMA value when sRGB is also present");
Patrick Scott5f6bd842010-06-28 16:55:16 -0400748#ifdef PNG_CONSOLE_IO_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700749 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800750#endif
751 return;
752 }
753#endif /* PNG_READ_sRGB_SUPPORTED */
754
755#ifdef PNG_FLOATING_POINT_SUPPORTED
756 file_gamma = (float)igamma / (float)100000.0;
757# ifdef PNG_READ_GAMMA_SUPPORTED
758 png_ptr->gamma = file_gamma;
759# endif
760 png_set_gAMA(png_ptr, info_ptr, file_gamma);
761#endif
762#ifdef PNG_FIXED_POINT_SUPPORTED
763 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
764#endif
765}
766#endif
767
Patrick Scott5f6bd842010-06-28 16:55:16 -0400768#ifdef PNG_READ_sBIT_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800769void /* PRIVATE */
770png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
771{
772 png_size_t truelen;
773 png_byte buf[4];
774
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700775 png_debug(1, "in png_handle_sBIT");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800776
777 buf[0] = buf[1] = buf[2] = buf[3] = 0;
778
779 if (!(png_ptr->mode & PNG_HAVE_IHDR))
780 png_error(png_ptr, "Missing IHDR before sBIT");
781 else if (png_ptr->mode & PNG_HAVE_IDAT)
782 {
783 png_warning(png_ptr, "Invalid sBIT after IDAT");
784 png_crc_finish(png_ptr, length);
785 return;
786 }
787 else if (png_ptr->mode & PNG_HAVE_PLTE)
788 {
789 /* Should be an error, but we can cope with it */
790 png_warning(png_ptr, "Out of place sBIT chunk");
791 }
792 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
793 {
794 png_warning(png_ptr, "Duplicate sBIT chunk");
795 png_crc_finish(png_ptr, length);
796 return;
797 }
798
799 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
800 truelen = 3;
801 else
802 truelen = (png_size_t)png_ptr->channels;
803
804 if (length != truelen || length > 4)
805 {
806 png_warning(png_ptr, "Incorrect sBIT chunk length");
807 png_crc_finish(png_ptr, length);
808 return;
809 }
810
811 png_crc_read(png_ptr, buf, truelen);
812 if (png_crc_finish(png_ptr, 0))
813 return;
814
815 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
816 {
817 png_ptr->sig_bit.red = buf[0];
818 png_ptr->sig_bit.green = buf[1];
819 png_ptr->sig_bit.blue = buf[2];
820 png_ptr->sig_bit.alpha = buf[3];
821 }
822 else
823 {
824 png_ptr->sig_bit.gray = buf[0];
825 png_ptr->sig_bit.red = buf[0];
826 png_ptr->sig_bit.green = buf[0];
827 png_ptr->sig_bit.blue = buf[0];
828 png_ptr->sig_bit.alpha = buf[1];
829 }
830 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
831}
832#endif
833
Patrick Scott5f6bd842010-06-28 16:55:16 -0400834#ifdef PNG_READ_cHRM_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800835void /* PRIVATE */
836png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
837{
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700838 png_byte buf[32];
The Android Open Source Project893912b2009-03-03 19:30:05 -0800839#ifdef PNG_FLOATING_POINT_SUPPORTED
840 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
841#endif
842 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
843 int_y_green, int_x_blue, int_y_blue;
844
845 png_uint_32 uint_x, uint_y;
846
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700847 png_debug(1, "in png_handle_cHRM");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800848
849 if (!(png_ptr->mode & PNG_HAVE_IHDR))
850 png_error(png_ptr, "Missing IHDR before cHRM");
851 else if (png_ptr->mode & PNG_HAVE_IDAT)
852 {
853 png_warning(png_ptr, "Invalid cHRM after IDAT");
854 png_crc_finish(png_ptr, length);
855 return;
856 }
857 else if (png_ptr->mode & PNG_HAVE_PLTE)
858 /* Should be an error, but we can cope with it */
859 png_warning(png_ptr, "Missing PLTE before cHRM");
860
861 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Patrick Scott5f6bd842010-06-28 16:55:16 -0400862#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800863 && !(info_ptr->valid & PNG_INFO_sRGB)
864#endif
865 )
866 {
867 png_warning(png_ptr, "Duplicate cHRM chunk");
868 png_crc_finish(png_ptr, length);
869 return;
870 }
871
872 if (length != 32)
873 {
874 png_warning(png_ptr, "Incorrect cHRM chunk length");
875 png_crc_finish(png_ptr, length);
876 return;
877 }
878
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700879 png_crc_read(png_ptr, buf, 32);
880 if (png_crc_finish(png_ptr, 0))
The Android Open Source Project893912b2009-03-03 19:30:05 -0800881 return;
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700882
883 uint_x = png_get_uint_32(buf);
884 uint_y = png_get_uint_32(buf + 4);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800885 int_x_white = (png_fixed_point)uint_x;
886 int_y_white = (png_fixed_point)uint_y;
887
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700888 uint_x = png_get_uint_32(buf + 8);
889 uint_y = png_get_uint_32(buf + 12);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800890 int_x_red = (png_fixed_point)uint_x;
891 int_y_red = (png_fixed_point)uint_y;
892
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700893 uint_x = png_get_uint_32(buf + 16);
894 uint_y = png_get_uint_32(buf + 20);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800895 int_x_green = (png_fixed_point)uint_x;
896 int_y_green = (png_fixed_point)uint_y;
897
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700898 uint_x = png_get_uint_32(buf + 24);
899 uint_y = png_get_uint_32(buf + 28);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800900 int_x_blue = (png_fixed_point)uint_x;
901 int_y_blue = (png_fixed_point)uint_y;
902
903#ifdef PNG_FLOATING_POINT_SUPPORTED
904 white_x = (float)int_x_white / (float)100000.0;
905 white_y = (float)int_y_white / (float)100000.0;
906 red_x = (float)int_x_red / (float)100000.0;
907 red_y = (float)int_y_red / (float)100000.0;
908 green_x = (float)int_x_green / (float)100000.0;
909 green_y = (float)int_y_green / (float)100000.0;
910 blue_x = (float)int_x_blue / (float)100000.0;
911 blue_y = (float)int_y_blue / (float)100000.0;
912#endif
913
Patrick Scott5f6bd842010-06-28 16:55:16 -0400914#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800915 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
916 {
917 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
918 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
919 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
920 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
921 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
922 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
923 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
924 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
925 {
926 png_warning(png_ptr,
927 "Ignoring incorrect cHRM value when sRGB is also present");
Patrick Scott5f6bd842010-06-28 16:55:16 -0400928#ifdef PNG_CONSOLE_IO_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800929#ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700930 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
The Android Open Source Project893912b2009-03-03 19:30:05 -0800931 white_x, white_y, red_x, red_y);
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700932 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
The Android Open Source Project893912b2009-03-03 19:30:05 -0800933 green_x, green_y, blue_x, blue_y);
934#else
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700935 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Patrick Scott5f6bd842010-06-28 16:55:16 -0400936 (long)int_x_white, (long)int_y_white,
937 (long)int_x_red, (long)int_y_red);
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700938 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Patrick Scott5f6bd842010-06-28 16:55:16 -0400939 (long)int_x_green, (long)int_y_green,
940 (long)int_x_blue, (long)int_y_blue);
The Android Open Source Project893912b2009-03-03 19:30:05 -0800941#endif
Patrick Scott5f6bd842010-06-28 16:55:16 -0400942#endif /* PNG_CONSOLE_IO_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800943 }
The Android Open Source Project893912b2009-03-03 19:30:05 -0800944 return;
945 }
946#endif /* PNG_READ_sRGB_SUPPORTED */
947
948#ifdef PNG_FLOATING_POINT_SUPPORTED
949 png_set_cHRM(png_ptr, info_ptr,
950 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
951#endif
952#ifdef PNG_FIXED_POINT_SUPPORTED
953 png_set_cHRM_fixed(png_ptr, info_ptr,
954 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
955 int_y_green, int_x_blue, int_y_blue);
956#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -0800957}
958#endif
959
Patrick Scott5f6bd842010-06-28 16:55:16 -0400960#ifdef PNG_READ_sRGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -0800961void /* PRIVATE */
962png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
963{
964 int intent;
965 png_byte buf[1];
966
The Android Open Source Project4215dd12009-03-09 11:52:12 -0700967 png_debug(1, "in png_handle_sRGB");
The Android Open Source Project893912b2009-03-03 19:30:05 -0800968
969 if (!(png_ptr->mode & PNG_HAVE_IHDR))
970 png_error(png_ptr, "Missing IHDR before sRGB");
971 else if (png_ptr->mode & PNG_HAVE_IDAT)
972 {
973 png_warning(png_ptr, "Invalid sRGB after IDAT");
974 png_crc_finish(png_ptr, length);
975 return;
976 }
977 else if (png_ptr->mode & PNG_HAVE_PLTE)
978 /* Should be an error, but we can cope with it */
979 png_warning(png_ptr, "Out of place sRGB chunk");
980
981 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
982 {
983 png_warning(png_ptr, "Duplicate sRGB chunk");
984 png_crc_finish(png_ptr, length);
985 return;
986 }
987
988 if (length != 1)
989 {
990 png_warning(png_ptr, "Incorrect sRGB chunk length");
991 png_crc_finish(png_ptr, length);
992 return;
993 }
994
995 png_crc_read(png_ptr, buf, 1);
996 if (png_crc_finish(png_ptr, 0))
997 return;
998
999 intent = buf[0];
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001000 /* Check for bad intent */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001001 if (intent >= PNG_sRGB_INTENT_LAST)
1002 {
1003 png_warning(png_ptr, "Unknown sRGB intent");
1004 return;
1005 }
1006
1007#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
1008 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
1009 {
1010 png_fixed_point igamma;
1011#ifdef PNG_FIXED_POINT_SUPPORTED
1012 igamma=info_ptr->int_gamma;
1013#else
1014# ifdef PNG_FLOATING_POINT_SUPPORTED
1015 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
1016# endif
1017#endif
1018 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
1019 {
1020 png_warning(png_ptr,
1021 "Ignoring incorrect gAMA value when sRGB is also present");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001022#ifdef PNG_CONSOLE_IO_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001023# ifdef PNG_FIXED_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001024 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
1025 (int)png_ptr->int_gamma);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001026# else
1027# ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001028 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001029# endif
1030# endif
1031#endif
1032 }
1033 }
1034#endif /* PNG_READ_gAMA_SUPPORTED */
1035
1036#ifdef PNG_READ_cHRM_SUPPORTED
1037#ifdef PNG_FIXED_POINT_SUPPORTED
1038 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
1039 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
1040 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
1041 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
1042 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
1043 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
1044 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
1045 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
1046 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
1047 {
1048 png_warning(png_ptr,
1049 "Ignoring incorrect cHRM value when sRGB is also present");
1050 }
1051#endif /* PNG_FIXED_POINT_SUPPORTED */
1052#endif /* PNG_READ_cHRM_SUPPORTED */
1053
1054 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1055}
1056#endif /* PNG_READ_sRGB_SUPPORTED */
1057
Patrick Scott5f6bd842010-06-28 16:55:16 -04001058#ifdef PNG_READ_iCCP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001059void /* PRIVATE */
1060png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1061/* Note: this does not properly handle chunks that are > 64K under DOS */
1062{
The Android Open Source Project893912b2009-03-03 19:30:05 -08001063 png_byte compression_type;
1064 png_bytep pC;
1065 png_charp profile;
1066 png_uint_32 skip = 0;
1067 png_uint_32 profile_size, profile_length;
1068 png_size_t slength, prefix_length, data_length;
1069
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001070 png_debug(1, "in png_handle_iCCP");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001071
1072 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1073 png_error(png_ptr, "Missing IHDR before iCCP");
1074 else if (png_ptr->mode & PNG_HAVE_IDAT)
1075 {
1076 png_warning(png_ptr, "Invalid iCCP after IDAT");
1077 png_crc_finish(png_ptr, length);
1078 return;
1079 }
1080 else if (png_ptr->mode & PNG_HAVE_PLTE)
1081 /* Should be an error, but we can cope with it */
1082 png_warning(png_ptr, "Out of place iCCP chunk");
1083
1084 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1085 {
1086 png_warning(png_ptr, "Duplicate iCCP chunk");
1087 png_crc_finish(png_ptr, length);
1088 return;
1089 }
1090
1091#ifdef PNG_MAX_MALLOC_64K
1092 if (length > (png_uint_32)65535L)
1093 {
1094 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1095 skip = length - (png_uint_32)65535L;
1096 length = (png_uint_32)65535L;
1097 }
1098#endif
1099
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001100 png_free(png_ptr, png_ptr->chunkdata);
1101 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001102 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001103 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001104
1105 if (png_crc_finish(png_ptr, skip))
1106 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001107 png_free(png_ptr, png_ptr->chunkdata);
1108 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001109 return;
1110 }
1111
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001112 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001113
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001114 for (profile = png_ptr->chunkdata; *profile; profile++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001115 /* Empty loop to find end of name */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001116
1117 ++profile;
1118
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001119 /* There should be at least one zero (the compression type byte)
1120 * following the separator, and we should be on it
1121 */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001122 if ( profile >= png_ptr->chunkdata + slength - 1)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001123 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001124 png_free(png_ptr, png_ptr->chunkdata);
1125 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001126 png_warning(png_ptr, "Malformed iCCP chunk");
1127 return;
1128 }
1129
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001130 /* Compression_type should always be zero */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001131 compression_type = *profile++;
1132 if (compression_type)
1133 {
1134 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001135 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 -08001136 wrote nonzero) */
1137 }
1138
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001139 prefix_length = profile - png_ptr->chunkdata;
1140 png_decompress_chunk(png_ptr, compression_type,
1141 slength, prefix_length, &data_length);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001142
1143 profile_length = data_length - prefix_length;
1144
1145 if ( prefix_length > data_length || profile_length < 4)
1146 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001147 png_free(png_ptr, png_ptr->chunkdata);
1148 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001149 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1150 return;
1151 }
1152
1153 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001154 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1155 profile_size = ((*(pC ))<<24) |
1156 ((*(pC + 1))<<16) |
1157 ((*(pC + 2))<< 8) |
1158 ((*(pC + 3)) );
The Android Open Source Project893912b2009-03-03 19:30:05 -08001159
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001160 if (profile_size < profile_length)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001161 profile_length = profile_size;
1162
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001163 if (profile_size > profile_length)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001164 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001165 png_free(png_ptr, png_ptr->chunkdata);
1166 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001167 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1168 return;
1169 }
1170
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001171 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1172 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1173 png_free(png_ptr, png_ptr->chunkdata);
1174 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001175}
1176#endif /* PNG_READ_iCCP_SUPPORTED */
1177
Patrick Scott5f6bd842010-06-28 16:55:16 -04001178#ifdef PNG_READ_sPLT_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001179void /* PRIVATE */
1180png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1181/* Note: this does not properly handle chunks that are > 64K under DOS */
1182{
The Android Open Source Project893912b2009-03-03 19:30:05 -08001183 png_bytep entry_start;
1184 png_sPLT_t new_palette;
Patrick Scott5f6bd842010-06-28 16:55:16 -04001185#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001186 png_sPLT_entryp pp;
1187#endif
1188 int data_length, entry_size, i;
1189 png_uint_32 skip = 0;
1190 png_size_t slength;
1191
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001192 png_debug(1, "in png_handle_sPLT");
1193
Patrick Scott5f6bd842010-06-28 16:55:16 -04001194#ifdef PNG_USER_LIMITS_SUPPORTED
1195
1196 if (png_ptr->user_chunk_cache_max != 0)
1197 {
1198 if (png_ptr->user_chunk_cache_max == 1)
1199 {
1200 png_crc_finish(png_ptr, length);
1201 return;
1202 }
1203 if (--png_ptr->user_chunk_cache_max == 1)
1204 {
1205 png_warning(png_ptr, "No space in chunk cache for sPLT");
1206 png_crc_finish(png_ptr, length);
1207 return;
1208 }
1209 }
1210#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08001211
1212 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1213 png_error(png_ptr, "Missing IHDR before sPLT");
1214 else if (png_ptr->mode & PNG_HAVE_IDAT)
1215 {
1216 png_warning(png_ptr, "Invalid sPLT after IDAT");
1217 png_crc_finish(png_ptr, length);
1218 return;
1219 }
1220
1221#ifdef PNG_MAX_MALLOC_64K
1222 if (length > (png_uint_32)65535L)
1223 {
1224 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1225 skip = length - (png_uint_32)65535L;
1226 length = (png_uint_32)65535L;
1227 }
1228#endif
1229
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001230 png_free(png_ptr, png_ptr->chunkdata);
1231 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001232 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001233 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001234
1235 if (png_crc_finish(png_ptr, skip))
1236 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001237 png_free(png_ptr, png_ptr->chunkdata);
1238 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001239 return;
1240 }
1241
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001242 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001243
Patrick Scott5f6bd842010-06-28 16:55:16 -04001244 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1245 entry_start++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001246 /* Empty loop to find end of name */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001247 ++entry_start;
1248
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001249 /* A sample depth should follow the separator, and we should be on it */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001250 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001251 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001252 png_free(png_ptr, png_ptr->chunkdata);
1253 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001254 png_warning(png_ptr, "malformed sPLT chunk");
1255 return;
1256 }
1257
1258 new_palette.depth = *entry_start++;
1259 entry_size = (new_palette.depth == 8 ? 6 : 10);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001260 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
The Android Open Source Project893912b2009-03-03 19:30:05 -08001261
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001262 /* Integrity-check the data length */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001263 if (data_length % entry_size)
1264 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001265 png_free(png_ptr, png_ptr->chunkdata);
1266 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001267 png_warning(png_ptr, "sPLT chunk has bad length");
1268 return;
1269 }
1270
1271 new_palette.nentries = (png_int_32) ( data_length / entry_size);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001272 if ((png_uint_32) new_palette.nentries >
1273 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
The Android Open Source Project893912b2009-03-03 19:30:05 -08001274 {
1275 png_warning(png_ptr, "sPLT chunk too long");
1276 return;
1277 }
1278 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1279 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1280 if (new_palette.entries == NULL)
1281 {
1282 png_warning(png_ptr, "sPLT chunk requires too much memory");
1283 return;
1284 }
1285
Patrick Scott5f6bd842010-06-28 16:55:16 -04001286#ifdef PNG_POINTER_INDEXING_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001287 for (i = 0; i < new_palette.nentries; i++)
1288 {
Patrick Scott5f6bd842010-06-28 16:55:16 -04001289 pp = new_palette.entries + i;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001290
1291 if (new_palette.depth == 8)
1292 {
1293 pp->red = *entry_start++;
1294 pp->green = *entry_start++;
1295 pp->blue = *entry_start++;
1296 pp->alpha = *entry_start++;
1297 }
1298 else
1299 {
1300 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1301 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1302 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1303 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1304 }
1305 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1306 }
1307#else
1308 pp = new_palette.entries;
1309 for (i = 0; i < new_palette.nentries; i++)
1310 {
1311
1312 if (new_palette.depth == 8)
1313 {
1314 pp[i].red = *entry_start++;
1315 pp[i].green = *entry_start++;
1316 pp[i].blue = *entry_start++;
1317 pp[i].alpha = *entry_start++;
1318 }
1319 else
1320 {
1321 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1322 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1323 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1324 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1325 }
1326 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1327 }
1328#endif
1329
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001330 /* Discard all chunk data except the name and stash that */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001331 new_palette.name = png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001332
1333 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1334
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001335 png_free(png_ptr, png_ptr->chunkdata);
1336 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001337 png_free(png_ptr, new_palette.entries);
1338}
1339#endif /* PNG_READ_sPLT_SUPPORTED */
1340
Patrick Scott5f6bd842010-06-28 16:55:16 -04001341#ifdef PNG_READ_tRNS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001342void /* PRIVATE */
1343png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1344{
1345 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1346
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001347 png_debug(1, "in png_handle_tRNS");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001348
1349 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1350 png_error(png_ptr, "Missing IHDR before tRNS");
1351 else if (png_ptr->mode & PNG_HAVE_IDAT)
1352 {
1353 png_warning(png_ptr, "Invalid tRNS after IDAT");
1354 png_crc_finish(png_ptr, length);
1355 return;
1356 }
1357 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1358 {
1359 png_warning(png_ptr, "Duplicate tRNS chunk");
1360 png_crc_finish(png_ptr, length);
1361 return;
1362 }
1363
1364 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1365 {
1366 png_byte buf[2];
1367
1368 if (length != 2)
1369 {
1370 png_warning(png_ptr, "Incorrect tRNS chunk length");
1371 png_crc_finish(png_ptr, length);
1372 return;
1373 }
1374
1375 png_crc_read(png_ptr, buf, 2);
1376 png_ptr->num_trans = 1;
1377 png_ptr->trans_values.gray = png_get_uint_16(buf);
1378 }
1379 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1380 {
1381 png_byte buf[6];
1382
1383 if (length != 6)
1384 {
1385 png_warning(png_ptr, "Incorrect tRNS chunk length");
1386 png_crc_finish(png_ptr, length);
1387 return;
1388 }
1389 png_crc_read(png_ptr, buf, (png_size_t)length);
1390 png_ptr->num_trans = 1;
1391 png_ptr->trans_values.red = png_get_uint_16(buf);
1392 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1393 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1394 }
1395 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1396 {
1397 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1398 {
1399 /* Should be an error, but we can cope with it. */
1400 png_warning(png_ptr, "Missing PLTE before tRNS");
1401 }
1402 if (length > (png_uint_32)png_ptr->num_palette ||
1403 length > PNG_MAX_PALETTE_LENGTH)
1404 {
1405 png_warning(png_ptr, "Incorrect tRNS chunk length");
1406 png_crc_finish(png_ptr, length);
1407 return;
1408 }
1409 if (length == 0)
1410 {
1411 png_warning(png_ptr, "Zero length tRNS chunk");
1412 png_crc_finish(png_ptr, length);
1413 return;
1414 }
1415 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1416 png_ptr->num_trans = (png_uint_16)length;
1417 }
1418 else
1419 {
1420 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1421 png_crc_finish(png_ptr, length);
1422 return;
1423 }
1424
1425 if (png_crc_finish(png_ptr, 0))
1426 {
1427 png_ptr->num_trans = 0;
1428 return;
1429 }
1430
1431 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1432 &(png_ptr->trans_values));
1433}
1434#endif
1435
Patrick Scott5f6bd842010-06-28 16:55:16 -04001436#ifdef PNG_READ_bKGD_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001437void /* PRIVATE */
1438png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1439{
1440 png_size_t truelen;
1441 png_byte buf[6];
1442
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001443 png_debug(1, "in png_handle_bKGD");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001444
1445 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1446 png_error(png_ptr, "Missing IHDR before bKGD");
1447 else if (png_ptr->mode & PNG_HAVE_IDAT)
1448 {
1449 png_warning(png_ptr, "Invalid bKGD after IDAT");
1450 png_crc_finish(png_ptr, length);
1451 return;
1452 }
1453 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1454 !(png_ptr->mode & PNG_HAVE_PLTE))
1455 {
1456 png_warning(png_ptr, "Missing PLTE before bKGD");
1457 png_crc_finish(png_ptr, length);
1458 return;
1459 }
1460 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1461 {
1462 png_warning(png_ptr, "Duplicate bKGD chunk");
1463 png_crc_finish(png_ptr, length);
1464 return;
1465 }
1466
1467 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1468 truelen = 1;
1469 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1470 truelen = 6;
1471 else
1472 truelen = 2;
1473
1474 if (length != truelen)
1475 {
1476 png_warning(png_ptr, "Incorrect bKGD chunk length");
1477 png_crc_finish(png_ptr, length);
1478 return;
1479 }
1480
1481 png_crc_read(png_ptr, buf, truelen);
1482 if (png_crc_finish(png_ptr, 0))
1483 return;
1484
1485 /* We convert the index value into RGB components so that we can allow
1486 * arbitrary RGB values for background when we have transparency, and
1487 * so it is easy to determine the RGB values of the background color
1488 * from the info_ptr struct. */
1489 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1490 {
1491 png_ptr->background.index = buf[0];
1492 if (info_ptr && info_ptr->num_palette)
1493 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001494 if (buf[0] >= info_ptr->num_palette)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001495 {
1496 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1497 return;
1498 }
1499 png_ptr->background.red =
1500 (png_uint_16)png_ptr->palette[buf[0]].red;
1501 png_ptr->background.green =
1502 (png_uint_16)png_ptr->palette[buf[0]].green;
1503 png_ptr->background.blue =
1504 (png_uint_16)png_ptr->palette[buf[0]].blue;
1505 }
1506 }
1507 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1508 {
1509 png_ptr->background.red =
1510 png_ptr->background.green =
1511 png_ptr->background.blue =
1512 png_ptr->background.gray = png_get_uint_16(buf);
1513 }
1514 else
1515 {
1516 png_ptr->background.red = png_get_uint_16(buf);
1517 png_ptr->background.green = png_get_uint_16(buf + 2);
1518 png_ptr->background.blue = png_get_uint_16(buf + 4);
1519 }
1520
1521 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1522}
1523#endif
1524
Patrick Scott5f6bd842010-06-28 16:55:16 -04001525#ifdef PNG_READ_hIST_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001526void /* PRIVATE */
1527png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1528{
1529 unsigned int num, i;
1530 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1531
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001532 png_debug(1, "in png_handle_hIST");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001533
1534 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1535 png_error(png_ptr, "Missing IHDR before hIST");
1536 else if (png_ptr->mode & PNG_HAVE_IDAT)
1537 {
1538 png_warning(png_ptr, "Invalid hIST after IDAT");
1539 png_crc_finish(png_ptr, length);
1540 return;
1541 }
1542 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1543 {
1544 png_warning(png_ptr, "Missing PLTE before hIST");
1545 png_crc_finish(png_ptr, length);
1546 return;
1547 }
1548 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1549 {
1550 png_warning(png_ptr, "Duplicate hIST chunk");
1551 png_crc_finish(png_ptr, length);
1552 return;
1553 }
1554
1555 num = length / 2 ;
1556 if (num != (unsigned int) png_ptr->num_palette || num >
1557 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1558 {
1559 png_warning(png_ptr, "Incorrect hIST chunk length");
1560 png_crc_finish(png_ptr, length);
1561 return;
1562 }
1563
1564 for (i = 0; i < num; i++)
1565 {
1566 png_byte buf[2];
1567
1568 png_crc_read(png_ptr, buf, 2);
1569 readbuf[i] = png_get_uint_16(buf);
1570 }
1571
1572 if (png_crc_finish(png_ptr, 0))
1573 return;
1574
1575 png_set_hIST(png_ptr, info_ptr, readbuf);
1576}
1577#endif
1578
Patrick Scott5f6bd842010-06-28 16:55:16 -04001579#ifdef PNG_READ_pHYs_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001580void /* PRIVATE */
1581png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1582{
1583 png_byte buf[9];
1584 png_uint_32 res_x, res_y;
1585 int unit_type;
1586
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001587 png_debug(1, "in png_handle_pHYs");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001588
1589 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1590 png_error(png_ptr, "Missing IHDR before pHYs");
1591 else if (png_ptr->mode & PNG_HAVE_IDAT)
1592 {
1593 png_warning(png_ptr, "Invalid pHYs after IDAT");
1594 png_crc_finish(png_ptr, length);
1595 return;
1596 }
1597 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1598 {
1599 png_warning(png_ptr, "Duplicate pHYs chunk");
1600 png_crc_finish(png_ptr, length);
1601 return;
1602 }
1603
1604 if (length != 9)
1605 {
1606 png_warning(png_ptr, "Incorrect pHYs chunk length");
1607 png_crc_finish(png_ptr, length);
1608 return;
1609 }
1610
1611 png_crc_read(png_ptr, buf, 9);
1612 if (png_crc_finish(png_ptr, 0))
1613 return;
1614
1615 res_x = png_get_uint_32(buf);
1616 res_y = png_get_uint_32(buf + 4);
1617 unit_type = buf[8];
1618 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1619}
1620#endif
1621
Patrick Scott5f6bd842010-06-28 16:55:16 -04001622#ifdef PNG_READ_oFFs_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001623void /* PRIVATE */
1624png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1625{
1626 png_byte buf[9];
1627 png_int_32 offset_x, offset_y;
1628 int unit_type;
1629
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001630 png_debug(1, "in png_handle_oFFs");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001631
1632 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1633 png_error(png_ptr, "Missing IHDR before oFFs");
1634 else if (png_ptr->mode & PNG_HAVE_IDAT)
1635 {
1636 png_warning(png_ptr, "Invalid oFFs after IDAT");
1637 png_crc_finish(png_ptr, length);
1638 return;
1639 }
1640 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1641 {
1642 png_warning(png_ptr, "Duplicate oFFs chunk");
1643 png_crc_finish(png_ptr, length);
1644 return;
1645 }
1646
1647 if (length != 9)
1648 {
1649 png_warning(png_ptr, "Incorrect oFFs chunk length");
1650 png_crc_finish(png_ptr, length);
1651 return;
1652 }
1653
1654 png_crc_read(png_ptr, buf, 9);
1655 if (png_crc_finish(png_ptr, 0))
1656 return;
1657
1658 offset_x = png_get_int_32(buf);
1659 offset_y = png_get_int_32(buf + 4);
1660 unit_type = buf[8];
1661 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1662}
1663#endif
1664
Patrick Scott5f6bd842010-06-28 16:55:16 -04001665#ifdef PNG_READ_pCAL_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001666/* Read the pCAL chunk (described in the PNG Extensions document) */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001667void /* PRIVATE */
1668png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1669{
The Android Open Source Project893912b2009-03-03 19:30:05 -08001670 png_int_32 X0, X1;
1671 png_byte type, nparams;
1672 png_charp buf, units, endptr;
1673 png_charpp params;
1674 png_size_t slength;
1675 int i;
1676
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001677 png_debug(1, "in png_handle_pCAL");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001678
1679 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1680 png_error(png_ptr, "Missing IHDR before pCAL");
1681 else if (png_ptr->mode & PNG_HAVE_IDAT)
1682 {
1683 png_warning(png_ptr, "Invalid pCAL after IDAT");
1684 png_crc_finish(png_ptr, length);
1685 return;
1686 }
1687 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1688 {
1689 png_warning(png_ptr, "Duplicate pCAL chunk");
1690 png_crc_finish(png_ptr, length);
1691 return;
1692 }
1693
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001694 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
The Android Open Source Project893912b2009-03-03 19:30:05 -08001695 length + 1);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001696 png_free(png_ptr, png_ptr->chunkdata);
1697 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1698 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001699 {
1700 png_warning(png_ptr, "No memory for pCAL purpose.");
1701 return;
1702 }
1703 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001704 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001705
1706 if (png_crc_finish(png_ptr, 0))
1707 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001708 png_free(png_ptr, png_ptr->chunkdata);
1709 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001710 return;
1711 }
1712
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001713 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001714
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001715 png_debug(3, "Finding end of pCAL purpose string");
1716 for (buf = png_ptr->chunkdata; *buf; buf++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001717 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001718
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001719 endptr = png_ptr->chunkdata + slength;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001720
1721 /* We need to have at least 12 bytes after the purpose string
1722 in order to get the parameter information. */
1723 if (endptr <= buf + 12)
1724 {
1725 png_warning(png_ptr, "Invalid pCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001726 png_free(png_ptr, png_ptr->chunkdata);
1727 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001728 return;
1729 }
1730
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001731 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001732 X0 = png_get_int_32((png_bytep)buf+1);
1733 X1 = png_get_int_32((png_bytep)buf+5);
1734 type = buf[9];
1735 nparams = buf[10];
1736 units = buf + 11;
1737
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001738 png_debug(3, "Checking pCAL equation type and number of parameters");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001739 /* Check that we have the right number of parameters for known
1740 equation types. */
1741 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1742 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1743 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1744 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1745 {
1746 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001747 png_free(png_ptr, png_ptr->chunkdata);
1748 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001749 return;
1750 }
1751 else if (type >= PNG_EQUATION_LAST)
1752 {
1753 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1754 }
1755
1756 for (buf = units; *buf; buf++)
1757 /* Empty loop to move past the units string. */ ;
1758
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001759 png_debug(3, "Allocating pCAL parameters array");
1760 params = (png_charpp)png_malloc_warn(png_ptr,
1761 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001762 if (params == NULL)
1763 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001764 png_free(png_ptr, png_ptr->chunkdata);
1765 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001766 png_warning(png_ptr, "No memory for pCAL params.");
1767 return;
1768 }
1769
1770 /* Get pointers to the start of each parameter string. */
1771 for (i = 0; i < (int)nparams; i++)
1772 {
1773 buf++; /* Skip the null string terminator from previous parameter. */
1774
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001775 png_debug1(3, "Reading pCAL parameter %d", i);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001776 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1777 /* Empty loop to move past each parameter string */ ;
1778
1779 /* Make sure we haven't run out of data yet */
1780 if (buf > endptr)
1781 {
1782 png_warning(png_ptr, "Invalid pCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001783 png_free(png_ptr, png_ptr->chunkdata);
1784 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001785 png_free(png_ptr, params);
1786 return;
1787 }
1788 }
1789
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001790 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
The Android Open Source Project893912b2009-03-03 19:30:05 -08001791 units, params);
1792
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001793 png_free(png_ptr, png_ptr->chunkdata);
1794 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001795 png_free(png_ptr, params);
1796}
1797#endif
1798
Patrick Scott5f6bd842010-06-28 16:55:16 -04001799#ifdef PNG_READ_sCAL_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001800/* Read the sCAL chunk */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001801void /* PRIVATE */
1802png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1803{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001804 png_charp ep;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001805#ifdef PNG_FLOATING_POINT_SUPPORTED
1806 double width, height;
1807 png_charp vp;
1808#else
1809#ifdef PNG_FIXED_POINT_SUPPORTED
1810 png_charp swidth, sheight;
1811#endif
1812#endif
1813 png_size_t slength;
1814
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001815 png_debug(1, "in png_handle_sCAL");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001816
1817 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1818 png_error(png_ptr, "Missing IHDR before sCAL");
1819 else if (png_ptr->mode & PNG_HAVE_IDAT)
1820 {
1821 png_warning(png_ptr, "Invalid sCAL after IDAT");
1822 png_crc_finish(png_ptr, length);
1823 return;
1824 }
1825 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1826 {
1827 png_warning(png_ptr, "Duplicate sCAL chunk");
1828 png_crc_finish(png_ptr, length);
1829 return;
1830 }
1831
Eric Vannier66dce0d2011-07-20 17:03:29 -07001832 /* Need unit type, width, \0, height: minimum 4 bytes */
1833 else if (length < 4)
1834 {
1835 png_warning(png_ptr, "sCAL chunk too short");
1836 png_crc_finish(png_ptr, length);
1837 return;
1838 }
1839
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001840 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
The Android Open Source Project893912b2009-03-03 19:30:05 -08001841 length + 1);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001842 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1843 if (png_ptr->chunkdata == NULL)
1844 {
1845 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001846 png_crc_finish(png_ptr, length);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001847 return;
1848 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001849 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001850 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001851
1852 if (png_crc_finish(png_ptr, 0))
1853 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001854 png_free(png_ptr, png_ptr->chunkdata);
1855 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001856 return;
1857 }
1858
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001859 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001860
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001861 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001862
1863#ifdef PNG_FLOATING_POINT_SUPPORTED
1864 width = png_strtod(png_ptr, ep, &vp);
1865 if (*vp)
1866 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001867 png_warning(png_ptr, "malformed width string in sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001868 png_free(png_ptr, png_ptr->chunkdata);
1869 png_ptr->chunkdata = NULL;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001870 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001871 }
1872#else
1873#ifdef PNG_FIXED_POINT_SUPPORTED
1874 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1875 if (swidth == NULL)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001876 {
1877 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001878 png_free(png_ptr, png_ptr->chunkdata);
1879 png_ptr->chunkdata = NULL;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001880 return;
1881 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001882 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1883#endif
1884#endif
1885
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001886 for (ep = png_ptr->chunkdata; *ep; ep++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001887 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001888 ep++;
1889
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001890 if (png_ptr->chunkdata + slength < ep)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001891 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001892 png_warning(png_ptr, "Truncated sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001893#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001894 png_free(png_ptr, swidth);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001895#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001896 png_free(png_ptr, png_ptr->chunkdata);
1897 png_ptr->chunkdata = NULL;
1898 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001899 }
1900
1901#ifdef PNG_FLOATING_POINT_SUPPORTED
1902 height = png_strtod(png_ptr, ep, &vp);
1903 if (*vp)
1904 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001905 png_warning(png_ptr, "malformed height string in sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001906 png_free(png_ptr, png_ptr->chunkdata);
1907 png_ptr->chunkdata = NULL;
1908#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1909 png_free(png_ptr, swidth);
1910#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001911 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001912 }
1913#else
1914#ifdef PNG_FIXED_POINT_SUPPORTED
1915 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1916 if (sheight == NULL)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001917 {
1918 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001919 png_free(png_ptr, png_ptr->chunkdata);
1920 png_ptr->chunkdata = NULL;
1921#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1922 png_free(png_ptr, swidth);
1923#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001924 return;
1925 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001926 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1927#endif
1928#endif
1929
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001930 if (png_ptr->chunkdata + slength < ep
The Android Open Source Project893912b2009-03-03 19:30:05 -08001931#ifdef PNG_FLOATING_POINT_SUPPORTED
1932 || width <= 0. || height <= 0.
1933#endif
1934 )
1935 {
1936 png_warning(png_ptr, "Invalid sCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001937 png_free(png_ptr, png_ptr->chunkdata);
1938 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001939#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1940 png_free(png_ptr, swidth);
1941 png_free(png_ptr, sheight);
1942#endif
1943 return;
1944 }
1945
1946
1947#ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001948 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001949#else
1950#ifdef PNG_FIXED_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001951 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001952#endif
1953#endif
1954
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001955 png_free(png_ptr, png_ptr->chunkdata);
1956 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001957#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1958 png_free(png_ptr, swidth);
1959 png_free(png_ptr, sheight);
1960#endif
1961}
1962#endif
1963
Patrick Scott5f6bd842010-06-28 16:55:16 -04001964#ifdef PNG_READ_tIME_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001965void /* PRIVATE */
1966png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1967{
1968 png_byte buf[7];
1969 png_time mod_time;
1970
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001971 png_debug(1, "in png_handle_tIME");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001972
1973 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1974 png_error(png_ptr, "Out of place tIME chunk");
1975 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1976 {
1977 png_warning(png_ptr, "Duplicate tIME chunk");
1978 png_crc_finish(png_ptr, length);
1979 return;
1980 }
1981
1982 if (png_ptr->mode & PNG_HAVE_IDAT)
1983 png_ptr->mode |= PNG_AFTER_IDAT;
1984
1985 if (length != 7)
1986 {
1987 png_warning(png_ptr, "Incorrect tIME chunk length");
1988 png_crc_finish(png_ptr, length);
1989 return;
1990 }
1991
1992 png_crc_read(png_ptr, buf, 7);
1993 if (png_crc_finish(png_ptr, 0))
1994 return;
1995
1996 mod_time.second = buf[6];
1997 mod_time.minute = buf[5];
1998 mod_time.hour = buf[4];
1999 mod_time.day = buf[3];
2000 mod_time.month = buf[2];
2001 mod_time.year = png_get_uint_16(buf);
2002
2003 png_set_tIME(png_ptr, info_ptr, &mod_time);
2004}
2005#endif
2006
Patrick Scott5f6bd842010-06-28 16:55:16 -04002007#ifdef PNG_READ_tEXt_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002008/* Note: this does not properly handle chunks that are > 64K under DOS */
2009void /* PRIVATE */
2010png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2011{
2012 png_textp text_ptr;
2013 png_charp key;
2014 png_charp text;
2015 png_uint_32 skip = 0;
2016 png_size_t slength;
2017 int ret;
2018
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002019 png_debug(1, "in png_handle_tEXt");
2020
Patrick Scott5f6bd842010-06-28 16:55:16 -04002021#ifdef PNG_USER_LIMITS_SUPPORTED
2022 if (png_ptr->user_chunk_cache_max != 0)
2023 {
2024 if (png_ptr->user_chunk_cache_max == 1)
2025 {
2026 png_crc_finish(png_ptr, length);
2027 return;
2028 }
2029 if (--png_ptr->user_chunk_cache_max == 1)
2030 {
2031 png_warning(png_ptr, "No space in chunk cache for tEXt");
2032 png_crc_finish(png_ptr, length);
2033 return;
2034 }
2035 }
2036#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002037
2038 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2039 png_error(png_ptr, "Missing IHDR before tEXt");
2040
2041 if (png_ptr->mode & PNG_HAVE_IDAT)
2042 png_ptr->mode |= PNG_AFTER_IDAT;
2043
2044#ifdef PNG_MAX_MALLOC_64K
2045 if (length > (png_uint_32)65535L)
2046 {
2047 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
2048 skip = length - (png_uint_32)65535L;
2049 length = (png_uint_32)65535L;
2050 }
2051#endif
2052
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002053 png_free(png_ptr, png_ptr->chunkdata);
2054
2055 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2056 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002057 {
2058 png_warning(png_ptr, "No memory to process text chunk.");
2059 return;
2060 }
2061 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002062 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002063
2064 if (png_crc_finish(png_ptr, skip))
2065 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002066 png_free(png_ptr, png_ptr->chunkdata);
2067 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002068 return;
2069 }
2070
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002071 key = png_ptr->chunkdata;
2072
The Android Open Source Project893912b2009-03-03 19:30:05 -08002073 key[slength] = 0x00;
2074
2075 for (text = key; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002076 /* Empty loop to find end of key */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002077
2078 if (text != key + slength)
2079 text++;
2080
2081 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2082 (png_uint_32)png_sizeof(png_text));
2083 if (text_ptr == NULL)
2084 {
2085 png_warning(png_ptr, "Not enough memory to process text chunk.");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002086 png_free(png_ptr, png_ptr->chunkdata);
2087 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002088 return;
2089 }
2090 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2091 text_ptr->key = key;
2092#ifdef PNG_iTXt_SUPPORTED
2093 text_ptr->lang = NULL;
2094 text_ptr->lang_key = NULL;
2095 text_ptr->itxt_length = 0;
2096#endif
2097 text_ptr->text = text;
2098 text_ptr->text_length = png_strlen(text);
2099
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002100 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002101
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002102 png_free(png_ptr, png_ptr->chunkdata);
2103 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002104 png_free(png_ptr, text_ptr);
2105 if (ret)
2106 png_warning(png_ptr, "Insufficient memory to process text chunk.");
2107}
2108#endif
2109
Patrick Scott5f6bd842010-06-28 16:55:16 -04002110#ifdef PNG_READ_zTXt_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002111/* Note: this does not correctly handle chunks that are > 64K under DOS */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002112void /* PRIVATE */
2113png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2114{
2115 png_textp text_ptr;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002116 png_charp text;
2117 int comp_type;
2118 int ret;
2119 png_size_t slength, prefix_len, data_len;
2120
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002121 png_debug(1, "in png_handle_zTXt");
2122
Patrick Scott5f6bd842010-06-28 16:55:16 -04002123#ifdef PNG_USER_LIMITS_SUPPORTED
2124 if (png_ptr->user_chunk_cache_max != 0)
2125 {
2126 if (png_ptr->user_chunk_cache_max == 1)
2127 {
2128 png_crc_finish(png_ptr, length);
2129 return;
2130 }
2131 if (--png_ptr->user_chunk_cache_max == 1)
2132 {
2133 png_warning(png_ptr, "No space in chunk cache for zTXt");
2134 png_crc_finish(png_ptr, length);
2135 return;
2136 }
2137 }
2138#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002139
The Android Open Source Project893912b2009-03-03 19:30:05 -08002140 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2141 png_error(png_ptr, "Missing IHDR before zTXt");
2142
2143 if (png_ptr->mode & PNG_HAVE_IDAT)
2144 png_ptr->mode |= PNG_AFTER_IDAT;
2145
2146#ifdef PNG_MAX_MALLOC_64K
2147 /* We will no doubt have problems with chunks even half this size, but
2148 there is no hard and fast rule to tell us where to stop. */
2149 if (length > (png_uint_32)65535L)
2150 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002151 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002152 png_crc_finish(png_ptr, length);
2153 return;
2154 }
2155#endif
2156
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002157 png_free(png_ptr, png_ptr->chunkdata);
2158 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2159 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002160 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002161 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002162 return;
2163 }
2164 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002165 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002166 if (png_crc_finish(png_ptr, 0))
2167 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002168 png_free(png_ptr, png_ptr->chunkdata);
2169 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002170 return;
2171 }
2172
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002173 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002174
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002175 for (text = png_ptr->chunkdata; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002176 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002177
2178 /* zTXt must have some text after the chunkdataword */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002179 if (text >= png_ptr->chunkdata + slength - 2)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002180 {
2181 png_warning(png_ptr, "Truncated zTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002182 png_free(png_ptr, png_ptr->chunkdata);
2183 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002184 return;
2185 }
2186 else
2187 {
2188 comp_type = *(++text);
2189 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2190 {
2191 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2192 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2193 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002194 text++; /* Skip the compression_method byte */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002195 }
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002196 prefix_len = text - png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002197
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002198 png_decompress_chunk(png_ptr, comp_type,
2199 (png_size_t)length, prefix_len, &data_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002200
2201 text_ptr = (png_textp)png_malloc_warn(png_ptr,
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002202 (png_uint_32)png_sizeof(png_text));
The Android Open Source Project893912b2009-03-03 19:30:05 -08002203 if (text_ptr == NULL)
2204 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002205 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
2206 png_free(png_ptr, png_ptr->chunkdata);
2207 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002208 return;
2209 }
2210 text_ptr->compression = comp_type;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002211 text_ptr->key = png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002212#ifdef PNG_iTXt_SUPPORTED
2213 text_ptr->lang = NULL;
2214 text_ptr->lang_key = NULL;
2215 text_ptr->itxt_length = 0;
2216#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002217 text_ptr->text = png_ptr->chunkdata + prefix_len;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002218 text_ptr->text_length = data_len;
2219
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002220 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002221
2222 png_free(png_ptr, text_ptr);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002223 png_free(png_ptr, png_ptr->chunkdata);
2224 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002225 if (ret)
2226 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2227}
2228#endif
2229
Patrick Scott5f6bd842010-06-28 16:55:16 -04002230#ifdef PNG_READ_iTXt_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002231/* Note: this does not correctly handle chunks that are > 64K under DOS */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002232void /* PRIVATE */
2233png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2234{
2235 png_textp text_ptr;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002236 png_charp key, lang, text, lang_key;
2237 int comp_flag;
2238 int comp_type = 0;
2239 int ret;
2240 png_size_t slength, prefix_len, data_len;
2241
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002242 png_debug(1, "in png_handle_iTXt");
2243
Patrick Scott5f6bd842010-06-28 16:55:16 -04002244#ifdef PNG_USER_LIMITS_SUPPORTED
2245 if (png_ptr->user_chunk_cache_max != 0)
2246 {
2247 if (png_ptr->user_chunk_cache_max == 1)
2248 {
2249 png_crc_finish(png_ptr, length);
2250 return;
2251 }
2252 if (--png_ptr->user_chunk_cache_max == 1)
2253 {
2254 png_warning(png_ptr, "No space in chunk cache for iTXt");
2255 png_crc_finish(png_ptr, length);
2256 return;
2257 }
2258 }
2259#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002260
2261 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2262 png_error(png_ptr, "Missing IHDR before iTXt");
2263
2264 if (png_ptr->mode & PNG_HAVE_IDAT)
2265 png_ptr->mode |= PNG_AFTER_IDAT;
2266
2267#ifdef PNG_MAX_MALLOC_64K
2268 /* We will no doubt have problems with chunks even half this size, but
2269 there is no hard and fast rule to tell us where to stop. */
2270 if (length > (png_uint_32)65535L)
2271 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002272 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002273 png_crc_finish(png_ptr, length);
2274 return;
2275 }
2276#endif
2277
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002278 png_free(png_ptr, png_ptr->chunkdata);
2279 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2280 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002281 {
2282 png_warning(png_ptr, "No memory to process iTXt chunk.");
2283 return;
2284 }
2285 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002286 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002287 if (png_crc_finish(png_ptr, 0))
2288 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002289 png_free(png_ptr, png_ptr->chunkdata);
2290 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002291 return;
2292 }
2293
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002294 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002295
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002296 for (lang = png_ptr->chunkdata; *lang; lang++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002297 /* Empty loop */ ;
2298 lang++; /* Skip NUL separator */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002299
2300 /* iTXt must have a language tag (possibly empty), two compression bytes,
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002301 * translated keyword (possibly empty), and possibly some text after the
2302 * keyword
2303 */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002304
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002305 if (lang >= png_ptr->chunkdata + slength - 3)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002306 {
2307 png_warning(png_ptr, "Truncated iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002308 png_free(png_ptr, png_ptr->chunkdata);
2309 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002310 return;
2311 }
2312 else
2313 {
2314 comp_flag = *lang++;
2315 comp_type = *lang++;
2316 }
2317
2318 for (lang_key = lang; *lang_key; lang_key++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002319 /* Empty loop */ ;
2320 lang_key++; /* Skip NUL separator */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002321
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002322 if (lang_key >= png_ptr->chunkdata + slength)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002323 {
2324 png_warning(png_ptr, "Truncated iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002325 png_free(png_ptr, png_ptr->chunkdata);
2326 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002327 return;
2328 }
2329
2330 for (text = lang_key; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002331 /* Empty loop */ ;
2332 text++; /* Skip NUL separator */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002333 if (text >= png_ptr->chunkdata + slength)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002334 {
2335 png_warning(png_ptr, "Malformed iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002336 png_free(png_ptr, png_ptr->chunkdata);
2337 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002338 return;
2339 }
2340
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002341 prefix_len = text - png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002342
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002343 key=png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002344 if (comp_flag)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002345 png_decompress_chunk(png_ptr, comp_type,
2346 (size_t)length, prefix_len, &data_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002347 else
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002348 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002349 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2350 (png_uint_32)png_sizeof(png_text));
2351 if (text_ptr == NULL)
2352 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002353 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2354 png_free(png_ptr, png_ptr->chunkdata);
2355 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002356 return;
2357 }
2358 text_ptr->compression = (int)comp_flag + 1;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002359 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2360 text_ptr->lang = png_ptr->chunkdata + (lang - key);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002361 text_ptr->itxt_length = data_len;
2362 text_ptr->text_length = 0;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002363 text_ptr->key = png_ptr->chunkdata;
2364 text_ptr->text = png_ptr->chunkdata + prefix_len;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002365
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002366 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002367
2368 png_free(png_ptr, text_ptr);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002369 png_free(png_ptr, png_ptr->chunkdata);
2370 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002371 if (ret)
2372 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2373}
2374#endif
2375
2376/* This function is called when we haven't found a handler for a
2377 chunk. If there isn't a problem with the chunk itself (ie bad
2378 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2379 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2380 case it will be saved away to be written out later. */
2381void /* PRIVATE */
2382png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2383{
2384 png_uint_32 skip = 0;
2385
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002386 png_debug(1, "in png_handle_unknown");
2387
Patrick Scott5f6bd842010-06-28 16:55:16 -04002388#ifdef PNG_USER_LIMITS_SUPPORTED
2389 if (png_ptr->user_chunk_cache_max != 0)
2390 {
2391 if (png_ptr->user_chunk_cache_max == 1)
2392 {
2393 png_crc_finish(png_ptr, length);
2394 return;
2395 }
2396 if (--png_ptr->user_chunk_cache_max == 1)
2397 {
2398 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2399 png_crc_finish(png_ptr, length);
2400 return;
2401 }
2402 }
2403#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002404
2405 if (png_ptr->mode & PNG_HAVE_IDAT)
2406 {
2407#ifdef PNG_USE_LOCAL_ARRAYS
2408 PNG_CONST PNG_IDAT;
2409#endif
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002410 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002411 png_ptr->mode |= PNG_AFTER_IDAT;
2412 }
2413
The Android Open Source Project893912b2009-03-03 19:30:05 -08002414 if (!(png_ptr->chunk_name[0] & 0x20))
2415 {
Patrick Scott5f6bd842010-06-28 16:55:16 -04002416#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002417 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
The Android Open Source Project893912b2009-03-03 19:30:05 -08002418 PNG_HANDLE_CHUNK_ALWAYS
Patrick Scott5f6bd842010-06-28 16:55:16 -04002419#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002420 && png_ptr->read_user_chunk_fn == NULL
2421#endif
2422 )
2423#endif
2424 png_chunk_error(png_ptr, "unknown critical chunk");
2425 }
2426
Patrick Scott5f6bd842010-06-28 16:55:16 -04002427#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002428 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
Patrick Scott5f6bd842010-06-28 16:55:16 -04002429#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002430 || (png_ptr->read_user_chunk_fn != NULL)
2431#endif
2432 )
The Android Open Source Project893912b2009-03-03 19:30:05 -08002433 {
2434#ifdef PNG_MAX_MALLOC_64K
2435 if (length > (png_uint_32)65535L)
2436 {
2437 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2438 skip = length - (png_uint_32)65535L;
2439 length = (png_uint_32)65535L;
2440 }
2441#endif
2442 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002443 (png_charp)png_ptr->chunk_name,
The Android Open Source Project893912b2009-03-03 19:30:05 -08002444 png_sizeof(png_ptr->unknown_chunk.name));
Patrick Scott5f6bd842010-06-28 16:55:16 -04002445 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2446 = '\0';
The Android Open Source Project893912b2009-03-03 19:30:05 -08002447 png_ptr->unknown_chunk.size = (png_size_t)length;
2448 if (length == 0)
2449 png_ptr->unknown_chunk.data = NULL;
2450 else
2451 {
2452 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2453 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2454 }
Patrick Scott5f6bd842010-06-28 16:55:16 -04002455#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002456 if (png_ptr->read_user_chunk_fn != NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002457 {
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002458 /* Callback to user unknown chunk handler */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002459 int ret;
2460 ret = (*(png_ptr->read_user_chunk_fn))
2461 (png_ptr, &png_ptr->unknown_chunk);
2462 if (ret < 0)
2463 png_chunk_error(png_ptr, "error in user chunk");
2464 if (ret == 0)
2465 {
2466 if (!(png_ptr->chunk_name[0] & 0x20))
Patrick Scott5f6bd842010-06-28 16:55:16 -04002467#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002468 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
The Android Open Source Project893912b2009-03-03 19:30:05 -08002469 PNG_HANDLE_CHUNK_ALWAYS)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002470#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002471 png_chunk_error(png_ptr, "unknown critical chunk");
2472 png_set_unknown_chunks(png_ptr, info_ptr,
2473 &png_ptr->unknown_chunk, 1);
2474 }
2475 }
2476 else
2477#endif
2478 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2479 png_free(png_ptr, png_ptr->unknown_chunk.data);
2480 png_ptr->unknown_chunk.data = NULL;
2481 }
2482 else
2483#endif
2484 skip = length;
2485
2486 png_crc_finish(png_ptr, skip);
2487
Patrick Scott5f6bd842010-06-28 16:55:16 -04002488#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002489 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002490#endif
2491}
2492
2493/* This function is called to verify that a chunk name is valid.
2494 This function can't have the "critical chunk check" incorporated
2495 into it, since in the future we will need to be able to call user
2496 functions to handle unknown critical chunks after we check that
2497 the chunk name itself is valid. */
2498
2499#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2500
2501void /* PRIVATE */
2502png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2503{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002504 png_debug(1, "in png_check_chunk_name");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002505 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2506 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2507 {
2508 png_chunk_error(png_ptr, "invalid chunk type");
2509 }
2510}
2511
2512/* Combines the row recently read in with the existing pixels in the
2513 row. This routine takes care of alpha and transparency if requested.
2514 This routine also handles the two methods of progressive display
2515 of interlaced images, depending on the mask value.
2516 The mask value describes which pixels are to be combined with
2517 the row. The pattern always repeats every 8 pixels, so just 8
2518 bits are needed. A one indicates the pixel is to be combined,
2519 a zero indicates the pixel is to be skipped. This is in addition
2520 to any alpha or transparency value associated with the pixel. If
2521 you want all pixels to be combined, pass 0xff (255) in mask. */
2522
2523void /* PRIVATE */
2524png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2525{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002526 png_debug(1, "in png_combine_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002527 if (mask == 0xff)
2528 {
2529 png_memcpy(row, png_ptr->row_buf + 1,
2530 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2531 }
2532 else
2533 {
2534 switch (png_ptr->row_info.pixel_depth)
2535 {
2536 case 1:
2537 {
2538 png_bytep sp = png_ptr->row_buf + 1;
2539 png_bytep dp = row;
2540 int s_inc, s_start, s_end;
2541 int m = 0x80;
2542 int shift;
2543 png_uint_32 i;
2544 png_uint_32 row_width = png_ptr->width;
2545
Patrick Scott5f6bd842010-06-28 16:55:16 -04002546#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002547 if (png_ptr->transformations & PNG_PACKSWAP)
2548 {
2549 s_start = 0;
2550 s_end = 7;
2551 s_inc = 1;
2552 }
2553 else
2554#endif
2555 {
2556 s_start = 7;
2557 s_end = 0;
2558 s_inc = -1;
2559 }
2560
2561 shift = s_start;
2562
2563 for (i = 0; i < row_width; i++)
2564 {
2565 if (m & mask)
2566 {
2567 int value;
2568
2569 value = (*sp >> shift) & 0x01;
2570 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2571 *dp |= (png_byte)(value << shift);
2572 }
2573
2574 if (shift == s_end)
2575 {
2576 shift = s_start;
2577 sp++;
2578 dp++;
2579 }
2580 else
2581 shift += s_inc;
2582
2583 if (m == 1)
2584 m = 0x80;
2585 else
2586 m >>= 1;
2587 }
2588 break;
2589 }
2590 case 2:
2591 {
2592 png_bytep sp = png_ptr->row_buf + 1;
2593 png_bytep dp = row;
2594 int s_start, s_end, s_inc;
2595 int m = 0x80;
2596 int shift;
2597 png_uint_32 i;
2598 png_uint_32 row_width = png_ptr->width;
2599 int value;
2600
Patrick Scott5f6bd842010-06-28 16:55:16 -04002601#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002602 if (png_ptr->transformations & PNG_PACKSWAP)
2603 {
2604 s_start = 0;
2605 s_end = 6;
2606 s_inc = 2;
2607 }
2608 else
2609#endif
2610 {
2611 s_start = 6;
2612 s_end = 0;
2613 s_inc = -2;
2614 }
2615
2616 shift = s_start;
2617
2618 for (i = 0; i < row_width; i++)
2619 {
2620 if (m & mask)
2621 {
2622 value = (*sp >> shift) & 0x03;
2623 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2624 *dp |= (png_byte)(value << shift);
2625 }
2626
2627 if (shift == s_end)
2628 {
2629 shift = s_start;
2630 sp++;
2631 dp++;
2632 }
2633 else
2634 shift += s_inc;
2635 if (m == 1)
2636 m = 0x80;
2637 else
2638 m >>= 1;
2639 }
2640 break;
2641 }
2642 case 4:
2643 {
2644 png_bytep sp = png_ptr->row_buf + 1;
2645 png_bytep dp = row;
2646 int s_start, s_end, s_inc;
2647 int m = 0x80;
2648 int shift;
2649 png_uint_32 i;
2650 png_uint_32 row_width = png_ptr->width;
2651 int value;
2652
Patrick Scott5f6bd842010-06-28 16:55:16 -04002653#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002654 if (png_ptr->transformations & PNG_PACKSWAP)
2655 {
2656 s_start = 0;
2657 s_end = 4;
2658 s_inc = 4;
2659 }
2660 else
2661#endif
2662 {
2663 s_start = 4;
2664 s_end = 0;
2665 s_inc = -4;
2666 }
2667 shift = s_start;
2668
2669 for (i = 0; i < row_width; i++)
2670 {
2671 if (m & mask)
2672 {
2673 value = (*sp >> shift) & 0xf;
2674 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2675 *dp |= (png_byte)(value << shift);
2676 }
2677
2678 if (shift == s_end)
2679 {
2680 shift = s_start;
2681 sp++;
2682 dp++;
2683 }
2684 else
2685 shift += s_inc;
2686 if (m == 1)
2687 m = 0x80;
2688 else
2689 m >>= 1;
2690 }
2691 break;
2692 }
2693 default:
2694 {
2695 png_bytep sp = png_ptr->row_buf + 1;
2696 png_bytep dp = row;
2697 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2698 png_uint_32 i;
2699 png_uint_32 row_width = png_ptr->width;
2700 png_byte m = 0x80;
2701
2702
2703 for (i = 0; i < row_width; i++)
2704 {
2705 if (m & mask)
2706 {
2707 png_memcpy(dp, sp, pixel_bytes);
2708 }
2709
2710 sp += pixel_bytes;
2711 dp += pixel_bytes;
2712
2713 if (m == 1)
2714 m = 0x80;
2715 else
2716 m >>= 1;
2717 }
2718 break;
2719 }
2720 }
2721 }
2722}
2723
2724#ifdef PNG_READ_INTERLACING_SUPPORTED
2725/* OLD pre-1.0.9 interface:
2726void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2727 png_uint_32 transformations)
2728 */
2729void /* PRIVATE */
2730png_do_read_interlace(png_structp png_ptr)
2731{
2732 png_row_infop row_info = &(png_ptr->row_info);
2733 png_bytep row = png_ptr->row_buf + 1;
2734 int pass = png_ptr->pass;
2735 png_uint_32 transformations = png_ptr->transformations;
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002736 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2737 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002738 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
The Android Open Source Project893912b2009-03-03 19:30:05 -08002739
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002740 png_debug(1, "in png_do_read_interlace");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002741 if (row != NULL && row_info != NULL)
2742 {
2743 png_uint_32 final_width;
2744
2745 final_width = row_info->width * png_pass_inc[pass];
2746
2747 switch (row_info->pixel_depth)
2748 {
2749 case 1:
2750 {
2751 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2752 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2753 int sshift, dshift;
2754 int s_start, s_end, s_inc;
2755 int jstop = png_pass_inc[pass];
2756 png_byte v;
2757 png_uint_32 i;
2758 int j;
2759
Patrick Scott5f6bd842010-06-28 16:55:16 -04002760#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002761 if (transformations & PNG_PACKSWAP)
2762 {
2763 sshift = (int)((row_info->width + 7) & 0x07);
2764 dshift = (int)((final_width + 7) & 0x07);
2765 s_start = 7;
2766 s_end = 0;
2767 s_inc = -1;
2768 }
2769 else
2770#endif
2771 {
2772 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2773 dshift = 7 - (int)((final_width + 7) & 0x07);
2774 s_start = 0;
2775 s_end = 7;
2776 s_inc = 1;
2777 }
2778
2779 for (i = 0; i < row_info->width; i++)
2780 {
2781 v = (png_byte)((*sp >> sshift) & 0x01);
2782 for (j = 0; j < jstop; j++)
2783 {
2784 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2785 *dp |= (png_byte)(v << dshift);
2786 if (dshift == s_end)
2787 {
2788 dshift = s_start;
2789 dp--;
2790 }
2791 else
2792 dshift += s_inc;
2793 }
2794 if (sshift == s_end)
2795 {
2796 sshift = s_start;
2797 sp--;
2798 }
2799 else
2800 sshift += s_inc;
2801 }
2802 break;
2803 }
2804 case 2:
2805 {
2806 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2807 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2808 int sshift, dshift;
2809 int s_start, s_end, s_inc;
2810 int jstop = png_pass_inc[pass];
2811 png_uint_32 i;
2812
Patrick Scott5f6bd842010-06-28 16:55:16 -04002813#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002814 if (transformations & PNG_PACKSWAP)
2815 {
2816 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2817 dshift = (int)(((final_width + 3) & 0x03) << 1);
2818 s_start = 6;
2819 s_end = 0;
2820 s_inc = -2;
2821 }
2822 else
2823#endif
2824 {
2825 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2826 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2827 s_start = 0;
2828 s_end = 6;
2829 s_inc = 2;
2830 }
2831
2832 for (i = 0; i < row_info->width; i++)
2833 {
2834 png_byte v;
2835 int j;
2836
2837 v = (png_byte)((*sp >> sshift) & 0x03);
2838 for (j = 0; j < jstop; j++)
2839 {
2840 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2841 *dp |= (png_byte)(v << dshift);
2842 if (dshift == s_end)
2843 {
2844 dshift = s_start;
2845 dp--;
2846 }
2847 else
2848 dshift += s_inc;
2849 }
2850 if (sshift == s_end)
2851 {
2852 sshift = s_start;
2853 sp--;
2854 }
2855 else
2856 sshift += s_inc;
2857 }
2858 break;
2859 }
2860 case 4:
2861 {
2862 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2863 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2864 int sshift, dshift;
2865 int s_start, s_end, s_inc;
2866 png_uint_32 i;
2867 int jstop = png_pass_inc[pass];
2868
Patrick Scott5f6bd842010-06-28 16:55:16 -04002869#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002870 if (transformations & PNG_PACKSWAP)
2871 {
2872 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2873 dshift = (int)(((final_width + 1) & 0x01) << 2);
2874 s_start = 4;
2875 s_end = 0;
2876 s_inc = -4;
2877 }
2878 else
2879#endif
2880 {
2881 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2882 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2883 s_start = 0;
2884 s_end = 4;
2885 s_inc = 4;
2886 }
2887
2888 for (i = 0; i < row_info->width; i++)
2889 {
2890 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2891 int j;
2892
2893 for (j = 0; j < jstop; j++)
2894 {
2895 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2896 *dp |= (png_byte)(v << dshift);
2897 if (dshift == s_end)
2898 {
2899 dshift = s_start;
2900 dp--;
2901 }
2902 else
2903 dshift += s_inc;
2904 }
2905 if (sshift == s_end)
2906 {
2907 sshift = s_start;
2908 sp--;
2909 }
2910 else
2911 sshift += s_inc;
2912 }
2913 break;
2914 }
2915 default:
2916 {
2917 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
Patrick Scott5f6bd842010-06-28 16:55:16 -04002918 png_bytep sp = row + (png_size_t)(row_info->width - 1)
2919 * pixel_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002920 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2921
2922 int jstop = png_pass_inc[pass];
2923 png_uint_32 i;
2924
2925 for (i = 0; i < row_info->width; i++)
2926 {
2927 png_byte v[8];
2928 int j;
2929
2930 png_memcpy(v, sp, pixel_bytes);
2931 for (j = 0; j < jstop; j++)
2932 {
2933 png_memcpy(dp, v, pixel_bytes);
2934 dp -= pixel_bytes;
2935 }
2936 sp -= pixel_bytes;
2937 }
2938 break;
2939 }
2940 }
2941 row_info->width = final_width;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002942 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002943 }
Patrick Scott5f6bd842010-06-28 16:55:16 -04002944#ifndef PNG_READ_PACKSWAP_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002945 transformations = transformations; /* Silence compiler warning */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002946#endif
2947}
2948#endif /* PNG_READ_INTERLACING_SUPPORTED */
2949
2950void /* PRIVATE */
2951png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2952 png_bytep prev_row, int filter)
2953{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002954 png_debug(1, "in png_read_filter_row");
2955 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002956 switch (filter)
2957 {
2958 case PNG_FILTER_VALUE_NONE:
2959 break;
2960 case PNG_FILTER_VALUE_SUB:
2961 {
2962 png_uint_32 i;
2963 png_uint_32 istop = row_info->rowbytes;
2964 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2965 png_bytep rp = row + bpp;
2966 png_bytep lp = row;
2967
2968 for (i = bpp; i < istop; i++)
2969 {
2970 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2971 rp++;
2972 }
2973 break;
2974 }
2975 case PNG_FILTER_VALUE_UP:
2976 {
2977 png_uint_32 i;
2978 png_uint_32 istop = row_info->rowbytes;
2979 png_bytep rp = row;
2980 png_bytep pp = prev_row;
2981
2982 for (i = 0; i < istop; i++)
2983 {
2984 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2985 rp++;
2986 }
2987 break;
2988 }
2989 case PNG_FILTER_VALUE_AVG:
2990 {
2991 png_uint_32 i;
2992 png_bytep rp = row;
2993 png_bytep pp = prev_row;
2994 png_bytep lp = row;
2995 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2996 png_uint_32 istop = row_info->rowbytes - bpp;
2997
2998 for (i = 0; i < bpp; i++)
2999 {
3000 *rp = (png_byte)(((int)(*rp) +
3001 ((int)(*pp++) / 2 )) & 0xff);
3002 rp++;
3003 }
3004
3005 for (i = 0; i < istop; i++)
3006 {
3007 *rp = (png_byte)(((int)(*rp) +
3008 (int)(*pp++ + *lp++) / 2 ) & 0xff);
3009 rp++;
3010 }
3011 break;
3012 }
3013 case PNG_FILTER_VALUE_PAETH:
3014 {
3015 png_uint_32 i;
3016 png_bytep rp = row;
3017 png_bytep pp = prev_row;
3018 png_bytep lp = row;
3019 png_bytep cp = prev_row;
3020 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3021 png_uint_32 istop=row_info->rowbytes - bpp;
3022
3023 for (i = 0; i < bpp; i++)
3024 {
3025 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3026 rp++;
3027 }
3028
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003029 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003030 {
3031 int a, b, c, pa, pb, pc, p;
3032
3033 a = *lp++;
3034 b = *pp++;
3035 c = *cp++;
3036
3037 p = b - c;
3038 pc = a - c;
3039
3040#ifdef PNG_USE_ABS
3041 pa = abs(p);
3042 pb = abs(pc);
3043 pc = abs(p + pc);
3044#else
3045 pa = p < 0 ? -p : p;
3046 pb = pc < 0 ? -pc : pc;
3047 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3048#endif
3049
3050 /*
3051 if (pa <= pb && pa <= pc)
3052 p = a;
3053 else if (pb <= pc)
3054 p = b;
3055 else
3056 p = c;
3057 */
3058
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003059 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003060
3061 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3062 rp++;
3063 }
3064 break;
3065 }
3066 default:
3067 png_warning(png_ptr, "Ignoring bad adaptive filter type");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003068 *row = 0;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003069 break;
3070 }
3071}
3072
Joseph Wen4ce0ee12010-08-20 10:42:22 +08003073#ifdef PNG_INDEX_SUPPORTED
3074void /* PRIVATE */
3075png_set_interlaced_pass(png_structp png_ptr, int pass)
3076{
3077 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3078
3079 /* Start of interlace block */
3080 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3081
3082 /* Offset to next interlace block */
3083 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3084
3085 /* Start of interlace block in the y direction */
3086 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3087
3088 /* Offset to next interlace block in the y direction */
3089 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3090
3091 png_ptr->pass = pass;
3092 png_ptr->iwidth = (png_ptr->width +
3093 png_pass_inc[png_ptr->pass] - 1 -
3094 png_pass_start[png_ptr->pass]) /
3095 png_pass_inc[png_ptr->pass];
3096}
3097#endif
3098
Patrick Scott5f6bd842010-06-28 16:55:16 -04003099#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003100void /* PRIVATE */
3101png_read_finish_row(png_structp png_ptr)
3102{
The Android Open Source Project893912b2009-03-03 19:30:05 -08003103#ifdef PNG_READ_INTERLACING_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003104 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003105
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003106 /* Start of interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003107 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3108
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003109 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003110 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3111
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003112 /* Start of interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003113 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3114
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003115 /* Offset to next interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003116 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3117#endif /* PNG_READ_INTERLACING_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003118
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003119 png_debug(1, "in png_read_finish_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003120 png_ptr->row_number++;
3121 if (png_ptr->row_number < png_ptr->num_rows)
3122 return;
3123
3124#ifdef PNG_READ_INTERLACING_SUPPORTED
3125 if (png_ptr->interlaced)
3126 {
3127 png_ptr->row_number = 0;
3128 png_memset_check(png_ptr, png_ptr->prev_row, 0,
3129 png_ptr->rowbytes + 1);
3130 do
3131 {
3132 png_ptr->pass++;
3133 if (png_ptr->pass >= 7)
3134 break;
3135 png_ptr->iwidth = (png_ptr->width +
3136 png_pass_inc[png_ptr->pass] - 1 -
3137 png_pass_start[png_ptr->pass]) /
3138 png_pass_inc[png_ptr->pass];
3139
The Android Open Source Project893912b2009-03-03 19:30:05 -08003140 if (!(png_ptr->transformations & PNG_INTERLACE))
3141 {
3142 png_ptr->num_rows = (png_ptr->height +
3143 png_pass_yinc[png_ptr->pass] - 1 -
3144 png_pass_ystart[png_ptr->pass]) /
3145 png_pass_yinc[png_ptr->pass];
3146 if (!(png_ptr->num_rows))
3147 continue;
3148 }
3149 else /* if (png_ptr->transformations & PNG_INTERLACE) */
3150 break;
3151 } while (png_ptr->iwidth == 0);
3152
3153 if (png_ptr->pass < 7)
3154 return;
3155 }
3156#endif /* PNG_READ_INTERLACING_SUPPORTED */
3157
3158 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
3159 {
3160#ifdef PNG_USE_LOCAL_ARRAYS
3161 PNG_CONST PNG_IDAT;
3162#endif
3163 char extra;
3164 int ret;
3165
3166 png_ptr->zstream.next_out = (Byte *)&extra;
3167 png_ptr->zstream.avail_out = (uInt)1;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003168 for (;;)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003169 {
3170 if (!(png_ptr->zstream.avail_in))
3171 {
3172 while (!png_ptr->idat_size)
3173 {
3174 png_byte chunk_length[4];
3175
3176 png_crc_finish(png_ptr, 0);
3177
3178 png_read_data(png_ptr, chunk_length, 4);
3179 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
3180 png_reset_crc(png_ptr);
3181 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
3182 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
3183 png_error(png_ptr, "Not enough image data");
3184
3185 }
3186 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3187 png_ptr->zstream.next_in = png_ptr->zbuf;
3188 if (png_ptr->zbuf_size > png_ptr->idat_size)
3189 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3190 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3191 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3192 }
3193 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3194 if (ret == Z_STREAM_END)
3195 {
3196 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3197 png_ptr->idat_size)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003198 png_warning(png_ptr, "Extra compressed data.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003199 png_ptr->mode |= PNG_AFTER_IDAT;
3200 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3201 break;
3202 }
3203 if (ret != Z_OK)
3204 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3205 "Decompression Error");
3206
3207 if (!(png_ptr->zstream.avail_out))
3208 {
3209 png_warning(png_ptr, "Extra compressed data.");
3210 png_ptr->mode |= PNG_AFTER_IDAT;
3211 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3212 break;
3213 }
3214
3215 }
3216 png_ptr->zstream.avail_out = 0;
3217 }
3218
3219 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003220 png_warning(png_ptr, "Extra compression data.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003221
3222 inflateReset(&png_ptr->zstream);
3223
3224 png_ptr->mode |= PNG_AFTER_IDAT;
3225}
Patrick Scott5f6bd842010-06-28 16:55:16 -04003226#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003227
3228void /* PRIVATE */
3229png_read_start_row(png_structp png_ptr)
3230{
The Android Open Source Project893912b2009-03-03 19:30:05 -08003231#ifdef PNG_READ_INTERLACING_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003232 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003233
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003234 /* Start of interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003235 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3236
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003237 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003238 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3239
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003240 /* Start of interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003241 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3242
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003243 /* Offset to next interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003244 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3245#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08003246
3247 int max_pixel_depth;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003248 png_size_t row_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003249
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003250 png_debug(1, "in png_read_start_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003251 png_ptr->zstream.avail_in = 0;
3252 png_init_read_transformations(png_ptr);
3253#ifdef PNG_READ_INTERLACING_SUPPORTED
3254 if (png_ptr->interlaced)
3255 {
3256 if (!(png_ptr->transformations & PNG_INTERLACE))
3257 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3258 png_pass_ystart[0]) / png_pass_yinc[0];
3259 else
3260 png_ptr->num_rows = png_ptr->height;
3261
3262 png_ptr->iwidth = (png_ptr->width +
3263 png_pass_inc[png_ptr->pass] - 1 -
3264 png_pass_start[png_ptr->pass]) /
3265 png_pass_inc[png_ptr->pass];
The Android Open Source Project893912b2009-03-03 19:30:05 -08003266 }
3267 else
3268#endif /* PNG_READ_INTERLACING_SUPPORTED */
3269 {
3270 png_ptr->num_rows = png_ptr->height;
3271 png_ptr->iwidth = png_ptr->width;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003272 }
3273 max_pixel_depth = png_ptr->pixel_depth;
3274
Patrick Scott5f6bd842010-06-28 16:55:16 -04003275#ifdef PNG_READ_PACK_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003276 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3277 max_pixel_depth = 8;
3278#endif
3279
Patrick Scott5f6bd842010-06-28 16:55:16 -04003280#ifdef PNG_READ_EXPAND_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003281 if (png_ptr->transformations & PNG_EXPAND)
3282 {
3283 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3284 {
3285 if (png_ptr->num_trans)
3286 max_pixel_depth = 32;
3287 else
3288 max_pixel_depth = 24;
3289 }
3290 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3291 {
3292 if (max_pixel_depth < 8)
3293 max_pixel_depth = 8;
3294 if (png_ptr->num_trans)
3295 max_pixel_depth *= 2;
3296 }
3297 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3298 {
3299 if (png_ptr->num_trans)
3300 {
3301 max_pixel_depth *= 4;
3302 max_pixel_depth /= 3;
3303 }
3304 }
3305 }
3306#endif
3307
Patrick Scott5f6bd842010-06-28 16:55:16 -04003308#ifdef PNG_READ_FILLER_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003309 if (png_ptr->transformations & (PNG_FILLER))
3310 {
3311 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3312 max_pixel_depth = 32;
3313 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3314 {
3315 if (max_pixel_depth <= 8)
3316 max_pixel_depth = 16;
3317 else
3318 max_pixel_depth = 32;
3319 }
3320 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3321 {
3322 if (max_pixel_depth <= 32)
3323 max_pixel_depth = 32;
3324 else
3325 max_pixel_depth = 64;
3326 }
3327 }
3328#endif
3329
Patrick Scott5f6bd842010-06-28 16:55:16 -04003330#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003331 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3332 {
3333 if (
Patrick Scott5f6bd842010-06-28 16:55:16 -04003334#ifdef PNG_READ_EXPAND_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003335 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3336#endif
Patrick Scott5f6bd842010-06-28 16:55:16 -04003337#ifdef PNG_READ_FILLER_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003338 (png_ptr->transformations & (PNG_FILLER)) ||
3339#endif
3340 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3341 {
3342 if (max_pixel_depth <= 16)
3343 max_pixel_depth = 32;
3344 else
3345 max_pixel_depth = 64;
3346 }
3347 else
3348 {
3349 if (max_pixel_depth <= 8)
3350 {
3351 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3352 max_pixel_depth = 32;
3353 else
3354 max_pixel_depth = 24;
3355 }
3356 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3357 max_pixel_depth = 64;
3358 else
3359 max_pixel_depth = 48;
3360 }
3361 }
3362#endif
3363
3364#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3365defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003366 if (png_ptr->transformations & PNG_USER_TRANSFORM)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003367 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003368 int user_pixel_depth = png_ptr->user_transform_depth*
The Android Open Source Project893912b2009-03-03 19:30:05 -08003369 png_ptr->user_transform_channels;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003370 if (user_pixel_depth > max_pixel_depth)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003371 max_pixel_depth=user_pixel_depth;
3372 }
3373#endif
3374
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003375 /* Align the width on the next larger 8 pixels. Mainly used
3376 * for interlacing
3377 */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003378 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003379 /* Calculate the maximum bytes needed, adding a byte and a pixel
3380 * for safety's sake
3381 */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003382 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
The Android Open Source Project893912b2009-03-03 19:30:05 -08003383 1 + ((max_pixel_depth + 7) >> 3);
3384#ifdef PNG_MAX_MALLOC_64K
3385 if (row_bytes > (png_uint_32)65536L)
3386 png_error(png_ptr, "This image requires a row greater than 64KB");
3387#endif
3388
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003389 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003390 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003391 png_free(png_ptr, png_ptr->big_row_buf);
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003392 if (png_ptr->interlaced)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003393 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3394 row_bytes + 64);
3395 else
3396 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3397 row_bytes + 64);
3398 png_ptr->old_big_row_buf_size = row_bytes + 64;
3399
3400 /* Use 32 bytes of padding before and after row_buf. */
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003401 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3402 png_ptr->old_big_row_buf_size = row_bytes + 64;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003403 }
3404
3405#ifdef PNG_MAX_MALLOC_64K
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003406 if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003407 png_error(png_ptr, "This image requires a row greater than 64KB");
3408#endif
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003409 if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
The Android Open Source Project893912b2009-03-03 19:30:05 -08003410 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3411
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003412 if (row_bytes + 1 > png_ptr->old_prev_row_size)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003413 {
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003414 png_free(png_ptr, png_ptr->prev_row);
3415 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3416 row_bytes + 1));
3417 png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
3418 png_ptr->old_prev_row_size = row_bytes + 1;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003419 }
3420
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003421 png_ptr->rowbytes = row_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003422
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003423 png_debug1(3, "width = %lu,", png_ptr->width);
3424 png_debug1(3, "height = %lu,", png_ptr->height);
3425 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3426 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
3427 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
Patrick Scott5f6bd842010-06-28 16:55:16 -04003428 png_debug1(3, "irowbytes = %lu",
3429 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08003430
3431 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3432}
3433#endif /* PNG_READ_SUPPORTED */