Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpngread.c
Go to the documentation of this file.
00001 00002 /* pngread.c - read a PNG file 00003 * 00004 * Last changed in libpng 1.5.7 [December 15, 2011] 00005 * Copyright (c) 1998-2011 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 an application calls directly to 00014 * read a PNG file or stream. 00015 */ 00016 00017 #include "pngpriv.h" 00018 00019 #ifdef PNG_READ_SUPPORTED 00020 00021 /* Create a PNG structure for reading, and allocate any memory needed. */ 00022 PNG_FUNCTION(png_structp,PNGAPI 00023 png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 00024 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) 00025 { 00026 00027 #ifdef PNG_USER_MEM_SUPPORTED 00028 return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, 00029 warn_fn, NULL, NULL, NULL)); 00030 } 00031 00032 /* Alternate create PNG structure for reading, and allocate any memory 00033 * needed. 00034 */ 00035 PNG_FUNCTION(png_structp,PNGAPI 00036 png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, 00037 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 00038 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 00039 { 00040 #endif /* PNG_USER_MEM_SUPPORTED */ 00041 00042 #ifdef PNG_SETJMP_SUPPORTED 00043 volatile 00044 #endif 00045 png_structp png_ptr; 00046 volatile int png_cleanup_needed = 0; 00047 00048 #ifdef PNG_SETJMP_SUPPORTED 00049 #ifdef USE_FAR_KEYWORD 00050 jmp_buf tmp_jmpbuf; 00051 #endif 00052 #endif 00053 00054 png_debug(1, "in png_create_read_struct"); 00055 00056 #ifdef PNG_USER_MEM_SUPPORTED 00057 png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, 00058 malloc_fn, mem_ptr); 00059 #else 00060 png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); 00061 #endif 00062 if (png_ptr == NULL) 00063 return (NULL); 00064 00065 /* Added at libpng-1.2.6 */ 00066 #ifdef PNG_USER_LIMITS_SUPPORTED 00067 png_ptr->user_width_max = PNG_USER_WIDTH_MAX; 00068 png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; 00069 00070 # ifdef PNG_USER_CHUNK_CACHE_MAX 00071 /* Added at libpng-1.2.43 and 1.4.0 */ 00072 png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; 00073 # endif 00074 00075 # ifdef PNG_SET_USER_CHUNK_MALLOC_MAX 00076 /* Added at libpng-1.2.43 and 1.4.1 */ 00077 png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; 00078 # endif 00079 #endif 00080 00081 #ifdef PNG_SETJMP_SUPPORTED 00082 /* Applications that neglect to set up their own setjmp() and then 00083 * encounter a png_error() will longjmp here. Since the jmpbuf is 00084 * then meaningless we abort instead of returning. 00085 */ 00086 #ifdef USE_FAR_KEYWORD 00087 if (setjmp(tmp_jmpbuf)) 00088 #else 00089 if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ 00090 #endif 00091 PNG_ABORT(); 00092 #ifdef USE_FAR_KEYWORD 00093 png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); 00094 #endif 00095 #endif /* PNG_SETJMP_SUPPORTED */ 00096 00097 #ifdef PNG_USER_MEM_SUPPORTED 00098 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); 00099 #endif 00100 00101 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); 00102 00103 /* Call the general version checker (shared with read and write code): */ 00104 if (!png_user_version_check(png_ptr, user_png_ver)) 00105 png_cleanup_needed = 1; 00106 00107 if (!png_cleanup_needed) 00108 { 00109 /* Initialize zbuf - compression buffer */ 00110 png_ptr->zbuf_size = PNG_ZBUF_SIZE; 00111 png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); 00112 00113 if (png_ptr->zbuf == NULL) 00114 png_cleanup_needed = 1; 00115 } 00116 00117 png_ptr->zstream.zalloc = png_zalloc; 00118 png_ptr->zstream.zfree = png_zfree; 00119 png_ptr->zstream.opaque = (voidpf)png_ptr; 00120 00121 if (!png_cleanup_needed) 00122 { 00123 switch (inflateInit(&png_ptr->zstream)) 00124 { 00125 case Z_OK: 00126 break; /* Do nothing */ 00127 00128 case Z_MEM_ERROR: 00129 png_warning(png_ptr, "zlib memory error"); 00130 png_cleanup_needed = 1; 00131 break; 00132 00133 case Z_STREAM_ERROR: 00134 png_warning(png_ptr, "zlib stream error"); 00135 png_cleanup_needed = 1; 00136 break; 00137 00138 case Z_VERSION_ERROR: 00139 png_warning(png_ptr, "zlib version error"); 00140 png_cleanup_needed = 1; 00141 break; 00142 00143 default: png_warning(png_ptr, "Unknown zlib error"); 00144 png_cleanup_needed = 1; 00145 } 00146 } 00147 00148 if (png_cleanup_needed) 00149 { 00150 /* Clean up PNG structure and deallocate any memory. */ 00151 png_free(png_ptr, png_ptr->zbuf); 00152 png_ptr->zbuf = NULL; 00153 #ifdef PNG_USER_MEM_SUPPORTED 00154 png_destroy_struct_2((png_voidp)png_ptr, 00155 (png_free_ptr)free_fn, (png_voidp)mem_ptr); 00156 #else 00157 png_destroy_struct((png_voidp)png_ptr); 00158 #endif 00159 return (NULL); 00160 } 00161 00162 png_ptr->zstream.next_out = png_ptr->zbuf; 00163 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 00164 00165 png_set_read_fn(png_ptr, NULL, NULL); 00166 00167 00168 return (png_ptr); 00169 } 00170 00171 00172 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 00173 /* Read the information before the actual image data. This has been 00174 * changed in v0.90 to allow reading a file that already has the magic 00175 * bytes read from the stream. You can tell libpng how many bytes have 00176 * been read from the beginning of the stream (up to the maximum of 8) 00177 * via png_set_sig_bytes(), and we will only check the remaining bytes 00178 * here. The application can then have access to the signature bytes we 00179 * read if it is determined that this isn't a valid PNG file. 00180 */ 00181 void PNGAPI 00182 png_read_info(png_structp png_ptr, png_infop info_ptr) 00183 { 00184 png_debug(1, "in png_read_info"); 00185 00186 if (png_ptr == NULL || info_ptr == NULL) 00187 return; 00188 00189 /* Read and check the PNG file signature. */ 00190 png_read_sig(png_ptr, info_ptr); 00191 00192 for (;;) 00193 { 00194 png_uint_32 length = png_read_chunk_header(png_ptr); 00195 png_uint_32 chunk_name = png_ptr->chunk_name; 00196 00197 /* This should be a binary subdivision search or a hash for 00198 * matching the chunk name rather than a linear search. 00199 */ 00200 if (chunk_name == png_IDAT) 00201 if (png_ptr->mode & PNG_AFTER_IDAT) 00202 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; 00203 00204 if (chunk_name == png_IHDR) 00205 png_handle_IHDR(png_ptr, info_ptr, length); 00206 00207 else if (chunk_name == png_IEND) 00208 png_handle_IEND(png_ptr, info_ptr, length); 00209 00210 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 00211 else if (png_chunk_unknown_handling(png_ptr, chunk_name) != 00212 PNG_HANDLE_CHUNK_AS_DEFAULT) 00213 { 00214 if (chunk_name == png_IDAT) 00215 png_ptr->mode |= PNG_HAVE_IDAT; 00216 00217 png_handle_unknown(png_ptr, info_ptr, length); 00218 00219 if (chunk_name == png_PLTE) 00220 png_ptr->mode |= PNG_HAVE_PLTE; 00221 00222 else if (chunk_name == png_IDAT) 00223 { 00224 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00225 png_error(png_ptr, "Missing IHDR before IDAT"); 00226 00227 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 00228 !(png_ptr->mode & PNG_HAVE_PLTE)) 00229 png_error(png_ptr, "Missing PLTE before IDAT"); 00230 00231 break; 00232 } 00233 } 00234 #endif 00235 else if (chunk_name == png_PLTE) 00236 png_handle_PLTE(png_ptr, info_ptr, length); 00237 00238 else if (chunk_name == png_IDAT) 00239 { 00240 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 00241 png_error(png_ptr, "Missing IHDR before IDAT"); 00242 00243 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 00244 !(png_ptr->mode & PNG_HAVE_PLTE)) 00245 png_error(png_ptr, "Missing PLTE before IDAT"); 00246 00247 png_ptr->idat_size = length; 00248 png_ptr->mode |= PNG_HAVE_IDAT; 00249 break; 00250 } 00251 00252 #ifdef PNG_READ_bKGD_SUPPORTED 00253 else if (chunk_name == png_bKGD) 00254 png_handle_bKGD(png_ptr, info_ptr, length); 00255 #endif 00256 00257 #ifdef PNG_READ_cHRM_SUPPORTED 00258 else if (chunk_name == png_cHRM) 00259 png_handle_cHRM(png_ptr, info_ptr, length); 00260 #endif 00261 00262 #ifdef PNG_READ_gAMA_SUPPORTED 00263 else if (chunk_name == png_gAMA) 00264 png_handle_gAMA(png_ptr, info_ptr, length); 00265 #endif 00266 00267 #ifdef PNG_READ_hIST_SUPPORTED 00268 else if (chunk_name == png_hIST) 00269 png_handle_hIST(png_ptr, info_ptr, length); 00270 #endif 00271 00272 #ifdef PNG_READ_oFFs_SUPPORTED 00273 else if (chunk_name == png_oFFs) 00274 png_handle_oFFs(png_ptr, info_ptr, length); 00275 #endif 00276 00277 #ifdef PNG_READ_pCAL_SUPPORTED 00278 else if (chunk_name == png_pCAL) 00279 png_handle_pCAL(png_ptr, info_ptr, length); 00280 #endif 00281 00282 #ifdef PNG_READ_sCAL_SUPPORTED 00283 else if (chunk_name == png_sCAL) 00284 png_handle_sCAL(png_ptr, info_ptr, length); 00285 #endif 00286 00287 #ifdef PNG_READ_pHYs_SUPPORTED 00288 else if (chunk_name == png_pHYs) 00289 png_handle_pHYs(png_ptr, info_ptr, length); 00290 #endif 00291 00292 #ifdef PNG_READ_sBIT_SUPPORTED 00293 else if (chunk_name == png_sBIT) 00294 png_handle_sBIT(png_ptr, info_ptr, length); 00295 #endif 00296 00297 #ifdef PNG_READ_sRGB_SUPPORTED 00298 else if (chunk_name == png_sRGB) 00299 png_handle_sRGB(png_ptr, info_ptr, length); 00300 #endif 00301 00302 #ifdef PNG_READ_iCCP_SUPPORTED 00303 else if (chunk_name == png_iCCP) 00304 png_handle_iCCP(png_ptr, info_ptr, length); 00305 #endif 00306 00307 #ifdef PNG_READ_sPLT_SUPPORTED 00308 else if (chunk_name == png_sPLT) 00309 png_handle_sPLT(png_ptr, info_ptr, length); 00310 #endif 00311 00312 #ifdef PNG_READ_tEXt_SUPPORTED 00313 else if (chunk_name == png_tEXt) 00314 png_handle_tEXt(png_ptr, info_ptr, length); 00315 #endif 00316 00317 #ifdef PNG_READ_tIME_SUPPORTED 00318 else if (chunk_name == png_tIME) 00319 png_handle_tIME(png_ptr, info_ptr, length); 00320 #endif 00321 00322 #ifdef PNG_READ_tRNS_SUPPORTED 00323 else if (chunk_name == png_tRNS) 00324 png_handle_tRNS(png_ptr, info_ptr, length); 00325 #endif 00326 00327 #ifdef PNG_READ_zTXt_SUPPORTED 00328 else if (chunk_name == png_zTXt) 00329 png_handle_zTXt(png_ptr, info_ptr, length); 00330 #endif 00331 00332 #ifdef PNG_READ_iTXt_SUPPORTED 00333 else if (chunk_name == png_iTXt) 00334 png_handle_iTXt(png_ptr, info_ptr, length); 00335 #endif 00336 00337 else 00338 png_handle_unknown(png_ptr, info_ptr, length); 00339 } 00340 } 00341 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 00342 00343 /* Optional call to update the users info_ptr structure */ 00344 void PNGAPI 00345 png_read_update_info(png_structp png_ptr, png_infop info_ptr) 00346 { 00347 png_debug(1, "in png_read_update_info"); 00348 00349 if (png_ptr == NULL) 00350 return; 00351 00352 png_read_start_row(png_ptr); 00353 00354 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 00355 png_read_transform_info(png_ptr, info_ptr); 00356 #else 00357 PNG_UNUSED(info_ptr) 00358 #endif 00359 } 00360 00361 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 00362 /* Initialize palette, background, etc, after transformations 00363 * are set, but before any reading takes place. This allows 00364 * the user to obtain a gamma-corrected palette, for example. 00365 * If the user doesn't call this, we will do it ourselves. 00366 */ 00367 void PNGAPI 00368 png_start_read_image(png_structp png_ptr) 00369 { 00370 png_debug(1, "in png_start_read_image"); 00371 00372 if (png_ptr != NULL) 00373 png_read_start_row(png_ptr); 00374 } 00375 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 00376 00377 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 00378 void PNGAPI 00379 png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) 00380 { 00381 int ret; 00382 00383 png_row_info row_info; 00384 00385 if (png_ptr == NULL) 00386 return; 00387 00388 png_debug2(1, "in png_read_row (row %lu, pass %d)", 00389 (unsigned long)png_ptr->row_number, png_ptr->pass); 00390 00391 /* png_read_start_row sets the information (in particular iwidth) for this 00392 * interlace pass. 00393 */ 00394 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 00395 png_read_start_row(png_ptr); 00396 00397 /* 1.5.6: row_info moved out of png_struct to a local here. */ 00398 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ 00399 row_info.color_type = png_ptr->color_type; 00400 row_info.bit_depth = png_ptr->bit_depth; 00401 row_info.channels = png_ptr->channels; 00402 row_info.pixel_depth = png_ptr->pixel_depth; 00403 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); 00404 00405 if (png_ptr->row_number == 0 && png_ptr->pass == 0) 00406 { 00407 /* Check for transforms that have been set but were defined out */ 00408 #if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) 00409 if (png_ptr->transformations & PNG_INVERT_MONO) 00410 png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); 00411 #endif 00412 00413 #if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) 00414 if (png_ptr->transformations & PNG_FILLER) 00415 png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); 00416 #endif 00417 00418 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 00419 !defined(PNG_READ_PACKSWAP_SUPPORTED) 00420 if (png_ptr->transformations & PNG_PACKSWAP) 00421 png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); 00422 #endif 00423 00424 #if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) 00425 if (png_ptr->transformations & PNG_PACK) 00426 png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); 00427 #endif 00428 00429 #if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) 00430 if (png_ptr->transformations & PNG_SHIFT) 00431 png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); 00432 #endif 00433 00434 #if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) 00435 if (png_ptr->transformations & PNG_BGR) 00436 png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); 00437 #endif 00438 00439 #if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) 00440 if (png_ptr->transformations & PNG_SWAP_BYTES) 00441 png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); 00442 #endif 00443 } 00444 00445 #ifdef PNG_READ_INTERLACING_SUPPORTED 00446 /* If interlaced and we do not need a new row, combine row and return. 00447 * Notice that the pixels we have from previous rows have been transformed 00448 * already; we can only combine like with like (transformed or 00449 * untransformed) and, because of the libpng API for interlaced images, this 00450 * means we must transform before de-interlacing. 00451 */ 00452 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) 00453 { 00454 switch (png_ptr->pass) 00455 { 00456 case 0: 00457 if (png_ptr->row_number & 0x07) 00458 { 00459 if (dsp_row != NULL) 00460 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00461 png_read_finish_row(png_ptr); 00462 return; 00463 } 00464 break; 00465 00466 case 1: 00467 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) 00468 { 00469 if (dsp_row != NULL) 00470 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00471 00472 png_read_finish_row(png_ptr); 00473 return; 00474 } 00475 break; 00476 00477 case 2: 00478 if ((png_ptr->row_number & 0x07) != 4) 00479 { 00480 if (dsp_row != NULL && (png_ptr->row_number & 4)) 00481 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00482 00483 png_read_finish_row(png_ptr); 00484 return; 00485 } 00486 break; 00487 00488 case 3: 00489 if ((png_ptr->row_number & 3) || png_ptr->width < 3) 00490 { 00491 if (dsp_row != NULL) 00492 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00493 00494 png_read_finish_row(png_ptr); 00495 return; 00496 } 00497 break; 00498 00499 case 4: 00500 if ((png_ptr->row_number & 3) != 2) 00501 { 00502 if (dsp_row != NULL && (png_ptr->row_number & 2)) 00503 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00504 00505 png_read_finish_row(png_ptr); 00506 return; 00507 } 00508 break; 00509 case 5: 00510 if ((png_ptr->row_number & 1) || png_ptr->width < 2) 00511 { 00512 if (dsp_row != NULL) 00513 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00514 00515 png_read_finish_row(png_ptr); 00516 return; 00517 } 00518 break; 00519 00520 default: 00521 case 6: 00522 if (!(png_ptr->row_number & 1)) 00523 { 00524 png_read_finish_row(png_ptr); 00525 return; 00526 } 00527 break; 00528 } 00529 } 00530 #endif 00531 00532 if (!(png_ptr->mode & PNG_HAVE_IDAT)) 00533 png_error(png_ptr, "Invalid attempt to read row data"); 00534 00535 png_ptr->zstream.next_out = png_ptr->row_buf; 00536 png_ptr->zstream.avail_out = 00537 (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, 00538 png_ptr->iwidth) + 1); 00539 00540 do 00541 { 00542 if (!(png_ptr->zstream.avail_in)) 00543 { 00544 while (!png_ptr->idat_size) 00545 { 00546 png_crc_finish(png_ptr, 0); 00547 00548 png_ptr->idat_size = png_read_chunk_header(png_ptr); 00549 if (png_ptr->chunk_name != png_IDAT) 00550 png_error(png_ptr, "Not enough image data"); 00551 } 00552 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; 00553 png_ptr->zstream.next_in = png_ptr->zbuf; 00554 if (png_ptr->zbuf_size > png_ptr->idat_size) 00555 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; 00556 png_crc_read(png_ptr, png_ptr->zbuf, 00557 (png_size_t)png_ptr->zstream.avail_in); 00558 png_ptr->idat_size -= png_ptr->zstream.avail_in; 00559 } 00560 00561 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); 00562 00563 if (ret == Z_STREAM_END) 00564 { 00565 if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || 00566 png_ptr->idat_size) 00567 png_benign_error(png_ptr, "Extra compressed data"); 00568 png_ptr->mode |= PNG_AFTER_IDAT; 00569 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; 00570 break; 00571 } 00572 00573 if (ret != Z_OK) 00574 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : 00575 "Decompression error"); 00576 00577 } while (png_ptr->zstream.avail_out); 00578 00579 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) 00580 { 00581 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) 00582 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, 00583 png_ptr->prev_row + 1, png_ptr->row_buf[0]); 00584 else 00585 png_error(png_ptr, "bad adaptive filter value"); 00586 } 00587 00588 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before 00589 * 1.5.6, while the buffer really is this big in current versions of libpng 00590 * it may not be in the future, so this was changed just to copy the 00591 * interlaced count: 00592 */ 00593 png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); 00594 00595 #ifdef PNG_MNG_FEATURES_SUPPORTED 00596 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 00597 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 00598 { 00599 /* Intrapixel differencing */ 00600 png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); 00601 } 00602 #endif 00603 00604 00605 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 00606 if (png_ptr->transformations) 00607 png_do_read_transformations(png_ptr, &row_info); 00608 #endif 00609 00610 /* The transformed pixel depth should match the depth now in row_info. */ 00611 if (png_ptr->transformed_pixel_depth == 0) 00612 { 00613 png_ptr->transformed_pixel_depth = row_info.pixel_depth; 00614 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) 00615 png_error(png_ptr, "sequential row overflow"); 00616 } 00617 00618 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) 00619 png_error(png_ptr, "internal sequential row size calculation error"); 00620 00621 #ifdef PNG_READ_INTERLACING_SUPPORTED 00622 /* Blow up interlaced rows to full size */ 00623 if (png_ptr->interlaced && 00624 (png_ptr->transformations & PNG_INTERLACE)) 00625 { 00626 if (png_ptr->pass < 6) 00627 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, 00628 png_ptr->transformations); 00629 00630 if (dsp_row != NULL) 00631 png_combine_row(png_ptr, dsp_row, 1/*display*/); 00632 00633 if (row != NULL) 00634 png_combine_row(png_ptr, row, 0/*row*/); 00635 } 00636 00637 else 00638 #endif 00639 { 00640 if (row != NULL) 00641 png_combine_row(png_ptr, row, -1/*ignored*/); 00642 00643 if (dsp_row != NULL) 00644 png_combine_row(png_ptr, dsp_row, -1/*ignored*/); 00645 } 00646 png_read_finish_row(png_ptr); 00647 00648 if (png_ptr->read_row_fn != NULL) 00649 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 00650 } 00651 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 00652 00653 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 00654 /* Read one or more rows of image data. If the image is interlaced, 00655 * and png_set_interlace_handling() has been called, the rows need to 00656 * contain the contents of the rows from the previous pass. If the 00657 * image has alpha or transparency, and png_handle_alpha()[*] has been 00658 * called, the rows contents must be initialized to the contents of the 00659 * screen. 00660 * 00661 * "row" holds the actual image, and pixels are placed in it 00662 * as they arrive. If the image is displayed after each pass, it will 00663 * appear to "sparkle" in. "display_row" can be used to display a 00664 * "chunky" progressive image, with finer detail added as it becomes 00665 * available. If you do not want this "chunky" display, you may pass 00666 * NULL for display_row. If you do not want the sparkle display, and 00667 * you have not called png_handle_alpha(), you may pass NULL for rows. 00668 * If you have called png_handle_alpha(), and the image has either an 00669 * alpha channel or a transparency chunk, you must provide a buffer for 00670 * rows. In this case, you do not have to provide a display_row buffer 00671 * also, but you may. If the image is not interlaced, or if you have 00672 * not called png_set_interlace_handling(), the display_row buffer will 00673 * be ignored, so pass NULL to it. 00674 * 00675 * [*] png_handle_alpha() does not exist yet, as of this version of libpng 00676 */ 00677 00678 void PNGAPI 00679 png_read_rows(png_structp png_ptr, png_bytepp row, 00680 png_bytepp display_row, png_uint_32 num_rows) 00681 { 00682 png_uint_32 i; 00683 png_bytepp rp; 00684 png_bytepp dp; 00685 00686 png_debug(1, "in png_read_rows"); 00687 00688 if (png_ptr == NULL) 00689 return; 00690 00691 rp = row; 00692 dp = display_row; 00693 if (rp != NULL && dp != NULL) 00694 for (i = 0; i < num_rows; i++) 00695 { 00696 png_bytep rptr = *rp++; 00697 png_bytep dptr = *dp++; 00698 00699 png_read_row(png_ptr, rptr, dptr); 00700 } 00701 00702 else if (rp != NULL) 00703 for (i = 0; i < num_rows; i++) 00704 { 00705 png_bytep rptr = *rp; 00706 png_read_row(png_ptr, rptr, NULL); 00707 rp++; 00708 } 00709 00710 else if (dp != NULL) 00711 for (i = 0; i < num_rows; i++) 00712 { 00713 png_bytep dptr = *dp; 00714 png_read_row(png_ptr, NULL, dptr); 00715 dp++; 00716 } 00717 } 00718 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 00719 00720 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 00721 /* Read the entire image. If the image has an alpha channel or a tRNS 00722 * chunk, and you have called png_handle_alpha()[*], you will need to 00723 * initialize the image to the current image that PNG will be overlaying. 00724 * We set the num_rows again here, in case it was incorrectly set in 00725 * png_read_start_row() by a call to png_read_update_info() or 00726 * png_start_read_image() if png_set_interlace_handling() wasn't called 00727 * prior to either of these functions like it should have been. You can 00728 * only call this function once. If you desire to have an image for 00729 * each pass of a interlaced image, use png_read_rows() instead. 00730 * 00731 * [*] png_handle_alpha() does not exist yet, as of this version of libpng 00732 */ 00733 void PNGAPI 00734 png_read_image(png_structp png_ptr, png_bytepp image) 00735 { 00736 png_uint_32 i, image_height; 00737 int pass, j; 00738 png_bytepp rp; 00739 00740 png_debug(1, "in png_read_image"); 00741 00742 if (png_ptr == NULL) 00743 return; 00744 00745 #ifdef PNG_READ_INTERLACING_SUPPORTED 00746 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 00747 { 00748 pass = png_set_interlace_handling(png_ptr); 00749 /* And make sure transforms are initialized. */ 00750 png_start_read_image(png_ptr); 00751 } 00752 else 00753 { 00754 if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) 00755 { 00756 /* Caller called png_start_read_image or png_read_update_info without 00757 * first turning on the PNG_INTERLACE transform. We can fix this here, 00758 * but the caller should do it! 00759 */ 00760 png_warning(png_ptr, "Interlace handling should be turned on when " 00761 "using png_read_image"); 00762 /* Make sure this is set correctly */ 00763 png_ptr->num_rows = png_ptr->height; 00764 } 00765 00766 /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in 00767 * the above error case. 00768 */ 00769 pass = png_set_interlace_handling(png_ptr); 00770 } 00771 #else 00772 if (png_ptr->interlaced) 00773 png_error(png_ptr, 00774 "Cannot read interlaced image -- interlace handler disabled"); 00775 00776 pass = 1; 00777 #endif 00778 00779 image_height=png_ptr->height; 00780 00781 for (j = 0; j < pass; j++) 00782 { 00783 rp = image; 00784 for (i = 0; i < image_height; i++) 00785 { 00786 png_read_row(png_ptr, *rp, NULL); 00787 rp++; 00788 } 00789 } 00790 } 00791 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 00792 00793 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 00794 /* Read the end of the PNG file. Will not read past the end of the 00795 * file, will verify the end is accurate, and will read any comments 00796 * or time information at the end of the file, if info is not NULL. 00797 */ 00798 void PNGAPI 00799 png_read_end(png_structp png_ptr, png_infop info_ptr) 00800 { 00801 png_debug(1, "in png_read_end"); 00802 00803 if (png_ptr == NULL) 00804 return; 00805 00806 png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ 00807 00808 do 00809 { 00810 png_uint_32 length = png_read_chunk_header(png_ptr); 00811 png_uint_32 chunk_name = png_ptr->chunk_name; 00812 00813 if (chunk_name == png_IHDR) 00814 png_handle_IHDR(png_ptr, info_ptr, length); 00815 00816 else if (chunk_name == png_IEND) 00817 png_handle_IEND(png_ptr, info_ptr, length); 00818 00819 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 00820 else if (png_chunk_unknown_handling(png_ptr, chunk_name) != 00821 PNG_HANDLE_CHUNK_AS_DEFAULT) 00822 { 00823 if (chunk_name == png_IDAT) 00824 { 00825 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) 00826 png_benign_error(png_ptr, "Too many IDATs found"); 00827 } 00828 png_handle_unknown(png_ptr, info_ptr, length); 00829 if (chunk_name == png_PLTE) 00830 png_ptr->mode |= PNG_HAVE_PLTE; 00831 } 00832 #endif 00833 00834 else if (chunk_name == png_IDAT) 00835 { 00836 /* Zero length IDATs are legal after the last IDAT has been 00837 * read, but not after other chunks have been read. 00838 */ 00839 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) 00840 png_benign_error(png_ptr, "Too many IDATs found"); 00841 00842 png_crc_finish(png_ptr, length); 00843 } 00844 else if (chunk_name == png_PLTE) 00845 png_handle_PLTE(png_ptr, info_ptr, length); 00846 00847 #ifdef PNG_READ_bKGD_SUPPORTED 00848 else if (chunk_name == png_bKGD) 00849 png_handle_bKGD(png_ptr, info_ptr, length); 00850 #endif 00851 00852 #ifdef PNG_READ_cHRM_SUPPORTED 00853 else if (chunk_name == png_cHRM) 00854 png_handle_cHRM(png_ptr, info_ptr, length); 00855 #endif 00856 00857 #ifdef PNG_READ_gAMA_SUPPORTED 00858 else if (chunk_name == png_gAMA) 00859 png_handle_gAMA(png_ptr, info_ptr, length); 00860 #endif 00861 00862 #ifdef PNG_READ_hIST_SUPPORTED 00863 else if (chunk_name == png_hIST) 00864 png_handle_hIST(png_ptr, info_ptr, length); 00865 #endif 00866 00867 #ifdef PNG_READ_oFFs_SUPPORTED 00868 else if (chunk_name == png_oFFs) 00869 png_handle_oFFs(png_ptr, info_ptr, length); 00870 #endif 00871 00872 #ifdef PNG_READ_pCAL_SUPPORTED 00873 else if (chunk_name == png_pCAL) 00874 png_handle_pCAL(png_ptr, info_ptr, length); 00875 #endif 00876 00877 #ifdef PNG_READ_sCAL_SUPPORTED 00878 else if (chunk_name == png_sCAL) 00879 png_handle_sCAL(png_ptr, info_ptr, length); 00880 #endif 00881 00882 #ifdef PNG_READ_pHYs_SUPPORTED 00883 else if (chunk_name == png_pHYs) 00884 png_handle_pHYs(png_ptr, info_ptr, length); 00885 #endif 00886 00887 #ifdef PNG_READ_sBIT_SUPPORTED 00888 else if (chunk_name == png_sBIT) 00889 png_handle_sBIT(png_ptr, info_ptr, length); 00890 #endif 00891 00892 #ifdef PNG_READ_sRGB_SUPPORTED 00893 else if (chunk_name == png_sRGB) 00894 png_handle_sRGB(png_ptr, info_ptr, length); 00895 #endif 00896 00897 #ifdef PNG_READ_iCCP_SUPPORTED 00898 else if (chunk_name == png_iCCP) 00899 png_handle_iCCP(png_ptr, info_ptr, length); 00900 #endif 00901 00902 #ifdef PNG_READ_sPLT_SUPPORTED 00903 else if (chunk_name == png_sPLT) 00904 png_handle_sPLT(png_ptr, info_ptr, length); 00905 #endif 00906 00907 #ifdef PNG_READ_tEXt_SUPPORTED 00908 else if (chunk_name == png_tEXt) 00909 png_handle_tEXt(png_ptr, info_ptr, length); 00910 #endif 00911 00912 #ifdef PNG_READ_tIME_SUPPORTED 00913 else if (chunk_name == png_tIME) 00914 png_handle_tIME(png_ptr, info_ptr, length); 00915 #endif 00916 00917 #ifdef PNG_READ_tRNS_SUPPORTED 00918 else if (chunk_name == png_tRNS) 00919 png_handle_tRNS(png_ptr, info_ptr, length); 00920 #endif 00921 00922 #ifdef PNG_READ_zTXt_SUPPORTED 00923 else if (chunk_name == png_zTXt) 00924 png_handle_zTXt(png_ptr, info_ptr, length); 00925 #endif 00926 00927 #ifdef PNG_READ_iTXt_SUPPORTED 00928 else if (chunk_name == png_iTXt) 00929 png_handle_iTXt(png_ptr, info_ptr, length); 00930 #endif 00931 00932 else 00933 png_handle_unknown(png_ptr, info_ptr, length); 00934 } while (!(png_ptr->mode & PNG_HAVE_IEND)); 00935 } 00936 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 00937 00938 /* Free all memory used by the read */ 00939 void PNGAPI 00940 png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, 00941 png_infopp end_info_ptr_ptr) 00942 { 00943 png_structp png_ptr = NULL; 00944 png_infop info_ptr = NULL, end_info_ptr = NULL; 00945 #ifdef PNG_USER_MEM_SUPPORTED 00946 png_free_ptr free_fn = NULL; 00947 png_voidp mem_ptr = NULL; 00948 #endif 00949 00950 png_debug(1, "in png_destroy_read_struct"); 00951 00952 if (png_ptr_ptr != NULL) 00953 png_ptr = *png_ptr_ptr; 00954 if (png_ptr == NULL) 00955 return; 00956 00957 #ifdef PNG_USER_MEM_SUPPORTED 00958 free_fn = png_ptr->free_fn; 00959 mem_ptr = png_ptr->mem_ptr; 00960 #endif 00961 00962 if (info_ptr_ptr != NULL) 00963 info_ptr = *info_ptr_ptr; 00964 00965 if (end_info_ptr_ptr != NULL) 00966 end_info_ptr = *end_info_ptr_ptr; 00967 00968 png_read_destroy(png_ptr, info_ptr, end_info_ptr); 00969 00970 if (info_ptr != NULL) 00971 { 00972 #ifdef PNG_TEXT_SUPPORTED 00973 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); 00974 #endif 00975 00976 #ifdef PNG_USER_MEM_SUPPORTED 00977 png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, 00978 (png_voidp)mem_ptr); 00979 #else 00980 png_destroy_struct((png_voidp)info_ptr); 00981 #endif 00982 *info_ptr_ptr = NULL; 00983 } 00984 00985 if (end_info_ptr != NULL) 00986 { 00987 #ifdef PNG_READ_TEXT_SUPPORTED 00988 png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); 00989 #endif 00990 #ifdef PNG_USER_MEM_SUPPORTED 00991 png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, 00992 (png_voidp)mem_ptr); 00993 #else 00994 png_destroy_struct((png_voidp)end_info_ptr); 00995 #endif 00996 *end_info_ptr_ptr = NULL; 00997 } 00998 00999 if (png_ptr != NULL) 01000 { 01001 #ifdef PNG_USER_MEM_SUPPORTED 01002 png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, 01003 (png_voidp)mem_ptr); 01004 #else 01005 png_destroy_struct((png_voidp)png_ptr); 01006 #endif 01007 *png_ptr_ptr = NULL; 01008 } 01009 } 01010 01011 /* Free all memory used by the read (old method) */ 01012 void /* PRIVATE */ 01013 png_read_destroy(png_structp png_ptr, png_infop info_ptr, 01014 png_infop end_info_ptr) 01015 { 01016 #ifdef PNG_SETJMP_SUPPORTED 01017 jmp_buf tmp_jmp; 01018 #endif 01019 png_error_ptr error_fn; 01020 #ifdef PNG_WARNINGS_SUPPORTED 01021 png_error_ptr warning_fn; 01022 #endif 01023 png_voidp error_ptr; 01024 #ifdef PNG_USER_MEM_SUPPORTED 01025 png_free_ptr free_fn; 01026 #endif 01027 01028 png_debug(1, "in png_read_destroy"); 01029 01030 if (info_ptr != NULL) 01031 png_info_destroy(png_ptr, info_ptr); 01032 01033 if (end_info_ptr != NULL) 01034 png_info_destroy(png_ptr, end_info_ptr); 01035 01036 #ifdef PNG_READ_GAMMA_SUPPORTED 01037 png_destroy_gamma_table(png_ptr); 01038 #endif 01039 01040 png_free(png_ptr, png_ptr->zbuf); 01041 png_free(png_ptr, png_ptr->big_row_buf); 01042 png_free(png_ptr, png_ptr->big_prev_row); 01043 png_free(png_ptr, png_ptr->chunkdata); 01044 01045 #ifdef PNG_READ_QUANTIZE_SUPPORTED 01046 png_free(png_ptr, png_ptr->palette_lookup); 01047 png_free(png_ptr, png_ptr->quantize_index); 01048 #endif 01049 01050 if (png_ptr->free_me & PNG_FREE_PLTE) 01051 png_zfree(png_ptr, png_ptr->palette); 01052 png_ptr->free_me &= ~PNG_FREE_PLTE; 01053 01054 #if defined(PNG_tRNS_SUPPORTED) || \ 01055 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 01056 if (png_ptr->free_me & PNG_FREE_TRNS) 01057 png_free(png_ptr, png_ptr->trans_alpha); 01058 png_ptr->free_me &= ~PNG_FREE_TRNS; 01059 #endif 01060 01061 #ifdef PNG_READ_hIST_SUPPORTED 01062 if (png_ptr->free_me & PNG_FREE_HIST) 01063 png_free(png_ptr, png_ptr->hist); 01064 png_ptr->free_me &= ~PNG_FREE_HIST; 01065 #endif 01066 01067 inflateEnd(&png_ptr->zstream); 01068 01069 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED 01070 png_free(png_ptr, png_ptr->save_buffer); 01071 #endif 01072 01073 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED 01074 #ifdef PNG_TEXT_SUPPORTED 01075 png_free(png_ptr, png_ptr->current_text); 01076 #endif /* PNG_TEXT_SUPPORTED */ 01077 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ 01078 01079 /* Save the important info out of the png_struct, in case it is 01080 * being used again. 01081 */ 01082 #ifdef PNG_SETJMP_SUPPORTED 01083 png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); 01084 #endif 01085 01086 error_fn = png_ptr->error_fn; 01087 #ifdef PNG_WARNINGS_SUPPORTED 01088 warning_fn = png_ptr->warning_fn; 01089 #endif 01090 error_ptr = png_ptr->error_ptr; 01091 #ifdef PNG_USER_MEM_SUPPORTED 01092 free_fn = png_ptr->free_fn; 01093 #endif 01094 01095 png_memset(png_ptr, 0, png_sizeof(png_struct)); 01096 01097 png_ptr->error_fn = error_fn; 01098 #ifdef PNG_WARNINGS_SUPPORTED 01099 png_ptr->warning_fn = warning_fn; 01100 #endif 01101 png_ptr->error_ptr = error_ptr; 01102 #ifdef PNG_USER_MEM_SUPPORTED 01103 png_ptr->free_fn = free_fn; 01104 #endif 01105 01106 #ifdef PNG_SETJMP_SUPPORTED 01107 png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf)); 01108 #endif 01109 01110 } 01111 01112 void PNGAPI 01113 png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) 01114 { 01115 if (png_ptr == NULL) 01116 return; 01117 01118 png_ptr->read_row_fn = read_row_fn; 01119 } 01120 01121 01122 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 01123 #ifdef PNG_INFO_IMAGE_SUPPORTED 01124 void PNGAPI 01125 png_read_png(png_structp png_ptr, png_infop info_ptr, 01126 int transforms, 01127 voidp params) 01128 { 01129 int row; 01130 01131 if (png_ptr == NULL || info_ptr == NULL) 01132 return; 01133 01134 /* png_read_info() gives us all of the information from the 01135 * PNG file before the first IDAT (image data chunk). 01136 */ 01137 png_read_info(png_ptr, info_ptr); 01138 if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) 01139 png_error(png_ptr, "Image is too high to process with png_read_png()"); 01140 01141 /* -------------- image transformations start here ------------------- */ 01142 01143 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 01144 /* Tell libpng to strip 16-bit/color files down to 8 bits per color. 01145 */ 01146 if (transforms & PNG_TRANSFORM_SCALE_16) 01147 { 01148 /* Added at libpng-1.5.4. "strip_16" produces the same result that it 01149 * did in earlier versions, while "scale_16" is now more accurate. 01150 */ 01151 png_set_scale_16(png_ptr); 01152 } 01153 #endif 01154 01155 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 01156 /* If both SCALE and STRIP are required pngrtran will effectively cancel the 01157 * latter by doing SCALE first. This is ok and allows apps not to check for 01158 * which is supported to get the right answer. 01159 */ 01160 if (transforms & PNG_TRANSFORM_STRIP_16) 01161 png_set_strip_16(png_ptr); 01162 #endif 01163 01164 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 01165 /* Strip alpha bytes from the input data without combining with 01166 * the background (not recommended). 01167 */ 01168 if (transforms & PNG_TRANSFORM_STRIP_ALPHA) 01169 png_set_strip_alpha(png_ptr); 01170 #endif 01171 01172 #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) 01173 /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single 01174 * byte into separate bytes (useful for paletted and grayscale images). 01175 */ 01176 if (transforms & PNG_TRANSFORM_PACKING) 01177 png_set_packing(png_ptr); 01178 #endif 01179 01180 #ifdef PNG_READ_PACKSWAP_SUPPORTED 01181 /* Change the order of packed pixels to least significant bit first 01182 * (not useful if you are using png_set_packing). 01183 */ 01184 if (transforms & PNG_TRANSFORM_PACKSWAP) 01185 png_set_packswap(png_ptr); 01186 #endif 01187 01188 #ifdef PNG_READ_EXPAND_SUPPORTED 01189 /* Expand paletted colors into true RGB triplets 01190 * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel 01191 * Expand paletted or RGB images with transparency to full alpha 01192 * channels so the data will be available as RGBA quartets. 01193 */ 01194 if (transforms & PNG_TRANSFORM_EXPAND) 01195 if ((png_ptr->bit_depth < 8) || 01196 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || 01197 (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) 01198 png_set_expand(png_ptr); 01199 #endif 01200 01201 /* We don't handle background color or gamma transformation or quantizing. 01202 */ 01203 01204 #ifdef PNG_READ_INVERT_SUPPORTED 01205 /* Invert monochrome files to have 0 as white and 1 as black 01206 */ 01207 if (transforms & PNG_TRANSFORM_INVERT_MONO) 01208 png_set_invert_mono(png_ptr); 01209 #endif 01210 01211 #ifdef PNG_READ_SHIFT_SUPPORTED 01212 /* If you want to shift the pixel values from the range [0,255] or 01213 * [0,65535] to the original [0,7] or [0,31], or whatever range the 01214 * colors were originally in: 01215 */ 01216 if ((transforms & PNG_TRANSFORM_SHIFT) 01217 && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) 01218 { 01219 png_color_8p sig_bit; 01220 01221 png_get_sBIT(png_ptr, info_ptr, &sig_bit); 01222 png_set_shift(png_ptr, sig_bit); 01223 } 01224 #endif 01225 01226 #ifdef PNG_READ_BGR_SUPPORTED 01227 /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ 01228 if (transforms & PNG_TRANSFORM_BGR) 01229 png_set_bgr(png_ptr); 01230 #endif 01231 01232 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 01233 /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ 01234 if (transforms & PNG_TRANSFORM_SWAP_ALPHA) 01235 png_set_swap_alpha(png_ptr); 01236 #endif 01237 01238 #ifdef PNG_READ_SWAP_SUPPORTED 01239 /* Swap bytes of 16-bit files to least significant byte first */ 01240 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) 01241 png_set_swap(png_ptr); 01242 #endif 01243 01244 /* Added at libpng-1.2.41 */ 01245 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 01246 /* Invert the alpha channel from opacity to transparency */ 01247 if (transforms & PNG_TRANSFORM_INVERT_ALPHA) 01248 png_set_invert_alpha(png_ptr); 01249 #endif 01250 01251 /* Added at libpng-1.2.41 */ 01252 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 01253 /* Expand grayscale image to RGB */ 01254 if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) 01255 png_set_gray_to_rgb(png_ptr); 01256 #endif 01257 01258 /* Added at libpng-1.5.4 */ 01259 #ifdef PNG_READ_EXPAND_16_SUPPORTED 01260 if (transforms & PNG_TRANSFORM_EXPAND_16) 01261 png_set_expand_16(png_ptr); 01262 #endif 01263 01264 /* We don't handle adding filler bytes */ 01265 01266 /* We use png_read_image and rely on that for interlace handling, but we also 01267 * call png_read_update_info therefore must turn on interlace handling now: 01268 */ 01269 (void)png_set_interlace_handling(png_ptr); 01270 01271 /* Optional call to gamma correct and add the background to the palette 01272 * and update info structure. REQUIRED if you are expecting libpng to 01273 * update the palette for you (i.e., you selected such a transform above). 01274 */ 01275 png_read_update_info(png_ptr, info_ptr); 01276 01277 /* -------------- image transformations end here ------------------- */ 01278 01279 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); 01280 if (info_ptr->row_pointers == NULL) 01281 { 01282 png_uint_32 iptr; 01283 01284 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, 01285 info_ptr->height * png_sizeof(png_bytep)); 01286 for (iptr=0; iptr<info_ptr->height; iptr++) 01287 info_ptr->row_pointers[iptr] = NULL; 01288 01289 info_ptr->free_me |= PNG_FREE_ROWS; 01290 01291 for (row = 0; row < (int)info_ptr->height; row++) 01292 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, 01293 png_get_rowbytes(png_ptr, info_ptr)); 01294 } 01295 01296 png_read_image(png_ptr, info_ptr->row_pointers); 01297 info_ptr->valid |= PNG_INFO_IDAT; 01298 01299 /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ 01300 png_read_end(png_ptr, info_ptr); 01301 01302 PNG_UNUSED(transforms) /* Quiet compiler warnings */ 01303 PNG_UNUSED(params) 01304 01305 } 01306 #endif /* PNG_INFO_IMAGE_SUPPORTED */ 01307 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 01308 #endif /* PNG_READ_SUPPORTED */ Generated on Fri May 25 2012 04:17:39 for ReactOS by
1.7.6.1
|