|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 00002 /* pngrutil.c - utilities to read a PNG file 00003 * 00004 * Last changed in libpng 1.2.38 [July 16, 2009] 00005 * Copyright (c) 1998-2009 Glenn Randers-Pehrson 00006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 00007 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 00008 * 00009 * This code is released under the libpng license. 00010 * For conditions of distribution and use, see the disclaimer 00011 * and license in png.h 00012 * 00013 * This file contains routines that are only called from within 00014 * libpng itself during the course of reading an image. 00015 */ 00016 00017 #define PNG_INTERNAL 00018 #include "png.h" 00019 #if defined(PNG_READ_SUPPORTED) 00020 00021 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) 00022 # define WIN32_WCE_OLD 00023 #endif 00024 00025 #ifdef PNG_FLOATING_POINT_SUPPORTED 00026 # if defined(WIN32_WCE_OLD) 00027 /* The strtod() function is not supported on WindowsCE */ 00028 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) 00029 { 00030 double result = 0; 00031 int len; 00032 wchar_t *str, *end; 00033 00034 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); 00035 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t)); 00036 if ( NULL != str ) 00037 { 00038 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); 00039 result = wcstod(str, &end); 00040 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); 00041 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); 00042 png_free(png_ptr, str); 00043 } 00044 return result; 00045 } 00046 # else 00047 # define png_strtod(p,a,b) strtod(a,b) 00048 # endif 00049 #endif 00050 00051 png_uint_32 PNGAPI 00052 png_get_uint_31(png_structp png_ptr, png_bytep buf) 00053 { 00054 #ifdef PNG_READ_BIG_ENDIAN_SUPPORTED 00055 png_uint_32 i = png_get_uint_32(buf); 00056 #else 00057 /* Avoid an extra function call by inlining the result. */ 00058 png_uint_32 i = ((png_uint_32)(*buf) << 24) + 00059 ((png_uint_32)(*(buf + 1)) << 16) + 00060 ((png_uint_32)(*(buf + 2)) << 8) + 00061 (png_uint_32)(*(buf + 3)); 00062 #endif 00063 if (i > PNG_UINT_31_MAX) 00064 png_error(png_ptr, "PNG unsigned integer out of range."); 00065 return (i); 00066 } 00067 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED 00068 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ 00069 png_uint_32 PNGAPI 00070 png_get_uint_32(png_bytep buf) 00071 { 00072 png_uint_32 i = ((png_uint_32)(*buf) << 24) + 00073 ((png_uint_32)(*(buf + 1)) << 16) + 00074 ((png_uint_32)(*(buf + 2)) << 8) + 00075 (png_uint_32)(*(buf + 3)); 00076 00077 return (i); 00078 } 00079 00080 /* Grab a signed 32-bit integer from a buffer in big-endian format. The 00081 * data is stored in the PNG file in two's complement format, and it is 00082 * assumed that the machine format for signed integers is the same. 00083 */ 00084 png_int_32 PNGAPI 00085 png_get_int_32(png_bytep buf) 00086 { 00087 png_int_32 i = ((png_int_32)(*buf) << 24) + 00088 ((png_int_32)(*(buf + 1)) << 16) + 00089 ((png_int_32)(*(buf + 2)) << 8) + 00090 (png_int_32)(*(buf + 3)); 00091 00092 return (i); 00093 } 00094 00095 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ 00096 png_uint_16 PNGAPI 00097 png_get_uint_16(png_bytep buf) 00098 { 00099 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + 00100 (png_uint_16)(*(buf + 1))); 00101 00102 return (i); 00103 } 00104 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ 00105 00106 /* Read the chunk header (length + type name). 00107 * Put the type name into png_ptr->chunk_name, and return the length. 00108 */ 00109 png_uint_32 /* PRIVATE */ 00110 png_read_chunk_header(png_structp png_ptr) 00111 { 00112 png_byte buf[8]; 00113 png_uint_32 length; 00114 00115 /* Read the length and the chunk name */ 00116 png_read_data(png_ptr, buf, 8); 00117 length = png_get_uint_31(png_ptr, buf); 00118 00119 /* Put the chunk name into png_ptr->chunk_name */ 00120 png_memcpy(png_ptr->chunk_name, buf + 4, 4); 00121 00122 png_debug2(0, "Reading %s chunk, length = %lu", 00123 png_ptr->chunk_name, length); 00124 00125 /* Reset the crc and run it over the chunk name */ 00126 png_reset_crc(png_ptr); 00127 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); 00128 00129 /* Check to see if chunk name is valid */ 00130 png_check_chunk_name(png_ptr, png_ptr->chunk_name); 00131 00132 return length; 00133 } 00134 00135 /* Read data, and (optionally) run it through the CRC. */ 00136 void /* PRIVATE */ 00137 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) 00138 { 00139 if (png_ptr == NULL) 00140 return; 00141 png_read_data(png_ptr, buf, length); 00142 png_calculate_crc(png_ptr, buf, length); 00143 } 00144 00145 /* Optionally skip data and then check the CRC. Depending on whether we 00146 * are reading a ancillary or critical chunk, and how the program has set 00147 * things up, we may calculate the CRC on the data and print a message. 00148 * Returns '1' if there was a CRC error, '0' otherwise. 00149 */ 00150 int /* PRIVATE */ 00151 png_crc_finish(png_structp png_ptr, png_uint_32 skip) 00152 { 00153 png_size_t i; 00154 png_size_t istop = png_ptr->zbuf_size; 00155 00156 for (i = (png_size_t)skip; i > istop; i -= istop) 00157 { 00158 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); 00159 } 00160 if (i) 00161 { 00162 png_crc_read(png_ptr, png_ptr->zbuf, i); 00163 } 00164 00165 if (png_crc_error(png_ptr)) 00166 { 00167 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ 00168 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || 00169 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ 00170 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) 00171 { 00172 png_chunk_warning(png_ptr, "CRC error"); 00173 } 00174 else 00175 { 00176 png_chunk_error(png_ptr, "CRC error"); 00177 } 00178 return (1); 00179 } 00180 00181 return (0); 00182 } 00183 00184 /* Compare the CRC stored in the PNG file with that calculated by libpng from 00185 * the data it has read thus far. 00186 */ 00187 int /* PRIVATE */ 00188 png_crc_error(png_structp png_ptr) 00189 { 00190 png_byte crc_bytes[4]; 00191 png_uint_32 crc; 00192 int need_crc = 1; 00193 00194 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ 00195 { 00196 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == 00197 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) 00198 need_crc = 0; 00199 } 00200 else /* critical */ 00201 { 00202 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) 00203 need_crc = 0; 00204 } 00205 00206 png_read_data(png_ptr, crc_bytes, 4); 00207 00208 if (need_crc) 00209 { 00210 crc = png_get_uint_32(crc_bytes); 00211 return ((int)(crc != png_ptr->crc)); 00212 } 00213 else 00214 return (0); 00215 } 00216 00217 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ 00218 defined(PNG_READ_iCCP_SUPPORTED) 00219 /* 00220 * Decompress trailing data in a chunk. The assumption is that chunkdata 00221 * points at an allocated area holding the contents of a chunk with a 00222 * trailing compressed part. What we get back is an allocated area 00223 * holding the original prefix part and an uncompressed version of the 00224 * trailing part (the malloc area passed in is freed). 00225 */ 00226 void /* PRIVATE */ 00227 png_decompress_chunk(png_structp png_ptr, int comp_type, 00228 png_size_t chunklength, 00229 png_size_t prefix_size, png_size_t *newlength) 00230 { 00231 static PNG_CONST char msg[] = "Error decoding compressed text"; 00232 png_charp text; 00233 png_size_t text_size; 00234 00235 if (comp_type == PNG_COMPRESSION_TYPE_BASE) 00236 { 00237 int ret = Z_OK; 00238 png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size); 00239 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); 00240 png_ptr->zstream.next_out = png_ptr->zbuf; 00241 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 00242 00243 text_size = 0; 00244 text = NULL; 00245 00246 while (png_ptr->zstream.avail_in) 00247 { 00248 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); 00249 if (ret != Z_OK && ret != Z_STREAM_END) 00250 { 00251 if (png_ptr->zstream.msg != NULL) 00252 png_warning(png_ptr, png_ptr->zstream.msg); 00253 else 00254 png_warning(png_ptr, msg); 00255 inflateReset(&png_ptr->zstream); 00256 png_ptr->zstream.avail_in = 0; 00257 00258 if (text == NULL) 00259 { 00260 text_size = prefix_size + png_sizeof(msg) + 1; 00261 text = (png_charp)png_malloc_warn(png_ptr, text_size); 00262 if (text == NULL) 00263 { 00264 png_free(png_ptr, png_ptr->chunkdata); 00265 png_ptr->chunkdata = NULL; 00266 png_error(png_ptr, "Not enough memory to decompress chunk"); 00267 } 00268 png_memcpy(text, png_ptr->chunkdata, prefix_size); 00269 } 00270 00271 text[text_size - 1] = 0x00; 00272 00273 /* Copy what we can of the error message into the text chunk */ 00274 text_size = (png_size_t)(chunklength - 00275 (text - png_ptr->chunkdata) - 1); 00276 if (text_size > png_sizeof(msg)) 00277 text_size = png_sizeof(msg); 00278 png_memcpy(text + prefix_size, msg, text_size); 00279 break; 00280 } 00281 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) 00282 { 00283 if (text == NULL) 00284 { 00285 text_size = prefix_size + 00286 png_ptr->zbuf_size - png_ptr->zstream.avail_out; 00287 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); 00288 if (text == NULL) 00289 { 00290 png_free(png_ptr, png_ptr->chunkdata); 00291 png_ptr->chunkdata = NULL; 00292 png_error(png_ptr, 00293 "Not enough memory to decompress chunk."); 00294 } 00295 png_memcpy(text + prefix_size, png_ptr->zbuf, 00296 text_size - prefix_size); 00297 png_memcpy(text, png_ptr->chunkdata, prefix_size); 00298 *(text + text_size) = 0x00; 00299 } 00300 else 00301 { 00302 png_charp tmp; 00303 00304 tmp = text; 00305 text = (png_charp)png_malloc_warn(png_ptr, 00306 (png_uint_32)(text_size + 00307 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); 00308 if (text == NULL) 00309 { 00310 png_free(png_ptr, tmp); 00311 png_free(png_ptr, png_ptr->chunkdata); 00312 png_ptr->chunkdata = NULL; 00313 png_error(png_ptr, 00314 "Not enough memory to decompress chunk.."); 00315 } 00316 png_memcpy(text, tmp, text_size); 00317 png_free(png_ptr, tmp); 00318 png_memcpy(text + text_size, png_ptr->zbuf, 00319 (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); 00320 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; 00321 *(text + text_size) = 0x00; 00322 } 00323 if (ret == Z_STREAM_END) 00324 break; 00325 else 00326 { 00327 png_ptr->zstream.next_out = png_ptr->zbuf; 00328 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 00329 } 00330 } 00331 } 00332 if (ret != Z_STREAM_END) 00333 { 00334 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) 00335 char umsg[52]; 00336 00337 if (ret == Z_BUF_ERROR) 00338 png_snprintf(umsg, 52, 00339 "Buffer error in compressed datastream in %s chunk", 00340 png_ptr->chunk_name); 00341 00342 else if (ret == Z_DATA_ERROR) 00343 png_snprintf(umsg, 52, 00344 "Data error in compressed datastream in %s chunk", 00345 png_ptr->chunk_name); 00346 00347 else 00348 png_snprintf(umsg, 52, 00349 "Incomplete compressed datastream in %s chunk", 00350 png_ptr->chunk_name); 00351 00352 png_warning(png_ptr, umsg); 00353 #else 00354 png_warning(png_ptr, 00355 "Incomplete compressed datastream in chunk other than IDAT"); 00356 #endif 00357 text_size = prefix_size; 00358 if (text == NULL) 00359 { 00360 text = (png_charp)png_malloc_warn(png_ptr, text_size+1); 00361 if (text == NULL) 00362 { 00363 png_free(png_ptr, png_ptr->chunkdata); 00364 png_ptr->chunkdata = NULL; 00365 png_error(png_ptr, "Not enough memory for text."); 00366 } 00367 png_memcpy(text, png_ptr->chunkdata, prefix_size); 00368 } 00369 *(text + text_size) = 0x00; 00370 } 00371 00372 inflateReset(&png_ptr->zstream); 00373 png_ptr->zstream.avail_in = 0; 00374 00375 png_free(png_ptr, png_ptr->chunkdata); 00376 png_ptr->chunkdata = text; 00377 *newlength=text_size; 00378 } 00379 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ 00380 { 00381 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) 00382 char umsg[50]; 00383 00384 png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type); 00385 png_warning(png_ptr, umsg); 00386 #else 00387 png_warning(png_ptr, "Unknown zTXt compression type"); 00388 #endif 00389 00390 *(png_ptr->chunkdata + prefix_size) = 0x00; 00391 *newlength = prefix_size; 00392 } 00393 } 00394 #endif 00395 00396 /* Read and check the IDHR chunk */ 00397 void /* PRIVATE */ 00398 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00399 { 00400 png_byte buf[13]; 00401 png_uint_32 width, height; 00402 int bit_depth, color_type, compression_type, filter_type; 00403 int interlace_type; 00404 00405 png_debug(1, "in png_handle_IHDR"); 00406 00407 if (png_ptr->mode & PNG_HAVE_IHDR) 00408 png_error(png_ptr, "Out of place IHDR"); 00409 00410 /* Check the length */ 00411 if (length != 13) 00412 png_error(png_ptr, "Invalid IHDR chunk"); 00413 00414 png_ptr->mode |= PNG_HAVE_IHDR; 00415 00416 png_crc_read(png_ptr, buf, 13); 00417 png_crc_finish(png_ptr, 0); 00418 00419 width = png_get_uint_31(png_ptr, buf); 00420 height = png_get_uint_31(png_ptr, buf + 4); 00421 bit_depth = buf[8]; 00422 color_type = buf[9]; 00423 compression_type = buf[10]; 00424 filter_type = buf[11]; 00425 interlace_type = buf[12]; 00426 00427 /* Set internal variables */ 00428 png_ptr->width = width; 00429 png_ptr->height = height; 00430 png_ptr->bit_depth = (png_byte)bit_depth; 00431 png_ptr->interlaced = (png_byte)interlace_type; 00432 png_ptr->color_type = (png_byte)color_type; 00433 #if defined(PNG_MNG_FEATURES_SUPPORTED) 00434 png_ptr->filter_type = (png_byte)filter_type; 00435 #endif 00436 png_ptr->compression_type = (png_byte)compression_type; 00437 00438 /* Find number of channels */ 00439 switch (png_ptr->color_type) 00440 { 00441 case PNG_COLOR_TYPE_GRAY: 00442 case PNG_COLOR_TYPE_PALETTE: 00443 png_ptr->channels = 1; 00444 break; 00445 00446 case PNG_COLOR_TYPE_RGB: 00447 png_ptr->channels = 3; 00448 break; 00449 00450 case PNG_COLOR_TYPE_GRAY_ALPHA: 00451 png_ptr->channels = 2; 00452 break; 00453 00454 case PNG_COLOR_TYPE_RGB_ALPHA: 00455 png_ptr->channels = 4; 00456 break; 00457 } 00458 00459 /* Set up other useful info */ 00460 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * 00461 png_ptr->channels); 00462 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); 00463 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); 00464 png_debug1(3, "channels = %d", png_ptr->channels); 00465 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes); 00466 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 00467 color_type, interlace_type, compression_type, filter_type); 00468 } 00469 00470 /* Read and check the palette */ 00471 void /* PRIVATE */ 00472 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00473 { 00474 png_color palette[PNG_MAX_PALETTE_LENGTH]; 00475 int num, i; 00476 #ifndef PNG_NO_POINTER_INDEXING 00477 png_colorp pal_ptr; 00478 #endif 00479 00480 png_debug(1, "in png_handle_PLTE"); 00481 00482 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00483 png_error(png_ptr, "Missing IHDR before PLTE"); 00484 00485 else if (png_ptr->mode & PNG_HAVE_IDAT) 00486 { 00487 png_warning(png_ptr, "Invalid PLTE after IDAT"); 00488 png_crc_finish(png_ptr, length); 00489 return; 00490 } 00491 00492 else if (png_ptr->mode & PNG_HAVE_PLTE) 00493 png_error(png_ptr, "Duplicate PLTE chunk"); 00494 00495 png_ptr->mode |= PNG_HAVE_PLTE; 00496 00497 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) 00498 { 00499 png_warning(png_ptr, 00500 "Ignoring PLTE chunk in grayscale PNG"); 00501 png_crc_finish(png_ptr, length); 00502 return; 00503 } 00504 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED) 00505 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) 00506 { 00507 png_crc_finish(png_ptr, length); 00508 return; 00509 } 00510 #endif 00511 00512 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) 00513 { 00514 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) 00515 { 00516 png_warning(png_ptr, "Invalid palette chunk"); 00517 png_crc_finish(png_ptr, length); 00518 return; 00519 } 00520 00521 else 00522 { 00523 png_error(png_ptr, "Invalid palette chunk"); 00524 } 00525 } 00526 00527 num = (int)length / 3; 00528 00529 #ifndef PNG_NO_POINTER_INDEXING 00530 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) 00531 { 00532 png_byte buf[3]; 00533 00534 png_crc_read(png_ptr, buf, 3); 00535 pal_ptr->red = buf[0]; 00536 pal_ptr->green = buf[1]; 00537 pal_ptr->blue = buf[2]; 00538 } 00539 #else 00540 for (i = 0; i < num; i++) 00541 { 00542 png_byte buf[3]; 00543 00544 png_crc_read(png_ptr, buf, 3); 00545 /* Don't depend upon png_color being any order */ 00546 palette[i].red = buf[0]; 00547 palette[i].green = buf[1]; 00548 palette[i].blue = buf[2]; 00549 } 00550 #endif 00551 00552 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do 00553 * whatever the normal CRC configuration tells us. However, if we 00554 * have an RGB image, the PLTE can be considered ancillary, so 00555 * we will act as though it is. 00556 */ 00557 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED) 00558 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 00559 #endif 00560 { 00561 png_crc_finish(png_ptr, 0); 00562 } 00563 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED) 00564 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ 00565 { 00566 /* If we don't want to use the data from an ancillary chunk, 00567 we have two options: an error abort, or a warning and we 00568 ignore the data in this chunk (which should be OK, since 00569 it's considered ancillary for a RGB or RGBA image). */ 00570 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) 00571 { 00572 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) 00573 { 00574 png_chunk_error(png_ptr, "CRC error"); 00575 } 00576 else 00577 { 00578 png_chunk_warning(png_ptr, "CRC error"); 00579 return; 00580 } 00581 } 00582 /* Otherwise, we (optionally) emit a warning and use the chunk. */ 00583 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) 00584 { 00585 png_chunk_warning(png_ptr, "CRC error"); 00586 } 00587 } 00588 #endif 00589 00590 png_set_PLTE(png_ptr, info_ptr, palette, num); 00591 00592 #if defined(PNG_READ_tRNS_SUPPORTED) 00593 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 00594 { 00595 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) 00596 { 00597 if (png_ptr->num_trans > (png_uint_16)num) 00598 { 00599 png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); 00600 png_ptr->num_trans = (png_uint_16)num; 00601 } 00602 if (info_ptr->num_trans > (png_uint_16)num) 00603 { 00604 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); 00605 info_ptr->num_trans = (png_uint_16)num; 00606 } 00607 } 00608 } 00609 #endif 00610 00611 } 00612 00613 void /* PRIVATE */ 00614 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00615 { 00616 png_debug(1, "in png_handle_IEND"); 00617 00618 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) 00619 { 00620 png_error(png_ptr, "No image in file"); 00621 } 00622 00623 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); 00624 00625 if (length != 0) 00626 { 00627 png_warning(png_ptr, "Incorrect IEND chunk length"); 00628 } 00629 png_crc_finish(png_ptr, length); 00630 00631 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ 00632 } 00633 00634 #if defined(PNG_READ_gAMA_SUPPORTED) 00635 void /* PRIVATE */ 00636 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00637 { 00638 png_fixed_point igamma; 00639 #ifdef PNG_FLOATING_POINT_SUPPORTED 00640 float file_gamma; 00641 #endif 00642 png_byte buf[4]; 00643 00644 png_debug(1, "in png_handle_gAMA"); 00645 00646 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00647 png_error(png_ptr, "Missing IHDR before gAMA"); 00648 else if (png_ptr->mode & PNG_HAVE_IDAT) 00649 { 00650 png_warning(png_ptr, "Invalid gAMA after IDAT"); 00651 png_crc_finish(png_ptr, length); 00652 return; 00653 } 00654 else if (png_ptr->mode & PNG_HAVE_PLTE) 00655 /* Should be an error, but we can cope with it */ 00656 png_warning(png_ptr, "Out of place gAMA chunk"); 00657 00658 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) 00659 #if defined(PNG_READ_sRGB_SUPPORTED) 00660 && !(info_ptr->valid & PNG_INFO_sRGB) 00661 #endif 00662 ) 00663 { 00664 png_warning(png_ptr, "Duplicate gAMA chunk"); 00665 png_crc_finish(png_ptr, length); 00666 return; 00667 } 00668 00669 if (length != 4) 00670 { 00671 png_warning(png_ptr, "Incorrect gAMA chunk length"); 00672 png_crc_finish(png_ptr, length); 00673 return; 00674 } 00675 00676 png_crc_read(png_ptr, buf, 4); 00677 if (png_crc_finish(png_ptr, 0)) 00678 return; 00679 00680 igamma = (png_fixed_point)png_get_uint_32(buf); 00681 /* Check for zero gamma */ 00682 if (igamma == 0) 00683 { 00684 png_warning(png_ptr, 00685 "Ignoring gAMA chunk with gamma=0"); 00686 return; 00687 } 00688 00689 #if defined(PNG_READ_sRGB_SUPPORTED) 00690 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) 00691 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) 00692 { 00693 png_warning(png_ptr, 00694 "Ignoring incorrect gAMA value when sRGB is also present"); 00695 #ifndef PNG_NO_CONSOLE_IO 00696 fprintf(stderr, "gamma = (%d/100000)", (int)igamma); 00697 #endif 00698 return; 00699 } 00700 #endif /* PNG_READ_sRGB_SUPPORTED */ 00701 00702 #ifdef PNG_FLOATING_POINT_SUPPORTED 00703 file_gamma = (float)igamma / (float)100000.0; 00704 # ifdef PNG_READ_GAMMA_SUPPORTED 00705 png_ptr->gamma = file_gamma; 00706 # endif 00707 png_set_gAMA(png_ptr, info_ptr, file_gamma); 00708 #endif 00709 #ifdef PNG_FIXED_POINT_SUPPORTED 00710 png_set_gAMA_fixed(png_ptr, info_ptr, igamma); 00711 #endif 00712 } 00713 #endif 00714 00715 #if defined(PNG_READ_sBIT_SUPPORTED) 00716 void /* PRIVATE */ 00717 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00718 { 00719 png_size_t truelen; 00720 png_byte buf[4]; 00721 00722 png_debug(1, "in png_handle_sBIT"); 00723 00724 buf[0] = buf[1] = buf[2] = buf[3] = 0; 00725 00726 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00727 png_error(png_ptr, "Missing IHDR before sBIT"); 00728 else if (png_ptr->mode & PNG_HAVE_IDAT) 00729 { 00730 png_warning(png_ptr, "Invalid sBIT after IDAT"); 00731 png_crc_finish(png_ptr, length); 00732 return; 00733 } 00734 else if (png_ptr->mode & PNG_HAVE_PLTE) 00735 { 00736 /* Should be an error, but we can cope with it */ 00737 png_warning(png_ptr, "Out of place sBIT chunk"); 00738 } 00739 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) 00740 { 00741 png_warning(png_ptr, "Duplicate sBIT chunk"); 00742 png_crc_finish(png_ptr, length); 00743 return; 00744 } 00745 00746 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 00747 truelen = 3; 00748 else 00749 truelen = (png_size_t)png_ptr->channels; 00750 00751 if (length != truelen || length > 4) 00752 { 00753 png_warning(png_ptr, "Incorrect sBIT chunk length"); 00754 png_crc_finish(png_ptr, length); 00755 return; 00756 } 00757 00758 png_crc_read(png_ptr, buf, truelen); 00759 if (png_crc_finish(png_ptr, 0)) 00760 return; 00761 00762 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) 00763 { 00764 png_ptr->sig_bit.red = buf[0]; 00765 png_ptr->sig_bit.green = buf[1]; 00766 png_ptr->sig_bit.blue = buf[2]; 00767 png_ptr->sig_bit.alpha = buf[3]; 00768 } 00769 else 00770 { 00771 png_ptr->sig_bit.gray = buf[0]; 00772 png_ptr->sig_bit.red = buf[0]; 00773 png_ptr->sig_bit.green = buf[0]; 00774 png_ptr->sig_bit.blue = buf[0]; 00775 png_ptr->sig_bit.alpha = buf[1]; 00776 } 00777 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); 00778 } 00779 #endif 00780 00781 #if defined(PNG_READ_cHRM_SUPPORTED) 00782 void /* PRIVATE */ 00783 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00784 { 00785 png_byte buf[32]; 00786 #ifdef PNG_FLOATING_POINT_SUPPORTED 00787 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; 00788 #endif 00789 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, 00790 int_y_green, int_x_blue, int_y_blue; 00791 00792 png_uint_32 uint_x, uint_y; 00793 00794 png_debug(1, "in png_handle_cHRM"); 00795 00796 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00797 png_error(png_ptr, "Missing IHDR before cHRM"); 00798 else if (png_ptr->mode & PNG_HAVE_IDAT) 00799 { 00800 png_warning(png_ptr, "Invalid cHRM after IDAT"); 00801 png_crc_finish(png_ptr, length); 00802 return; 00803 } 00804 else if (png_ptr->mode & PNG_HAVE_PLTE) 00805 /* Should be an error, but we can cope with it */ 00806 png_warning(png_ptr, "Missing PLTE before cHRM"); 00807 00808 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) 00809 #if defined(PNG_READ_sRGB_SUPPORTED) 00810 && !(info_ptr->valid & PNG_INFO_sRGB) 00811 #endif 00812 ) 00813 { 00814 png_warning(png_ptr, "Duplicate cHRM chunk"); 00815 png_crc_finish(png_ptr, length); 00816 return; 00817 } 00818 00819 if (length != 32) 00820 { 00821 png_warning(png_ptr, "Incorrect cHRM chunk length"); 00822 png_crc_finish(png_ptr, length); 00823 return; 00824 } 00825 00826 png_crc_read(png_ptr, buf, 32); 00827 if (png_crc_finish(png_ptr, 0)) 00828 return; 00829 00830 uint_x = png_get_uint_32(buf); 00831 uint_y = png_get_uint_32(buf + 4); 00832 int_x_white = (png_fixed_point)uint_x; 00833 int_y_white = (png_fixed_point)uint_y; 00834 00835 uint_x = png_get_uint_32(buf + 8); 00836 uint_y = png_get_uint_32(buf + 12); 00837 int_x_red = (png_fixed_point)uint_x; 00838 int_y_red = (png_fixed_point)uint_y; 00839 00840 uint_x = png_get_uint_32(buf + 16); 00841 uint_y = png_get_uint_32(buf + 20); 00842 int_x_green = (png_fixed_point)uint_x; 00843 int_y_green = (png_fixed_point)uint_y; 00844 00845 uint_x = png_get_uint_32(buf + 24); 00846 uint_y = png_get_uint_32(buf + 28); 00847 int_x_blue = (png_fixed_point)uint_x; 00848 int_y_blue = (png_fixed_point)uint_y; 00849 00850 #ifdef PNG_FLOATING_POINT_SUPPORTED 00851 white_x = (float)int_x_white / (float)100000.0; 00852 white_y = (float)int_y_white / (float)100000.0; 00853 red_x = (float)int_x_red / (float)100000.0; 00854 red_y = (float)int_y_red / (float)100000.0; 00855 green_x = (float)int_x_green / (float)100000.0; 00856 green_y = (float)int_y_green / (float)100000.0; 00857 blue_x = (float)int_x_blue / (float)100000.0; 00858 blue_y = (float)int_y_blue / (float)100000.0; 00859 #endif 00860 00861 #if defined(PNG_READ_sRGB_SUPPORTED) 00862 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) 00863 { 00864 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || 00865 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || 00866 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || 00867 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || 00868 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || 00869 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || 00870 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || 00871 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) 00872 { 00873 png_warning(png_ptr, 00874 "Ignoring incorrect cHRM value when sRGB is also present"); 00875 #ifndef PNG_NO_CONSOLE_IO 00876 #ifdef PNG_FLOATING_POINT_SUPPORTED 00877 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", 00878 white_x, white_y, red_x, red_y); 00879 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", 00880 green_x, green_y, blue_x, blue_y); 00881 #else 00882 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", 00883 int_x_white, int_y_white, int_x_red, int_y_red); 00884 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", 00885 int_x_green, int_y_green, int_x_blue, int_y_blue); 00886 #endif 00887 #endif /* PNG_NO_CONSOLE_IO */ 00888 } 00889 return; 00890 } 00891 #endif /* PNG_READ_sRGB_SUPPORTED */ 00892 00893 #ifdef PNG_FLOATING_POINT_SUPPORTED 00894 png_set_cHRM(png_ptr, info_ptr, 00895 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); 00896 #endif 00897 #ifdef PNG_FIXED_POINT_SUPPORTED 00898 png_set_cHRM_fixed(png_ptr, info_ptr, 00899 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, 00900 int_y_green, int_x_blue, int_y_blue); 00901 #endif 00902 } 00903 #endif 00904 00905 #if defined(PNG_READ_sRGB_SUPPORTED) 00906 void /* PRIVATE */ 00907 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 00908 { 00909 int intent; 00910 png_byte buf[1]; 00911 00912 png_debug(1, "in png_handle_sRGB"); 00913 00914 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00915 png_error(png_ptr, "Missing IHDR before sRGB"); 00916 else if (png_ptr->mode & PNG_HAVE_IDAT) 00917 { 00918 png_warning(png_ptr, "Invalid sRGB after IDAT"); 00919 png_crc_finish(png_ptr, length); 00920 return; 00921 } 00922 else if (png_ptr->mode & PNG_HAVE_PLTE) 00923 /* Should be an error, but we can cope with it */ 00924 png_warning(png_ptr, "Out of place sRGB chunk"); 00925 00926 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) 00927 { 00928 png_warning(png_ptr, "Duplicate sRGB chunk"); 00929 png_crc_finish(png_ptr, length); 00930 return; 00931 } 00932 00933 if (length != 1) 00934 { 00935 png_warning(png_ptr, "Incorrect sRGB chunk length"); 00936 png_crc_finish(png_ptr, length); 00937 return; 00938 } 00939 00940 png_crc_read(png_ptr, buf, 1); 00941 if (png_crc_finish(png_ptr, 0)) 00942 return; 00943 00944 intent = buf[0]; 00945 /* Check for bad intent */ 00946 if (intent >= PNG_sRGB_INTENT_LAST) 00947 { 00948 png_warning(png_ptr, "Unknown sRGB intent"); 00949 return; 00950 } 00951 00952 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) 00953 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) 00954 { 00955 png_fixed_point igamma; 00956 #ifdef PNG_FIXED_POINT_SUPPORTED 00957 igamma=info_ptr->int_gamma; 00958 #else 00959 # ifdef PNG_FLOATING_POINT_SUPPORTED 00960 igamma=(png_fixed_point)(info_ptr->gamma * 100000.); 00961 # endif 00962 #endif 00963 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) 00964 { 00965 png_warning(png_ptr, 00966 "Ignoring incorrect gAMA value when sRGB is also present"); 00967 #ifndef PNG_NO_CONSOLE_IO 00968 # ifdef PNG_FIXED_POINT_SUPPORTED 00969 fprintf(stderr, "incorrect gamma=(%d/100000)\n", 00970 (int)png_ptr->int_gamma); 00971 # else 00972 # ifdef PNG_FLOATING_POINT_SUPPORTED 00973 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma); 00974 # endif 00975 # endif 00976 #endif 00977 } 00978 } 00979 #endif /* PNG_READ_gAMA_SUPPORTED */ 00980 00981 #ifdef PNG_READ_cHRM_SUPPORTED 00982 #ifdef PNG_FIXED_POINT_SUPPORTED 00983 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) 00984 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || 00985 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || 00986 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || 00987 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || 00988 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || 00989 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || 00990 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || 00991 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) 00992 { 00993 png_warning(png_ptr, 00994 "Ignoring incorrect cHRM value when sRGB is also present"); 00995 } 00996 #endif /* PNG_FIXED_POINT_SUPPORTED */ 00997 #endif /* PNG_READ_cHRM_SUPPORTED */ 00998 00999 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); 01000 } 01001 #endif /* PNG_READ_sRGB_SUPPORTED */ 01002 01003 #if defined(PNG_READ_iCCP_SUPPORTED) 01004 void /* PRIVATE */ 01005 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01006 /* Note: this does not properly handle chunks that are > 64K under DOS */ 01007 { 01008 png_byte compression_type; 01009 png_bytep pC; 01010 png_charp profile; 01011 png_uint_32 skip = 0; 01012 png_uint_32 profile_size, profile_length; 01013 png_size_t slength, prefix_length, data_length; 01014 01015 png_debug(1, "in png_handle_iCCP"); 01016 01017 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01018 png_error(png_ptr, "Missing IHDR before iCCP"); 01019 else if (png_ptr->mode & PNG_HAVE_IDAT) 01020 { 01021 png_warning(png_ptr, "Invalid iCCP after IDAT"); 01022 png_crc_finish(png_ptr, length); 01023 return; 01024 } 01025 else if (png_ptr->mode & PNG_HAVE_PLTE) 01026 /* Should be an error, but we can cope with it */ 01027 png_warning(png_ptr, "Out of place iCCP chunk"); 01028 01029 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) 01030 { 01031 png_warning(png_ptr, "Duplicate iCCP chunk"); 01032 png_crc_finish(png_ptr, length); 01033 return; 01034 } 01035 01036 #ifdef PNG_MAX_MALLOC_64K 01037 if (length > (png_uint_32)65535L) 01038 { 01039 png_warning(png_ptr, "iCCP chunk too large to fit in memory"); 01040 skip = length - (png_uint_32)65535L; 01041 length = (png_uint_32)65535L; 01042 } 01043 #endif 01044 01045 png_free(png_ptr, png_ptr->chunkdata); 01046 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); 01047 slength = (png_size_t)length; 01048 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 01049 01050 if (png_crc_finish(png_ptr, skip)) 01051 { 01052 png_free(png_ptr, png_ptr->chunkdata); 01053 png_ptr->chunkdata = NULL; 01054 return; 01055 } 01056 01057 png_ptr->chunkdata[slength] = 0x00; 01058 01059 for (profile = png_ptr->chunkdata; *profile; profile++) 01060 /* Empty loop to find end of name */ ; 01061 01062 ++profile; 01063 01064 /* There should be at least one zero (the compression type byte) 01065 * following the separator, and we should be on it 01066 */ 01067 if ( profile >= png_ptr->chunkdata + slength - 1) 01068 { 01069 png_free(png_ptr, png_ptr->chunkdata); 01070 png_ptr->chunkdata = NULL; 01071 png_warning(png_ptr, "Malformed iCCP chunk"); 01072 return; 01073 } 01074 01075 /* Compression_type should always be zero */ 01076 compression_type = *profile++; 01077 if (compression_type) 01078 { 01079 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); 01080 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 01081 wrote nonzero) */ 01082 } 01083 01084 prefix_length = profile - png_ptr->chunkdata; 01085 png_decompress_chunk(png_ptr, compression_type, 01086 slength, prefix_length, &data_length); 01087 01088 profile_length = data_length - prefix_length; 01089 01090 if ( prefix_length > data_length || profile_length < 4) 01091 { 01092 png_free(png_ptr, png_ptr->chunkdata); 01093 png_ptr->chunkdata = NULL; 01094 png_warning(png_ptr, "Profile size field missing from iCCP chunk"); 01095 return; 01096 } 01097 01098 /* Check the profile_size recorded in the first 32 bits of the ICC profile */ 01099 pC = (png_bytep)(png_ptr->chunkdata + prefix_length); 01100 profile_size = ((*(pC ))<<24) | 01101 ((*(pC + 1))<<16) | 01102 ((*(pC + 2))<< 8) | 01103 ((*(pC + 3)) ); 01104 01105 if (profile_size < profile_length) 01106 profile_length = profile_size; 01107 01108 if (profile_size > profile_length) 01109 { 01110 png_free(png_ptr, png_ptr->chunkdata); 01111 png_ptr->chunkdata = NULL; 01112 png_warning(png_ptr, "Ignoring truncated iCCP profile."); 01113 return; 01114 } 01115 01116 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, 01117 compression_type, png_ptr->chunkdata + prefix_length, profile_length); 01118 png_free(png_ptr, png_ptr->chunkdata); 01119 png_ptr->chunkdata = NULL; 01120 } 01121 #endif /* PNG_READ_iCCP_SUPPORTED */ 01122 01123 #if defined(PNG_READ_sPLT_SUPPORTED) 01124 void /* PRIVATE */ 01125 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01126 /* Note: this does not properly handle chunks that are > 64K under DOS */ 01127 { 01128 png_bytep entry_start; 01129 png_sPLT_t new_palette; 01130 #ifdef PNG_NO_POINTER_INDEXING 01131 png_sPLT_entryp pp; 01132 #endif 01133 int data_length, entry_size, i; 01134 png_uint_32 skip = 0; 01135 png_size_t slength; 01136 01137 png_debug(1, "in png_handle_sPLT"); 01138 01139 01140 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01141 png_error(png_ptr, "Missing IHDR before sPLT"); 01142 else if (png_ptr->mode & PNG_HAVE_IDAT) 01143 { 01144 png_warning(png_ptr, "Invalid sPLT after IDAT"); 01145 png_crc_finish(png_ptr, length); 01146 return; 01147 } 01148 01149 #ifdef PNG_MAX_MALLOC_64K 01150 if (length > (png_uint_32)65535L) 01151 { 01152 png_warning(png_ptr, "sPLT chunk too large to fit in memory"); 01153 skip = length - (png_uint_32)65535L; 01154 length = (png_uint_32)65535L; 01155 } 01156 #endif 01157 01158 png_free(png_ptr, png_ptr->chunkdata); 01159 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); 01160 slength = (png_size_t)length; 01161 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 01162 01163 if (png_crc_finish(png_ptr, skip)) 01164 { 01165 png_free(png_ptr, png_ptr->chunkdata); 01166 png_ptr->chunkdata = NULL; 01167 return; 01168 } 01169 01170 png_ptr->chunkdata[slength] = 0x00; 01171 01172 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++) 01173 /* Empty loop to find end of name */ ; 01174 ++entry_start; 01175 01176 /* A sample depth should follow the separator, and we should be on it */ 01177 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) 01178 { 01179 png_free(png_ptr, png_ptr->chunkdata); 01180 png_ptr->chunkdata = NULL; 01181 png_warning(png_ptr, "malformed sPLT chunk"); 01182 return; 01183 } 01184 01185 new_palette.depth = *entry_start++; 01186 entry_size = (new_palette.depth == 8 ? 6 : 10); 01187 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata)); 01188 01189 /* Integrity-check the data length */ 01190 if (data_length % entry_size) 01191 { 01192 png_free(png_ptr, png_ptr->chunkdata); 01193 png_ptr->chunkdata = NULL; 01194 png_warning(png_ptr, "sPLT chunk has bad length"); 01195 return; 01196 } 01197 01198 new_palette.nentries = (png_int_32) ( data_length / entry_size); 01199 if ((png_uint_32) new_palette.nentries > 01200 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry))) 01201 { 01202 png_warning(png_ptr, "sPLT chunk too long"); 01203 return; 01204 } 01205 new_palette.entries = (png_sPLT_entryp)png_malloc_warn( 01206 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); 01207 if (new_palette.entries == NULL) 01208 { 01209 png_warning(png_ptr, "sPLT chunk requires too much memory"); 01210 return; 01211 } 01212 01213 #ifndef PNG_NO_POINTER_INDEXING 01214 for (i = 0; i < new_palette.nentries; i++) 01215 { 01216 png_sPLT_entryp pp = new_palette.entries + i; 01217 01218 if (new_palette.depth == 8) 01219 { 01220 pp->red = *entry_start++; 01221 pp->green = *entry_start++; 01222 pp->blue = *entry_start++; 01223 pp->alpha = *entry_start++; 01224 } 01225 else 01226 { 01227 pp->red = png_get_uint_16(entry_start); entry_start += 2; 01228 pp->green = png_get_uint_16(entry_start); entry_start += 2; 01229 pp->blue = png_get_uint_16(entry_start); entry_start += 2; 01230 pp->alpha = png_get_uint_16(entry_start); entry_start += 2; 01231 } 01232 pp->frequency = png_get_uint_16(entry_start); entry_start += 2; 01233 } 01234 #else 01235 pp = new_palette.entries; 01236 for (i = 0; i < new_palette.nentries; i++) 01237 { 01238 01239 if (new_palette.depth == 8) 01240 { 01241 pp[i].red = *entry_start++; 01242 pp[i].green = *entry_start++; 01243 pp[i].blue = *entry_start++; 01244 pp[i].alpha = *entry_start++; 01245 } 01246 else 01247 { 01248 pp[i].red = png_get_uint_16(entry_start); entry_start += 2; 01249 pp[i].green = png_get_uint_16(entry_start); entry_start += 2; 01250 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; 01251 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; 01252 } 01253 pp->frequency = png_get_uint_16(entry_start); entry_start += 2; 01254 } 01255 #endif 01256 01257 /* Discard all chunk data except the name and stash that */ 01258 new_palette.name = png_ptr->chunkdata; 01259 01260 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); 01261 01262 png_free(png_ptr, png_ptr->chunkdata); 01263 png_ptr->chunkdata = NULL; 01264 png_free(png_ptr, new_palette.entries); 01265 } 01266 #endif /* PNG_READ_sPLT_SUPPORTED */ 01267 01268 #if defined(PNG_READ_tRNS_SUPPORTED) 01269 void /* PRIVATE */ 01270 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01271 { 01272 png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; 01273 01274 png_debug(1, "in png_handle_tRNS"); 01275 01276 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01277 png_error(png_ptr, "Missing IHDR before tRNS"); 01278 else if (png_ptr->mode & PNG_HAVE_IDAT) 01279 { 01280 png_warning(png_ptr, "Invalid tRNS after IDAT"); 01281 png_crc_finish(png_ptr, length); 01282 return; 01283 } 01284 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) 01285 { 01286 png_warning(png_ptr, "Duplicate tRNS chunk"); 01287 png_crc_finish(png_ptr, length); 01288 return; 01289 } 01290 01291 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) 01292 { 01293 png_byte buf[2]; 01294 01295 if (length != 2) 01296 { 01297 png_warning(png_ptr, "Incorrect tRNS chunk length"); 01298 png_crc_finish(png_ptr, length); 01299 return; 01300 } 01301 01302 png_crc_read(png_ptr, buf, 2); 01303 png_ptr->num_trans = 1; 01304 png_ptr->trans_values.gray = png_get_uint_16(buf); 01305 } 01306 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) 01307 { 01308 png_byte buf[6]; 01309 01310 if (length != 6) 01311 { 01312 png_warning(png_ptr, "Incorrect tRNS chunk length"); 01313 png_crc_finish(png_ptr, length); 01314 return; 01315 } 01316 png_crc_read(png_ptr, buf, (png_size_t)length); 01317 png_ptr->num_trans = 1; 01318 png_ptr->trans_values.red = png_get_uint_16(buf); 01319 png_ptr->trans_values.green = png_get_uint_16(buf + 2); 01320 png_ptr->trans_values.blue = png_get_uint_16(buf + 4); 01321 } 01322 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01323 { 01324 if (!(png_ptr->mode & PNG_HAVE_PLTE)) 01325 { 01326 /* Should be an error, but we can cope with it. */ 01327 png_warning(png_ptr, "Missing PLTE before tRNS"); 01328 } 01329 if (length > (png_uint_32)png_ptr->num_palette || 01330 length > PNG_MAX_PALETTE_LENGTH) 01331 { 01332 png_warning(png_ptr, "Incorrect tRNS chunk length"); 01333 png_crc_finish(png_ptr, length); 01334 return; 01335 } 01336 if (length == 0) 01337 { 01338 png_warning(png_ptr, "Zero length tRNS chunk"); 01339 png_crc_finish(png_ptr, length); 01340 return; 01341 } 01342 png_crc_read(png_ptr, readbuf, (png_size_t)length); 01343 png_ptr->num_trans = (png_uint_16)length; 01344 } 01345 else 01346 { 01347 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); 01348 png_crc_finish(png_ptr, length); 01349 return; 01350 } 01351 01352 if (png_crc_finish(png_ptr, 0)) 01353 { 01354 png_ptr->num_trans = 0; 01355 return; 01356 } 01357 01358 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, 01359 &(png_ptr->trans_values)); 01360 } 01361 #endif 01362 01363 #if defined(PNG_READ_bKGD_SUPPORTED) 01364 void /* PRIVATE */ 01365 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01366 { 01367 png_size_t truelen; 01368 png_byte buf[6]; 01369 01370 png_debug(1, "in png_handle_bKGD"); 01371 01372 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01373 png_error(png_ptr, "Missing IHDR before bKGD"); 01374 else if (png_ptr->mode & PNG_HAVE_IDAT) 01375 { 01376 png_warning(png_ptr, "Invalid bKGD after IDAT"); 01377 png_crc_finish(png_ptr, length); 01378 return; 01379 } 01380 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 01381 !(png_ptr->mode & PNG_HAVE_PLTE)) 01382 { 01383 png_warning(png_ptr, "Missing PLTE before bKGD"); 01384 png_crc_finish(png_ptr, length); 01385 return; 01386 } 01387 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) 01388 { 01389 png_warning(png_ptr, "Duplicate bKGD chunk"); 01390 png_crc_finish(png_ptr, length); 01391 return; 01392 } 01393 01394 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01395 truelen = 1; 01396 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) 01397 truelen = 6; 01398 else 01399 truelen = 2; 01400 01401 if (length != truelen) 01402 { 01403 png_warning(png_ptr, "Incorrect bKGD chunk length"); 01404 png_crc_finish(png_ptr, length); 01405 return; 01406 } 01407 01408 png_crc_read(png_ptr, buf, truelen); 01409 if (png_crc_finish(png_ptr, 0)) 01410 return; 01411 01412 /* We convert the index value into RGB components so that we can allow 01413 * arbitrary RGB values for background when we have transparency, and 01414 * so it is easy to determine the RGB values of the background color 01415 * from the info_ptr struct. */ 01416 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01417 { 01418 png_ptr->background.index = buf[0]; 01419 if (info_ptr && info_ptr->num_palette) 01420 { 01421 if (buf[0] >= info_ptr->num_palette) 01422 { 01423 png_warning(png_ptr, "Incorrect bKGD chunk index value"); 01424 return; 01425 } 01426 png_ptr->background.red = 01427 (png_uint_16)png_ptr->palette[buf[0]].red; 01428 png_ptr->background.green = 01429 (png_uint_16)png_ptr->palette[buf[0]].green; 01430 png_ptr->background.blue = 01431 (png_uint_16)png_ptr->palette[buf[0]].blue; 01432 } 01433 } 01434 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ 01435 { 01436 png_ptr->background.red = 01437 png_ptr->background.green = 01438 png_ptr->background.blue = 01439 png_ptr->background.gray = png_get_uint_16(buf); 01440 } 01441 else 01442 { 01443 png_ptr->background.red = png_get_uint_16(buf); 01444 png_ptr->background.green = png_get_uint_16(buf + 2); 01445 png_ptr->background.blue = png_get_uint_16(buf + 4); 01446 } 01447 01448 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); 01449 } 01450 #endif 01451 01452 #if defined(PNG_READ_hIST_SUPPORTED) 01453 void /* PRIVATE */ 01454 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01455 { 01456 unsigned int num, i; 01457 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; 01458 01459 png_debug(1, "in png_handle_hIST"); 01460 01461 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01462 png_error(png_ptr, "Missing IHDR before hIST"); 01463 else if (png_ptr->mode & PNG_HAVE_IDAT) 01464 { 01465 png_warning(png_ptr, "Invalid hIST after IDAT"); 01466 png_crc_finish(png_ptr, length); 01467 return; 01468 } 01469 else if (!(png_ptr->mode & PNG_HAVE_PLTE)) 01470 { 01471 png_warning(png_ptr, "Missing PLTE before hIST"); 01472 png_crc_finish(png_ptr, length); 01473 return; 01474 } 01475 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) 01476 { 01477 png_warning(png_ptr, "Duplicate hIST chunk"); 01478 png_crc_finish(png_ptr, length); 01479 return; 01480 } 01481 01482 num = length / 2 ; 01483 if (num != (unsigned int) png_ptr->num_palette || num > 01484 (unsigned int) PNG_MAX_PALETTE_LENGTH) 01485 { 01486 png_warning(png_ptr, "Incorrect hIST chunk length"); 01487 png_crc_finish(png_ptr, length); 01488 return; 01489 } 01490 01491 for (i = 0; i < num; i++) 01492 { 01493 png_byte buf[2]; 01494 01495 png_crc_read(png_ptr, buf, 2); 01496 readbuf[i] = png_get_uint_16(buf); 01497 } 01498 01499 if (png_crc_finish(png_ptr, 0)) 01500 return; 01501 01502 png_set_hIST(png_ptr, info_ptr, readbuf); 01503 } 01504 #endif 01505 01506 #if defined(PNG_READ_pHYs_SUPPORTED) 01507 void /* PRIVATE */ 01508 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01509 { 01510 png_byte buf[9]; 01511 png_uint_32 res_x, res_y; 01512 int unit_type; 01513 01514 png_debug(1, "in png_handle_pHYs"); 01515 01516 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01517 png_error(png_ptr, "Missing IHDR before pHYs"); 01518 else if (png_ptr->mode & PNG_HAVE_IDAT) 01519 { 01520 png_warning(png_ptr, "Invalid pHYs after IDAT"); 01521 png_crc_finish(png_ptr, length); 01522 return; 01523 } 01524 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) 01525 { 01526 png_warning(png_ptr, "Duplicate pHYs chunk"); 01527 png_crc_finish(png_ptr, length); 01528 return; 01529 } 01530 01531 if (length != 9) 01532 { 01533 png_warning(png_ptr, "Incorrect pHYs chunk length"); 01534 png_crc_finish(png_ptr, length); 01535 return; 01536 } 01537 01538 png_crc_read(png_ptr, buf, 9); 01539 if (png_crc_finish(png_ptr, 0)) 01540 return; 01541 01542 res_x = png_get_uint_32(buf); 01543 res_y = png_get_uint_32(buf + 4); 01544 unit_type = buf[8]; 01545 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); 01546 } 01547 #endif 01548 01549 #if defined(PNG_READ_oFFs_SUPPORTED) 01550 void /* PRIVATE */ 01551 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01552 { 01553 png_byte buf[9]; 01554 png_int_32 offset_x, offset_y; 01555 int unit_type; 01556 01557 png_debug(1, "in png_handle_oFFs"); 01558 01559 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01560 png_error(png_ptr, "Missing IHDR before oFFs"); 01561 else if (png_ptr->mode & PNG_HAVE_IDAT) 01562 { 01563 png_warning(png_ptr, "Invalid oFFs after IDAT"); 01564 png_crc_finish(png_ptr, length); 01565 return; 01566 } 01567 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) 01568 { 01569 png_warning(png_ptr, "Duplicate oFFs chunk"); 01570 png_crc_finish(png_ptr, length); 01571 return; 01572 } 01573 01574 if (length != 9) 01575 { 01576 png_warning(png_ptr, "Incorrect oFFs chunk length"); 01577 png_crc_finish(png_ptr, length); 01578 return; 01579 } 01580 01581 png_crc_read(png_ptr, buf, 9); 01582 if (png_crc_finish(png_ptr, 0)) 01583 return; 01584 01585 offset_x = png_get_int_32(buf); 01586 offset_y = png_get_int_32(buf + 4); 01587 unit_type = buf[8]; 01588 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); 01589 } 01590 #endif 01591 01592 #if defined(PNG_READ_pCAL_SUPPORTED) 01593 /* Read the pCAL chunk (described in the PNG Extensions document) */ 01594 void /* PRIVATE */ 01595 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01596 { 01597 png_int_32 X0, X1; 01598 png_byte type, nparams; 01599 png_charp buf, units, endptr; 01600 png_charpp params; 01601 png_size_t slength; 01602 int i; 01603 01604 png_debug(1, "in png_handle_pCAL"); 01605 01606 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01607 png_error(png_ptr, "Missing IHDR before pCAL"); 01608 else if (png_ptr->mode & PNG_HAVE_IDAT) 01609 { 01610 png_warning(png_ptr, "Invalid pCAL after IDAT"); 01611 png_crc_finish(png_ptr, length); 01612 return; 01613 } 01614 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) 01615 { 01616 png_warning(png_ptr, "Duplicate pCAL chunk"); 01617 png_crc_finish(png_ptr, length); 01618 return; 01619 } 01620 01621 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)", 01622 length + 1); 01623 png_free(png_ptr, png_ptr->chunkdata); 01624 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); 01625 if (png_ptr->chunkdata == NULL) 01626 { 01627 png_warning(png_ptr, "No memory for pCAL purpose."); 01628 return; 01629 } 01630 slength = (png_size_t)length; 01631 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 01632 01633 if (png_crc_finish(png_ptr, 0)) 01634 { 01635 png_free(png_ptr, png_ptr->chunkdata); 01636 png_ptr->chunkdata = NULL; 01637 return; 01638 } 01639 01640 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ 01641 01642 png_debug(3, "Finding end of pCAL purpose string"); 01643 for (buf = png_ptr->chunkdata; *buf; buf++) 01644 /* Empty loop */ ; 01645 01646 endptr = png_ptr->chunkdata + slength; 01647 01648 /* We need to have at least 12 bytes after the purpose string 01649 in order to get the parameter information. */ 01650 if (endptr <= buf + 12) 01651 { 01652 png_warning(png_ptr, "Invalid pCAL data"); 01653 png_free(png_ptr, png_ptr->chunkdata); 01654 png_ptr->chunkdata = NULL; 01655 return; 01656 } 01657 01658 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); 01659 X0 = png_get_int_32((png_bytep)buf+1); 01660 X1 = png_get_int_32((png_bytep)buf+5); 01661 type = buf[9]; 01662 nparams = buf[10]; 01663 units = buf + 11; 01664 01665 png_debug(3, "Checking pCAL equation type and number of parameters"); 01666 /* Check that we have the right number of parameters for known 01667 equation types. */ 01668 if ((type == PNG_EQUATION_LINEAR && nparams != 2) || 01669 (type == PNG_EQUATION_BASE_E && nparams != 3) || 01670 (type == PNG_EQUATION_ARBITRARY && nparams != 3) || 01671 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) 01672 { 01673 png_warning(png_ptr, "Invalid pCAL parameters for equation type"); 01674 png_free(png_ptr, png_ptr->chunkdata); 01675 png_ptr->chunkdata = NULL; 01676 return; 01677 } 01678 else if (type >= PNG_EQUATION_LAST) 01679 { 01680 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); 01681 } 01682 01683 for (buf = units; *buf; buf++) 01684 /* Empty loop to move past the units string. */ ; 01685 01686 png_debug(3, "Allocating pCAL parameters array"); 01687 params = (png_charpp)png_malloc_warn(png_ptr, 01688 (png_uint_32)(nparams * png_sizeof(png_charp))) ; 01689 if (params == NULL) 01690 { 01691 png_free(png_ptr, png_ptr->chunkdata); 01692 png_ptr->chunkdata = NULL; 01693 png_warning(png_ptr, "No memory for pCAL params."); 01694 return; 01695 } 01696 01697 /* Get pointers to the start of each parameter string. */ 01698 for (i = 0; i < (int)nparams; i++) 01699 { 01700 buf++; /* Skip the null string terminator from previous parameter. */ 01701 01702 png_debug1(3, "Reading pCAL parameter %d", i); 01703 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) 01704 /* Empty loop to move past each parameter string */ ; 01705 01706 /* Make sure we haven't run out of data yet */ 01707 if (buf > endptr) 01708 { 01709 png_warning(png_ptr, "Invalid pCAL data"); 01710 png_free(png_ptr, png_ptr->chunkdata); 01711 png_ptr->chunkdata = NULL; 01712 png_free(png_ptr, params); 01713 return; 01714 } 01715 } 01716 01717 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, 01718 units, params); 01719 01720 png_free(png_ptr, png_ptr->chunkdata); 01721 png_ptr->chunkdata = NULL; 01722 png_free(png_ptr, params); 01723 } 01724 #endif 01725 01726 #if defined(PNG_READ_sCAL_SUPPORTED) 01727 /* Read the sCAL chunk */ 01728 void /* PRIVATE */ 01729 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01730 { 01731 png_charp ep; 01732 #ifdef PNG_FLOATING_POINT_SUPPORTED 01733 double width, height; 01734 png_charp vp; 01735 #else 01736 #ifdef PNG_FIXED_POINT_SUPPORTED 01737 png_charp swidth, sheight; 01738 #endif 01739 #endif 01740 png_size_t slength; 01741 01742 png_debug(1, "in png_handle_sCAL"); 01743 01744 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01745 png_error(png_ptr, "Missing IHDR before sCAL"); 01746 else if (png_ptr->mode & PNG_HAVE_IDAT) 01747 { 01748 png_warning(png_ptr, "Invalid sCAL after IDAT"); 01749 png_crc_finish(png_ptr, length); 01750 return; 01751 } 01752 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) 01753 { 01754 png_warning(png_ptr, "Duplicate sCAL chunk"); 01755 png_crc_finish(png_ptr, length); 01756 return; 01757 } 01758 01759 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)", 01760 length + 1); 01761 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); 01762 if (png_ptr->chunkdata == NULL) 01763 { 01764 png_warning(png_ptr, "Out of memory while processing sCAL chunk"); 01765 return; 01766 } 01767 slength = (png_size_t)length; 01768 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 01769 01770 if (png_crc_finish(png_ptr, 0)) 01771 { 01772 png_free(png_ptr, png_ptr->chunkdata); 01773 png_ptr->chunkdata = NULL; 01774 return; 01775 } 01776 01777 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ 01778 01779 ep = png_ptr->chunkdata + 1; /* Skip unit byte */ 01780 01781 #ifdef PNG_FLOATING_POINT_SUPPORTED 01782 width = png_strtod(png_ptr, ep, &vp); 01783 if (*vp) 01784 { 01785 png_warning(png_ptr, "malformed width string in sCAL chunk"); 01786 return; 01787 } 01788 #else 01789 #ifdef PNG_FIXED_POINT_SUPPORTED 01790 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); 01791 if (swidth == NULL) 01792 { 01793 png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); 01794 return; 01795 } 01796 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); 01797 #endif 01798 #endif 01799 01800 for (ep = png_ptr->chunkdata; *ep; ep++) 01801 /* Empty loop */ ; 01802 ep++; 01803 01804 if (png_ptr->chunkdata + slength < ep) 01805 { 01806 png_warning(png_ptr, "Truncated sCAL chunk"); 01807 #if defined(PNG_FIXED_POINT_SUPPORTED) && \ 01808 !defined(PNG_FLOATING_POINT_SUPPORTED) 01809 png_free(png_ptr, swidth); 01810 #endif 01811 png_free(png_ptr, png_ptr->chunkdata); 01812 png_ptr->chunkdata = NULL; 01813 return; 01814 } 01815 01816 #ifdef PNG_FLOATING_POINT_SUPPORTED 01817 height = png_strtod(png_ptr, ep, &vp); 01818 if (*vp) 01819 { 01820 png_warning(png_ptr, "malformed height string in sCAL chunk"); 01821 return; 01822 } 01823 #else 01824 #ifdef PNG_FIXED_POINT_SUPPORTED 01825 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); 01826 if (sheight == NULL) 01827 { 01828 png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); 01829 return; 01830 } 01831 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); 01832 #endif 01833 #endif 01834 01835 if (png_ptr->chunkdata + slength < ep 01836 #ifdef PNG_FLOATING_POINT_SUPPORTED 01837 || width <= 0. || height <= 0. 01838 #endif 01839 ) 01840 { 01841 png_warning(png_ptr, "Invalid sCAL data"); 01842 png_free(png_ptr, png_ptr->chunkdata); 01843 png_ptr->chunkdata = NULL; 01844 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) 01845 png_free(png_ptr, swidth); 01846 png_free(png_ptr, sheight); 01847 #endif 01848 return; 01849 } 01850 01851 01852 #ifdef PNG_FLOATING_POINT_SUPPORTED 01853 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height); 01854 #else 01855 #ifdef PNG_FIXED_POINT_SUPPORTED 01856 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight); 01857 #endif 01858 #endif 01859 01860 png_free(png_ptr, png_ptr->chunkdata); 01861 png_ptr->chunkdata = NULL; 01862 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) 01863 png_free(png_ptr, swidth); 01864 png_free(png_ptr, sheight); 01865 #endif 01866 } 01867 #endif 01868 01869 #if defined(PNG_READ_tIME_SUPPORTED) 01870 void /* PRIVATE */ 01871 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01872 { 01873 png_byte buf[7]; 01874 png_time mod_time; 01875 01876 png_debug(1, "in png_handle_tIME"); 01877 01878 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01879 png_error(png_ptr, "Out of place tIME chunk"); 01880 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) 01881 { 01882 png_warning(png_ptr, "Duplicate tIME chunk"); 01883 png_crc_finish(png_ptr, length); 01884 return; 01885 } 01886 01887 if (png_ptr->mode & PNG_HAVE_IDAT) 01888 png_ptr->mode |= PNG_AFTER_IDAT; 01889 01890 if (length != 7) 01891 { 01892 png_warning(png_ptr, "Incorrect tIME chunk length"); 01893 png_crc_finish(png_ptr, length); 01894 return; 01895 } 01896 01897 png_crc_read(png_ptr, buf, 7); 01898 if (png_crc_finish(png_ptr, 0)) 01899 return; 01900 01901 mod_time.second = buf[6]; 01902 mod_time.minute = buf[5]; 01903 mod_time.hour = buf[4]; 01904 mod_time.day = buf[3]; 01905 mod_time.month = buf[2]; 01906 mod_time.year = png_get_uint_16(buf); 01907 01908 png_set_tIME(png_ptr, info_ptr, &mod_time); 01909 } 01910 #endif 01911 01912 #if defined(PNG_READ_tEXt_SUPPORTED) 01913 /* Note: this does not properly handle chunks that are > 64K under DOS */ 01914 void /* PRIVATE */ 01915 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 01916 { 01917 png_textp text_ptr; 01918 png_charp key; 01919 png_charp text; 01920 png_uint_32 skip = 0; 01921 png_size_t slength; 01922 int ret; 01923 01924 png_debug(1, "in png_handle_tEXt"); 01925 01926 01927 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 01928 png_error(png_ptr, "Missing IHDR before tEXt"); 01929 01930 if (png_ptr->mode & PNG_HAVE_IDAT) 01931 png_ptr->mode |= PNG_AFTER_IDAT; 01932 01933 #ifdef PNG_MAX_MALLOC_64K 01934 if (length > (png_uint_32)65535L) 01935 { 01936 png_warning(png_ptr, "tEXt chunk too large to fit in memory"); 01937 skip = length - (png_uint_32)65535L; 01938 length = (png_uint_32)65535L; 01939 } 01940 #endif 01941 01942 png_free(png_ptr, png_ptr->chunkdata); 01943 01944 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); 01945 if (png_ptr->chunkdata == NULL) 01946 { 01947 png_warning(png_ptr, "No memory to process text chunk."); 01948 return; 01949 } 01950 slength = (png_size_t)length; 01951 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 01952 01953 if (png_crc_finish(png_ptr, skip)) 01954 { 01955 png_free(png_ptr, png_ptr->chunkdata); 01956 png_ptr->chunkdata = NULL; 01957 return; 01958 } 01959 01960 key = png_ptr->chunkdata; 01961 01962 key[slength] = 0x00; 01963 01964 for (text = key; *text; text++) 01965 /* Empty loop to find end of key */ ; 01966 01967 if (text != key + slength) 01968 text++; 01969 01970 text_ptr = (png_textp)png_malloc_warn(png_ptr, 01971 (png_uint_32)png_sizeof(png_text)); 01972 if (text_ptr == NULL) 01973 { 01974 png_warning(png_ptr, "Not enough memory to process text chunk."); 01975 png_free(png_ptr, png_ptr->chunkdata); 01976 png_ptr->chunkdata = NULL; 01977 return; 01978 } 01979 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; 01980 text_ptr->key = key; 01981 #ifdef PNG_iTXt_SUPPORTED 01982 text_ptr->lang = NULL; 01983 text_ptr->lang_key = NULL; 01984 text_ptr->itxt_length = 0; 01985 #endif 01986 text_ptr->text = text; 01987 text_ptr->text_length = png_strlen(text); 01988 01989 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); 01990 01991 png_free(png_ptr, png_ptr->chunkdata); 01992 png_ptr->chunkdata = NULL; 01993 png_free(png_ptr, text_ptr); 01994 if (ret) 01995 png_warning(png_ptr, "Insufficient memory to process text chunk."); 01996 } 01997 #endif 01998 01999 #if defined(PNG_READ_zTXt_SUPPORTED) 02000 /* Note: this does not correctly handle chunks that are > 64K under DOS */ 02001 void /* PRIVATE */ 02002 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 02003 { 02004 png_textp text_ptr; 02005 png_charp text; 02006 int comp_type; 02007 int ret; 02008 png_size_t slength, prefix_len, data_len; 02009 02010 png_debug(1, "in png_handle_zTXt"); 02011 02012 02013 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 02014 png_error(png_ptr, "Missing IHDR before zTXt"); 02015 02016 if (png_ptr->mode & PNG_HAVE_IDAT) 02017 png_ptr->mode |= PNG_AFTER_IDAT; 02018 02019 #ifdef PNG_MAX_MALLOC_64K 02020 /* We will no doubt have problems with chunks even half this size, but 02021 there is no hard and fast rule to tell us where to stop. */ 02022 if (length > (png_uint_32)65535L) 02023 { 02024 png_warning(png_ptr, "zTXt chunk too large to fit in memory"); 02025 png_crc_finish(png_ptr, length); 02026 return; 02027 } 02028 #endif 02029 02030 png_free(png_ptr, png_ptr->chunkdata); 02031 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); 02032 if (png_ptr->chunkdata == NULL) 02033 { 02034 png_warning(png_ptr, "Out of memory processing zTXt chunk."); 02035 return; 02036 } 02037 slength = (png_size_t)length; 02038 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 02039 if (png_crc_finish(png_ptr, 0)) 02040 { 02041 png_free(png_ptr, png_ptr->chunkdata); 02042 png_ptr->chunkdata = NULL; 02043 return; 02044 } 02045 02046 png_ptr->chunkdata[slength] = 0x00; 02047 02048 for (text = png_ptr->chunkdata; *text; text++) 02049 /* Empty loop */ ; 02050 02051 /* zTXt must have some text after the chunkdataword */ 02052 if (text >= png_ptr->chunkdata + slength - 2) 02053 { 02054 png_warning(png_ptr, "Truncated zTXt chunk"); 02055 png_free(png_ptr, png_ptr->chunkdata); 02056 png_ptr->chunkdata = NULL; 02057 return; 02058 } 02059 else 02060 { 02061 comp_type = *(++text); 02062 if (comp_type != PNG_TEXT_COMPRESSION_zTXt) 02063 { 02064 png_warning(png_ptr, "Unknown compression type in zTXt chunk"); 02065 comp_type = PNG_TEXT_COMPRESSION_zTXt; 02066 } 02067 text++; /* Skip the compression_method byte */ 02068 } 02069 prefix_len = text - png_ptr->chunkdata; 02070 02071 png_decompress_chunk(png_ptr, comp_type, 02072 (png_size_t)length, prefix_len, &data_len); 02073 02074 text_ptr = (png_textp)png_malloc_warn(png_ptr, 02075 (png_uint_32)png_sizeof(png_text)); 02076 if (text_ptr == NULL) 02077 { 02078 png_warning(png_ptr, "Not enough memory to process zTXt chunk."); 02079 png_free(png_ptr, png_ptr->chunkdata); 02080 png_ptr->chunkdata = NULL; 02081 return; 02082 } 02083 text_ptr->compression = comp_type; 02084 text_ptr->key = png_ptr->chunkdata; 02085 #ifdef PNG_iTXt_SUPPORTED 02086 text_ptr->lang = NULL; 02087 text_ptr->lang_key = NULL; 02088 text_ptr->itxt_length = 0; 02089 #endif 02090 text_ptr->text = png_ptr->chunkdata + prefix_len; 02091 text_ptr->text_length = data_len; 02092 02093 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); 02094 02095 png_free(png_ptr, text_ptr); 02096 png_free(png_ptr, png_ptr->chunkdata); 02097 png_ptr->chunkdata = NULL; 02098 if (ret) 02099 png_error(png_ptr, "Insufficient memory to store zTXt chunk."); 02100 } 02101 #endif 02102 02103 #if defined(PNG_READ_iTXt_SUPPORTED) 02104 /* Note: this does not correctly handle chunks that are > 64K under DOS */ 02105 void /* PRIVATE */ 02106 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 02107 { 02108 png_textp text_ptr; 02109 png_charp key, lang, text, lang_key; 02110 int comp_flag; 02111 int comp_type = 0; 02112 int ret; 02113 png_size_t slength, prefix_len, data_len; 02114 02115 png_debug(1, "in png_handle_iTXt"); 02116 02117 02118 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 02119 png_error(png_ptr, "Missing IHDR before iTXt"); 02120 02121 if (png_ptr->mode & PNG_HAVE_IDAT) 02122 png_ptr->mode |= PNG_AFTER_IDAT; 02123 02124 #ifdef PNG_MAX_MALLOC_64K 02125 /* We will no doubt have problems with chunks even half this size, but 02126 there is no hard and fast rule to tell us where to stop. */ 02127 if (length > (png_uint_32)65535L) 02128 { 02129 png_warning(png_ptr, "iTXt chunk too large to fit in memory"); 02130 png_crc_finish(png_ptr, length); 02131 return; 02132 } 02133 #endif 02134 02135 png_free(png_ptr, png_ptr->chunkdata); 02136 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); 02137 if (png_ptr->chunkdata == NULL) 02138 { 02139 png_warning(png_ptr, "No memory to process iTXt chunk."); 02140 return; 02141 } 02142 slength = (png_size_t)length; 02143 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); 02144 if (png_crc_finish(png_ptr, 0)) 02145 { 02146 png_free(png_ptr, png_ptr->chunkdata); 02147 png_ptr->chunkdata = NULL; 02148 return; 02149 } 02150 02151 png_ptr->chunkdata[slength] = 0x00; 02152 02153 for (lang = png_ptr->chunkdata; *lang; lang++) 02154 /* Empty loop */ ; 02155 lang++; /* Skip NUL separator */ 02156 02157 /* iTXt must have a language tag (possibly empty), two compression bytes, 02158 * translated keyword (possibly empty), and possibly some text after the 02159 * keyword 02160 */ 02161 02162 if (lang >= png_ptr->chunkdata + slength - 3) 02163 { 02164 png_warning(png_ptr, "Truncated iTXt chunk"); 02165 png_free(png_ptr, png_ptr->chunkdata); 02166 png_ptr->chunkdata = NULL; 02167 return; 02168 } 02169 else 02170 { 02171 comp_flag = *lang++; 02172 comp_type = *lang++; 02173 } 02174 02175 for (lang_key = lang; *lang_key; lang_key++) 02176 /* Empty loop */ ; 02177 lang_key++; /* Skip NUL separator */ 02178 02179 if (lang_key >= png_ptr->chunkdata + slength) 02180 { 02181 png_warning(png_ptr, "Truncated iTXt chunk"); 02182 png_free(png_ptr, png_ptr->chunkdata); 02183 png_ptr->chunkdata = NULL; 02184 return; 02185 } 02186 02187 for (text = lang_key; *text; text++) 02188 /* Empty loop */ ; 02189 text++; /* Skip NUL separator */ 02190 if (text >= png_ptr->chunkdata + slength) 02191 { 02192 png_warning(png_ptr, "Malformed iTXt chunk"); 02193 png_free(png_ptr, png_ptr->chunkdata); 02194 png_ptr->chunkdata = NULL; 02195 return; 02196 } 02197 02198 prefix_len = text - png_ptr->chunkdata; 02199 02200 key=png_ptr->chunkdata; 02201 if (comp_flag) 02202 png_decompress_chunk(png_ptr, comp_type, 02203 (size_t)length, prefix_len, &data_len); 02204 else 02205 data_len = png_strlen(png_ptr->chunkdata + prefix_len); 02206 text_ptr = (png_textp)png_malloc_warn(png_ptr, 02207 (png_uint_32)png_sizeof(png_text)); 02208 if (text_ptr == NULL) 02209 { 02210 png_warning(png_ptr, "Not enough memory to process iTXt chunk."); 02211 png_free(png_ptr, png_ptr->chunkdata); 02212 png_ptr->chunkdata = NULL; 02213 return; 02214 } 02215 text_ptr->compression = (int)comp_flag + 1; 02216 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); 02217 text_ptr->lang = png_ptr->chunkdata + (lang - key); 02218 text_ptr->itxt_length = data_len; 02219 text_ptr->text_length = 0; 02220 text_ptr->key = png_ptr->chunkdata; 02221 text_ptr->text = png_ptr->chunkdata + prefix_len; 02222 02223 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); 02224 02225 png_free(png_ptr, text_ptr); 02226 png_free(png_ptr, png_ptr->chunkdata); 02227 png_ptr->chunkdata = NULL; 02228 if (ret) 02229 png_error(png_ptr, "Insufficient memory to store iTXt chunk."); 02230 } 02231 #endif 02232 02233 /* This function is called when we haven't found a handler for a 02234 chunk. If there isn't a problem with the chunk itself (ie bad 02235 chunk name, CRC, or a critical chunk), the chunk is silently ignored 02236 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which 02237 case it will be saved away to be written out later. */ 02238 void /* PRIVATE */ 02239 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 02240 { 02241 png_uint_32 skip = 0; 02242 02243 png_debug(1, "in png_handle_unknown"); 02244 02245 02246 if (png_ptr->mode & PNG_HAVE_IDAT) 02247 { 02248 #ifdef PNG_USE_LOCAL_ARRAYS 02249 PNG_CONST PNG_IDAT; 02250 #endif 02251 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ 02252 png_ptr->mode |= PNG_AFTER_IDAT; 02253 } 02254 02255 if (!(png_ptr->chunk_name[0] & 0x20)) 02256 { 02257 #if defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) 02258 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != 02259 PNG_HANDLE_CHUNK_ALWAYS 02260 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) 02261 && png_ptr->read_user_chunk_fn == NULL 02262 #endif 02263 ) 02264 #endif 02265 png_chunk_error(png_ptr, "unknown critical chunk"); 02266 } 02267 02268 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) 02269 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) 02270 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) 02271 || (png_ptr->read_user_chunk_fn != NULL) 02272 #endif 02273 ) 02274 { 02275 #ifdef PNG_MAX_MALLOC_64K 02276 if (length > (png_uint_32)65535L) 02277 { 02278 png_warning(png_ptr, "unknown chunk too large to fit in memory"); 02279 skip = length - (png_uint_32)65535L; 02280 length = (png_uint_32)65535L; 02281 } 02282 #endif 02283 png_memcpy((png_charp)png_ptr->unknown_chunk.name, 02284 (png_charp)png_ptr->chunk_name, 02285 png_sizeof(png_ptr->unknown_chunk.name)); 02286 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0'; 02287 png_ptr->unknown_chunk.size = (png_size_t)length; 02288 if (length == 0) 02289 png_ptr->unknown_chunk.data = NULL; 02290 else 02291 { 02292 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); 02293 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); 02294 } 02295 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) 02296 if (png_ptr->read_user_chunk_fn != NULL) 02297 { 02298 /* Callback to user unknown chunk handler */ 02299 int ret; 02300 ret = (*(png_ptr->read_user_chunk_fn)) 02301 (png_ptr, &png_ptr->unknown_chunk); 02302 if (ret < 0) 02303 png_chunk_error(png_ptr, "error in user chunk"); 02304 if (ret == 0) 02305 { 02306 if (!(png_ptr->chunk_name[0] & 0x20)) 02307 #if defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) 02308 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != 02309 PNG_HANDLE_CHUNK_ALWAYS) 02310 #endif 02311 png_chunk_error(png_ptr, "unknown critical chunk"); 02312 png_set_unknown_chunks(png_ptr, info_ptr, 02313 &png_ptr->unknown_chunk, 1); 02314 } 02315 } 02316 else 02317 #endif 02318 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); 02319 png_free(png_ptr, png_ptr->unknown_chunk.data); 02320 png_ptr->unknown_chunk.data = NULL; 02321 } 02322 else 02323 #endif 02324 skip = length; 02325 02326 png_crc_finish(png_ptr, skip); 02327 02328 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) 02329 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ 02330 #endif 02331 } 02332 02333 /* This function is called to verify that a chunk name is valid. 02334 This function can't have the "critical chunk check" incorporated 02335 into it, since in the future we will need to be able to call user 02336 functions to handle unknown critical chunks after we check that 02337 the chunk name itself is valid. */ 02338 02339 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) 02340 02341 void /* PRIVATE */ 02342 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) 02343 { 02344 png_debug(1, "in png_check_chunk_name"); 02345 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || 02346 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) 02347 { 02348 png_chunk_error(png_ptr, "invalid chunk type"); 02349 } 02350 } 02351 02352 /* Combines the row recently read in with the existing pixels in the 02353 row. This routine takes care of alpha and transparency if requested. 02354 This routine also handles the two methods of progressive display 02355 of interlaced images, depending on the mask value. 02356 The mask value describes which pixels are to be combined with 02357 the row. The pattern always repeats every 8 pixels, so just 8 02358 bits are needed. A one indicates the pixel is to be combined, 02359 a zero indicates the pixel is to be skipped. This is in addition 02360 to any alpha or transparency value associated with the pixel. If 02361 you want all pixels to be combined, pass 0xff (255) in mask. */ 02362 02363 void /* PRIVATE */ 02364 png_combine_row(png_structp png_ptr, png_bytep row, int mask) 02365 { 02366 png_debug(1, "in png_combine_row"); 02367 if (mask == 0xff) 02368 { 02369 png_memcpy(row, png_ptr->row_buf + 1, 02370 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); 02371 } 02372 else 02373 { 02374 switch (png_ptr->row_info.pixel_depth) 02375 { 02376 case 1: 02377 { 02378 png_bytep sp = png_ptr->row_buf + 1; 02379 png_bytep dp = row; 02380 int s_inc, s_start, s_end; 02381 int m = 0x80; 02382 int shift; 02383 png_uint_32 i; 02384 png_uint_32 row_width = png_ptr->width; 02385 02386 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 02387 if (png_ptr->transformations & PNG_PACKSWAP) 02388 { 02389 s_start = 0; 02390 s_end = 7; 02391 s_inc = 1; 02392 } 02393 else 02394 #endif 02395 { 02396 s_start = 7; 02397 s_end = 0; 02398 s_inc = -1; 02399 } 02400 02401 shift = s_start; 02402 02403 for (i = 0; i < row_width; i++) 02404 { 02405 if (m & mask) 02406 { 02407 int value; 02408 02409 value = (*sp >> shift) & 0x01; 02410 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); 02411 *dp |= (png_byte)(value << shift); 02412 } 02413 02414 if (shift == s_end) 02415 { 02416 shift = s_start; 02417 sp++; 02418 dp++; 02419 } 02420 else 02421 shift += s_inc; 02422 02423 if (m == 1) 02424 m = 0x80; 02425 else 02426 m >>= 1; 02427 } 02428 break; 02429 } 02430 case 2: 02431 { 02432 png_bytep sp = png_ptr->row_buf + 1; 02433 png_bytep dp = row; 02434 int s_start, s_end, s_inc; 02435 int m = 0x80; 02436 int shift; 02437 png_uint_32 i; 02438 png_uint_32 row_width = png_ptr->width; 02439 int value; 02440 02441 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 02442 if (png_ptr->transformations & PNG_PACKSWAP) 02443 { 02444 s_start = 0; 02445 s_end = 6; 02446 s_inc = 2; 02447 } 02448 else 02449 #endif 02450 { 02451 s_start = 6; 02452 s_end = 0; 02453 s_inc = -2; 02454 } 02455 02456 shift = s_start; 02457 02458 for (i = 0; i < row_width; i++) 02459 { 02460 if (m & mask) 02461 { 02462 value = (*sp >> shift) & 0x03; 02463 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 02464 *dp |= (png_byte)(value << shift); 02465 } 02466 02467 if (shift == s_end) 02468 { 02469 shift = s_start; 02470 sp++; 02471 dp++; 02472 } 02473 else 02474 shift += s_inc; 02475 if (m == 1) 02476 m = 0x80; 02477 else 02478 m >>= 1; 02479 } 02480 break; 02481 } 02482 case 4: 02483 { 02484 png_bytep sp = png_ptr->row_buf + 1; 02485 png_bytep dp = row; 02486 int s_start, s_end, s_inc; 02487 int m = 0x80; 02488 int shift; 02489 png_uint_32 i; 02490 png_uint_32 row_width = png_ptr->width; 02491 int value; 02492 02493 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 02494 if (png_ptr->transformations & PNG_PACKSWAP) 02495 { 02496 s_start = 0; 02497 s_end = 4; 02498 s_inc = 4; 02499 } 02500 else 02501 #endif 02502 { 02503 s_start = 4; 02504 s_end = 0; 02505 s_inc = -4; 02506 } 02507 shift = s_start; 02508 02509 for (i = 0; i < row_width; i++) 02510 { 02511 if (m & mask) 02512 { 02513 value = (*sp >> shift) & 0xf; 02514 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 02515 *dp |= (png_byte)(value << shift); 02516 } 02517 02518 if (shift == s_end) 02519 { 02520 shift = s_start; 02521 sp++; 02522 dp++; 02523 } 02524 else 02525 shift += s_inc; 02526 if (m == 1) 02527 m = 0x80; 02528 else 02529 m >>= 1; 02530 } 02531 break; 02532 } 02533 default: 02534 { 02535 png_bytep sp = png_ptr->row_buf + 1; 02536 png_bytep dp = row; 02537 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); 02538 png_uint_32 i; 02539 png_uint_32 row_width = png_ptr->width; 02540 png_byte m = 0x80; 02541 02542 02543 for (i = 0; i < row_width; i++) 02544 { 02545 if (m & mask) 02546 { 02547 png_memcpy(dp, sp, pixel_bytes); 02548 } 02549 02550 sp += pixel_bytes; 02551 dp += pixel_bytes; 02552 02553 if (m == 1) 02554 m = 0x80; 02555 else 02556 m >>= 1; 02557 } 02558 break; 02559 } 02560 } 02561 } 02562 } 02563 02564 #ifdef PNG_READ_INTERLACING_SUPPORTED 02565 /* OLD pre-1.0.9 interface: 02566 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, 02567 png_uint_32 transformations) 02568 */ 02569 void /* PRIVATE */ 02570 png_do_read_interlace(png_structp png_ptr) 02571 { 02572 png_row_infop row_info = &(png_ptr->row_info); 02573 png_bytep row = png_ptr->row_buf + 1; 02574 int pass = png_ptr->pass; 02575 png_uint_32 transformations = png_ptr->transformations; 02576 #ifdef PNG_USE_LOCAL_ARRAYS 02577 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 02578 /* Offset to next interlace block */ 02579 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 02580 #endif 02581 02582 png_debug(1, "in png_do_read_interlace"); 02583 if (row != NULL && row_info != NULL) 02584 { 02585 png_uint_32 final_width; 02586 02587 final_width = row_info->width * png_pass_inc[pass]; 02588 02589 switch (row_info->pixel_depth) 02590 { 02591 case 1: 02592 { 02593 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); 02594 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); 02595 int sshift, dshift; 02596 int s_start, s_end, s_inc; 02597 int jstop = png_pass_inc[pass]; 02598 png_byte v; 02599 png_uint_32 i; 02600 int j; 02601 02602 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 02603 if (transformations & PNG_PACKSWAP) 02604 { 02605 sshift = (int)((row_info->width + 7) & 0x07); 02606 dshift = (int)((final_width + 7) & 0x07); 02607 s_start = 7; 02608 s_end = 0; 02609 s_inc = -1; 02610 } 02611 else 02612 #endif 02613 { 02614 sshift = 7 - (int)((row_info->width + 7) & 0x07); 02615 dshift = 7 - (int)((final_width + 7) & 0x07); 02616 s_start = 0; 02617 s_end = 7; 02618 s_inc = 1; 02619 } 02620 02621 for (i = 0; i < row_info->width; i++) 02622 { 02623 v = (png_byte)((*sp >> sshift) & 0x01); 02624 for (j = 0; j < jstop; j++) 02625 { 02626 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); 02627 *dp |= (png_byte)(v << dshift); 02628 if (dshift == s_end) 02629 { 02630 dshift = s_start; 02631 dp--; 02632 } 02633 else 02634 dshift += s_inc; 02635 } 02636 if (sshift == s_end) 02637 { 02638 sshift = s_start; 02639 sp--; 02640 } 02641 else 02642 sshift += s_inc; 02643 } 02644 break; 02645 } 02646 case 2: 02647 { 02648 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); 02649 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); 02650 int sshift, dshift; 02651 int s_start, s_end, s_inc; 02652 int jstop = png_pass_inc[pass]; 02653 png_uint_32 i; 02654 02655 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 02656 if (transformations & PNG_PACKSWAP) 02657 { 02658 sshift = (int)(((row_info->width + 3) & 0x03) << 1); 02659 dshift = (int)(((final_width + 3) & 0x03) << 1); 02660 s_start = 6; 02661 s_end = 0; 02662 s_inc = -2; 02663 } 02664 else 02665 #endif 02666 { 02667 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); 02668 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); 02669 s_start = 0; 02670 s_end = 6; 02671 s_inc = 2; 02672 } 02673 02674 for (i = 0; i < row_info->width; i++) 02675 { 02676 png_byte v; 02677 int j; 02678 02679 v = (png_byte)((*sp >> sshift) & 0x03); 02680 for (j = 0; j < jstop; j++) 02681 { 02682 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); 02683 *dp |= (png_byte)(v << dshift); 02684 if (dshift == s_end) 02685 { 02686 dshift = s_start; 02687 dp--; 02688 } 02689 else 02690 dshift += s_inc; 02691 } 02692 if (sshift == s_end) 02693 { 02694 sshift = s_start; 02695 sp--; 02696 } 02697 else 02698 sshift += s_inc; 02699 } 02700 break; 02701 } 02702 case 4: 02703 { 02704 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); 02705 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); 02706 int sshift, dshift; 02707 int s_start, s_end, s_inc; 02708 png_uint_32 i; 02709 int jstop = png_pass_inc[pass]; 02710 02711 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 02712 if (transformations & PNG_PACKSWAP) 02713 { 02714 sshift = (int)(((row_info->width + 1) & 0x01) << 2); 02715 dshift = (int)(((final_width + 1) & 0x01) << 2); 02716 s_start = 4; 02717 s_end = 0; 02718 s_inc = -4; 02719 } 02720 else 02721 #endif 02722 { 02723 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); 02724 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); 02725 s_start = 0; 02726 s_end = 4; 02727 s_inc = 4; 02728 } 02729 02730 for (i = 0; i < row_info->width; i++) 02731 { 02732 png_byte v = (png_byte)((*sp >> sshift) & 0xf); 02733 int j; 02734 02735 for (j = 0; j < jstop; j++) 02736 { 02737 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); 02738 *dp |= (png_byte)(v << dshift); 02739 if (dshift == s_end) 02740 { 02741 dshift = s_start; 02742 dp--; 02743 } 02744 else 02745 dshift += s_inc; 02746 } 02747 if (sshift == s_end) 02748 { 02749 sshift = s_start; 02750 sp--; 02751 } 02752 else 02753 sshift += s_inc; 02754 } 02755 break; 02756 } 02757 default: 02758 { 02759 png_size_t pixel_bytes = (row_info->pixel_depth >> 3); 02760 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; 02761 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; 02762 02763 int jstop = png_pass_inc[pass]; 02764 png_uint_32 i; 02765 02766 for (i = 0; i < row_info->width; i++) 02767 { 02768 png_byte v[8]; 02769 int j; 02770 02771 png_memcpy(v, sp, pixel_bytes); 02772 for (j = 0; j < jstop; j++) 02773 { 02774 png_memcpy(dp, v, pixel_bytes); 02775 dp -= pixel_bytes; 02776 } 02777 sp -= pixel_bytes; 02778 } 02779 break; 02780 } 02781 } 02782 row_info->width = final_width; 02783 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); 02784 } 02785 #if !defined(PNG_READ_PACKSWAP_SUPPORTED) 02786 transformations = transformations; /* Silence compiler warning */ 02787 #endif 02788 } 02789 #endif /* PNG_READ_INTERLACING_SUPPORTED */ 02790 02791 void /* PRIVATE */ 02792 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, 02793 png_bytep prev_row, int filter) 02794 { 02795 png_debug(1, "in png_read_filter_row"); 02796 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter); 02797 switch (filter) 02798 { 02799 case PNG_FILTER_VALUE_NONE: 02800 break; 02801 case PNG_FILTER_VALUE_SUB: 02802 { 02803 png_uint_32 i; 02804 png_uint_32 istop = row_info->rowbytes; 02805 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; 02806 png_bytep rp = row + bpp; 02807 png_bytep lp = row; 02808 02809 for (i = bpp; i < istop; i++) 02810 { 02811 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); 02812 rp++; 02813 } 02814 break; 02815 } 02816 case PNG_FILTER_VALUE_UP: 02817 { 02818 png_uint_32 i; 02819 png_uint_32 istop = row_info->rowbytes; 02820 png_bytep rp = row; 02821 png_bytep pp = prev_row; 02822 02823 for (i = 0; i < istop; i++) 02824 { 02825 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); 02826 rp++; 02827 } 02828 break; 02829 } 02830 case PNG_FILTER_VALUE_AVG: 02831 { 02832 png_uint_32 i; 02833 png_bytep rp = row; 02834 png_bytep pp = prev_row; 02835 png_bytep lp = row; 02836 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; 02837 png_uint_32 istop = row_info->rowbytes - bpp; 02838 02839 for (i = 0; i < bpp; i++) 02840 { 02841 *rp = (png_byte)(((int)(*rp) + 02842 ((int)(*pp++) / 2 )) & 0xff); 02843 rp++; 02844 } 02845 02846 for (i = 0; i < istop; i++) 02847 { 02848 *rp = (png_byte)(((int)(*rp) + 02849 (int)(*pp++ + *lp++) / 2 ) & 0xff); 02850 rp++; 02851 } 02852 break; 02853 } 02854 case PNG_FILTER_VALUE_PAETH: 02855 { 02856 png_uint_32 i; 02857 png_bytep rp = row; 02858 png_bytep pp = prev_row; 02859 png_bytep lp = row; 02860 png_bytep cp = prev_row; 02861 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; 02862 png_uint_32 istop=row_info->rowbytes - bpp; 02863 02864 for (i = 0; i < bpp; i++) 02865 { 02866 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); 02867 rp++; 02868 } 02869 02870 for (i = 0; i < istop; i++) /* Use leftover rp,pp */ 02871 { 02872 int a, b, c, pa, pb, pc, p; 02873 02874 a = *lp++; 02875 b = *pp++; 02876 c = *cp++; 02877 02878 p = b - c; 02879 pc = a - c; 02880 02881 #ifdef PNG_USE_ABS 02882 pa = abs(p); 02883 pb = abs(pc); 02884 pc = abs(p + pc); 02885 #else 02886 pa = p < 0 ? -p : p; 02887 pb = pc < 0 ? -pc : pc; 02888 pc = (p + pc) < 0 ? -(p + pc) : p + pc; 02889 #endif 02890 02891 /* 02892 if (pa <= pb && pa <= pc) 02893 p = a; 02894 else if (pb <= pc) 02895 p = b; 02896 else 02897 p = c; 02898 */ 02899 02900 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; 02901 02902 *rp = (png_byte)(((int)(*rp) + p) & 0xff); 02903 rp++; 02904 } 02905 break; 02906 } 02907 default: 02908 png_warning(png_ptr, "Ignoring bad adaptive filter type"); 02909 *row = 0; 02910 break; 02911 } 02912 } 02913 02914 #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED 02915 void /* PRIVATE */ 02916 png_read_finish_row(png_structp png_ptr) 02917 { 02918 #ifdef PNG_USE_LOCAL_ARRAYS 02919 #ifdef PNG_READ_INTERLACING_SUPPORTED 02920 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 02921 02922 /* Start of interlace block */ 02923 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 02924 02925 /* Offset to next interlace block */ 02926 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 02927 02928 /* Start of interlace block in the y direction */ 02929 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 02930 02931 /* Offset to next interlace block in the y direction */ 02932 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 02933 #endif /* PNG_READ_INTERLACING_SUPPORTED */ 02934 #endif 02935 02936 png_debug(1, "in png_read_finish_row"); 02937 png_ptr->row_number++; 02938 if (png_ptr->row_number < png_ptr->num_rows) 02939 return; 02940 02941 #ifdef PNG_READ_INTERLACING_SUPPORTED 02942 if (png_ptr->interlaced) 02943 { 02944 png_ptr->row_number = 0; 02945 png_memset_check(png_ptr, png_ptr->prev_row, 0, 02946 png_ptr->rowbytes + 1); 02947 do 02948 { 02949 png_ptr->pass++; 02950 if (png_ptr->pass >= 7) 02951 break; 02952 png_ptr->iwidth = (png_ptr->width + 02953 png_pass_inc[png_ptr->pass] - 1 - 02954 png_pass_start[png_ptr->pass]) / 02955 png_pass_inc[png_ptr->pass]; 02956 02957 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, 02958 png_ptr->iwidth) + 1; 02959 02960 if (!(png_ptr->transformations & PNG_INTERLACE)) 02961 { 02962 png_ptr->num_rows = (png_ptr->height + 02963 png_pass_yinc[png_ptr->pass] - 1 - 02964 png_pass_ystart[png_ptr->pass]) / 02965 png_pass_yinc[png_ptr->pass]; 02966 if (!(png_ptr->num_rows)) 02967 continue; 02968 } 02969 else /* if (png_ptr->transformations & PNG_INTERLACE) */ 02970 break; 02971 } while (png_ptr->iwidth == 0); 02972 02973 if (png_ptr->pass < 7) 02974 return; 02975 } 02976 #endif /* PNG_READ_INTERLACING_SUPPORTED */ 02977 02978 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) 02979 { 02980 #ifdef PNG_USE_LOCAL_ARRAYS 02981 PNG_CONST PNG_IDAT; 02982 #endif 02983 char extra; 02984 int ret; 02985 02986 png_ptr->zstream.next_out = (Byte *)&extra; 02987 png_ptr->zstream.avail_out = (uInt)1; 02988 for (;;) 02989 { 02990 if (!(png_ptr->zstream.avail_in)) 02991 { 02992 while (!png_ptr->idat_size) 02993 { 02994 png_byte chunk_length[4]; 02995 02996 png_crc_finish(png_ptr, 0); 02997 02998 png_read_data(png_ptr, chunk_length, 4); 02999 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); 03000 png_reset_crc(png_ptr); 03001 png_crc_read(png_ptr, png_ptr->chunk_name, 4); 03002 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) 03003 png_error(png_ptr, "Not enough image data"); 03004 03005 } 03006 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; 03007 png_ptr->zstream.next_in = png_ptr->zbuf; 03008 if (png_ptr->zbuf_size > png_ptr->idat_size) 03009 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; 03010 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); 03011 png_ptr->idat_size -= png_ptr->zstream.avail_in; 03012 } 03013 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); 03014 if (ret == Z_STREAM_END) 03015 { 03016 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || 03017 png_ptr->idat_size) 03018 png_warning(png_ptr, "Extra compressed data"); 03019 png_ptr->mode |= PNG_AFTER_IDAT; 03020 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; 03021 break; 03022 } 03023 if (ret != Z_OK) 03024 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : 03025 "Decompression Error"); 03026 03027 if (!(png_ptr->zstream.avail_out)) 03028 { 03029 png_warning(png_ptr, "Extra compressed data."); 03030 png_ptr->mode |= PNG_AFTER_IDAT; 03031 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; 03032 break; 03033 } 03034 03035 } 03036 png_ptr->zstream.avail_out = 0; 03037 } 03038 03039 if (png_ptr->idat_size || png_ptr->zstream.avail_in) 03040 png_warning(png_ptr, "Extra compression data"); 03041 03042 inflateReset(&png_ptr->zstream); 03043 03044 png_ptr->mode |= PNG_AFTER_IDAT; 03045 } 03046 #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ 03047 03048 void /* PRIVATE */ 03049 png_read_start_row(png_structp png_ptr) 03050 { 03051 #ifdef PNG_USE_LOCAL_ARRAYS 03052 #ifdef PNG_READ_INTERLACING_SUPPORTED 03053 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 03054 03055 /* Start of interlace block */ 03056 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 03057 03058 /* Offset to next interlace block */ 03059 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 03060 03061 /* Start of interlace block in the y direction */ 03062 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 03063 03064 /* Offset to next interlace block in the y direction */ 03065 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 03066 #endif 03067 #endif 03068 03069 int max_pixel_depth; 03070 png_size_t row_bytes; 03071 03072 png_debug(1, "in png_read_start_row"); 03073 png_ptr->zstream.avail_in = 0; 03074 png_init_read_transformations(png_ptr); 03075 #ifdef PNG_READ_INTERLACING_SUPPORTED 03076 if (png_ptr->interlaced) 03077 { 03078 if (!(png_ptr->transformations & PNG_INTERLACE)) 03079 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - 03080 png_pass_ystart[0]) / png_pass_yinc[0]; 03081 else 03082 png_ptr->num_rows = png_ptr->height; 03083 03084 png_ptr->iwidth = (png_ptr->width + 03085 png_pass_inc[png_ptr->pass] - 1 - 03086 png_pass_start[png_ptr->pass]) / 03087 png_pass_inc[png_ptr->pass]; 03088 03089 png_ptr->irowbytes = 03090 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; 03091 } 03092 else 03093 #endif /* PNG_READ_INTERLACING_SUPPORTED */ 03094 { 03095 png_ptr->num_rows = png_ptr->height; 03096 png_ptr->iwidth = png_ptr->width; 03097 png_ptr->irowbytes = png_ptr->rowbytes + 1; 03098 } 03099 max_pixel_depth = png_ptr->pixel_depth; 03100 03101 #if defined(PNG_READ_PACK_SUPPORTED) 03102 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) 03103 max_pixel_depth = 8; 03104 #endif 03105 03106 #if defined(PNG_READ_EXPAND_SUPPORTED) 03107 if (png_ptr->transformations & PNG_EXPAND) 03108 { 03109 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 03110 { 03111 if (png_ptr->num_trans) 03112 max_pixel_depth = 32; 03113 else 03114 max_pixel_depth = 24; 03115 } 03116 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) 03117 { 03118 if (max_pixel_depth < 8) 03119 max_pixel_depth = 8; 03120 if (png_ptr->num_trans) 03121 max_pixel_depth *= 2; 03122 } 03123 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) 03124 { 03125 if (png_ptr->num_trans) 03126 { 03127 max_pixel_depth *= 4; 03128 max_pixel_depth /= 3; 03129 } 03130 } 03131 } 03132 #endif 03133 03134 #if defined(PNG_READ_FILLER_SUPPORTED) 03135 if (png_ptr->transformations & (PNG_FILLER)) 03136 { 03137 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 03138 max_pixel_depth = 32; 03139 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) 03140 { 03141 if (max_pixel_depth <= 8) 03142 max_pixel_depth = 16; 03143 else 03144 max_pixel_depth = 32; 03145 } 03146 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) 03147 { 03148 if (max_pixel_depth <= 32) 03149 max_pixel_depth = 32; 03150 else 03151 max_pixel_depth = 64; 03152 } 03153 } 03154 #endif 03155 03156 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 03157 if (png_ptr->transformations & PNG_GRAY_TO_RGB) 03158 { 03159 if ( 03160 #if defined(PNG_READ_EXPAND_SUPPORTED) 03161 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || 03162 #endif 03163 #if defined(PNG_READ_FILLER_SUPPORTED) 03164 (png_ptr->transformations & (PNG_FILLER)) || 03165 #endif 03166 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 03167 { 03168 if (max_pixel_depth <= 16) 03169 max_pixel_depth = 32; 03170 else 03171 max_pixel_depth = 64; 03172 } 03173 else 03174 { 03175 if (max_pixel_depth <= 8) 03176 { 03177 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 03178 max_pixel_depth = 32; 03179 else 03180 max_pixel_depth = 24; 03181 } 03182 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 03183 max_pixel_depth = 64; 03184 else 03185 max_pixel_depth = 48; 03186 } 03187 } 03188 #endif 03189 03190 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ 03191 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) 03192 if (png_ptr->transformations & PNG_USER_TRANSFORM) 03193 { 03194 int user_pixel_depth = png_ptr->user_transform_depth* 03195 png_ptr->user_transform_channels; 03196 if (user_pixel_depth > max_pixel_depth) 03197 max_pixel_depth=user_pixel_depth; 03198 } 03199 #endif 03200 03201 /* Align the width on the next larger 8 pixels. Mainly used 03202 * for interlacing 03203 */ 03204 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); 03205 /* Calculate the maximum bytes needed, adding a byte and a pixel 03206 * for safety's sake 03207 */ 03208 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + 03209 1 + ((max_pixel_depth + 7) >> 3); 03210 #ifdef PNG_MAX_MALLOC_64K 03211 if (row_bytes > (png_uint_32)65536L) 03212 png_error(png_ptr, "This image requires a row greater than 64KB"); 03213 #endif 03214 03215 if (row_bytes + 64 > png_ptr->old_big_row_buf_size) 03216 { 03217 png_free(png_ptr, png_ptr->big_row_buf); 03218 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 64); 03219 if (png_ptr->interlaced) 03220 png_memset(png_ptr->big_row_buf, 0, row_bytes + 64); 03221 png_ptr->row_buf = png_ptr->big_row_buf + 32; 03222 png_ptr->old_big_row_buf_size = row_bytes + 64; 03223 } 03224 03225 #ifdef PNG_MAX_MALLOC_64K 03226 if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L) 03227 png_error(png_ptr, "This image requires a row greater than 64KB"); 03228 #endif 03229 if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1)) 03230 png_error(png_ptr, "Row has too many bytes to allocate in memory."); 03231 03232 if (row_bytes + 1 > png_ptr->old_prev_row_size) 03233 { 03234 png_free(png_ptr, png_ptr->prev_row); 03235 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( 03236 row_bytes + 1)); 03237 png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1); 03238 png_ptr->old_prev_row_size = row_bytes + 1; 03239 } 03240 03241 png_ptr->rowbytes = row_bytes; 03242 03243 png_debug1(3, "width = %lu,", png_ptr->width); 03244 png_debug1(3, "height = %lu,", png_ptr->height); 03245 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth); 03246 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows); 03247 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes); 03248 png_debug1(3, "irowbytes = %lu", png_ptr->irowbytes); 03249 03250 png_ptr->flags |= PNG_FLAG_ROW_INIT; 03251 } 03252 #endif /* PNG_READ_SUPPORTED */