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