blob: 77968871e6e9207a7569629c3478a898eb0bd2b2 [file] [log] [blame]
The Android Open Source Project893912b2009-03-03 19:30:05 -08001
2/* pngrutil.c - utilities to read a PNG file
3 *
Patrick Scott5f6bd842010-06-28 16:55:16 -04004 * Last changed in libpng 1.2.44 [June 26, 2010]
5 * Copyright (c) 1998-2010 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
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001832 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
The Android Open Source Project893912b2009-03-03 19:30:05 -08001833 length + 1);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001834 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1835 if (png_ptr->chunkdata == NULL)
1836 {
1837 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001838 png_crc_finish(png_ptr, length);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001839 return;
1840 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001841 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001842 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001843
1844 if (png_crc_finish(png_ptr, 0))
1845 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001846 png_free(png_ptr, png_ptr->chunkdata);
1847 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001848 return;
1849 }
1850
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001851 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001852
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001853 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
The Android Open Source Project893912b2009-03-03 19:30:05 -08001854
1855#ifdef PNG_FLOATING_POINT_SUPPORTED
1856 width = png_strtod(png_ptr, ep, &vp);
1857 if (*vp)
1858 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001859 png_warning(png_ptr, "malformed width string in sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001860 png_free(png_ptr, png_ptr->chunkdata);
1861 png_ptr->chunkdata = NULL;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001862 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001863 }
1864#else
1865#ifdef PNG_FIXED_POINT_SUPPORTED
1866 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1867 if (swidth == NULL)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001868 {
1869 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001870 png_free(png_ptr, png_ptr->chunkdata);
1871 png_ptr->chunkdata = NULL;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001872 return;
1873 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001874 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1875#endif
1876#endif
1877
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001878 for (ep = png_ptr->chunkdata; *ep; ep++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04001879 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001880 ep++;
1881
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001882 if (png_ptr->chunkdata + slength < ep)
The Android Open Source Project893912b2009-03-03 19:30:05 -08001883 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001884 png_warning(png_ptr, "Truncated sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001885#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001886 png_free(png_ptr, swidth);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001887#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001888 png_free(png_ptr, png_ptr->chunkdata);
1889 png_ptr->chunkdata = NULL;
1890 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001891 }
1892
1893#ifdef PNG_FLOATING_POINT_SUPPORTED
1894 height = png_strtod(png_ptr, ep, &vp);
1895 if (*vp)
1896 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001897 png_warning(png_ptr, "malformed height string in sCAL chunk");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001898 png_free(png_ptr, png_ptr->chunkdata);
1899 png_ptr->chunkdata = NULL;
1900#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1901 png_free(png_ptr, swidth);
1902#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001903 return;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001904 }
1905#else
1906#ifdef PNG_FIXED_POINT_SUPPORTED
1907 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1908 if (sheight == NULL)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001909 {
1910 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
Patrick Scott5f6bd842010-06-28 16:55:16 -04001911 png_free(png_ptr, png_ptr->chunkdata);
1912 png_ptr->chunkdata = NULL;
1913#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1914 png_free(png_ptr, swidth);
1915#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001916 return;
1917 }
The Android Open Source Project893912b2009-03-03 19:30:05 -08001918 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1919#endif
1920#endif
1921
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001922 if (png_ptr->chunkdata + slength < ep
The Android Open Source Project893912b2009-03-03 19:30:05 -08001923#ifdef PNG_FLOATING_POINT_SUPPORTED
1924 || width <= 0. || height <= 0.
1925#endif
1926 )
1927 {
1928 png_warning(png_ptr, "Invalid sCAL data");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001929 png_free(png_ptr, png_ptr->chunkdata);
1930 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001931#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1932 png_free(png_ptr, swidth);
1933 png_free(png_ptr, sheight);
1934#endif
1935 return;
1936 }
1937
1938
1939#ifdef PNG_FLOATING_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001940 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001941#else
1942#ifdef PNG_FIXED_POINT_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001943 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
The Android Open Source Project893912b2009-03-03 19:30:05 -08001944#endif
1945#endif
1946
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001947 png_free(png_ptr, png_ptr->chunkdata);
1948 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08001949#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1950 png_free(png_ptr, swidth);
1951 png_free(png_ptr, sheight);
1952#endif
1953}
1954#endif
1955
Patrick Scott5f6bd842010-06-28 16:55:16 -04001956#ifdef PNG_READ_tIME_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08001957void /* PRIVATE */
1958png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1959{
1960 png_byte buf[7];
1961 png_time mod_time;
1962
The Android Open Source Project4215dd12009-03-09 11:52:12 -07001963 png_debug(1, "in png_handle_tIME");
The Android Open Source Project893912b2009-03-03 19:30:05 -08001964
1965 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1966 png_error(png_ptr, "Out of place tIME chunk");
1967 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1968 {
1969 png_warning(png_ptr, "Duplicate tIME chunk");
1970 png_crc_finish(png_ptr, length);
1971 return;
1972 }
1973
1974 if (png_ptr->mode & PNG_HAVE_IDAT)
1975 png_ptr->mode |= PNG_AFTER_IDAT;
1976
1977 if (length != 7)
1978 {
1979 png_warning(png_ptr, "Incorrect tIME chunk length");
1980 png_crc_finish(png_ptr, length);
1981 return;
1982 }
1983
1984 png_crc_read(png_ptr, buf, 7);
1985 if (png_crc_finish(png_ptr, 0))
1986 return;
1987
1988 mod_time.second = buf[6];
1989 mod_time.minute = buf[5];
1990 mod_time.hour = buf[4];
1991 mod_time.day = buf[3];
1992 mod_time.month = buf[2];
1993 mod_time.year = png_get_uint_16(buf);
1994
1995 png_set_tIME(png_ptr, info_ptr, &mod_time);
1996}
1997#endif
1998
Patrick Scott5f6bd842010-06-28 16:55:16 -04001999#ifdef PNG_READ_tEXt_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002000/* Note: this does not properly handle chunks that are > 64K under DOS */
2001void /* PRIVATE */
2002png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2003{
2004 png_textp text_ptr;
2005 png_charp key;
2006 png_charp text;
2007 png_uint_32 skip = 0;
2008 png_size_t slength;
2009 int ret;
2010
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002011 png_debug(1, "in png_handle_tEXt");
2012
Patrick Scott5f6bd842010-06-28 16:55:16 -04002013#ifdef PNG_USER_LIMITS_SUPPORTED
2014 if (png_ptr->user_chunk_cache_max != 0)
2015 {
2016 if (png_ptr->user_chunk_cache_max == 1)
2017 {
2018 png_crc_finish(png_ptr, length);
2019 return;
2020 }
2021 if (--png_ptr->user_chunk_cache_max == 1)
2022 {
2023 png_warning(png_ptr, "No space in chunk cache for tEXt");
2024 png_crc_finish(png_ptr, length);
2025 return;
2026 }
2027 }
2028#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002029
2030 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2031 png_error(png_ptr, "Missing IHDR before tEXt");
2032
2033 if (png_ptr->mode & PNG_HAVE_IDAT)
2034 png_ptr->mode |= PNG_AFTER_IDAT;
2035
2036#ifdef PNG_MAX_MALLOC_64K
2037 if (length > (png_uint_32)65535L)
2038 {
2039 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
2040 skip = length - (png_uint_32)65535L;
2041 length = (png_uint_32)65535L;
2042 }
2043#endif
2044
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002045 png_free(png_ptr, png_ptr->chunkdata);
2046
2047 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2048 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002049 {
2050 png_warning(png_ptr, "No memory to process text chunk.");
2051 return;
2052 }
2053 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002054 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002055
2056 if (png_crc_finish(png_ptr, skip))
2057 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002058 png_free(png_ptr, png_ptr->chunkdata);
2059 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002060 return;
2061 }
2062
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002063 key = png_ptr->chunkdata;
2064
The Android Open Source Project893912b2009-03-03 19:30:05 -08002065 key[slength] = 0x00;
2066
2067 for (text = key; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002068 /* Empty loop to find end of key */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002069
2070 if (text != key + slength)
2071 text++;
2072
2073 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2074 (png_uint_32)png_sizeof(png_text));
2075 if (text_ptr == NULL)
2076 {
2077 png_warning(png_ptr, "Not enough memory to process text chunk.");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002078 png_free(png_ptr, png_ptr->chunkdata);
2079 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002080 return;
2081 }
2082 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2083 text_ptr->key = key;
2084#ifdef PNG_iTXt_SUPPORTED
2085 text_ptr->lang = NULL;
2086 text_ptr->lang_key = NULL;
2087 text_ptr->itxt_length = 0;
2088#endif
2089 text_ptr->text = text;
2090 text_ptr->text_length = png_strlen(text);
2091
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002092 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002093
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002094 png_free(png_ptr, png_ptr->chunkdata);
2095 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002096 png_free(png_ptr, text_ptr);
2097 if (ret)
2098 png_warning(png_ptr, "Insufficient memory to process text chunk.");
2099}
2100#endif
2101
Patrick Scott5f6bd842010-06-28 16:55:16 -04002102#ifdef PNG_READ_zTXt_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002103/* Note: this does not correctly handle chunks that are > 64K under DOS */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002104void /* PRIVATE */
2105png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2106{
2107 png_textp text_ptr;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002108 png_charp text;
2109 int comp_type;
2110 int ret;
2111 png_size_t slength, prefix_len, data_len;
2112
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002113 png_debug(1, "in png_handle_zTXt");
2114
Patrick Scott5f6bd842010-06-28 16:55:16 -04002115#ifdef PNG_USER_LIMITS_SUPPORTED
2116 if (png_ptr->user_chunk_cache_max != 0)
2117 {
2118 if (png_ptr->user_chunk_cache_max == 1)
2119 {
2120 png_crc_finish(png_ptr, length);
2121 return;
2122 }
2123 if (--png_ptr->user_chunk_cache_max == 1)
2124 {
2125 png_warning(png_ptr, "No space in chunk cache for zTXt");
2126 png_crc_finish(png_ptr, length);
2127 return;
2128 }
2129 }
2130#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002131
The Android Open Source Project893912b2009-03-03 19:30:05 -08002132 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2133 png_error(png_ptr, "Missing IHDR before zTXt");
2134
2135 if (png_ptr->mode & PNG_HAVE_IDAT)
2136 png_ptr->mode |= PNG_AFTER_IDAT;
2137
2138#ifdef PNG_MAX_MALLOC_64K
2139 /* We will no doubt have problems with chunks even half this size, but
2140 there is no hard and fast rule to tell us where to stop. */
2141 if (length > (png_uint_32)65535L)
2142 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002143 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002144 png_crc_finish(png_ptr, length);
2145 return;
2146 }
2147#endif
2148
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002149 png_free(png_ptr, png_ptr->chunkdata);
2150 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2151 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002152 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002153 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002154 return;
2155 }
2156 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002157 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002158 if (png_crc_finish(png_ptr, 0))
2159 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002160 png_free(png_ptr, png_ptr->chunkdata);
2161 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002162 return;
2163 }
2164
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002165 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002166
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002167 for (text = png_ptr->chunkdata; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002168 /* Empty loop */ ;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002169
2170 /* zTXt must have some text after the chunkdataword */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002171 if (text >= png_ptr->chunkdata + slength - 2)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002172 {
2173 png_warning(png_ptr, "Truncated zTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002174 png_free(png_ptr, png_ptr->chunkdata);
2175 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002176 return;
2177 }
2178 else
2179 {
2180 comp_type = *(++text);
2181 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2182 {
2183 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2184 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2185 }
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002186 text++; /* Skip the compression_method byte */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002187 }
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002188 prefix_len = text - png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002189
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002190 png_decompress_chunk(png_ptr, comp_type,
2191 (png_size_t)length, prefix_len, &data_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002192
2193 text_ptr = (png_textp)png_malloc_warn(png_ptr,
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002194 (png_uint_32)png_sizeof(png_text));
The Android Open Source Project893912b2009-03-03 19:30:05 -08002195 if (text_ptr == NULL)
2196 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002197 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
2198 png_free(png_ptr, png_ptr->chunkdata);
2199 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002200 return;
2201 }
2202 text_ptr->compression = comp_type;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002203 text_ptr->key = png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002204#ifdef PNG_iTXt_SUPPORTED
2205 text_ptr->lang = NULL;
2206 text_ptr->lang_key = NULL;
2207 text_ptr->itxt_length = 0;
2208#endif
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002209 text_ptr->text = png_ptr->chunkdata + prefix_len;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002210 text_ptr->text_length = data_len;
2211
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002212 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002213
2214 png_free(png_ptr, text_ptr);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002215 png_free(png_ptr, png_ptr->chunkdata);
2216 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002217 if (ret)
2218 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2219}
2220#endif
2221
Patrick Scott5f6bd842010-06-28 16:55:16 -04002222#ifdef PNG_READ_iTXt_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002223/* Note: this does not correctly handle chunks that are > 64K under DOS */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002224void /* PRIVATE */
2225png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2226{
2227 png_textp text_ptr;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002228 png_charp key, lang, text, lang_key;
2229 int comp_flag;
2230 int comp_type = 0;
2231 int ret;
2232 png_size_t slength, prefix_len, data_len;
2233
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002234 png_debug(1, "in png_handle_iTXt");
2235
Patrick Scott5f6bd842010-06-28 16:55:16 -04002236#ifdef PNG_USER_LIMITS_SUPPORTED
2237 if (png_ptr->user_chunk_cache_max != 0)
2238 {
2239 if (png_ptr->user_chunk_cache_max == 1)
2240 {
2241 png_crc_finish(png_ptr, length);
2242 return;
2243 }
2244 if (--png_ptr->user_chunk_cache_max == 1)
2245 {
2246 png_warning(png_ptr, "No space in chunk cache for iTXt");
2247 png_crc_finish(png_ptr, length);
2248 return;
2249 }
2250 }
2251#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002252
2253 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2254 png_error(png_ptr, "Missing IHDR before iTXt");
2255
2256 if (png_ptr->mode & PNG_HAVE_IDAT)
2257 png_ptr->mode |= PNG_AFTER_IDAT;
2258
2259#ifdef PNG_MAX_MALLOC_64K
2260 /* We will no doubt have problems with chunks even half this size, but
2261 there is no hard and fast rule to tell us where to stop. */
2262 if (length > (png_uint_32)65535L)
2263 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002264 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002265 png_crc_finish(png_ptr, length);
2266 return;
2267 }
2268#endif
2269
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002270 png_free(png_ptr, png_ptr->chunkdata);
2271 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2272 if (png_ptr->chunkdata == NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002273 {
2274 png_warning(png_ptr, "No memory to process iTXt chunk.");
2275 return;
2276 }
2277 slength = (png_size_t)length;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002278 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002279 if (png_crc_finish(png_ptr, 0))
2280 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002281 png_free(png_ptr, png_ptr->chunkdata);
2282 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002283 return;
2284 }
2285
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002286 png_ptr->chunkdata[slength] = 0x00;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002287
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002288 for (lang = png_ptr->chunkdata; *lang; lang++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002289 /* Empty loop */ ;
2290 lang++; /* Skip NUL separator */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002291
2292 /* iTXt must have a language tag (possibly empty), two compression bytes,
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002293 * translated keyword (possibly empty), and possibly some text after the
2294 * keyword
2295 */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002296
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002297 if (lang >= png_ptr->chunkdata + slength - 3)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002298 {
2299 png_warning(png_ptr, "Truncated iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002300 png_free(png_ptr, png_ptr->chunkdata);
2301 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002302 return;
2303 }
2304 else
2305 {
2306 comp_flag = *lang++;
2307 comp_type = *lang++;
2308 }
2309
2310 for (lang_key = lang; *lang_key; lang_key++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002311 /* Empty loop */ ;
2312 lang_key++; /* Skip NUL separator */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002313
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002314 if (lang_key >= png_ptr->chunkdata + slength)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002315 {
2316 png_warning(png_ptr, "Truncated iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002317 png_free(png_ptr, png_ptr->chunkdata);
2318 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002319 return;
2320 }
2321
2322 for (text = lang_key; *text; text++)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002323 /* Empty loop */ ;
2324 text++; /* Skip NUL separator */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002325 if (text >= png_ptr->chunkdata + slength)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002326 {
2327 png_warning(png_ptr, "Malformed iTXt chunk");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002328 png_free(png_ptr, png_ptr->chunkdata);
2329 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002330 return;
2331 }
2332
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002333 prefix_len = text - png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002334
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002335 key=png_ptr->chunkdata;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002336 if (comp_flag)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002337 png_decompress_chunk(png_ptr, comp_type,
2338 (size_t)length, prefix_len, &data_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002339 else
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002340 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002341 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2342 (png_uint_32)png_sizeof(png_text));
2343 if (text_ptr == NULL)
2344 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002345 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2346 png_free(png_ptr, png_ptr->chunkdata);
2347 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002348 return;
2349 }
2350 text_ptr->compression = (int)comp_flag + 1;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002351 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2352 text_ptr->lang = png_ptr->chunkdata + (lang - key);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002353 text_ptr->itxt_length = data_len;
2354 text_ptr->text_length = 0;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002355 text_ptr->key = png_ptr->chunkdata;
2356 text_ptr->text = png_ptr->chunkdata + prefix_len;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002357
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002358 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002359
2360 png_free(png_ptr, text_ptr);
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002361 png_free(png_ptr, png_ptr->chunkdata);
2362 png_ptr->chunkdata = NULL;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002363 if (ret)
2364 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2365}
2366#endif
2367
2368/* This function is called when we haven't found a handler for a
2369 chunk. If there isn't a problem with the chunk itself (ie bad
2370 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2371 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2372 case it will be saved away to be written out later. */
2373void /* PRIVATE */
2374png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2375{
2376 png_uint_32 skip = 0;
2377
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002378 png_debug(1, "in png_handle_unknown");
2379
Patrick Scott5f6bd842010-06-28 16:55:16 -04002380#ifdef PNG_USER_LIMITS_SUPPORTED
2381 if (png_ptr->user_chunk_cache_max != 0)
2382 {
2383 if (png_ptr->user_chunk_cache_max == 1)
2384 {
2385 png_crc_finish(png_ptr, length);
2386 return;
2387 }
2388 if (--png_ptr->user_chunk_cache_max == 1)
2389 {
2390 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2391 png_crc_finish(png_ptr, length);
2392 return;
2393 }
2394 }
2395#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002396
2397 if (png_ptr->mode & PNG_HAVE_IDAT)
2398 {
2399#ifdef PNG_USE_LOCAL_ARRAYS
2400 PNG_CONST PNG_IDAT;
2401#endif
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002402 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002403 png_ptr->mode |= PNG_AFTER_IDAT;
2404 }
2405
The Android Open Source Project893912b2009-03-03 19:30:05 -08002406 if (!(png_ptr->chunk_name[0] & 0x20))
2407 {
Patrick Scott5f6bd842010-06-28 16:55:16 -04002408#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002409 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
The Android Open Source Project893912b2009-03-03 19:30:05 -08002410 PNG_HANDLE_CHUNK_ALWAYS
Patrick Scott5f6bd842010-06-28 16:55:16 -04002411#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002412 && png_ptr->read_user_chunk_fn == NULL
2413#endif
2414 )
2415#endif
2416 png_chunk_error(png_ptr, "unknown critical chunk");
2417 }
2418
Patrick Scott5f6bd842010-06-28 16:55:16 -04002419#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002420 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
Patrick Scott5f6bd842010-06-28 16:55:16 -04002421#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002422 || (png_ptr->read_user_chunk_fn != NULL)
2423#endif
2424 )
The Android Open Source Project893912b2009-03-03 19:30:05 -08002425 {
2426#ifdef PNG_MAX_MALLOC_64K
2427 if (length > (png_uint_32)65535L)
2428 {
2429 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2430 skip = length - (png_uint_32)65535L;
2431 length = (png_uint_32)65535L;
2432 }
2433#endif
2434 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002435 (png_charp)png_ptr->chunk_name,
The Android Open Source Project893912b2009-03-03 19:30:05 -08002436 png_sizeof(png_ptr->unknown_chunk.name));
Patrick Scott5f6bd842010-06-28 16:55:16 -04002437 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2438 = '\0';
The Android Open Source Project893912b2009-03-03 19:30:05 -08002439 png_ptr->unknown_chunk.size = (png_size_t)length;
2440 if (length == 0)
2441 png_ptr->unknown_chunk.data = NULL;
2442 else
2443 {
2444 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2445 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2446 }
Patrick Scott5f6bd842010-06-28 16:55:16 -04002447#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002448 if (png_ptr->read_user_chunk_fn != NULL)
The Android Open Source Project893912b2009-03-03 19:30:05 -08002449 {
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002450 /* Callback to user unknown chunk handler */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002451 int ret;
2452 ret = (*(png_ptr->read_user_chunk_fn))
2453 (png_ptr, &png_ptr->unknown_chunk);
2454 if (ret < 0)
2455 png_chunk_error(png_ptr, "error in user chunk");
2456 if (ret == 0)
2457 {
2458 if (!(png_ptr->chunk_name[0] & 0x20))
Patrick Scott5f6bd842010-06-28 16:55:16 -04002459#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002460 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
The Android Open Source Project893912b2009-03-03 19:30:05 -08002461 PNG_HANDLE_CHUNK_ALWAYS)
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002462#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08002463 png_chunk_error(png_ptr, "unknown critical chunk");
2464 png_set_unknown_chunks(png_ptr, info_ptr,
2465 &png_ptr->unknown_chunk, 1);
2466 }
2467 }
2468 else
2469#endif
2470 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2471 png_free(png_ptr, png_ptr->unknown_chunk.data);
2472 png_ptr->unknown_chunk.data = NULL;
2473 }
2474 else
2475#endif
2476 skip = length;
2477
2478 png_crc_finish(png_ptr, skip);
2479
Patrick Scott5f6bd842010-06-28 16:55:16 -04002480#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002481 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002482#endif
2483}
2484
2485/* This function is called to verify that a chunk name is valid.
2486 This function can't have the "critical chunk check" incorporated
2487 into it, since in the future we will need to be able to call user
2488 functions to handle unknown critical chunks after we check that
2489 the chunk name itself is valid. */
2490
2491#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2492
2493void /* PRIVATE */
2494png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2495{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002496 png_debug(1, "in png_check_chunk_name");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002497 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2498 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2499 {
2500 png_chunk_error(png_ptr, "invalid chunk type");
2501 }
2502}
2503
2504/* Combines the row recently read in with the existing pixels in the
2505 row. This routine takes care of alpha and transparency if requested.
2506 This routine also handles the two methods of progressive display
2507 of interlaced images, depending on the mask value.
2508 The mask value describes which pixels are to be combined with
2509 the row. The pattern always repeats every 8 pixels, so just 8
2510 bits are needed. A one indicates the pixel is to be combined,
2511 a zero indicates the pixel is to be skipped. This is in addition
2512 to any alpha or transparency value associated with the pixel. If
2513 you want all pixels to be combined, pass 0xff (255) in mask. */
2514
2515void /* PRIVATE */
2516png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2517{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002518 png_debug(1, "in png_combine_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002519 if (mask == 0xff)
2520 {
2521 png_memcpy(row, png_ptr->row_buf + 1,
2522 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2523 }
2524 else
2525 {
2526 switch (png_ptr->row_info.pixel_depth)
2527 {
2528 case 1:
2529 {
2530 png_bytep sp = png_ptr->row_buf + 1;
2531 png_bytep dp = row;
2532 int s_inc, s_start, s_end;
2533 int m = 0x80;
2534 int shift;
2535 png_uint_32 i;
2536 png_uint_32 row_width = png_ptr->width;
2537
Patrick Scott5f6bd842010-06-28 16:55:16 -04002538#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002539 if (png_ptr->transformations & PNG_PACKSWAP)
2540 {
2541 s_start = 0;
2542 s_end = 7;
2543 s_inc = 1;
2544 }
2545 else
2546#endif
2547 {
2548 s_start = 7;
2549 s_end = 0;
2550 s_inc = -1;
2551 }
2552
2553 shift = s_start;
2554
2555 for (i = 0; i < row_width; i++)
2556 {
2557 if (m & mask)
2558 {
2559 int value;
2560
2561 value = (*sp >> shift) & 0x01;
2562 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2563 *dp |= (png_byte)(value << shift);
2564 }
2565
2566 if (shift == s_end)
2567 {
2568 shift = s_start;
2569 sp++;
2570 dp++;
2571 }
2572 else
2573 shift += s_inc;
2574
2575 if (m == 1)
2576 m = 0x80;
2577 else
2578 m >>= 1;
2579 }
2580 break;
2581 }
2582 case 2:
2583 {
2584 png_bytep sp = png_ptr->row_buf + 1;
2585 png_bytep dp = row;
2586 int s_start, s_end, s_inc;
2587 int m = 0x80;
2588 int shift;
2589 png_uint_32 i;
2590 png_uint_32 row_width = png_ptr->width;
2591 int value;
2592
Patrick Scott5f6bd842010-06-28 16:55:16 -04002593#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002594 if (png_ptr->transformations & PNG_PACKSWAP)
2595 {
2596 s_start = 0;
2597 s_end = 6;
2598 s_inc = 2;
2599 }
2600 else
2601#endif
2602 {
2603 s_start = 6;
2604 s_end = 0;
2605 s_inc = -2;
2606 }
2607
2608 shift = s_start;
2609
2610 for (i = 0; i < row_width; i++)
2611 {
2612 if (m & mask)
2613 {
2614 value = (*sp >> shift) & 0x03;
2615 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2616 *dp |= (png_byte)(value << shift);
2617 }
2618
2619 if (shift == s_end)
2620 {
2621 shift = s_start;
2622 sp++;
2623 dp++;
2624 }
2625 else
2626 shift += s_inc;
2627 if (m == 1)
2628 m = 0x80;
2629 else
2630 m >>= 1;
2631 }
2632 break;
2633 }
2634 case 4:
2635 {
2636 png_bytep sp = png_ptr->row_buf + 1;
2637 png_bytep dp = row;
2638 int s_start, s_end, s_inc;
2639 int m = 0x80;
2640 int shift;
2641 png_uint_32 i;
2642 png_uint_32 row_width = png_ptr->width;
2643 int value;
2644
Patrick Scott5f6bd842010-06-28 16:55:16 -04002645#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002646 if (png_ptr->transformations & PNG_PACKSWAP)
2647 {
2648 s_start = 0;
2649 s_end = 4;
2650 s_inc = 4;
2651 }
2652 else
2653#endif
2654 {
2655 s_start = 4;
2656 s_end = 0;
2657 s_inc = -4;
2658 }
2659 shift = s_start;
2660
2661 for (i = 0; i < row_width; i++)
2662 {
2663 if (m & mask)
2664 {
2665 value = (*sp >> shift) & 0xf;
2666 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2667 *dp |= (png_byte)(value << shift);
2668 }
2669
2670 if (shift == s_end)
2671 {
2672 shift = s_start;
2673 sp++;
2674 dp++;
2675 }
2676 else
2677 shift += s_inc;
2678 if (m == 1)
2679 m = 0x80;
2680 else
2681 m >>= 1;
2682 }
2683 break;
2684 }
2685 default:
2686 {
2687 png_bytep sp = png_ptr->row_buf + 1;
2688 png_bytep dp = row;
2689 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2690 png_uint_32 i;
2691 png_uint_32 row_width = png_ptr->width;
2692 png_byte m = 0x80;
2693
2694
2695 for (i = 0; i < row_width; i++)
2696 {
2697 if (m & mask)
2698 {
2699 png_memcpy(dp, sp, pixel_bytes);
2700 }
2701
2702 sp += pixel_bytes;
2703 dp += pixel_bytes;
2704
2705 if (m == 1)
2706 m = 0x80;
2707 else
2708 m >>= 1;
2709 }
2710 break;
2711 }
2712 }
2713 }
2714}
2715
2716#ifdef PNG_READ_INTERLACING_SUPPORTED
2717/* OLD pre-1.0.9 interface:
2718void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2719 png_uint_32 transformations)
2720 */
2721void /* PRIVATE */
2722png_do_read_interlace(png_structp png_ptr)
2723{
2724 png_row_infop row_info = &(png_ptr->row_info);
2725 png_bytep row = png_ptr->row_buf + 1;
2726 int pass = png_ptr->pass;
2727 png_uint_32 transformations = png_ptr->transformations;
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002728 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2729 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002730 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
The Android Open Source Project893912b2009-03-03 19:30:05 -08002731
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002732 png_debug(1, "in png_do_read_interlace");
The Android Open Source Project893912b2009-03-03 19:30:05 -08002733 if (row != NULL && row_info != NULL)
2734 {
2735 png_uint_32 final_width;
2736
2737 final_width = row_info->width * png_pass_inc[pass];
2738
2739 switch (row_info->pixel_depth)
2740 {
2741 case 1:
2742 {
2743 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2744 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2745 int sshift, dshift;
2746 int s_start, s_end, s_inc;
2747 int jstop = png_pass_inc[pass];
2748 png_byte v;
2749 png_uint_32 i;
2750 int j;
2751
Patrick Scott5f6bd842010-06-28 16:55:16 -04002752#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002753 if (transformations & PNG_PACKSWAP)
2754 {
2755 sshift = (int)((row_info->width + 7) & 0x07);
2756 dshift = (int)((final_width + 7) & 0x07);
2757 s_start = 7;
2758 s_end = 0;
2759 s_inc = -1;
2760 }
2761 else
2762#endif
2763 {
2764 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2765 dshift = 7 - (int)((final_width + 7) & 0x07);
2766 s_start = 0;
2767 s_end = 7;
2768 s_inc = 1;
2769 }
2770
2771 for (i = 0; i < row_info->width; i++)
2772 {
2773 v = (png_byte)((*sp >> sshift) & 0x01);
2774 for (j = 0; j < jstop; j++)
2775 {
2776 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2777 *dp |= (png_byte)(v << dshift);
2778 if (dshift == s_end)
2779 {
2780 dshift = s_start;
2781 dp--;
2782 }
2783 else
2784 dshift += s_inc;
2785 }
2786 if (sshift == s_end)
2787 {
2788 sshift = s_start;
2789 sp--;
2790 }
2791 else
2792 sshift += s_inc;
2793 }
2794 break;
2795 }
2796 case 2:
2797 {
2798 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2799 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2800 int sshift, dshift;
2801 int s_start, s_end, s_inc;
2802 int jstop = png_pass_inc[pass];
2803 png_uint_32 i;
2804
Patrick Scott5f6bd842010-06-28 16:55:16 -04002805#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002806 if (transformations & PNG_PACKSWAP)
2807 {
2808 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2809 dshift = (int)(((final_width + 3) & 0x03) << 1);
2810 s_start = 6;
2811 s_end = 0;
2812 s_inc = -2;
2813 }
2814 else
2815#endif
2816 {
2817 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2818 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2819 s_start = 0;
2820 s_end = 6;
2821 s_inc = 2;
2822 }
2823
2824 for (i = 0; i < row_info->width; i++)
2825 {
2826 png_byte v;
2827 int j;
2828
2829 v = (png_byte)((*sp >> sshift) & 0x03);
2830 for (j = 0; j < jstop; j++)
2831 {
2832 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2833 *dp |= (png_byte)(v << dshift);
2834 if (dshift == s_end)
2835 {
2836 dshift = s_start;
2837 dp--;
2838 }
2839 else
2840 dshift += s_inc;
2841 }
2842 if (sshift == s_end)
2843 {
2844 sshift = s_start;
2845 sp--;
2846 }
2847 else
2848 sshift += s_inc;
2849 }
2850 break;
2851 }
2852 case 4:
2853 {
2854 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2855 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2856 int sshift, dshift;
2857 int s_start, s_end, s_inc;
2858 png_uint_32 i;
2859 int jstop = png_pass_inc[pass];
2860
Patrick Scott5f6bd842010-06-28 16:55:16 -04002861#ifdef PNG_READ_PACKSWAP_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08002862 if (transformations & PNG_PACKSWAP)
2863 {
2864 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2865 dshift = (int)(((final_width + 1) & 0x01) << 2);
2866 s_start = 4;
2867 s_end = 0;
2868 s_inc = -4;
2869 }
2870 else
2871#endif
2872 {
2873 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2874 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2875 s_start = 0;
2876 s_end = 4;
2877 s_inc = 4;
2878 }
2879
2880 for (i = 0; i < row_info->width; i++)
2881 {
2882 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2883 int j;
2884
2885 for (j = 0; j < jstop; j++)
2886 {
2887 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2888 *dp |= (png_byte)(v << dshift);
2889 if (dshift == s_end)
2890 {
2891 dshift = s_start;
2892 dp--;
2893 }
2894 else
2895 dshift += s_inc;
2896 }
2897 if (sshift == s_end)
2898 {
2899 sshift = s_start;
2900 sp--;
2901 }
2902 else
2903 sshift += s_inc;
2904 }
2905 break;
2906 }
2907 default:
2908 {
2909 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
Patrick Scott5f6bd842010-06-28 16:55:16 -04002910 png_bytep sp = row + (png_size_t)(row_info->width - 1)
2911 * pixel_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08002912 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2913
2914 int jstop = png_pass_inc[pass];
2915 png_uint_32 i;
2916
2917 for (i = 0; i < row_info->width; i++)
2918 {
2919 png_byte v[8];
2920 int j;
2921
2922 png_memcpy(v, sp, pixel_bytes);
2923 for (j = 0; j < jstop; j++)
2924 {
2925 png_memcpy(dp, v, pixel_bytes);
2926 dp -= pixel_bytes;
2927 }
2928 sp -= pixel_bytes;
2929 }
2930 break;
2931 }
2932 }
2933 row_info->width = final_width;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002934 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002935 }
Patrick Scott5f6bd842010-06-28 16:55:16 -04002936#ifndef PNG_READ_PACKSWAP_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04002937 transformations = transformations; /* Silence compiler warning */
The Android Open Source Project893912b2009-03-03 19:30:05 -08002938#endif
2939}
2940#endif /* PNG_READ_INTERLACING_SUPPORTED */
2941
2942void /* PRIVATE */
2943png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2944 png_bytep prev_row, int filter)
2945{
The Android Open Source Project4215dd12009-03-09 11:52:12 -07002946 png_debug(1, "in png_read_filter_row");
2947 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
The Android Open Source Project893912b2009-03-03 19:30:05 -08002948 switch (filter)
2949 {
2950 case PNG_FILTER_VALUE_NONE:
2951 break;
2952 case PNG_FILTER_VALUE_SUB:
2953 {
2954 png_uint_32 i;
2955 png_uint_32 istop = row_info->rowbytes;
2956 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2957 png_bytep rp = row + bpp;
2958 png_bytep lp = row;
2959
2960 for (i = bpp; i < istop; i++)
2961 {
2962 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2963 rp++;
2964 }
2965 break;
2966 }
2967 case PNG_FILTER_VALUE_UP:
2968 {
2969 png_uint_32 i;
2970 png_uint_32 istop = row_info->rowbytes;
2971 png_bytep rp = row;
2972 png_bytep pp = prev_row;
2973
2974 for (i = 0; i < istop; i++)
2975 {
2976 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2977 rp++;
2978 }
2979 break;
2980 }
2981 case PNG_FILTER_VALUE_AVG:
2982 {
2983 png_uint_32 i;
2984 png_bytep rp = row;
2985 png_bytep pp = prev_row;
2986 png_bytep lp = row;
2987 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2988 png_uint_32 istop = row_info->rowbytes - bpp;
2989
2990 for (i = 0; i < bpp; i++)
2991 {
2992 *rp = (png_byte)(((int)(*rp) +
2993 ((int)(*pp++) / 2 )) & 0xff);
2994 rp++;
2995 }
2996
2997 for (i = 0; i < istop; i++)
2998 {
2999 *rp = (png_byte)(((int)(*rp) +
3000 (int)(*pp++ + *lp++) / 2 ) & 0xff);
3001 rp++;
3002 }
3003 break;
3004 }
3005 case PNG_FILTER_VALUE_PAETH:
3006 {
3007 png_uint_32 i;
3008 png_bytep rp = row;
3009 png_bytep pp = prev_row;
3010 png_bytep lp = row;
3011 png_bytep cp = prev_row;
3012 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3013 png_uint_32 istop=row_info->rowbytes - bpp;
3014
3015 for (i = 0; i < bpp; i++)
3016 {
3017 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3018 rp++;
3019 }
3020
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003021 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003022 {
3023 int a, b, c, pa, pb, pc, p;
3024
3025 a = *lp++;
3026 b = *pp++;
3027 c = *cp++;
3028
3029 p = b - c;
3030 pc = a - c;
3031
3032#ifdef PNG_USE_ABS
3033 pa = abs(p);
3034 pb = abs(pc);
3035 pc = abs(p + pc);
3036#else
3037 pa = p < 0 ? -p : p;
3038 pb = pc < 0 ? -pc : pc;
3039 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3040#endif
3041
3042 /*
3043 if (pa <= pb && pa <= pc)
3044 p = a;
3045 else if (pb <= pc)
3046 p = b;
3047 else
3048 p = c;
3049 */
3050
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003051 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003052
3053 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3054 rp++;
3055 }
3056 break;
3057 }
3058 default:
3059 png_warning(png_ptr, "Ignoring bad adaptive filter type");
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003060 *row = 0;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003061 break;
3062 }
3063}
3064
Joseph Wen4ce0ee12010-08-20 10:42:22 +08003065#ifdef PNG_INDEX_SUPPORTED
3066void /* PRIVATE */
3067png_set_interlaced_pass(png_structp png_ptr, int pass)
3068{
3069 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3070
3071 /* Start of interlace block */
3072 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3073
3074 /* Offset to next interlace block */
3075 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3076
3077 /* Start of interlace block in the y direction */
3078 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3079
3080 /* Offset to next interlace block in the y direction */
3081 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3082
3083 png_ptr->pass = pass;
3084 png_ptr->iwidth = (png_ptr->width +
3085 png_pass_inc[png_ptr->pass] - 1 -
3086 png_pass_start[png_ptr->pass]) /
3087 png_pass_inc[png_ptr->pass];
3088}
3089#endif
3090
Patrick Scott5f6bd842010-06-28 16:55:16 -04003091#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003092void /* PRIVATE */
3093png_read_finish_row(png_structp png_ptr)
3094{
The Android Open Source Project893912b2009-03-03 19:30:05 -08003095#ifdef PNG_READ_INTERLACING_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003096 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003097
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003098 /* Start of interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003099 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3100
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003101 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003102 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3103
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003104 /* Start of interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003105 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3106
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003107 /* Offset to next interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003108 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3109#endif /* PNG_READ_INTERLACING_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003110
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003111 png_debug(1, "in png_read_finish_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003112 png_ptr->row_number++;
3113 if (png_ptr->row_number < png_ptr->num_rows)
3114 return;
3115
3116#ifdef PNG_READ_INTERLACING_SUPPORTED
3117 if (png_ptr->interlaced)
3118 {
3119 png_ptr->row_number = 0;
3120 png_memset_check(png_ptr, png_ptr->prev_row, 0,
3121 png_ptr->rowbytes + 1);
3122 do
3123 {
3124 png_ptr->pass++;
3125 if (png_ptr->pass >= 7)
3126 break;
3127 png_ptr->iwidth = (png_ptr->width +
3128 png_pass_inc[png_ptr->pass] - 1 -
3129 png_pass_start[png_ptr->pass]) /
3130 png_pass_inc[png_ptr->pass];
3131
The Android Open Source Project893912b2009-03-03 19:30:05 -08003132 if (!(png_ptr->transformations & PNG_INTERLACE))
3133 {
3134 png_ptr->num_rows = (png_ptr->height +
3135 png_pass_yinc[png_ptr->pass] - 1 -
3136 png_pass_ystart[png_ptr->pass]) /
3137 png_pass_yinc[png_ptr->pass];
3138 if (!(png_ptr->num_rows))
3139 continue;
3140 }
3141 else /* if (png_ptr->transformations & PNG_INTERLACE) */
3142 break;
3143 } while (png_ptr->iwidth == 0);
3144
3145 if (png_ptr->pass < 7)
3146 return;
3147 }
3148#endif /* PNG_READ_INTERLACING_SUPPORTED */
3149
3150 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
3151 {
3152#ifdef PNG_USE_LOCAL_ARRAYS
3153 PNG_CONST PNG_IDAT;
3154#endif
3155 char extra;
3156 int ret;
3157
3158 png_ptr->zstream.next_out = (Byte *)&extra;
3159 png_ptr->zstream.avail_out = (uInt)1;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003160 for (;;)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003161 {
3162 if (!(png_ptr->zstream.avail_in))
3163 {
3164 while (!png_ptr->idat_size)
3165 {
3166 png_byte chunk_length[4];
3167
3168 png_crc_finish(png_ptr, 0);
3169
3170 png_read_data(png_ptr, chunk_length, 4);
3171 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
3172 png_reset_crc(png_ptr);
3173 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
3174 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
3175 png_error(png_ptr, "Not enough image data");
3176
3177 }
3178 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3179 png_ptr->zstream.next_in = png_ptr->zbuf;
3180 if (png_ptr->zbuf_size > png_ptr->idat_size)
3181 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3182 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3183 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3184 }
3185 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3186 if (ret == Z_STREAM_END)
3187 {
3188 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3189 png_ptr->idat_size)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003190 png_warning(png_ptr, "Extra compressed data.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003191 png_ptr->mode |= PNG_AFTER_IDAT;
3192 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3193 break;
3194 }
3195 if (ret != Z_OK)
3196 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3197 "Decompression Error");
3198
3199 if (!(png_ptr->zstream.avail_out))
3200 {
3201 png_warning(png_ptr, "Extra compressed data.");
3202 png_ptr->mode |= PNG_AFTER_IDAT;
3203 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3204 break;
3205 }
3206
3207 }
3208 png_ptr->zstream.avail_out = 0;
3209 }
3210
3211 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003212 png_warning(png_ptr, "Extra compression data.");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003213
3214 inflateReset(&png_ptr->zstream);
3215
3216 png_ptr->mode |= PNG_AFTER_IDAT;
3217}
Patrick Scott5f6bd842010-06-28 16:55:16 -04003218#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003219
3220void /* PRIVATE */
3221png_read_start_row(png_structp png_ptr)
3222{
The Android Open Source Project893912b2009-03-03 19:30:05 -08003223#ifdef PNG_READ_INTERLACING_SUPPORTED
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003224 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003225
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003226 /* Start of interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003227 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3228
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003229 /* Offset to next interlace block */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003230 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3231
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003232 /* Start of interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003233 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3234
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003235 /* Offset to next interlace block in the y direction */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003236 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3237#endif
The Android Open Source Project893912b2009-03-03 19:30:05 -08003238
3239 int max_pixel_depth;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003240 png_size_t row_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003241
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003242 png_debug(1, "in png_read_start_row");
The Android Open Source Project893912b2009-03-03 19:30:05 -08003243 png_ptr->zstream.avail_in = 0;
3244 png_init_read_transformations(png_ptr);
3245#ifdef PNG_READ_INTERLACING_SUPPORTED
3246 if (png_ptr->interlaced)
3247 {
3248 if (!(png_ptr->transformations & PNG_INTERLACE))
3249 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3250 png_pass_ystart[0]) / png_pass_yinc[0];
3251 else
3252 png_ptr->num_rows = png_ptr->height;
3253
3254 png_ptr->iwidth = (png_ptr->width +
3255 png_pass_inc[png_ptr->pass] - 1 -
3256 png_pass_start[png_ptr->pass]) /
3257 png_pass_inc[png_ptr->pass];
The Android Open Source Project893912b2009-03-03 19:30:05 -08003258 }
3259 else
3260#endif /* PNG_READ_INTERLACING_SUPPORTED */
3261 {
3262 png_ptr->num_rows = png_ptr->height;
3263 png_ptr->iwidth = png_ptr->width;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003264 }
3265 max_pixel_depth = png_ptr->pixel_depth;
3266
Patrick Scott5f6bd842010-06-28 16:55:16 -04003267#ifdef PNG_READ_PACK_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003268 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3269 max_pixel_depth = 8;
3270#endif
3271
Patrick Scott5f6bd842010-06-28 16:55:16 -04003272#ifdef PNG_READ_EXPAND_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003273 if (png_ptr->transformations & PNG_EXPAND)
3274 {
3275 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3276 {
3277 if (png_ptr->num_trans)
3278 max_pixel_depth = 32;
3279 else
3280 max_pixel_depth = 24;
3281 }
3282 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3283 {
3284 if (max_pixel_depth < 8)
3285 max_pixel_depth = 8;
3286 if (png_ptr->num_trans)
3287 max_pixel_depth *= 2;
3288 }
3289 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3290 {
3291 if (png_ptr->num_trans)
3292 {
3293 max_pixel_depth *= 4;
3294 max_pixel_depth /= 3;
3295 }
3296 }
3297 }
3298#endif
3299
Patrick Scott5f6bd842010-06-28 16:55:16 -04003300#ifdef PNG_READ_FILLER_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003301 if (png_ptr->transformations & (PNG_FILLER))
3302 {
3303 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3304 max_pixel_depth = 32;
3305 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3306 {
3307 if (max_pixel_depth <= 8)
3308 max_pixel_depth = 16;
3309 else
3310 max_pixel_depth = 32;
3311 }
3312 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3313 {
3314 if (max_pixel_depth <= 32)
3315 max_pixel_depth = 32;
3316 else
3317 max_pixel_depth = 64;
3318 }
3319 }
3320#endif
3321
Patrick Scott5f6bd842010-06-28 16:55:16 -04003322#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003323 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3324 {
3325 if (
Patrick Scott5f6bd842010-06-28 16:55:16 -04003326#ifdef PNG_READ_EXPAND_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003327 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3328#endif
Patrick Scott5f6bd842010-06-28 16:55:16 -04003329#ifdef PNG_READ_FILLER_SUPPORTED
The Android Open Source Project893912b2009-03-03 19:30:05 -08003330 (png_ptr->transformations & (PNG_FILLER)) ||
3331#endif
3332 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3333 {
3334 if (max_pixel_depth <= 16)
3335 max_pixel_depth = 32;
3336 else
3337 max_pixel_depth = 64;
3338 }
3339 else
3340 {
3341 if (max_pixel_depth <= 8)
3342 {
3343 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3344 max_pixel_depth = 32;
3345 else
3346 max_pixel_depth = 24;
3347 }
3348 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3349 max_pixel_depth = 64;
3350 else
3351 max_pixel_depth = 48;
3352 }
3353 }
3354#endif
3355
3356#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3357defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003358 if (png_ptr->transformations & PNG_USER_TRANSFORM)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003359 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003360 int user_pixel_depth = png_ptr->user_transform_depth*
The Android Open Source Project893912b2009-03-03 19:30:05 -08003361 png_ptr->user_transform_channels;
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003362 if (user_pixel_depth > max_pixel_depth)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003363 max_pixel_depth=user_pixel_depth;
3364 }
3365#endif
3366
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003367 /* Align the width on the next larger 8 pixels. Mainly used
3368 * for interlacing
3369 */
The Android Open Source Project893912b2009-03-03 19:30:05 -08003370 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003371 /* Calculate the maximum bytes needed, adding a byte and a pixel
3372 * for safety's sake
3373 */
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003374 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
The Android Open Source Project893912b2009-03-03 19:30:05 -08003375 1 + ((max_pixel_depth + 7) >> 3);
3376#ifdef PNG_MAX_MALLOC_64K
3377 if (row_bytes > (png_uint_32)65536L)
3378 png_error(png_ptr, "This image requires a row greater than 64KB");
3379#endif
3380
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003381 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003382 {
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003383 png_free(png_ptr, png_ptr->big_row_buf);
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003384 if (png_ptr->interlaced)
Patrick Scott5f6bd842010-06-28 16:55:16 -04003385 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3386 row_bytes + 64);
3387 else
3388 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3389 row_bytes + 64);
3390 png_ptr->old_big_row_buf_size = row_bytes + 64;
3391
3392 /* Use 32 bytes of padding before and after row_buf. */
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003393 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3394 png_ptr->old_big_row_buf_size = row_bytes + 64;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003395 }
3396
3397#ifdef PNG_MAX_MALLOC_64K
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003398 if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003399 png_error(png_ptr, "This image requires a row greater than 64KB");
3400#endif
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003401 if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
The Android Open Source Project893912b2009-03-03 19:30:05 -08003402 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3403
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003404 if (row_bytes + 1 > png_ptr->old_prev_row_size)
The Android Open Source Project893912b2009-03-03 19:30:05 -08003405 {
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003406 png_free(png_ptr, png_ptr->prev_row);
3407 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3408 row_bytes + 1));
3409 png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
3410 png_ptr->old_prev_row_size = row_bytes + 1;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003411 }
3412
Patrick Scotta0bb96c2009-07-22 11:50:02 -04003413 png_ptr->rowbytes = row_bytes;
The Android Open Source Project893912b2009-03-03 19:30:05 -08003414
The Android Open Source Project4215dd12009-03-09 11:52:12 -07003415 png_debug1(3, "width = %lu,", png_ptr->width);
3416 png_debug1(3, "height = %lu,", png_ptr->height);
3417 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3418 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
3419 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
Patrick Scott5f6bd842010-06-28 16:55:16 -04003420 png_debug1(3, "irowbytes = %lu",
3421 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
The Android Open Source Project893912b2009-03-03 19:30:05 -08003422
3423 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3424}
3425#endif /* PNG_READ_SUPPORTED */