Path: blob/master/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
41155 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324/* pngread.c - read a PNG file25*26* This file is available under and governed by the GNU General Public27* License version 2 only, as published by the Free Software Foundation.28* However, the following notice accompanied the original version of this29* file and, per its terms, should not be removed:30*31* Copyright (c) 2018-2019 Cosmin Truta32* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson33* Copyright (c) 1996-1997 Andreas Dilger34* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.35*36* This code is released under the libpng license.37* For conditions of distribution and use, see the disclaimer38* and license in png.h39*40* This file contains routines that an application calls directly to41* read a PNG file or stream.42*/4344#include "pngpriv.h"45#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)46# include <errno.h>47#endif4849#ifdef PNG_READ_SUPPORTED5051/* Create a PNG structure for reading, and allocate any memory needed. */52PNG_FUNCTION(png_structp,PNGAPI53png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,54png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)55{56#ifndef PNG_USER_MEM_SUPPORTED57png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,58error_fn, warn_fn, NULL, NULL, NULL);59#else60return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,61warn_fn, NULL, NULL, NULL);62}6364/* Alternate create PNG structure for reading, and allocate any memory65* needed.66*/67PNG_FUNCTION(png_structp,PNGAPI68png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,69png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,70png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)71{72png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,73error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);74#endif /* USER_MEM */7576if (png_ptr != NULL)77{78png_ptr->mode = PNG_IS_READ_STRUCT;7980/* Added in libpng-1.6.0; this can be used to detect a read structure if81* required (it will be zero in a write structure.)82*/83# ifdef PNG_SEQUENTIAL_READ_SUPPORTED84png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;85# endif8687# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED88png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;8990/* In stable builds only warn if an application error can be completely91* handled.92*/93# if PNG_RELEASE_BUILD94png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;95# endif96# endif9798/* TODO: delay this, it can be done in png_init_io (if the app doesn't99* do it itself) avoiding setting the default function if it is not100* required.101*/102png_set_read_fn(png_ptr, NULL, NULL);103}104105return png_ptr;106}107108109#ifdef PNG_SEQUENTIAL_READ_SUPPORTED110/* Read the information before the actual image data. This has been111* changed in v0.90 to allow reading a file that already has the magic112* bytes read from the stream. You can tell libpng how many bytes have113* been read from the beginning of the stream (up to the maximum of 8)114* via png_set_sig_bytes(), and we will only check the remaining bytes115* here. The application can then have access to the signature bytes we116* read if it is determined that this isn't a valid PNG file.117*/118void PNGAPI119png_read_info(png_structrp png_ptr, png_inforp info_ptr)120{121#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED122int keep;123#endif124125png_debug(1, "in png_read_info");126127if (png_ptr == NULL || info_ptr == NULL)128return;129130/* Read and check the PNG file signature. */131png_read_sig(png_ptr, info_ptr);132133for (;;)134{135png_uint_32 length = png_read_chunk_header(png_ptr);136png_uint_32 chunk_name = png_ptr->chunk_name;137138/* IDAT logic needs to happen here to simplify getting the two flags139* right.140*/141if (chunk_name == png_IDAT)142{143if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)144png_chunk_error(png_ptr, "Missing IHDR before IDAT");145146else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&147(png_ptr->mode & PNG_HAVE_PLTE) == 0)148png_chunk_error(png_ptr, "Missing PLTE before IDAT");149150else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)151png_chunk_benign_error(png_ptr, "Too many IDATs found");152153png_ptr->mode |= PNG_HAVE_IDAT;154}155156else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)157{158png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;159png_ptr->mode |= PNG_AFTER_IDAT;160}161162/* This should be a binary subdivision search or a hash for163* matching the chunk name rather than a linear search.164*/165if (chunk_name == png_IHDR)166png_handle_IHDR(png_ptr, info_ptr, length);167168else if (chunk_name == png_IEND)169png_handle_IEND(png_ptr, info_ptr, length);170171#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED172else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)173{174png_handle_unknown(png_ptr, info_ptr, length, keep);175176if (chunk_name == png_PLTE)177png_ptr->mode |= PNG_HAVE_PLTE;178179else if (chunk_name == png_IDAT)180{181png_ptr->idat_size = 0; /* It has been consumed */182break;183}184}185#endif186else if (chunk_name == png_PLTE)187png_handle_PLTE(png_ptr, info_ptr, length);188189else if (chunk_name == png_IDAT)190{191png_ptr->idat_size = length;192break;193}194195#ifdef PNG_READ_bKGD_SUPPORTED196else if (chunk_name == png_bKGD)197png_handle_bKGD(png_ptr, info_ptr, length);198#endif199200#ifdef PNG_READ_cHRM_SUPPORTED201else if (chunk_name == png_cHRM)202png_handle_cHRM(png_ptr, info_ptr, length);203#endif204205#ifdef PNG_READ_eXIf_SUPPORTED206else if (chunk_name == png_eXIf)207png_handle_eXIf(png_ptr, info_ptr, length);208#endif209210#ifdef PNG_READ_gAMA_SUPPORTED211else if (chunk_name == png_gAMA)212png_handle_gAMA(png_ptr, info_ptr, length);213#endif214215#ifdef PNG_READ_hIST_SUPPORTED216else if (chunk_name == png_hIST)217png_handle_hIST(png_ptr, info_ptr, length);218#endif219220#ifdef PNG_READ_oFFs_SUPPORTED221else if (chunk_name == png_oFFs)222png_handle_oFFs(png_ptr, info_ptr, length);223#endif224225#ifdef PNG_READ_pCAL_SUPPORTED226else if (chunk_name == png_pCAL)227png_handle_pCAL(png_ptr, info_ptr, length);228#endif229230#ifdef PNG_READ_sCAL_SUPPORTED231else if (chunk_name == png_sCAL)232png_handle_sCAL(png_ptr, info_ptr, length);233#endif234235#ifdef PNG_READ_pHYs_SUPPORTED236else if (chunk_name == png_pHYs)237png_handle_pHYs(png_ptr, info_ptr, length);238#endif239240#ifdef PNG_READ_sBIT_SUPPORTED241else if (chunk_name == png_sBIT)242png_handle_sBIT(png_ptr, info_ptr, length);243#endif244245#ifdef PNG_READ_sRGB_SUPPORTED246else if (chunk_name == png_sRGB)247png_handle_sRGB(png_ptr, info_ptr, length);248#endif249250#ifdef PNG_READ_iCCP_SUPPORTED251else if (chunk_name == png_iCCP)252png_handle_iCCP(png_ptr, info_ptr, length);253#endif254255#ifdef PNG_READ_sPLT_SUPPORTED256else if (chunk_name == png_sPLT)257png_handle_sPLT(png_ptr, info_ptr, length);258#endif259260#ifdef PNG_READ_tEXt_SUPPORTED261else if (chunk_name == png_tEXt)262png_handle_tEXt(png_ptr, info_ptr, length);263#endif264265#ifdef PNG_READ_tIME_SUPPORTED266else if (chunk_name == png_tIME)267png_handle_tIME(png_ptr, info_ptr, length);268#endif269270#ifdef PNG_READ_tRNS_SUPPORTED271else if (chunk_name == png_tRNS)272png_handle_tRNS(png_ptr, info_ptr, length);273#endif274275#ifdef PNG_READ_zTXt_SUPPORTED276else if (chunk_name == png_zTXt)277png_handle_zTXt(png_ptr, info_ptr, length);278#endif279280#ifdef PNG_READ_iTXt_SUPPORTED281else if (chunk_name == png_iTXt)282png_handle_iTXt(png_ptr, info_ptr, length);283#endif284285else286png_handle_unknown(png_ptr, info_ptr, length,287PNG_HANDLE_CHUNK_AS_DEFAULT);288}289}290#endif /* SEQUENTIAL_READ */291292/* Optional call to update the users info_ptr structure */293void PNGAPI294png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)295{296png_debug(1, "in png_read_update_info");297298if (png_ptr != NULL)299{300if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)301{302png_read_start_row(png_ptr);303304# ifdef PNG_READ_TRANSFORMS_SUPPORTED305png_read_transform_info(png_ptr, info_ptr);306# else307PNG_UNUSED(info_ptr)308# endif309}310311/* New in 1.6.0 this avoids the bug of doing the initializations twice */312else313png_app_error(png_ptr,314"png_read_update_info/png_start_read_image: duplicate call");315}316}317318#ifdef PNG_SEQUENTIAL_READ_SUPPORTED319/* Initialize palette, background, etc, after transformations320* are set, but before any reading takes place. This allows321* the user to obtain a gamma-corrected palette, for example.322* If the user doesn't call this, we will do it ourselves.323*/324void PNGAPI325png_start_read_image(png_structrp png_ptr)326{327png_debug(1, "in png_start_read_image");328329if (png_ptr != NULL)330{331if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)332png_read_start_row(png_ptr);333334/* New in 1.6.0 this avoids the bug of doing the initializations twice */335else336png_app_error(png_ptr,337"png_start_read_image/png_read_update_info: duplicate call");338}339}340#endif /* SEQUENTIAL_READ */341342#ifdef PNG_SEQUENTIAL_READ_SUPPORTED343#ifdef PNG_MNG_FEATURES_SUPPORTED344/* Undoes intrapixel differencing,345* NOTE: this is apparently only supported in the 'sequential' reader.346*/347static void348png_do_read_intrapixel(png_row_infop row_info, png_bytep row)349{350png_debug(1, "in png_do_read_intrapixel");351352if (353(row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)354{355int bytes_per_pixel;356png_uint_32 row_width = row_info->width;357358if (row_info->bit_depth == 8)359{360png_bytep rp;361png_uint_32 i;362363if (row_info->color_type == PNG_COLOR_TYPE_RGB)364bytes_per_pixel = 3;365366else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)367bytes_per_pixel = 4;368369else370return;371372for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)373{374*(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);375*(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);376}377}378else if (row_info->bit_depth == 16)379{380png_bytep rp;381png_uint_32 i;382383if (row_info->color_type == PNG_COLOR_TYPE_RGB)384bytes_per_pixel = 6;385386else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)387bytes_per_pixel = 8;388389else390return;391392for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)393{394png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);395png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);396png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);397png_uint_32 red = (s0 + s1 + 65536) & 0xffff;398png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;399*(rp ) = (png_byte)((red >> 8) & 0xff);400*(rp + 1) = (png_byte)(red & 0xff);401*(rp + 4) = (png_byte)((blue >> 8) & 0xff);402*(rp + 5) = (png_byte)(blue & 0xff);403}404}405}406}407#endif /* MNG_FEATURES */408409void PNGAPI410png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)411{412png_row_info row_info;413414if (png_ptr == NULL)415return;416417png_debug2(1, "in png_read_row (row %lu, pass %d)",418(unsigned long)png_ptr->row_number, png_ptr->pass);419420/* png_read_start_row sets the information (in particular iwidth) for this421* interlace pass.422*/423if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)424png_read_start_row(png_ptr);425426/* 1.5.6: row_info moved out of png_struct to a local here. */427row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */428row_info.color_type = png_ptr->color_type;429row_info.bit_depth = png_ptr->bit_depth;430row_info.channels = png_ptr->channels;431row_info.pixel_depth = png_ptr->pixel_depth;432row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);433434#ifdef PNG_WARNINGS_SUPPORTED435if (png_ptr->row_number == 0 && png_ptr->pass == 0)436{437/* Check for transforms that have been set but were defined out */438#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)439if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)440png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");441#endif442443#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)444if ((png_ptr->transformations & PNG_FILLER) != 0)445png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");446#endif447448#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \449!defined(PNG_READ_PACKSWAP_SUPPORTED)450if ((png_ptr->transformations & PNG_PACKSWAP) != 0)451png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");452#endif453454#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)455if ((png_ptr->transformations & PNG_PACK) != 0)456png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");457#endif458459#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)460if ((png_ptr->transformations & PNG_SHIFT) != 0)461png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");462#endif463464#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)465if ((png_ptr->transformations & PNG_BGR) != 0)466png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");467#endif468469#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)470if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)471png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");472#endif473}474#endif /* WARNINGS */475476#ifdef PNG_READ_INTERLACING_SUPPORTED477/* If interlaced and we do not need a new row, combine row and return.478* Notice that the pixels we have from previous rows have been transformed479* already; we can only combine like with like (transformed or480* untransformed) and, because of the libpng API for interlaced images, this481* means we must transform before de-interlacing.482*/483if (png_ptr->interlaced != 0 &&484(png_ptr->transformations & PNG_INTERLACE) != 0)485{486switch (png_ptr->pass)487{488case 0:489if (png_ptr->row_number & 0x07)490{491if (dsp_row != NULL)492png_combine_row(png_ptr, dsp_row, 1/*display*/);493png_read_finish_row(png_ptr);494return;495}496break;497498case 1:499if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)500{501if (dsp_row != NULL)502png_combine_row(png_ptr, dsp_row, 1/*display*/);503504png_read_finish_row(png_ptr);505return;506}507break;508509case 2:510if ((png_ptr->row_number & 0x07) != 4)511{512if (dsp_row != NULL && (png_ptr->row_number & 4))513png_combine_row(png_ptr, dsp_row, 1/*display*/);514515png_read_finish_row(png_ptr);516return;517}518break;519520case 3:521if ((png_ptr->row_number & 3) || png_ptr->width < 3)522{523if (dsp_row != NULL)524png_combine_row(png_ptr, dsp_row, 1/*display*/);525526png_read_finish_row(png_ptr);527return;528}529break;530531case 4:532if ((png_ptr->row_number & 3) != 2)533{534if (dsp_row != NULL && (png_ptr->row_number & 2))535png_combine_row(png_ptr, dsp_row, 1/*display*/);536537png_read_finish_row(png_ptr);538return;539}540break;541542case 5:543if ((png_ptr->row_number & 1) || png_ptr->width < 2)544{545if (dsp_row != NULL)546png_combine_row(png_ptr, dsp_row, 1/*display*/);547548png_read_finish_row(png_ptr);549return;550}551break;552553default:554case 6:555if ((png_ptr->row_number & 1) == 0)556{557png_read_finish_row(png_ptr);558return;559}560break;561}562}563#endif564565if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)566png_error(png_ptr, "Invalid attempt to read row data");567568/* Fill the row with IDAT data: */569png_ptr->row_buf[0]=255; /* to force error if no data was found */570png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);571572if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)573{574if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)575png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,576png_ptr->prev_row + 1, png_ptr->row_buf[0]);577else578png_error(png_ptr, "bad adaptive filter value");579}580581/* libpng 1.5.6: the following line was copying png_ptr->rowbytes before582* 1.5.6, while the buffer really is this big in current versions of libpng583* it may not be in the future, so this was changed just to copy the584* interlaced count:585*/586memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);587588#ifdef PNG_MNG_FEATURES_SUPPORTED589if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&590(png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))591{592/* Intrapixel differencing */593png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);594}595#endif596597#ifdef PNG_READ_TRANSFORMS_SUPPORTED598if (png_ptr->transformations)599png_do_read_transformations(png_ptr, &row_info);600#endif601602/* The transformed pixel depth should match the depth now in row_info. */603if (png_ptr->transformed_pixel_depth == 0)604{605png_ptr->transformed_pixel_depth = row_info.pixel_depth;606if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)607png_error(png_ptr, "sequential row overflow");608}609610else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)611png_error(png_ptr, "internal sequential row size calculation error");612613#ifdef PNG_READ_INTERLACING_SUPPORTED614/* Expand interlaced rows to full size */615if (png_ptr->interlaced != 0 &&616(png_ptr->transformations & PNG_INTERLACE) != 0)617{618if (png_ptr->pass < 6)619png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,620png_ptr->transformations);621622if (dsp_row != NULL)623png_combine_row(png_ptr, dsp_row, 1/*display*/);624625if (row != NULL)626png_combine_row(png_ptr, row, 0/*row*/);627}628629else630#endif631{632if (row != NULL)633png_combine_row(png_ptr, row, -1/*ignored*/);634635if (dsp_row != NULL)636png_combine_row(png_ptr, dsp_row, -1/*ignored*/);637}638png_read_finish_row(png_ptr);639640if (png_ptr->read_row_fn != NULL)641(*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);642643}644#endif /* SEQUENTIAL_READ */645646#ifdef PNG_SEQUENTIAL_READ_SUPPORTED647/* Read one or more rows of image data. If the image is interlaced,648* and png_set_interlace_handling() has been called, the rows need to649* contain the contents of the rows from the previous pass. If the650* image has alpha or transparency, and png_handle_alpha()[*] has been651* called, the rows contents must be initialized to the contents of the652* screen.653*654* "row" holds the actual image, and pixels are placed in it655* as they arrive. If the image is displayed after each pass, it will656* appear to "sparkle" in. "display_row" can be used to display a657* "chunky" progressive image, with finer detail added as it becomes658* available. If you do not want this "chunky" display, you may pass659* NULL for display_row. If you do not want the sparkle display, and660* you have not called png_handle_alpha(), you may pass NULL for rows.661* If you have called png_handle_alpha(), and the image has either an662* alpha channel or a transparency chunk, you must provide a buffer for663* rows. In this case, you do not have to provide a display_row buffer664* also, but you may. If the image is not interlaced, or if you have665* not called png_set_interlace_handling(), the display_row buffer will666* be ignored, so pass NULL to it.667*668* [*] png_handle_alpha() does not exist yet, as of this version of libpng669*/670671void PNGAPI672png_read_rows(png_structrp png_ptr, png_bytepp row,673png_bytepp display_row, png_uint_32 num_rows)674{675png_uint_32 i;676png_bytepp rp;677png_bytepp dp;678679png_debug(1, "in png_read_rows");680681if (png_ptr == NULL)682return;683684rp = row;685dp = display_row;686if (rp != NULL && dp != NULL)687for (i = 0; i < num_rows; i++)688{689png_bytep rptr = *rp++;690png_bytep dptr = *dp++;691692png_read_row(png_ptr, rptr, dptr);693}694695else if (rp != NULL)696for (i = 0; i < num_rows; i++)697{698png_bytep rptr = *rp;699png_read_row(png_ptr, rptr, NULL);700rp++;701}702703else if (dp != NULL)704for (i = 0; i < num_rows; i++)705{706png_bytep dptr = *dp;707png_read_row(png_ptr, NULL, dptr);708dp++;709}710}711#endif /* SEQUENTIAL_READ */712713#ifdef PNG_SEQUENTIAL_READ_SUPPORTED714/* Read the entire image. If the image has an alpha channel or a tRNS715* chunk, and you have called png_handle_alpha()[*], you will need to716* initialize the image to the current image that PNG will be overlaying.717* We set the num_rows again here, in case it was incorrectly set in718* png_read_start_row() by a call to png_read_update_info() or719* png_start_read_image() if png_set_interlace_handling() wasn't called720* prior to either of these functions like it should have been. You can721* only call this function once. If you desire to have an image for722* each pass of a interlaced image, use png_read_rows() instead.723*724* [*] png_handle_alpha() does not exist yet, as of this version of libpng725*/726void PNGAPI727png_read_image(png_structrp png_ptr, png_bytepp image)728{729png_uint_32 i, image_height;730int pass, j;731png_bytepp rp;732733png_debug(1, "in png_read_image");734735if (png_ptr == NULL)736return;737738#ifdef PNG_READ_INTERLACING_SUPPORTED739if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)740{741pass = png_set_interlace_handling(png_ptr);742/* And make sure transforms are initialized. */743png_start_read_image(png_ptr);744}745else746{747if (png_ptr->interlaced != 0 &&748(png_ptr->transformations & PNG_INTERLACE) == 0)749{750/* Caller called png_start_read_image or png_read_update_info without751* first turning on the PNG_INTERLACE transform. We can fix this here,752* but the caller should do it!753*/754png_warning(png_ptr, "Interlace handling should be turned on when "755"using png_read_image");756/* Make sure this is set correctly */757png_ptr->num_rows = png_ptr->height;758}759760/* Obtain the pass number, which also turns on the PNG_INTERLACE flag in761* the above error case.762*/763pass = png_set_interlace_handling(png_ptr);764}765#else766if (png_ptr->interlaced)767png_error(png_ptr,768"Cannot read interlaced image -- interlace handler disabled");769770pass = 1;771#endif772773image_height=png_ptr->height;774775for (j = 0; j < pass; j++)776{777rp = image;778for (i = 0; i < image_height; i++)779{780png_read_row(png_ptr, *rp, NULL);781rp++;782}783}784}785#endif /* SEQUENTIAL_READ */786787#ifdef PNG_SEQUENTIAL_READ_SUPPORTED788/* Read the end of the PNG file. Will not read past the end of the789* file, will verify the end is accurate, and will read any comments790* or time information at the end of the file, if info is not NULL.791*/792void PNGAPI793png_read_end(png_structrp png_ptr, png_inforp info_ptr)794{795#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED796int keep;797#endif798799png_debug(1, "in png_read_end");800801if (png_ptr == NULL)802return;803804/* If png_read_end is called in the middle of reading the rows there may805* still be pending IDAT data and an owned zstream. Deal with this here.806*/807#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED808if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0)809#endif810png_read_finish_IDAT(png_ptr);811812#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED813/* Report invalid palette index; added at libng-1.5.10 */814if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&815png_ptr->num_palette_max > png_ptr->num_palette)816png_benign_error(png_ptr, "Read palette index exceeding num_palette");817#endif818819do820{821png_uint_32 length = png_read_chunk_header(png_ptr);822png_uint_32 chunk_name = png_ptr->chunk_name;823824if (chunk_name != png_IDAT)825png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;826827if (chunk_name == png_IEND)828png_handle_IEND(png_ptr, info_ptr, length);829830else if (chunk_name == png_IHDR)831png_handle_IHDR(png_ptr, info_ptr, length);832833else if (info_ptr == NULL)834png_crc_finish(png_ptr, length);835836#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED837else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)838{839if (chunk_name == png_IDAT)840{841if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))842|| (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)843png_benign_error(png_ptr, ".Too many IDATs found");844}845png_handle_unknown(png_ptr, info_ptr, length, keep);846if (chunk_name == png_PLTE)847png_ptr->mode |= PNG_HAVE_PLTE;848}849#endif850851else if (chunk_name == png_IDAT)852{853/* Zero length IDATs are legal after the last IDAT has been854* read, but not after other chunks have been read. 1.6 does not855* always read all the deflate data; specifically it cannot be relied856* upon to read the Adler32 at the end. If it doesn't ignore IDAT857* chunks which are longer than zero as well:858*/859if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))860|| (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)861png_benign_error(png_ptr, "..Too many IDATs found");862863png_crc_finish(png_ptr, length);864}865else if (chunk_name == png_PLTE)866png_handle_PLTE(png_ptr, info_ptr, length);867868#ifdef PNG_READ_bKGD_SUPPORTED869else if (chunk_name == png_bKGD)870png_handle_bKGD(png_ptr, info_ptr, length);871#endif872873#ifdef PNG_READ_cHRM_SUPPORTED874else if (chunk_name == png_cHRM)875png_handle_cHRM(png_ptr, info_ptr, length);876#endif877878#ifdef PNG_READ_eXIf_SUPPORTED879else if (chunk_name == png_eXIf)880png_handle_eXIf(png_ptr, info_ptr, length);881#endif882883#ifdef PNG_READ_gAMA_SUPPORTED884else if (chunk_name == png_gAMA)885png_handle_gAMA(png_ptr, info_ptr, length);886#endif887888#ifdef PNG_READ_hIST_SUPPORTED889else if (chunk_name == png_hIST)890png_handle_hIST(png_ptr, info_ptr, length);891#endif892893#ifdef PNG_READ_oFFs_SUPPORTED894else if (chunk_name == png_oFFs)895png_handle_oFFs(png_ptr, info_ptr, length);896#endif897898#ifdef PNG_READ_pCAL_SUPPORTED899else if (chunk_name == png_pCAL)900png_handle_pCAL(png_ptr, info_ptr, length);901#endif902903#ifdef PNG_READ_sCAL_SUPPORTED904else if (chunk_name == png_sCAL)905png_handle_sCAL(png_ptr, info_ptr, length);906#endif907908#ifdef PNG_READ_pHYs_SUPPORTED909else if (chunk_name == png_pHYs)910png_handle_pHYs(png_ptr, info_ptr, length);911#endif912913#ifdef PNG_READ_sBIT_SUPPORTED914else if (chunk_name == png_sBIT)915png_handle_sBIT(png_ptr, info_ptr, length);916#endif917918#ifdef PNG_READ_sRGB_SUPPORTED919else if (chunk_name == png_sRGB)920png_handle_sRGB(png_ptr, info_ptr, length);921#endif922923#ifdef PNG_READ_iCCP_SUPPORTED924else if (chunk_name == png_iCCP)925png_handle_iCCP(png_ptr, info_ptr, length);926#endif927928#ifdef PNG_READ_sPLT_SUPPORTED929else if (chunk_name == png_sPLT)930png_handle_sPLT(png_ptr, info_ptr, length);931#endif932933#ifdef PNG_READ_tEXt_SUPPORTED934else if (chunk_name == png_tEXt)935png_handle_tEXt(png_ptr, info_ptr, length);936#endif937938#ifdef PNG_READ_tIME_SUPPORTED939else if (chunk_name == png_tIME)940png_handle_tIME(png_ptr, info_ptr, length);941#endif942943#ifdef PNG_READ_tRNS_SUPPORTED944else if (chunk_name == png_tRNS)945png_handle_tRNS(png_ptr, info_ptr, length);946#endif947948#ifdef PNG_READ_zTXt_SUPPORTED949else if (chunk_name == png_zTXt)950png_handle_zTXt(png_ptr, info_ptr, length);951#endif952953#ifdef PNG_READ_iTXt_SUPPORTED954else if (chunk_name == png_iTXt)955png_handle_iTXt(png_ptr, info_ptr, length);956#endif957958else959png_handle_unknown(png_ptr, info_ptr, length,960PNG_HANDLE_CHUNK_AS_DEFAULT);961} while ((png_ptr->mode & PNG_HAVE_IEND) == 0);962}963#endif /* SEQUENTIAL_READ */964965/* Free all memory used in the read struct */966static void967png_read_destroy(png_structrp png_ptr)968{969png_debug(1, "in png_read_destroy");970971#ifdef PNG_READ_GAMMA_SUPPORTED972png_destroy_gamma_table(png_ptr);973#endif974975png_free(png_ptr, png_ptr->big_row_buf);976png_ptr->big_row_buf = NULL;977png_free(png_ptr, png_ptr->big_prev_row);978png_ptr->big_prev_row = NULL;979png_free(png_ptr, png_ptr->read_buffer);980png_ptr->read_buffer = NULL;981982#ifdef PNG_READ_QUANTIZE_SUPPORTED983png_free(png_ptr, png_ptr->palette_lookup);984png_ptr->palette_lookup = NULL;985png_free(png_ptr, png_ptr->quantize_index);986png_ptr->quantize_index = NULL;987#endif988989if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)990{991png_zfree(png_ptr, png_ptr->palette);992png_ptr->palette = NULL;993}994png_ptr->free_me &= ~PNG_FREE_PLTE;995996#if defined(PNG_tRNS_SUPPORTED) || \997defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)998if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)999{1000png_free(png_ptr, png_ptr->trans_alpha);1001png_ptr->trans_alpha = NULL;1002}1003png_ptr->free_me &= ~PNG_FREE_TRNS;1004#endif10051006inflateEnd(&png_ptr->zstream);10071008#ifdef PNG_PROGRESSIVE_READ_SUPPORTED1009png_free(png_ptr, png_ptr->save_buffer);1010png_ptr->save_buffer = NULL;1011#endif10121013#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \1014defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)1015png_free(png_ptr, png_ptr->unknown_chunk.data);1016png_ptr->unknown_chunk.data = NULL;1017#endif10181019#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED1020png_free(png_ptr, png_ptr->chunk_list);1021png_ptr->chunk_list = NULL;1022#endif10231024#if defined(PNG_READ_EXPAND_SUPPORTED) && \1025defined(PNG_ARM_NEON_IMPLEMENTATION)1026png_free(png_ptr, png_ptr->riffled_palette);1027png_ptr->riffled_palette = NULL;1028#endif10291030/* NOTE: the 'setjmp' buffer may still be allocated and the memory and error1031* callbacks are still set at this point. They are required to complete the1032* destruction of the png_struct itself.1033*/1034}10351036/* Free all memory used by the read */1037void PNGAPI1038png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,1039png_infopp end_info_ptr_ptr)1040{1041png_structrp png_ptr = NULL;10421043png_debug(1, "in png_destroy_read_struct");10441045if (png_ptr_ptr != NULL)1046png_ptr = *png_ptr_ptr;10471048if (png_ptr == NULL)1049return;10501051/* libpng 1.6.0: use the API to destroy info structs to ensure consistent1052* behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API.1053* The extra was, apparently, unnecessary yet this hides memory leak bugs.1054*/1055png_destroy_info_struct(png_ptr, end_info_ptr_ptr);1056png_destroy_info_struct(png_ptr, info_ptr_ptr);10571058*png_ptr_ptr = NULL;1059png_read_destroy(png_ptr);1060png_destroy_png_struct(png_ptr);1061}10621063void PNGAPI1064png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)1065{1066if (png_ptr == NULL)1067return;10681069png_ptr->read_row_fn = read_row_fn;1070}107110721073#ifdef PNG_SEQUENTIAL_READ_SUPPORTED1074#ifdef PNG_INFO_IMAGE_SUPPORTED1075void PNGAPI1076png_read_png(png_structrp png_ptr, png_inforp info_ptr,1077int transforms, voidp params)1078{1079if (png_ptr == NULL || info_ptr == NULL)1080return;10811082/* png_read_info() gives us all of the information from the1083* PNG file before the first IDAT (image data chunk).1084*/1085png_read_info(png_ptr, info_ptr);1086if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))1087png_error(png_ptr, "Image is too high to process with png_read_png()");10881089/* -------------- image transformations start here ------------------- */1090/* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM1091* is not implemented. This will only happen in de-configured (non-default)1092* libpng builds. The results can be unexpected - png_read_png may return1093* short or mal-formed rows because the transform is skipped.1094*/10951096/* Tell libpng to strip 16-bit/color files down to 8 bits per color.1097*/1098if ((transforms & PNG_TRANSFORM_SCALE_16) != 0)1099/* Added at libpng-1.5.4. "strip_16" produces the same result that it1100* did in earlier versions, while "scale_16" is now more accurate.1101*/1102#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED1103png_set_scale_16(png_ptr);1104#else1105png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");1106#endif11071108/* If both SCALE and STRIP are required pngrtran will effectively cancel the1109* latter by doing SCALE first. This is ok and allows apps not to check for1110* which is supported to get the right answer.1111*/1112if ((transforms & PNG_TRANSFORM_STRIP_16) != 0)1113#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED1114png_set_strip_16(png_ptr);1115#else1116png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");1117#endif11181119/* Strip alpha bytes from the input data without combining with1120* the background (not recommended).1121*/1122if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0)1123#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED1124png_set_strip_alpha(png_ptr);1125#else1126png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");1127#endif11281129/* Extract multiple pixels with bit depths of 1, 2, or 4 from a single1130* byte into separate bytes (useful for paletted and grayscale images).1131*/1132if ((transforms & PNG_TRANSFORM_PACKING) != 0)1133#ifdef PNG_READ_PACK_SUPPORTED1134png_set_packing(png_ptr);1135#else1136png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");1137#endif11381139/* Change the order of packed pixels to least significant bit first1140* (not useful if you are using png_set_packing).1141*/1142if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)1143#ifdef PNG_READ_PACKSWAP_SUPPORTED1144png_set_packswap(png_ptr);1145#else1146png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");1147#endif11481149/* Expand paletted colors into true RGB triplets1150* Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel1151* Expand paletted or RGB images with transparency to full alpha1152* channels so the data will be available as RGBA quartets.1153*/1154if ((transforms & PNG_TRANSFORM_EXPAND) != 0)1155#ifdef PNG_READ_EXPAND_SUPPORTED1156png_set_expand(png_ptr);1157#else1158png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");1159#endif11601161/* We don't handle background color or gamma transformation or quantizing.1162*/11631164/* Invert monochrome files to have 0 as white and 1 as black1165*/1166if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)1167#ifdef PNG_READ_INVERT_SUPPORTED1168png_set_invert_mono(png_ptr);1169#else1170png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");1171#endif11721173/* If you want to shift the pixel values from the range [0,255] or1174* [0,65535] to the original [0,7] or [0,31], or whatever range the1175* colors were originally in:1176*/1177if ((transforms & PNG_TRANSFORM_SHIFT) != 0)1178#ifdef PNG_READ_SHIFT_SUPPORTED1179if ((info_ptr->valid & PNG_INFO_sBIT) != 0)1180png_set_shift(png_ptr, &info_ptr->sig_bit);1181#else1182png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");1183#endif11841185/* Flip the RGB pixels to BGR (or RGBA to BGRA) */1186if ((transforms & PNG_TRANSFORM_BGR) != 0)1187#ifdef PNG_READ_BGR_SUPPORTED1188png_set_bgr(png_ptr);1189#else1190png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");1191#endif11921193/* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */1194if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)1195#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED1196png_set_swap_alpha(png_ptr);1197#else1198png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");1199#endif12001201/* Swap bytes of 16-bit files to least significant byte first */1202if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)1203#ifdef PNG_READ_SWAP_SUPPORTED1204png_set_swap(png_ptr);1205#else1206png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");1207#endif12081209/* Added at libpng-1.2.41 */1210/* Invert the alpha channel from opacity to transparency */1211if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)1212#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED1213png_set_invert_alpha(png_ptr);1214#else1215png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");1216#endif12171218/* Added at libpng-1.2.41 */1219/* Expand grayscale image to RGB */1220if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0)1221#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED1222png_set_gray_to_rgb(png_ptr);1223#else1224png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");1225#endif12261227/* Added at libpng-1.5.4 */1228if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0)1229#ifdef PNG_READ_EXPAND_16_SUPPORTED1230png_set_expand_16(png_ptr);1231#else1232png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");1233#endif12341235/* We don't handle adding filler bytes */12361237/* We use png_read_image and rely on that for interlace handling, but we also1238* call png_read_update_info therefore must turn on interlace handling now:1239*/1240(void)png_set_interlace_handling(png_ptr);12411242/* Optional call to gamma correct and add the background to the palette1243* and update info structure. REQUIRED if you are expecting libpng to1244* update the palette for you (i.e., you selected such a transform above).1245*/1246png_read_update_info(png_ptr, info_ptr);12471248/* -------------- image transformations end here ------------------- */12491250png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);1251if (info_ptr->row_pointers == NULL)1252{1253png_uint_32 iptr;12541255info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,1256info_ptr->height * (sizeof (png_bytep))));12571258for (iptr=0; iptr<info_ptr->height; iptr++)1259info_ptr->row_pointers[iptr] = NULL;12601261info_ptr->free_me |= PNG_FREE_ROWS;12621263for (iptr = 0; iptr < info_ptr->height; iptr++)1264info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,1265png_malloc(png_ptr, info_ptr->rowbytes));1266}12671268png_read_image(png_ptr, info_ptr->row_pointers);1269info_ptr->valid |= PNG_INFO_IDAT;12701271/* Read rest of file, and get additional chunks in info_ptr - REQUIRED */1272png_read_end(png_ptr, info_ptr);12731274PNG_UNUSED(params)1275}1276#endif /* INFO_IMAGE */1277#endif /* SEQUENTIAL_READ */12781279#ifdef PNG_SIMPLIFIED_READ_SUPPORTED1280/* SIMPLIFIED READ1281*1282* This code currently relies on the sequential reader, though it could easily1283* be made to work with the progressive one.1284*/1285/* Arguments to png_image_finish_read: */12861287/* Encoding of PNG data (used by the color-map code) */1288# define P_NOTSET 0 /* File encoding not yet known */1289# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */1290# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */1291# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */1292# define P_LINEAR8 4 /* 8-bit linear: only from a file value */12931294/* Color-map processing: after libpng has run on the PNG image further1295* processing may be needed to convert the data to color-map indices.1296*/1297#define PNG_CMAP_NONE 01298#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */1299#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */1300#define PNG_CMAP_RGB 3 /* Process RGB data */1301#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */13021303/* The following document where the background is for each processing case. */1304#define PNG_CMAP_NONE_BACKGROUND 2561305#define PNG_CMAP_GA_BACKGROUND 2311306#define PNG_CMAP_TRANS_BACKGROUND 2541307#define PNG_CMAP_RGB_BACKGROUND 2561308#define PNG_CMAP_RGB_ALPHA_BACKGROUND 21613091310typedef struct1311{1312/* Arguments: */1313png_imagep image;1314png_voidp buffer;1315png_int_32 row_stride;1316png_voidp colormap;1317png_const_colorp background;1318/* Local variables: */1319png_voidp local_row;1320png_voidp first_row;1321ptrdiff_t row_bytes; /* step between rows */1322int file_encoding; /* E_ values above */1323png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */1324int colormap_processing; /* PNG_CMAP_ values above */1325} png_image_read_control;13261327/* Do all the *safe* initialization - 'safe' means that png_error won't be1328* called, so setting up the jmp_buf is not required. This means that anything1329* called from here must *not* call png_malloc - it has to call png_malloc_warn1330* instead so that control is returned safely back to this routine.1331*/1332static int1333png_image_read_init(png_imagep image)1334{1335if (image->opaque == NULL)1336{1337png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,1338png_safe_error, png_safe_warning);13391340/* And set the rest of the structure to NULL to ensure that the various1341* fields are consistent.1342*/1343memset(image, 0, (sizeof *image));1344image->version = PNG_IMAGE_VERSION;13451346if (png_ptr != NULL)1347{1348png_infop info_ptr = png_create_info_struct(png_ptr);13491350if (info_ptr != NULL)1351{1352png_controlp control = png_voidcast(png_controlp,1353png_malloc_warn(png_ptr, (sizeof *control)));13541355if (control != NULL)1356{1357memset(control, 0, (sizeof *control));13581359control->png_ptr = png_ptr;1360control->info_ptr = info_ptr;1361control->for_write = 0;13621363image->opaque = control;1364return 1;1365}13661367/* Error clean up */1368png_destroy_info_struct(png_ptr, &info_ptr);1369}13701371png_destroy_read_struct(&png_ptr, NULL, NULL);1372}13731374return png_image_error(image, "png_image_read: out of memory");1375}13761377return png_image_error(image, "png_image_read: opaque pointer not NULL");1378}13791380/* Utility to find the base format of a PNG file from a png_struct. */1381static png_uint_321382png_image_format(png_structrp png_ptr)1383{1384png_uint_32 format = 0;13851386if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)1387format |= PNG_FORMAT_FLAG_COLOR;13881389if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)1390format |= PNG_FORMAT_FLAG_ALPHA;13911392/* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS1393* sets the png_struct fields; that's all we are interested in here. The1394* precise interaction with an app call to png_set_tRNS and PNG file reading1395* is unclear.1396*/1397else if (png_ptr->num_trans > 0)1398format |= PNG_FORMAT_FLAG_ALPHA;13991400if (png_ptr->bit_depth == 16)1401format |= PNG_FORMAT_FLAG_LINEAR;14021403if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0)1404format |= PNG_FORMAT_FLAG_COLORMAP;14051406return format;1407}14081409/* Is the given gamma significantly different from sRGB? The test is the same1410* one used in pngrtran.c when deciding whether to do gamma correction. The1411* arithmetic optimizes the division by using the fact that the inverse of the1412* file sRGB gamma is 2.21413*/1414static int1415png_gamma_not_sRGB(png_fixed_point g)1416{1417if (g < PNG_FP_1)1418{1419/* An uninitialized gamma is assumed to be sRGB for the simplified API. */1420if (g == 0)1421return 0;14221423return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);1424}14251426return 1;1427}14281429/* Do the main body of a 'png_image_begin_read' function; read the PNG file1430* header and fill in all the information. This is executed in a safe context,1431* unlike the init routine above.1432*/1433static int1434png_image_read_header(png_voidp argument)1435{1436png_imagep image = png_voidcast(png_imagep, argument);1437png_structrp png_ptr = image->opaque->png_ptr;1438png_inforp info_ptr = image->opaque->info_ptr;14391440#ifdef PNG_BENIGN_ERRORS_SUPPORTED1441png_set_benign_errors(png_ptr, 1/*warn*/);1442#endif1443png_read_info(png_ptr, info_ptr);14441445/* Do this the fast way; just read directly out of png_struct. */1446image->width = png_ptr->width;1447image->height = png_ptr->height;14481449{1450png_uint_32 format = png_image_format(png_ptr);14511452image->format = format;14531454#ifdef PNG_COLORSPACE_SUPPORTED1455/* Does the colorspace match sRGB? If there is no color endpoint1456* (colorant) information assume yes, otherwise require the1457* 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the1458* colorspace has been determined to be invalid ignore it.1459*/1460if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags1461& (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|1462PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))1463image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;1464#endif1465}14661467/* We need the maximum number of entries regardless of the format the1468* application sets here.1469*/1470{1471png_uint_32 cmap_entries;14721473switch (png_ptr->color_type)1474{1475case PNG_COLOR_TYPE_GRAY:1476cmap_entries = 1U << png_ptr->bit_depth;1477break;14781479case PNG_COLOR_TYPE_PALETTE:1480cmap_entries = (png_uint_32)png_ptr->num_palette;1481break;14821483default:1484cmap_entries = 256;1485break;1486}14871488if (cmap_entries > 256)1489cmap_entries = 256;14901491image->colormap_entries = cmap_entries;1492}14931494return 1;1495}14961497#ifdef PNG_STDIO_SUPPORTED1498int PNGAPI1499png_image_begin_read_from_stdio(png_imagep image, FILE* file)1500{1501if (image != NULL && image->version == PNG_IMAGE_VERSION)1502{1503if (file != NULL)1504{1505if (png_image_read_init(image) != 0)1506{1507/* This is slightly evil, but png_init_io doesn't do anything other1508* than this and we haven't changed the standard IO functions so1509* this saves a 'safe' function.1510*/1511image->opaque->png_ptr->io_ptr = file;1512return png_safe_execute(image, png_image_read_header, image);1513}1514}15151516else1517return png_image_error(image,1518"png_image_begin_read_from_stdio: invalid argument");1519}15201521else if (image != NULL)1522return png_image_error(image,1523"png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");15241525return 0;1526}15271528int PNGAPI1529png_image_begin_read_from_file(png_imagep image, const char *file_name)1530{1531if (image != NULL && image->version == PNG_IMAGE_VERSION)1532{1533if (file_name != NULL)1534{1535FILE *fp = fopen(file_name, "rb");15361537if (fp != NULL)1538{1539if (png_image_read_init(image) != 0)1540{1541image->opaque->png_ptr->io_ptr = fp;1542image->opaque->owned_file = 1;1543return png_safe_execute(image, png_image_read_header, image);1544}15451546/* Clean up: just the opened file. */1547(void)fclose(fp);1548}15491550else1551return png_image_error(image, strerror(errno));1552}15531554else1555return png_image_error(image,1556"png_image_begin_read_from_file: invalid argument");1557}15581559else if (image != NULL)1560return png_image_error(image,1561"png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");15621563return 0;1564}1565#endif /* STDIO */15661567static void PNGCBAPI1568png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need)1569{1570if (png_ptr != NULL)1571{1572png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);1573if (image != NULL)1574{1575png_controlp cp = image->opaque;1576if (cp != NULL)1577{1578png_const_bytep memory = cp->memory;1579size_t size = cp->size;15801581if (memory != NULL && size >= need)1582{1583memcpy(out, memory, need);1584cp->memory = memory + need;1585cp->size = size - need;1586return;1587}15881589png_error(png_ptr, "read beyond end of data");1590}1591}15921593png_error(png_ptr, "invalid memory read");1594}1595}15961597int PNGAPI png_image_begin_read_from_memory(png_imagep image,1598png_const_voidp memory, size_t size)1599{1600if (image != NULL && image->version == PNG_IMAGE_VERSION)1601{1602if (memory != NULL && size > 0)1603{1604if (png_image_read_init(image) != 0)1605{1606/* Now set the IO functions to read from the memory buffer and1607* store it into io_ptr. Again do this in-place to avoid calling a1608* libpng function that requires error handling.1609*/1610image->opaque->memory = png_voidcast(png_const_bytep, memory);1611image->opaque->size = size;1612image->opaque->png_ptr->io_ptr = image;1613image->opaque->png_ptr->read_data_fn = png_image_memory_read;16141615return png_safe_execute(image, png_image_read_header, image);1616}1617}16181619else1620return png_image_error(image,1621"png_image_begin_read_from_memory: invalid argument");1622}16231624else if (image != NULL)1625return png_image_error(image,1626"png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");16271628return 0;1629}16301631/* Utility function to skip chunks that are not used by the simplified image1632* read functions and an appropriate macro to call it.1633*/1634#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED1635static void1636png_image_skip_unused_chunks(png_structrp png_ptr)1637{1638/* Prepare the reader to ignore all recognized chunks whose data will not1639* be used, i.e., all chunks recognized by libpng except for those1640* involved in basic image reading:1641*1642* IHDR, PLTE, IDAT, IEND1643*1644* Or image data handling:1645*1646* tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.1647*1648* This provides a small performance improvement and eliminates any1649* potential vulnerability to security problems in the unused chunks.1650*1651* At present the iCCP chunk data isn't used, so iCCP chunk can be ignored1652* too. This allows the simplified API to be compiled without iCCP support,1653* however if the support is there the chunk is still checked to detect1654* errors (which are unfortunately quite common.)1655*/1656{1657static const png_byte chunks_to_process[] = {165898, 75, 71, 68, '\0', /* bKGD */165999, 72, 82, 77, '\0', /* cHRM */1660103, 65, 77, 65, '\0', /* gAMA */1661# ifdef PNG_READ_iCCP_SUPPORTED1662105, 67, 67, 80, '\0', /* iCCP */1663# endif1664115, 66, 73, 84, '\0', /* sBIT */1665115, 82, 71, 66, '\0', /* sRGB */1666};16671668/* Ignore unknown chunks and all other chunks except for the1669* IHDR, PLTE, tRNS, IDAT, and IEND chunks.1670*/1671png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,1672NULL, -1);16731674/* But do not ignore image data handling chunks */1675png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,1676chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);1677}1678}16791680# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)1681#else1682# define PNG_SKIP_CHUNKS(p) ((void)0)1683#endif /* HANDLE_AS_UNKNOWN */16841685/* The following macro gives the exact rounded answer for all values in the1686* range 0..255 (it actually divides by 51.2, but the rounding still generates1687* the correct numbers 0..51688*/1689#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)16901691/* Utility functions to make particular color-maps */1692static void1693set_file_encoding(png_image_read_control *display)1694{1695png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;1696if (png_gamma_significant(g) != 0)1697{1698if (png_gamma_not_sRGB(g) != 0)1699{1700display->file_encoding = P_FILE;1701display->gamma_to_linear = png_reciprocal(g);1702}17031704else1705display->file_encoding = P_sRGB;1706}17071708else1709display->file_encoding = P_LINEAR8;1710}17111712static unsigned int1713decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)1714{1715if (encoding == P_FILE) /* double check */1716encoding = display->file_encoding;17171718if (encoding == P_NOTSET) /* must be the file encoding */1719{1720set_file_encoding(display);1721encoding = display->file_encoding;1722}17231724switch (encoding)1725{1726case P_FILE:1727value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);1728break;17291730case P_sRGB:1731value = png_sRGB_table[value];1732break;17331734case P_LINEAR:1735break;17361737case P_LINEAR8:1738value *= 257;1739break;17401741#ifdef __GNUC__1742default:1743png_error(display->image->opaque->png_ptr,1744"unexpected encoding (internal error)");1745#endif1746}17471748return value;1749}17501751static png_uint_321752png_colormap_compose(png_image_read_control *display,1753png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,1754png_uint_32 background, int encoding)1755{1756/* The file value is composed on the background, the background has the given1757* encoding and so does the result, the file is encoded with P_FILE and the1758* file and alpha are 8-bit values. The (output) encoding will always be1759* P_LINEAR or P_sRGB.1760*/1761png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);1762png_uint_32 b = decode_gamma(display, background, encoding);17631764/* The alpha is always an 8-bit value (it comes from the palette), the value1765* scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.1766*/1767f = f * alpha + b * (255-alpha);17681769if (encoding == P_LINEAR)1770{1771/* Scale to 65535; divide by 255, approximately (in fact this is extremely1772* accurate, it divides by 255.00000005937181414556, with no overflow.)1773*/1774f *= 257; /* Now scaled by 65535 */1775f += f >> 16;1776f = (f+32768) >> 16;1777}17781779else /* P_sRGB */1780f = PNG_sRGB_FROM_LINEAR(f);17811782return f;1783}17841785/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must1786* be 8-bit.1787*/1788static void1789png_create_colormap_entry(png_image_read_control *display,1790png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,1791png_uint_32 alpha, int encoding)1792{1793png_imagep image = display->image;1794int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?1795P_LINEAR : P_sRGB;1796int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&1797(red != green || green != blue);17981799if (ip > 255)1800png_error(image->opaque->png_ptr, "color-map index out of range");18011802/* Update the cache with whether the file gamma is significantly different1803* from sRGB.1804*/1805if (encoding == P_FILE)1806{1807if (display->file_encoding == P_NOTSET)1808set_file_encoding(display);18091810/* Note that the cached value may be P_FILE too, but if it is then the1811* gamma_to_linear member has been set.1812*/1813encoding = display->file_encoding;1814}18151816if (encoding == P_FILE)1817{1818png_fixed_point g = display->gamma_to_linear;18191820red = png_gamma_16bit_correct(red*257, g);1821green = png_gamma_16bit_correct(green*257, g);1822blue = png_gamma_16bit_correct(blue*257, g);18231824if (convert_to_Y != 0 || output_encoding == P_LINEAR)1825{1826alpha *= 257;1827encoding = P_LINEAR;1828}18291830else1831{1832red = PNG_sRGB_FROM_LINEAR(red * 255);1833green = PNG_sRGB_FROM_LINEAR(green * 255);1834blue = PNG_sRGB_FROM_LINEAR(blue * 255);1835encoding = P_sRGB;1836}1837}18381839else if (encoding == P_LINEAR8)1840{1841/* This encoding occurs quite frequently in test cases because PngSuite1842* includes a gAMA 1.0 chunk with most images.1843*/1844red *= 257;1845green *= 257;1846blue *= 257;1847alpha *= 257;1848encoding = P_LINEAR;1849}18501851else if (encoding == P_sRGB &&1852(convert_to_Y != 0 || output_encoding == P_LINEAR))1853{1854/* The values are 8-bit sRGB values, but must be converted to 16-bit1855* linear.1856*/1857red = png_sRGB_table[red];1858green = png_sRGB_table[green];1859blue = png_sRGB_table[blue];1860alpha *= 257;1861encoding = P_LINEAR;1862}18631864/* This is set if the color isn't gray but the output is. */1865if (encoding == P_LINEAR)1866{1867if (convert_to_Y != 0)1868{1869/* NOTE: these values are copied from png_do_rgb_to_gray */1870png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green +1871(png_uint_32)2366 * blue;18721873if (output_encoding == P_LINEAR)1874y = (y + 16384) >> 15;18751876else1877{1878/* y is scaled by 32768, we need it scaled by 255: */1879y = (y + 128) >> 8;1880y *= 255;1881y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);1882alpha = PNG_DIV257(alpha);1883encoding = P_sRGB;1884}18851886blue = red = green = y;1887}18881889else if (output_encoding == P_sRGB)1890{1891red = PNG_sRGB_FROM_LINEAR(red * 255);1892green = PNG_sRGB_FROM_LINEAR(green * 255);1893blue = PNG_sRGB_FROM_LINEAR(blue * 255);1894alpha = PNG_DIV257(alpha);1895encoding = P_sRGB;1896}1897}18981899if (encoding != output_encoding)1900png_error(image->opaque->png_ptr, "bad encoding (internal error)");19011902/* Store the value. */1903{1904# ifdef PNG_FORMAT_AFIRST_SUPPORTED1905int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&1906(image->format & PNG_FORMAT_FLAG_ALPHA) != 0;1907# else1908# define afirst 01909# endif1910# ifdef PNG_FORMAT_BGR_SUPPORTED1911int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;1912# else1913# define bgr 01914# endif19151916if (output_encoding == P_LINEAR)1917{1918png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);19191920entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);19211922/* The linear 16-bit values must be pre-multiplied by the alpha channel1923* value, if less than 65535 (this is, effectively, composite on black1924* if the alpha channel is removed.)1925*/1926switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))1927{1928case 4:1929entry[afirst ? 0 : 3] = (png_uint_16)alpha;1930/* FALLTHROUGH */19311932case 3:1933if (alpha < 65535)1934{1935if (alpha > 0)1936{1937blue = (blue * alpha + 32767U)/65535U;1938green = (green * alpha + 32767U)/65535U;1939red = (red * alpha + 32767U)/65535U;1940}19411942else1943red = green = blue = 0;1944}1945entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;1946entry[afirst + 1] = (png_uint_16)green;1947entry[afirst + bgr] = (png_uint_16)red;1948break;19491950case 2:1951entry[1 ^ afirst] = (png_uint_16)alpha;1952/* FALLTHROUGH */19531954case 1:1955if (alpha < 65535)1956{1957if (alpha > 0)1958green = (green * alpha + 32767U)/65535U;19591960else1961green = 0;1962}1963entry[afirst] = (png_uint_16)green;1964break;19651966default:1967break;1968}1969}19701971else /* output encoding is P_sRGB */1972{1973png_bytep entry = png_voidcast(png_bytep, display->colormap);19741975entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);19761977switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))1978{1979case 4:1980entry[afirst ? 0 : 3] = (png_byte)alpha;1981/* FALLTHROUGH */1982case 3:1983entry[afirst + (2 ^ bgr)] = (png_byte)blue;1984entry[afirst + 1] = (png_byte)green;1985entry[afirst + bgr] = (png_byte)red;1986break;19871988case 2:1989entry[1 ^ afirst] = (png_byte)alpha;1990/* FALLTHROUGH */1991case 1:1992entry[afirst] = (png_byte)green;1993break;19941995default:1996break;1997}1998}19992000# ifdef afirst2001# undef afirst2002# endif2003# ifdef bgr2004# undef bgr2005# endif2006}2007}20082009static int2010make_gray_file_colormap(png_image_read_control *display)2011{2012unsigned int i;20132014for (i=0; i<256; ++i)2015png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);20162017return (int)i;2018}20192020static int2021make_gray_colormap(png_image_read_control *display)2022{2023unsigned int i;20242025for (i=0; i<256; ++i)2026png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);20272028return (int)i;2029}2030#define PNG_GRAY_COLORMAP_ENTRIES 25620312032static int2033make_ga_colormap(png_image_read_control *display)2034{2035unsigned int i, a;20362037/* Alpha is retained, the output will be a color-map with entries2038* selected by six levels of alpha. One transparent entry, 6 gray2039* levels for all the intermediate alpha values, leaving 230 entries2040* for the opaque grays. The color-map entries are the six values2041* [0..5]*51, the GA processing uses PNG_DIV51(value) to find the2042* relevant entry.2043*2044* if (alpha > 229) // opaque2045* {2046* // The 231 entries are selected to make the math below work:2047* base = 0;2048* entry = (231 * gray + 128) >> 8;2049* }2050* else if (alpha < 26) // transparent2051* {2052* base = 231;2053* entry = 0;2054* }2055* else // partially opaque2056* {2057* base = 226 + 6 * PNG_DIV51(alpha);2058* entry = PNG_DIV51(gray);2059* }2060*/2061i = 0;2062while (i < 231)2063{2064unsigned int gray = (i * 256 + 115) / 231;2065png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);2066}20672068/* 255 is used here for the component values for consistency with the code2069* that undoes premultiplication in pngwrite.c.2070*/2071png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);20722073for (a=1; a<5; ++a)2074{2075unsigned int g;20762077for (g=0; g<6; ++g)2078png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,2079P_sRGB);2080}20812082return (int)i;2083}20842085#define PNG_GA_COLORMAP_ENTRIES 25620862087static int2088make_rgb_colormap(png_image_read_control *display)2089{2090unsigned int i, r;20912092/* Build a 6x6x6 opaque RGB cube */2093for (i=r=0; r<6; ++r)2094{2095unsigned int g;20962097for (g=0; g<6; ++g)2098{2099unsigned int b;21002101for (b=0; b<6; ++b)2102png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,2103P_sRGB);2104}2105}21062107return (int)i;2108}21092110#define PNG_RGB_COLORMAP_ENTRIES 21621112112/* Return a palette index to the above palette given three 8-bit sRGB values. */2113#define PNG_RGB_INDEX(r,g,b) \2114((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))21152116static int2117png_image_read_colormap(png_voidp argument)2118{2119png_image_read_control *display =2120png_voidcast(png_image_read_control*, argument);2121png_imagep image = display->image;21222123png_structrp png_ptr = image->opaque->png_ptr;2124png_uint_32 output_format = image->format;2125int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?2126P_LINEAR : P_sRGB;21272128unsigned int cmap_entries;2129unsigned int output_processing; /* Output processing option */2130unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */21312132/* Background information; the background color and the index of this color2133* in the color-map if it exists (else 256).2134*/2135unsigned int background_index = 256;2136png_uint_32 back_r, back_g, back_b;21372138/* Flags to accumulate things that need to be done to the input. */2139int expand_tRNS = 0;21402141/* Exclude the NYI feature of compositing onto a color-mapped buffer; it is2142* very difficult to do, the results look awful, and it is difficult to see2143* what possible use it is because the application can't control the2144* color-map.2145*/2146if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||2147png_ptr->num_trans > 0) /* alpha in input */ &&2148((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)2149{2150if (output_encoding == P_LINEAR) /* compose on black */2151back_b = back_g = back_r = 0;21522153else if (display->background == NULL /* no way to remove it */)2154png_error(png_ptr,2155"background color must be supplied to remove alpha/transparency");21562157/* Get a copy of the background color (this avoids repeating the checks2158* below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the2159* output format.2160*/2161else2162{2163back_g = display->background->green;2164if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0)2165{2166back_r = display->background->red;2167back_b = display->background->blue;2168}2169else2170back_b = back_r = back_g;2171}2172}21732174else if (output_encoding == P_LINEAR)2175back_b = back_r = back_g = 65535;21762177else2178back_b = back_r = back_g = 255;21792180/* Default the input file gamma if required - this is necessary because2181* libpng assumes that if no gamma information is present the data is in the2182* output format, but the simplified API deduces the gamma from the input2183* format.2184*/2185if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)2186{2187/* Do this directly, not using the png_colorspace functions, to ensure2188* that it happens even if the colorspace is invalid (though probably if2189* it is the setting will be ignored) Note that the same thing can be2190* achieved at the application interface with png_set_gAMA.2191*/2192if (png_ptr->bit_depth == 16 &&2193(image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)2194png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;21952196else2197png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;21982199png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;2200}22012202/* Decide what to do based on the PNG color type of the input data. The2203* utility function png_create_colormap_entry deals with most aspects of the2204* output transformations; this code works out how to produce bytes of2205* color-map entries from the original format.2206*/2207switch (png_ptr->color_type)2208{2209case PNG_COLOR_TYPE_GRAY:2210if (png_ptr->bit_depth <= 8)2211{2212/* There at most 256 colors in the output, regardless of2213* transparency.2214*/2215unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;22162217cmap_entries = 1U << png_ptr->bit_depth;2218if (cmap_entries > image->colormap_entries)2219png_error(png_ptr, "gray[8] color-map: too few entries");22202221step = 255 / (cmap_entries - 1);2222output_processing = PNG_CMAP_NONE;22232224/* If there is a tRNS chunk then this either selects a transparent2225* value or, if the output has no alpha, the background color.2226*/2227if (png_ptr->num_trans > 0)2228{2229trans = png_ptr->trans_color.gray;22302231if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)2232back_alpha = output_encoding == P_LINEAR ? 65535 : 255;2233}22342235/* png_create_colormap_entry just takes an RGBA and writes the2236* corresponding color-map entry using the format from 'image',2237* including the required conversion to sRGB or linear as2238* appropriate. The input values are always either sRGB (if the2239* gamma correction flag is 0) or 0..255 scaled file encoded values2240* (if the function must gamma correct them).2241*/2242for (i=val=0; i<cmap_entries; ++i, val += step)2243{2244/* 'i' is a file value. While this will result in duplicated2245* entries for 8-bit non-sRGB encoded files it is necessary to2246* have non-gamma corrected values to do tRNS handling.2247*/2248if (i != trans)2249png_create_colormap_entry(display, i, val, val, val, 255,2250P_FILE/*8-bit with file gamma*/);22512252/* Else this entry is transparent. The colors don't matter if2253* there is an alpha channel (back_alpha == 0), but it does no2254* harm to pass them in; the values are not set above so this2255* passes in white.2256*2257* NOTE: this preserves the full precision of the application2258* supplied background color when it is used.2259*/2260else2261png_create_colormap_entry(display, i, back_r, back_g, back_b,2262back_alpha, output_encoding);2263}22642265/* We need libpng to preserve the original encoding. */2266data_encoding = P_FILE;22672268/* The rows from libpng, while technically gray values, are now also2269* color-map indices; however, they may need to be expanded to 12270* byte per pixel. This is what png_set_packing does (i.e., it2271* unpacks the bit values into bytes.)2272*/2273if (png_ptr->bit_depth < 8)2274png_set_packing(png_ptr);2275}22762277else /* bit depth is 16 */2278{2279/* The 16-bit input values can be converted directly to 8-bit gamma2280* encoded values; however, if a tRNS chunk is present 257 color-map2281* entries are required. This means that the extra entry requires2282* special processing; add an alpha channel, sacrifice gray level2283* 254 and convert transparent (alpha==0) entries to that.2284*2285* Use libpng to chop the data to 8 bits. Convert it to sRGB at the2286* same time to minimize quality loss. If a tRNS chunk is present2287* this means libpng must handle it too; otherwise it is impossible2288* to do the exact match on the 16-bit value.2289*2290* If the output has no alpha channel *and* the background color is2291* gray then it is possible to let libpng handle the substitution by2292* ensuring that the corresponding gray level matches the background2293* color exactly.2294*/2295data_encoding = P_sRGB;22962297if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)2298png_error(png_ptr, "gray[16] color-map: too few entries");22992300cmap_entries = (unsigned int)make_gray_colormap(display);23012302if (png_ptr->num_trans > 0)2303{2304unsigned int back_alpha;23052306if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)2307back_alpha = 0;23082309else2310{2311if (back_r == back_g && back_g == back_b)2312{2313/* Background is gray; no special processing will be2314* required.2315*/2316png_color_16 c;2317png_uint_32 gray = back_g;23182319if (output_encoding == P_LINEAR)2320{2321gray = PNG_sRGB_FROM_LINEAR(gray * 255);23222323/* And make sure the corresponding palette entry2324* matches.2325*/2326png_create_colormap_entry(display, gray, back_g, back_g,2327back_g, 65535, P_LINEAR);2328}23292330/* The background passed to libpng, however, must be the2331* sRGB value.2332*/2333c.index = 0; /*unused*/2334c.gray = c.red = c.green = c.blue = (png_uint_16)gray;23352336/* NOTE: does this work without expanding tRNS to alpha?2337* It should be the color->gray case below apparently2338* doesn't.2339*/2340png_set_background_fixed(png_ptr, &c,2341PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,23420/*gamma: not used*/);23432344output_processing = PNG_CMAP_NONE;2345break;2346}2347#ifdef __COVERITY__2348/* Coverity claims that output_encoding cannot be 2 (P_LINEAR)2349* here.2350*/2351back_alpha = 255;2352#else2353back_alpha = output_encoding == P_LINEAR ? 65535 : 255;2354#endif2355}23562357/* output_processing means that the libpng-processed row will be2358* 8-bit GA and it has to be processing to single byte color-map2359* values. Entry 254 is replaced by either a completely2360* transparent entry or by the background color at full2361* precision (and the background color is not a simple gray2362* level in this case.)2363*/2364expand_tRNS = 1;2365output_processing = PNG_CMAP_TRANS;2366background_index = 254;23672368/* And set (overwrite) color-map entry 254 to the actual2369* background color at full precision.2370*/2371png_create_colormap_entry(display, 254, back_r, back_g, back_b,2372back_alpha, output_encoding);2373}23742375else2376output_processing = PNG_CMAP_NONE;2377}2378break;23792380case PNG_COLOR_TYPE_GRAY_ALPHA:2381/* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum2382* of 65536 combinations. If, however, the alpha channel is to be2383* removed there are only 256 possibilities if the background is gray.2384* (Otherwise there is a subset of the 65536 possibilities defined by2385* the triangle between black, white and the background color.)2386*2387* Reduce 16-bit files to 8-bit and sRGB encode the result. No need to2388* worry about tRNS matching - tRNS is ignored if there is an alpha2389* channel.2390*/2391data_encoding = P_sRGB;23922393if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)2394{2395if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)2396png_error(png_ptr, "gray+alpha color-map: too few entries");23972398cmap_entries = (unsigned int)make_ga_colormap(display);23992400background_index = PNG_CMAP_GA_BACKGROUND;2401output_processing = PNG_CMAP_GA;2402}24032404else /* alpha is removed */2405{2406/* Alpha must be removed as the PNG data is processed when the2407* background is a color because the G and A channels are2408* independent and the vector addition (non-parallel vectors) is a2409* 2-D problem.2410*2411* This can be reduced to the same algorithm as above by making a2412* colormap containing gray levels (for the opaque grays), a2413* background entry (for a transparent pixel) and a set of four six2414* level color values, one set for each intermediate alpha value.2415* See the comments in make_ga_colormap for how this works in the2416* per-pixel processing.2417*2418* If the background is gray, however, we only need a 256 entry gray2419* level color map. It is sufficient to make the entry generated2420* for the background color be exactly the color specified.2421*/2422if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||2423(back_r == back_g && back_g == back_b))2424{2425/* Background is gray; no special processing will be required. */2426png_color_16 c;2427png_uint_32 gray = back_g;24282429if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)2430png_error(png_ptr, "gray-alpha color-map: too few entries");24312432cmap_entries = (unsigned int)make_gray_colormap(display);24332434if (output_encoding == P_LINEAR)2435{2436gray = PNG_sRGB_FROM_LINEAR(gray * 255);24372438/* And make sure the corresponding palette entry matches. */2439png_create_colormap_entry(display, gray, back_g, back_g,2440back_g, 65535, P_LINEAR);2441}24422443/* The background passed to libpng, however, must be the sRGB2444* value.2445*/2446c.index = 0; /*unused*/2447c.gray = c.red = c.green = c.blue = (png_uint_16)gray;24482449png_set_background_fixed(png_ptr, &c,2450PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,24510/*gamma: not used*/);24522453output_processing = PNG_CMAP_NONE;2454}24552456else2457{2458png_uint_32 i, a;24592460/* This is the same as png_make_ga_colormap, above, except that2461* the entries are all opaque.2462*/2463if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)2464png_error(png_ptr, "ga-alpha color-map: too few entries");24652466i = 0;2467while (i < 231)2468{2469png_uint_32 gray = (i * 256 + 115) / 231;2470png_create_colormap_entry(display, i++, gray, gray, gray,2471255, P_sRGB);2472}24732474/* NOTE: this preserves the full precision of the application2475* background color.2476*/2477background_index = i;2478png_create_colormap_entry(display, i++, back_r, back_g, back_b,2479#ifdef __COVERITY__2480/* Coverity claims that output_encoding2481* cannot be 2 (P_LINEAR) here.2482*/ 255U,2483#else2484output_encoding == P_LINEAR ? 65535U : 255U,2485#endif2486output_encoding);24872488/* For non-opaque input composite on the sRGB background - this2489* requires inverting the encoding for each component. The input2490* is still converted to the sRGB encoding because this is a2491* reasonable approximate to the logarithmic curve of human2492* visual sensitivity, at least over the narrow range which PNG2493* represents. Consequently 'G' is always sRGB encoded, while2494* 'A' is linear. We need the linear background colors.2495*/2496if (output_encoding == P_sRGB) /* else already linear */2497{2498/* This may produce a value not exactly matching the2499* background, but that's ok because these numbers are only2500* used when alpha != 02501*/2502back_r = png_sRGB_table[back_r];2503back_g = png_sRGB_table[back_g];2504back_b = png_sRGB_table[back_b];2505}25062507for (a=1; a<5; ++a)2508{2509unsigned int g;25102511/* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled2512* by an 8-bit alpha value (0..255).2513*/2514png_uint_32 alpha = 51 * a;2515png_uint_32 back_rx = (255-alpha) * back_r;2516png_uint_32 back_gx = (255-alpha) * back_g;2517png_uint_32 back_bx = (255-alpha) * back_b;25182519for (g=0; g<6; ++g)2520{2521png_uint_32 gray = png_sRGB_table[g*51] * alpha;25222523png_create_colormap_entry(display, i++,2524PNG_sRGB_FROM_LINEAR(gray + back_rx),2525PNG_sRGB_FROM_LINEAR(gray + back_gx),2526PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);2527}2528}25292530cmap_entries = i;2531output_processing = PNG_CMAP_GA;2532}2533}2534break;25352536case PNG_COLOR_TYPE_RGB:2537case PNG_COLOR_TYPE_RGB_ALPHA:2538/* Exclude the case where the output is gray; we can always handle this2539* with the cases above.2540*/2541if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)2542{2543/* The color-map will be grayscale, so we may as well convert the2544* input RGB values to a simple grayscale and use the grayscale2545* code above.2546*2547* NOTE: calling this apparently damages the recognition of the2548* transparent color in background color handling; call2549* png_set_tRNS_to_alpha before png_set_background_fixed.2550*/2551png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,2552-1);2553data_encoding = P_sRGB;25542555/* The output will now be one or two 8-bit gray or gray+alpha2556* channels. The more complex case arises when the input has alpha.2557*/2558if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||2559png_ptr->num_trans > 0) &&2560(output_format & PNG_FORMAT_FLAG_ALPHA) != 0)2561{2562/* Both input and output have an alpha channel, so no background2563* processing is required; just map the GA bytes to the right2564* color-map entry.2565*/2566expand_tRNS = 1;25672568if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)2569png_error(png_ptr, "rgb[ga] color-map: too few entries");25702571cmap_entries = (unsigned int)make_ga_colormap(display);2572background_index = PNG_CMAP_GA_BACKGROUND;2573output_processing = PNG_CMAP_GA;2574}25752576else2577{2578/* Either the input or the output has no alpha channel, so there2579* will be no non-opaque pixels in the color-map; it will just be2580* grayscale.2581*/2582if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)2583png_error(png_ptr, "rgb[gray] color-map: too few entries");25842585/* Ideally this code would use libpng to do the gamma correction,2586* but if an input alpha channel is to be removed we will hit the2587* libpng bug in gamma+compose+rgb-to-gray (the double gamma2588* correction bug). Fix this by dropping the gamma correction in2589* this case and doing it in the palette; this will result in2590* duplicate palette entries, but that's better than the2591* alternative of double gamma correction.2592*/2593if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||2594png_ptr->num_trans > 0) &&2595png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)2596{2597cmap_entries = (unsigned int)make_gray_file_colormap(display);2598data_encoding = P_FILE;2599}26002601else2602cmap_entries = (unsigned int)make_gray_colormap(display);26032604/* But if the input has alpha or transparency it must be removed2605*/2606if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||2607png_ptr->num_trans > 0)2608{2609png_color_16 c;2610png_uint_32 gray = back_g;26112612/* We need to ensure that the application background exists in2613* the colormap and that completely transparent pixels map to2614* it. Achieve this simply by ensuring that the entry2615* selected for the background really is the background color.2616*/2617if (data_encoding == P_FILE) /* from the fixup above */2618{2619/* The app supplied a gray which is in output_encoding, we2620* need to convert it to a value of the input (P_FILE)2621* encoding then set this palette entry to the required2622* output encoding.2623*/2624if (output_encoding == P_sRGB)2625gray = png_sRGB_table[gray]; /* now P_LINEAR */26262627gray = PNG_DIV257(png_gamma_16bit_correct(gray,2628png_ptr->colorspace.gamma)); /* now P_FILE */26292630/* And make sure the corresponding palette entry contains2631* exactly the required sRGB value.2632*/2633png_create_colormap_entry(display, gray, back_g, back_g,2634back_g, 0/*unused*/, output_encoding);2635}26362637else if (output_encoding == P_LINEAR)2638{2639gray = PNG_sRGB_FROM_LINEAR(gray * 255);26402641/* And make sure the corresponding palette entry matches.2642*/2643png_create_colormap_entry(display, gray, back_g, back_g,2644back_g, 0/*unused*/, P_LINEAR);2645}26462647/* The background passed to libpng, however, must be the2648* output (normally sRGB) value.2649*/2650c.index = 0; /*unused*/2651c.gray = c.red = c.green = c.blue = (png_uint_16)gray;26522653/* NOTE: the following is apparently a bug in libpng. Without2654* it the transparent color recognition in2655* png_set_background_fixed seems to go wrong.2656*/2657expand_tRNS = 1;2658png_set_background_fixed(png_ptr, &c,2659PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,26600/*gamma: not used*/);2661}26622663output_processing = PNG_CMAP_NONE;2664}2665}26662667else /* output is color */2668{2669/* We could use png_quantize here so long as there is no transparent2670* color or alpha; png_quantize ignores alpha. Easier overall just2671* to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.2672* Consequently we always want libpng to produce sRGB data.2673*/2674data_encoding = P_sRGB;26752676/* Is there any transparency or alpha? */2677if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||2678png_ptr->num_trans > 0)2679{2680/* Is there alpha in the output too? If so all four channels are2681* processed into a special RGB cube with alpha support.2682*/2683if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)2684{2685png_uint_32 r;26862687if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)2688png_error(png_ptr, "rgb+alpha color-map: too few entries");26892690cmap_entries = (unsigned int)make_rgb_colormap(display);26912692/* Add a transparent entry. */2693png_create_colormap_entry(display, cmap_entries, 255, 255,2694255, 0, P_sRGB);26952696/* This is stored as the background index for the processing2697* algorithm.2698*/2699background_index = cmap_entries++;27002701/* Add 27 r,g,b entries each with alpha 0.5. */2702for (r=0; r<256; r = (r << 1) | 0x7f)2703{2704png_uint_32 g;27052706for (g=0; g<256; g = (g << 1) | 0x7f)2707{2708png_uint_32 b;27092710/* This generates components with the values 0, 127 and2711* 2552712*/2713for (b=0; b<256; b = (b << 1) | 0x7f)2714png_create_colormap_entry(display, cmap_entries++,2715r, g, b, 128, P_sRGB);2716}2717}27182719expand_tRNS = 1;2720output_processing = PNG_CMAP_RGB_ALPHA;2721}27222723else2724{2725/* Alpha/transparency must be removed. The background must2726* exist in the color map (achieved by setting adding it after2727* the 666 color-map). If the standard processing code will2728* pick up this entry automatically that's all that is2729* required; libpng can be called to do the background2730* processing.2731*/2732unsigned int sample_size =2733PNG_IMAGE_SAMPLE_SIZE(output_format);2734png_uint_32 r, g, b; /* sRGB background */27352736if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)2737png_error(png_ptr, "rgb-alpha color-map: too few entries");27382739cmap_entries = (unsigned int)make_rgb_colormap(display);27402741png_create_colormap_entry(display, cmap_entries, back_r,2742back_g, back_b, 0/*unused*/, output_encoding);27432744if (output_encoding == P_LINEAR)2745{2746r = PNG_sRGB_FROM_LINEAR(back_r * 255);2747g = PNG_sRGB_FROM_LINEAR(back_g * 255);2748b = PNG_sRGB_FROM_LINEAR(back_b * 255);2749}27502751else2752{2753r = back_r;2754g = back_g;2755b = back_g;2756}27572758/* Compare the newly-created color-map entry with the one the2759* PNG_CMAP_RGB algorithm will use. If the two entries don't2760* match, add the new one and set this as the background2761* index.2762*/2763if (memcmp((png_const_bytep)display->colormap +2764sample_size * cmap_entries,2765(png_const_bytep)display->colormap +2766sample_size * PNG_RGB_INDEX(r,g,b),2767sample_size) != 0)2768{2769/* The background color must be added. */2770background_index = cmap_entries++;27712772/* Add 27 r,g,b entries each with created by composing with2773* the background at alpha 0.5.2774*/2775for (r=0; r<256; r = (r << 1) | 0x7f)2776{2777for (g=0; g<256; g = (g << 1) | 0x7f)2778{2779/* This generates components with the values 0, 1272780* and 2552781*/2782for (b=0; b<256; b = (b << 1) | 0x7f)2783png_create_colormap_entry(display, cmap_entries++,2784png_colormap_compose(display, r, P_sRGB, 128,2785back_r, output_encoding),2786png_colormap_compose(display, g, P_sRGB, 128,2787back_g, output_encoding),2788png_colormap_compose(display, b, P_sRGB, 128,2789back_b, output_encoding),27900/*unused*/, output_encoding);2791}2792}27932794expand_tRNS = 1;2795output_processing = PNG_CMAP_RGB_ALPHA;2796}27972798else /* background color is in the standard color-map */2799{2800png_color_16 c;28012802c.index = 0; /*unused*/2803c.red = (png_uint_16)back_r;2804c.gray = c.green = (png_uint_16)back_g;2805c.blue = (png_uint_16)back_b;28062807png_set_background_fixed(png_ptr, &c,2808PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,28090/*gamma: not used*/);28102811output_processing = PNG_CMAP_RGB;2812}2813}2814}28152816else /* no alpha or transparency in the input */2817{2818/* Alpha in the output is irrelevant, simply map the opaque input2819* pixels to the 6x6x6 color-map.2820*/2821if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)2822png_error(png_ptr, "rgb color-map: too few entries");28232824cmap_entries = (unsigned int)make_rgb_colormap(display);2825output_processing = PNG_CMAP_RGB;2826}2827}2828break;28292830case PNG_COLOR_TYPE_PALETTE:2831/* It's already got a color-map. It may be necessary to eliminate the2832* tRNS entries though.2833*/2834{2835unsigned int num_trans = png_ptr->num_trans;2836png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;2837png_const_colorp colormap = png_ptr->palette;2838int do_background = trans != NULL &&2839(output_format & PNG_FORMAT_FLAG_ALPHA) == 0;2840unsigned int i;28412842/* Just in case: */2843if (trans == NULL)2844num_trans = 0;28452846output_processing = PNG_CMAP_NONE;2847data_encoding = P_FILE; /* Don't change from color-map indices */2848cmap_entries = (unsigned int)png_ptr->num_palette;2849if (cmap_entries > 256)2850cmap_entries = 256;28512852if (cmap_entries > (unsigned int)image->colormap_entries)2853png_error(png_ptr, "palette color-map: too few entries");28542855for (i=0; i < cmap_entries; ++i)2856{2857if (do_background != 0 && i < num_trans && trans[i] < 255)2858{2859if (trans[i] == 0)2860png_create_colormap_entry(display, i, back_r, back_g,2861back_b, 0, output_encoding);28622863else2864{2865/* Must compose the PNG file color in the color-map entry2866* on the sRGB color in 'back'.2867*/2868png_create_colormap_entry(display, i,2869png_colormap_compose(display, colormap[i].red,2870P_FILE, trans[i], back_r, output_encoding),2871png_colormap_compose(display, colormap[i].green,2872P_FILE, trans[i], back_g, output_encoding),2873png_colormap_compose(display, colormap[i].blue,2874P_FILE, trans[i], back_b, output_encoding),2875output_encoding == P_LINEAR ? trans[i] * 257U :2876trans[i],2877output_encoding);2878}2879}28802881else2882png_create_colormap_entry(display, i, colormap[i].red,2883colormap[i].green, colormap[i].blue,2884i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);2885}28862887/* The PNG data may have indices packed in fewer than 8 bits, it2888* must be expanded if so.2889*/2890if (png_ptr->bit_depth < 8)2891png_set_packing(png_ptr);2892}2893break;28942895default:2896png_error(png_ptr, "invalid PNG color type");2897/*NOT REACHED*/2898}28992900/* Now deal with the output processing */2901if (expand_tRNS != 0 && png_ptr->num_trans > 0 &&2902(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)2903png_set_tRNS_to_alpha(png_ptr);29042905switch (data_encoding)2906{2907case P_sRGB:2908/* Change to 8-bit sRGB */2909png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);2910/* FALLTHROUGH */29112912case P_FILE:2913if (png_ptr->bit_depth > 8)2914png_set_scale_16(png_ptr);2915break;29162917#ifdef __GNUC__2918default:2919png_error(png_ptr, "bad data option (internal error)");2920#endif2921}29222923if (cmap_entries > 256 || cmap_entries > image->colormap_entries)2924png_error(png_ptr, "color map overflow (BAD internal error)");29252926image->colormap_entries = cmap_entries;29272928/* Double check using the recorded background index */2929switch (output_processing)2930{2931case PNG_CMAP_NONE:2932if (background_index != PNG_CMAP_NONE_BACKGROUND)2933goto bad_background;2934break;29352936case PNG_CMAP_GA:2937if (background_index != PNG_CMAP_GA_BACKGROUND)2938goto bad_background;2939break;29402941case PNG_CMAP_TRANS:2942if (background_index >= cmap_entries ||2943background_index != PNG_CMAP_TRANS_BACKGROUND)2944goto bad_background;2945break;29462947case PNG_CMAP_RGB:2948if (background_index != PNG_CMAP_RGB_BACKGROUND)2949goto bad_background;2950break;29512952case PNG_CMAP_RGB_ALPHA:2953if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)2954goto bad_background;2955break;29562957default:2958png_error(png_ptr, "bad processing option (internal error)");29592960bad_background:2961png_error(png_ptr, "bad background index (internal error)");2962}29632964display->colormap_processing = (int)output_processing;29652966return 1/*ok*/;2967}29682969/* The final part of the color-map read called from png_image_finish_read. */2970static int2971png_image_read_and_map(png_voidp argument)2972{2973png_image_read_control *display = png_voidcast(png_image_read_control*,2974argument);2975png_imagep image = display->image;2976png_structrp png_ptr = image->opaque->png_ptr;2977int passes;29782979/* Called when the libpng data must be transformed into the color-mapped2980* form. There is a local row buffer in display->local and this routine must2981* do the interlace handling.2982*/2983switch (png_ptr->interlaced)2984{2985case PNG_INTERLACE_NONE:2986passes = 1;2987break;29882989case PNG_INTERLACE_ADAM7:2990passes = PNG_INTERLACE_ADAM7_PASSES;2991break;29922993default:2994png_error(png_ptr, "unknown interlace type");2995}29962997{2998png_uint_32 height = image->height;2999png_uint_32 width = image->width;3000int proc = display->colormap_processing;3001png_bytep first_row = png_voidcast(png_bytep, display->first_row);3002ptrdiff_t step_row = display->row_bytes;3003int pass;30043005for (pass = 0; pass < passes; ++pass)3006{3007unsigned int startx, stepx, stepy;3008png_uint_32 y;30093010if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)3011{3012/* The row may be empty for a short image: */3013if (PNG_PASS_COLS(width, pass) == 0)3014continue;30153016startx = PNG_PASS_START_COL(pass);3017stepx = PNG_PASS_COL_OFFSET(pass);3018y = PNG_PASS_START_ROW(pass);3019stepy = PNG_PASS_ROW_OFFSET(pass);3020}30213022else3023{3024y = 0;3025startx = 0;3026stepx = stepy = 1;3027}30283029for (; y<height; y += stepy)3030{3031png_bytep inrow = png_voidcast(png_bytep, display->local_row);3032png_bytep outrow = first_row + y * step_row;3033png_const_bytep end_row = outrow + width;30343035/* Read read the libpng data into the temporary buffer. */3036png_read_row(png_ptr, inrow, NULL);30373038/* Now process the row according to the processing option, note3039* that the caller verifies that the format of the libpng output3040* data is as required.3041*/3042outrow += startx;3043switch (proc)3044{3045case PNG_CMAP_GA:3046for (; outrow < end_row; outrow += stepx)3047{3048/* The data is always in the PNG order */3049unsigned int gray = *inrow++;3050unsigned int alpha = *inrow++;3051unsigned int entry;30523053/* NOTE: this code is copied as a comment in3054* make_ga_colormap above. Please update the3055* comment if you change this code!3056*/3057if (alpha > 229) /* opaque */3058{3059entry = (231 * gray + 128) >> 8;3060}3061else if (alpha < 26) /* transparent */3062{3063entry = 231;3064}3065else /* partially opaque */3066{3067entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);3068}30693070*outrow = (png_byte)entry;3071}3072break;30733074case PNG_CMAP_TRANS:3075for (; outrow < end_row; outrow += stepx)3076{3077png_byte gray = *inrow++;3078png_byte alpha = *inrow++;30793080if (alpha == 0)3081*outrow = PNG_CMAP_TRANS_BACKGROUND;30823083else if (gray != PNG_CMAP_TRANS_BACKGROUND)3084*outrow = gray;30853086else3087*outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);3088}3089break;30903091case PNG_CMAP_RGB:3092for (; outrow < end_row; outrow += stepx)3093{3094*outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);3095inrow += 3;3096}3097break;30983099case PNG_CMAP_RGB_ALPHA:3100for (; outrow < end_row; outrow += stepx)3101{3102unsigned int alpha = inrow[3];31033104/* Because the alpha entries only hold alpha==0.5 values3105* split the processing at alpha==0.25 (64) and 0.753106* (196).3107*/31083109if (alpha >= 196)3110*outrow = PNG_RGB_INDEX(inrow[0], inrow[1],3111inrow[2]);31123113else if (alpha < 64)3114*outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;31153116else3117{3118/* Likewise there are three entries for each of r, g3119* and b. We could select the entry by popcount on3120* the top two bits on those architectures that3121* support it, this is what the code below does,3122* crudely.3123*/3124unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;31253126/* Here are how the values map:3127*3128* 0x00 .. 0x3f -> 03129* 0x40 .. 0xbf -> 13130* 0xc0 .. 0xff -> 23131*3132* So, as above with the explicit alpha checks, the3133* breakpoints are at 64 and 196.3134*/3135if (inrow[0] & 0x80) back_i += 9; /* red */3136if (inrow[0] & 0x40) back_i += 9;3137if (inrow[0] & 0x80) back_i += 3; /* green */3138if (inrow[0] & 0x40) back_i += 3;3139if (inrow[0] & 0x80) back_i += 1; /* blue */3140if (inrow[0] & 0x40) back_i += 1;31413142*outrow = (png_byte)back_i;3143}31443145inrow += 4;3146}3147break;31483149default:3150break;3151}3152}3153}3154}31553156return 1;3157}31583159static int3160png_image_read_colormapped(png_voidp argument)3161{3162png_image_read_control *display = png_voidcast(png_image_read_control*,3163argument);3164png_imagep image = display->image;3165png_controlp control = image->opaque;3166png_structrp png_ptr = control->png_ptr;3167png_inforp info_ptr = control->info_ptr;31683169int passes = 0; /* As a flag */31703171PNG_SKIP_CHUNKS(png_ptr);31723173/* Update the 'info' structure and make sure the result is as required; first3174* make sure to turn on the interlace handling if it will be required3175* (because it can't be turned on *after* the call to png_read_update_info!)3176*/3177if (display->colormap_processing == PNG_CMAP_NONE)3178passes = png_set_interlace_handling(png_ptr);31793180png_read_update_info(png_ptr, info_ptr);31813182/* The expected output can be deduced from the colormap_processing option. */3183switch (display->colormap_processing)3184{3185case PNG_CMAP_NONE:3186/* Output must be one channel and one byte per pixel, the output3187* encoding can be anything.3188*/3189if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||3190info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&3191info_ptr->bit_depth == 8)3192break;31933194goto bad_output;31953196case PNG_CMAP_TRANS:3197case PNG_CMAP_GA:3198/* Output must be two channels and the 'G' one must be sRGB, the latter3199* can be checked with an exact number because it should have been set3200* to this number above!3201*/3202if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&3203info_ptr->bit_depth == 8 &&3204png_ptr->screen_gamma == PNG_GAMMA_sRGB &&3205image->colormap_entries == 256)3206break;32073208goto bad_output;32093210case PNG_CMAP_RGB:3211/* Output must be 8-bit sRGB encoded RGB */3212if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&3213info_ptr->bit_depth == 8 &&3214png_ptr->screen_gamma == PNG_GAMMA_sRGB &&3215image->colormap_entries == 216)3216break;32173218goto bad_output;32193220case PNG_CMAP_RGB_ALPHA:3221/* Output must be 8-bit sRGB encoded RGBA */3222if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&3223info_ptr->bit_depth == 8 &&3224png_ptr->screen_gamma == PNG_GAMMA_sRGB &&3225image->colormap_entries == 244 /* 216 + 1 + 27 */)3226break;32273228goto bad_output;32293230default:3231bad_output:3232png_error(png_ptr, "bad color-map processing (internal error)");3233}32343235/* Now read the rows. Do this here if it is possible to read directly into3236* the output buffer, otherwise allocate a local row buffer of the maximum3237* size libpng requires and call the relevant processing routine safely.3238*/3239{3240png_voidp first_row = display->buffer;3241ptrdiff_t row_bytes = display->row_stride;32423243/* The following expression is designed to work correctly whether it gives3244* a signed or an unsigned result.3245*/3246if (row_bytes < 0)3247{3248char *ptr = png_voidcast(char*, first_row);3249ptr += (image->height-1) * (-row_bytes);3250first_row = png_voidcast(png_voidp, ptr);3251}32523253display->first_row = first_row;3254display->row_bytes = row_bytes;3255}32563257if (passes == 0)3258{3259int result;3260png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));32613262display->local_row = row;3263result = png_safe_execute(image, png_image_read_and_map, display);3264display->local_row = NULL;3265png_free(png_ptr, row);32663267return result;3268}32693270else3271{3272png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;32733274while (--passes >= 0)3275{3276png_uint_32 y = image->height;3277png_bytep row = png_voidcast(png_bytep, display->first_row);32783279for (; y > 0; --y)3280{3281png_read_row(png_ptr, row, NULL);3282row += row_bytes;3283}3284}32853286return 1;3287}3288}32893290/* Just the row reading part of png_image_read. */3291static int3292png_image_read_composite(png_voidp argument)3293{3294png_image_read_control *display = png_voidcast(png_image_read_control*,3295argument);3296png_imagep image = display->image;3297png_structrp png_ptr = image->opaque->png_ptr;3298int passes;32993300switch (png_ptr->interlaced)3301{3302case PNG_INTERLACE_NONE:3303passes = 1;3304break;33053306case PNG_INTERLACE_ADAM7:3307passes = PNG_INTERLACE_ADAM7_PASSES;3308break;33093310default:3311png_error(png_ptr, "unknown interlace type");3312}33133314{3315png_uint_32 height = image->height;3316png_uint_32 width = image->width;3317ptrdiff_t step_row = display->row_bytes;3318unsigned int channels =3319(image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;3320int pass;33213322for (pass = 0; pass < passes; ++pass)3323{3324unsigned int startx, stepx, stepy;3325png_uint_32 y;33263327if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)3328{3329/* The row may be empty for a short image: */3330if (PNG_PASS_COLS(width, pass) == 0)3331continue;33323333startx = PNG_PASS_START_COL(pass) * channels;3334stepx = PNG_PASS_COL_OFFSET(pass) * channels;3335y = PNG_PASS_START_ROW(pass);3336stepy = PNG_PASS_ROW_OFFSET(pass);3337}33383339else3340{3341y = 0;3342startx = 0;3343stepx = channels;3344stepy = 1;3345}33463347for (; y<height; y += stepy)3348{3349png_bytep inrow = png_voidcast(png_bytep, display->local_row);3350png_bytep outrow;3351png_const_bytep end_row;33523353/* Read the row, which is packed: */3354png_read_row(png_ptr, inrow, NULL);33553356outrow = png_voidcast(png_bytep, display->first_row);3357outrow += y * step_row;3358end_row = outrow + width * channels;33593360/* Now do the composition on each pixel in this row. */3361outrow += startx;3362for (; outrow < end_row; outrow += stepx)3363{3364png_byte alpha = inrow[channels];33653366if (alpha > 0) /* else no change to the output */3367{3368unsigned int c;33693370for (c=0; c<channels; ++c)3371{3372png_uint_32 component = inrow[c];33733374if (alpha < 255) /* else just use component */3375{3376/* This is PNG_OPTIMIZED_ALPHA, the component value3377* is a linear 8-bit value. Combine this with the3378* current outrow[c] value which is sRGB encoded.3379* Arithmetic here is 16-bits to preserve the output3380* values correctly.3381*/3382component *= 257*255; /* =65535 */3383component += (255-alpha)*png_sRGB_table[outrow[c]];33843385/* So 'component' is scaled by 255*65535 and is3386* therefore appropriate for the sRGB to linear3387* conversion table.3388*/3389component = PNG_sRGB_FROM_LINEAR(component);3390}33913392outrow[c] = (png_byte)component;3393}3394}33953396inrow += channels+1; /* components and alpha channel */3397}3398}3399}3400}34013402return 1;3403}34043405/* The do_local_background case; called when all the following transforms are to3406* be done:3407*3408* PNG_RGB_TO_GRAY3409* PNG_COMPOSITE3410* PNG_GAMMA3411*3412* This is a work-around for the fact that both the PNG_RGB_TO_GRAY and3413* PNG_COMPOSITE code performs gamma correction, so we get double gamma3414* correction. The fix-up is to prevent the PNG_COMPOSITE operation from3415* happening inside libpng, so this routine sees an 8 or 16-bit gray+alpha3416* row and handles the removal or pre-multiplication of the alpha channel.3417*/3418static int3419png_image_read_background(png_voidp argument)3420{3421png_image_read_control *display = png_voidcast(png_image_read_control*,3422argument);3423png_imagep image = display->image;3424png_structrp png_ptr = image->opaque->png_ptr;3425png_inforp info_ptr = image->opaque->info_ptr;3426png_uint_32 height = image->height;3427png_uint_32 width = image->width;3428int pass, passes;34293430/* Double check the convoluted logic below. We expect to get here with3431* libpng doing rgb to gray and gamma correction but background processing3432* left to the png_image_read_background function. The rows libpng produce3433* might be 8 or 16-bit but should always have two channels; gray plus alpha.3434*/3435if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)3436png_error(png_ptr, "lost rgb to gray");34373438if ((png_ptr->transformations & PNG_COMPOSE) != 0)3439png_error(png_ptr, "unexpected compose");34403441if (png_get_channels(png_ptr, info_ptr) != 2)3442png_error(png_ptr, "lost/gained channels");34433444/* Expect the 8-bit case to always remove the alpha channel */3445if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&3446(image->format & PNG_FORMAT_FLAG_ALPHA) != 0)3447png_error(png_ptr, "unexpected 8-bit transformation");34483449switch (png_ptr->interlaced)3450{3451case PNG_INTERLACE_NONE:3452passes = 1;3453break;34543455case PNG_INTERLACE_ADAM7:3456passes = PNG_INTERLACE_ADAM7_PASSES;3457break;34583459default:3460png_error(png_ptr, "unknown interlace type");3461}34623463/* Use direct access to info_ptr here because otherwise the simplified API3464* would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is3465* checking the value after libpng expansions, not the original value in the3466* PNG.3467*/3468switch (info_ptr->bit_depth)3469{3470case 8:3471/* 8-bit sRGB gray values with an alpha channel; the alpha channel is3472* to be removed by composing on a background: either the row if3473* display->background is NULL or display->background->green if not.3474* Unlike the code above ALPHA_OPTIMIZED has *not* been done.3475*/3476{3477png_bytep first_row = png_voidcast(png_bytep, display->first_row);3478ptrdiff_t step_row = display->row_bytes;34793480for (pass = 0; pass < passes; ++pass)3481{3482png_bytep row = png_voidcast(png_bytep, display->first_row);3483unsigned int startx, stepx, stepy;3484png_uint_32 y;34853486if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)3487{3488/* The row may be empty for a short image: */3489if (PNG_PASS_COLS(width, pass) == 0)3490continue;34913492startx = PNG_PASS_START_COL(pass);3493stepx = PNG_PASS_COL_OFFSET(pass);3494y = PNG_PASS_START_ROW(pass);3495stepy = PNG_PASS_ROW_OFFSET(pass);3496}34973498else3499{3500y = 0;3501startx = 0;3502stepx = stepy = 1;3503}35043505if (display->background == NULL)3506{3507for (; y<height; y += stepy)3508{3509png_bytep inrow = png_voidcast(png_bytep,3510display->local_row);3511png_bytep outrow = first_row + y * step_row;3512png_const_bytep end_row = outrow + width;35133514/* Read the row, which is packed: */3515png_read_row(png_ptr, inrow, NULL);35163517/* Now do the composition on each pixel in this row. */3518outrow += startx;3519for (; outrow < end_row; outrow += stepx)3520{3521png_byte alpha = inrow[1];35223523if (alpha > 0) /* else no change to the output */3524{3525png_uint_32 component = inrow[0];35263527if (alpha < 255) /* else just use component */3528{3529/* Since PNG_OPTIMIZED_ALPHA was not set it is3530* necessary to invert the sRGB transfer3531* function and multiply the alpha out.3532*/3533component = png_sRGB_table[component] * alpha;3534component += png_sRGB_table[outrow[0]] *3535(255-alpha);3536component = PNG_sRGB_FROM_LINEAR(component);3537}35383539outrow[0] = (png_byte)component;3540}35413542inrow += 2; /* gray and alpha channel */3543}3544}3545}35463547else /* constant background value */3548{3549png_byte background8 = display->background->green;3550png_uint_16 background = png_sRGB_table[background8];35513552for (; y<height; y += stepy)3553{3554png_bytep inrow = png_voidcast(png_bytep,3555display->local_row);3556png_bytep outrow = first_row + y * step_row;3557png_const_bytep end_row = outrow + width;35583559/* Read the row, which is packed: */3560png_read_row(png_ptr, inrow, NULL);35613562/* Now do the composition on each pixel in this row. */3563outrow += startx;3564for (; outrow < end_row; outrow += stepx)3565{3566png_byte alpha = inrow[1];35673568if (alpha > 0) /* else use background */3569{3570png_uint_32 component = inrow[0];35713572if (alpha < 255) /* else just use component */3573{3574component = png_sRGB_table[component] * alpha;3575component += background * (255-alpha);3576component = PNG_sRGB_FROM_LINEAR(component);3577}35783579outrow[0] = (png_byte)component;3580}35813582else3583outrow[0] = background8;35843585inrow += 2; /* gray and alpha channel */3586}35873588row += display->row_bytes;3589}3590}3591}3592}3593break;35943595case 16:3596/* 16-bit linear with pre-multiplied alpha; the pre-multiplication must3597* still be done and, maybe, the alpha channel removed. This code also3598* handles the alpha-first option.3599*/3600{3601png_uint_16p first_row = png_voidcast(png_uint_16p,3602display->first_row);3603/* The division by two is safe because the caller passed in a3604* stride which was multiplied by 2 (below) to get row_bytes.3605*/3606ptrdiff_t step_row = display->row_bytes / 2;3607unsigned int preserve_alpha = (image->format &3608PNG_FORMAT_FLAG_ALPHA) != 0;3609unsigned int outchannels = 1U+preserve_alpha;3610int swap_alpha = 0;36113612# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED3613if (preserve_alpha != 0 &&3614(image->format & PNG_FORMAT_FLAG_AFIRST) != 0)3615swap_alpha = 1;3616# endif36173618for (pass = 0; pass < passes; ++pass)3619{3620unsigned int startx, stepx, stepy;3621png_uint_32 y;36223623/* The 'x' start and step are adjusted to output components here.3624*/3625if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)3626{3627/* The row may be empty for a short image: */3628if (PNG_PASS_COLS(width, pass) == 0)3629continue;36303631startx = PNG_PASS_START_COL(pass) * outchannels;3632stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;3633y = PNG_PASS_START_ROW(pass);3634stepy = PNG_PASS_ROW_OFFSET(pass);3635}36363637else3638{3639y = 0;3640startx = 0;3641stepx = outchannels;3642stepy = 1;3643}36443645for (; y<height; y += stepy)3646{3647png_const_uint_16p inrow;3648png_uint_16p outrow = first_row + y*step_row;3649png_uint_16p end_row = outrow + width * outchannels;36503651/* Read the row, which is packed: */3652png_read_row(png_ptr, png_voidcast(png_bytep,3653display->local_row), NULL);3654inrow = png_voidcast(png_const_uint_16p, display->local_row);36553656/* Now do the pre-multiplication on each pixel in this row.3657*/3658outrow += startx;3659for (; outrow < end_row; outrow += stepx)3660{3661png_uint_32 component = inrow[0];3662png_uint_16 alpha = inrow[1];36633664if (alpha > 0) /* else 0 */3665{3666if (alpha < 65535) /* else just use component */3667{3668component *= alpha;3669component += 32767;3670component /= 65535;3671}3672}36733674else3675component = 0;36763677outrow[swap_alpha] = (png_uint_16)component;3678if (preserve_alpha != 0)3679outrow[1 ^ swap_alpha] = alpha;36803681inrow += 2; /* components and alpha channel */3682}3683}3684}3685}3686break;36873688#ifdef __GNUC__3689default:3690png_error(png_ptr, "unexpected bit depth");3691#endif3692}36933694return 1;3695}36963697/* The guts of png_image_finish_read as a png_safe_execute callback. */3698static int3699png_image_read_direct(png_voidp argument)3700{3701png_image_read_control *display = png_voidcast(png_image_read_control*,3702argument);3703png_imagep image = display->image;3704png_structrp png_ptr = image->opaque->png_ptr;3705png_inforp info_ptr = image->opaque->info_ptr;37063707png_uint_32 format = image->format;3708int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;3709int do_local_compose = 0;3710int do_local_background = 0; /* to avoid double gamma correction bug */3711int passes = 0;37123713/* Add transforms to ensure the correct output format is produced then check3714* that the required implementation support is there. Always expand; always3715* need 8 bits minimum, no palette and expanded tRNS.3716*/3717png_set_expand(png_ptr);37183719/* Now check the format to see if it was modified. */3720{3721png_uint_32 base_format = png_image_format(png_ptr) &3722~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;3723png_uint_32 change = format ^ base_format;3724png_fixed_point output_gamma;3725int mode; /* alpha mode */37263727/* Do this first so that we have a record if rgb to gray is happening. */3728if ((change & PNG_FORMAT_FLAG_COLOR) != 0)3729{3730/* gray<->color transformation required. */3731if ((format & PNG_FORMAT_FLAG_COLOR) != 0)3732png_set_gray_to_rgb(png_ptr);37333734else3735{3736/* libpng can't do both rgb to gray and3737* background/pre-multiplication if there is also significant gamma3738* correction, because both operations require linear colors and3739* the code only supports one transform doing the gamma correction.3740* Handle this by doing the pre-multiplication or background3741* operation in this code, if necessary.3742*3743* TODO: fix this by rewriting pngrtran.c (!)3744*3745* For the moment (given that fixing this in pngrtran.c is an3746* enormous change) 'do_local_background' is used to indicate that3747* the problem exists.3748*/3749if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)3750do_local_background = 1/*maybe*/;37513752png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,3753PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);3754}37553756change &= ~PNG_FORMAT_FLAG_COLOR;3757}37583759/* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.3760*/3761{3762png_fixed_point input_gamma_default;37633764if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&3765(image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)3766input_gamma_default = PNG_GAMMA_LINEAR;3767else3768input_gamma_default = PNG_DEFAULT_sRGB;37693770/* Call png_set_alpha_mode to set the default for the input gamma; the3771* output gamma is set by a second call below.3772*/3773png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);3774}37753776if (linear != 0)3777{3778/* If there *is* an alpha channel in the input it must be multiplied3779* out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.3780*/3781if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)3782mode = PNG_ALPHA_STANDARD; /* associated alpha */37833784else3785mode = PNG_ALPHA_PNG;37863787output_gamma = PNG_GAMMA_LINEAR;3788}37893790else3791{3792mode = PNG_ALPHA_PNG;3793output_gamma = PNG_DEFAULT_sRGB;3794}37953796if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)3797{3798mode = PNG_ALPHA_OPTIMIZED;3799change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;3800}38013802/* If 'do_local_background' is set check for the presence of gamma3803* correction; this is part of the work-round for the libpng bug3804* described above.3805*3806* TODO: fix libpng and remove this.3807*/3808if (do_local_background != 0)3809{3810png_fixed_point gtest;38113812/* This is 'png_gamma_threshold' from pngrtran.c; the test used for3813* gamma correction, the screen gamma hasn't been set on png_struct3814* yet; it's set below. png_struct::gamma, however, is set to the3815* final value.3816*/3817if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma,3818PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)3819do_local_background = 0;38203821else if (mode == PNG_ALPHA_STANDARD)3822{3823do_local_background = 2/*required*/;3824mode = PNG_ALPHA_PNG; /* prevent libpng doing it */3825}38263827/* else leave as 1 for the checks below */3828}38293830/* If the bit-depth changes then handle that here. */3831if ((change & PNG_FORMAT_FLAG_LINEAR) != 0)3832{3833if (linear != 0 /*16-bit output*/)3834png_set_expand_16(png_ptr);38353836else /* 8-bit output */3837png_set_scale_16(png_ptr);38383839change &= ~PNG_FORMAT_FLAG_LINEAR;3840}38413842/* Now the background/alpha channel changes. */3843if ((change & PNG_FORMAT_FLAG_ALPHA) != 0)3844{3845/* Removing an alpha channel requires composition for the 8-bit3846* formats; for the 16-bit it is already done, above, by the3847* pre-multiplication and the channel just needs to be stripped.3848*/3849if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)3850{3851/* If RGB->gray is happening the alpha channel must be left and the3852* operation completed locally.3853*3854* TODO: fix libpng and remove this.3855*/3856if (do_local_background != 0)3857do_local_background = 2/*required*/;38583859/* 16-bit output: just remove the channel */3860else if (linear != 0) /* compose on black (well, pre-multiply) */3861png_set_strip_alpha(png_ptr);38623863/* 8-bit output: do an appropriate compose */3864else if (display->background != NULL)3865{3866png_color_16 c;38673868c.index = 0; /*unused*/3869c.red = display->background->red;3870c.green = display->background->green;3871c.blue = display->background->blue;3872c.gray = display->background->green;38733874/* This is always an 8-bit sRGB value, using the 'green' channel3875* for gray is much better than calculating the luminance here;3876* we can get off-by-one errors in that calculation relative to3877* the app expectations and that will show up in transparent3878* pixels.3879*/3880png_set_background_fixed(png_ptr, &c,3881PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,38820/*gamma: not used*/);3883}38843885else /* compose on row: implemented below. */3886{3887do_local_compose = 1;3888/* This leaves the alpha channel in the output, so it has to be3889* removed by the code below. Set the encoding to the 'OPTIMIZE'3890* one so the code only has to hack on the pixels that require3891* composition.3892*/3893mode = PNG_ALPHA_OPTIMIZED;3894}3895}38963897else /* output needs an alpha channel */3898{3899/* This is tricky because it happens before the swap operation has3900* been accomplished; however, the swap does *not* swap the added3901* alpha channel (weird API), so it must be added in the correct3902* place.3903*/3904png_uint_32 filler; /* opaque filler */3905int where;39063907if (linear != 0)3908filler = 65535;39093910else3911filler = 255;39123913#ifdef PNG_FORMAT_AFIRST_SUPPORTED3914if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)3915{3916where = PNG_FILLER_BEFORE;3917change &= ~PNG_FORMAT_FLAG_AFIRST;3918}39193920else3921#endif3922where = PNG_FILLER_AFTER;39233924png_set_add_alpha(png_ptr, filler, where);3925}39263927/* This stops the (irrelevant) call to swap_alpha below. */3928change &= ~PNG_FORMAT_FLAG_ALPHA;3929}39303931/* Now set the alpha mode correctly; this is always done, even if there is3932* no alpha channel in either the input or the output because it correctly3933* sets the output gamma.3934*/3935png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);39363937# ifdef PNG_FORMAT_BGR_SUPPORTED3938if ((change & PNG_FORMAT_FLAG_BGR) != 0)3939{3940/* Check only the output format; PNG is never BGR; don't do this if3941* the output is gray, but fix up the 'format' value in that case.3942*/3943if ((format & PNG_FORMAT_FLAG_COLOR) != 0)3944png_set_bgr(png_ptr);39453946else3947format &= ~PNG_FORMAT_FLAG_BGR;39483949change &= ~PNG_FORMAT_FLAG_BGR;3950}3951# endif39523953# ifdef PNG_FORMAT_AFIRST_SUPPORTED3954if ((change & PNG_FORMAT_FLAG_AFIRST) != 0)3955{3956/* Only relevant if there is an alpha channel - it's particularly3957* important to handle this correctly because do_local_compose may3958* be set above and then libpng will keep the alpha channel for this3959* code to remove.3960*/3961if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)3962{3963/* Disable this if doing a local background,3964* TODO: remove this when local background is no longer required.3965*/3966if (do_local_background != 2)3967png_set_swap_alpha(png_ptr);3968}39693970else3971format &= ~PNG_FORMAT_FLAG_AFIRST;39723973change &= ~PNG_FORMAT_FLAG_AFIRST;3974}3975# endif39763977/* If the *output* is 16-bit then we need to check for a byte-swap on this3978* architecture.3979*/3980if (linear != 0)3981{3982png_uint_16 le = 0x0001;39833984if ((*(png_const_bytep) & le) != 0)3985png_set_swap(png_ptr);3986}39873988/* If change is not now 0 some transformation is missing - error out. */3989if (change != 0)3990png_error(png_ptr, "png_read_image: unsupported transformation");3991}39923993PNG_SKIP_CHUNKS(png_ptr);39943995/* Update the 'info' structure and make sure the result is as required; first3996* make sure to turn on the interlace handling if it will be required3997* (because it can't be turned on *after* the call to png_read_update_info!)3998*3999* TODO: remove the do_local_background fixup below.4000*/4001if (do_local_compose == 0 && do_local_background != 2)4002passes = png_set_interlace_handling(png_ptr);40034004png_read_update_info(png_ptr, info_ptr);40054006{4007png_uint_32 info_format = 0;40084009if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)4010info_format |= PNG_FORMAT_FLAG_COLOR;40114012if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)4013{4014/* do_local_compose removes this channel below. */4015if (do_local_compose == 0)4016{4017/* do_local_background does the same if required. */4018if (do_local_background != 2 ||4019(format & PNG_FORMAT_FLAG_ALPHA) != 0)4020info_format |= PNG_FORMAT_FLAG_ALPHA;4021}4022}40234024else if (do_local_compose != 0) /* internal error */4025png_error(png_ptr, "png_image_read: alpha channel lost");40264027if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) {4028info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;4029}40304031if (info_ptr->bit_depth == 16)4032info_format |= PNG_FORMAT_FLAG_LINEAR;40334034#ifdef PNG_FORMAT_BGR_SUPPORTED4035if ((png_ptr->transformations & PNG_BGR) != 0)4036info_format |= PNG_FORMAT_FLAG_BGR;4037#endif40384039#ifdef PNG_FORMAT_AFIRST_SUPPORTED4040if (do_local_background == 2)4041{4042if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)4043info_format |= PNG_FORMAT_FLAG_AFIRST;4044}40454046if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||4047((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&4048(png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))4049{4050if (do_local_background == 2)4051png_error(png_ptr, "unexpected alpha swap transformation");40524053info_format |= PNG_FORMAT_FLAG_AFIRST;4054}4055# endif40564057/* This is actually an internal error. */4058if (info_format != format)4059png_error(png_ptr, "png_read_image: invalid transformations");4060}40614062/* Now read the rows. If do_local_compose is set then it is necessary to use4063* a local row buffer. The output will be GA, RGBA or BGRA and must be4064* converted to G, RGB or BGR as appropriate. The 'local_row' member of the4065* display acts as a flag.4066*/4067{4068png_voidp first_row = display->buffer;4069ptrdiff_t row_bytes = display->row_stride;40704071if (linear != 0)4072row_bytes *= 2;40734074/* The following expression is designed to work correctly whether it gives4075* a signed or an unsigned result.4076*/4077if (row_bytes < 0)4078{4079char *ptr = png_voidcast(char*, first_row);4080ptr += (image->height-1) * (-row_bytes);4081first_row = png_voidcast(png_voidp, ptr);4082}40834084display->first_row = first_row;4085display->row_bytes = row_bytes;4086}40874088if (do_local_compose != 0)4089{4090int result;4091png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));40924093display->local_row = row;4094result = png_safe_execute(image, png_image_read_composite, display);4095display->local_row = NULL;4096png_free(png_ptr, row);40974098return result;4099}41004101else if (do_local_background == 2)4102{4103int result;4104png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));41054106display->local_row = row;4107result = png_safe_execute(image, png_image_read_background, display);4108display->local_row = NULL;4109png_free(png_ptr, row);41104111return result;4112}41134114else4115{4116png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;41174118while (--passes >= 0)4119{4120png_uint_32 y = image->height;4121png_bytep row = png_voidcast(png_bytep, display->first_row);41224123for (; y > 0; --y)4124{4125png_read_row(png_ptr, row, NULL);4126row += row_bytes;4127}4128}41294130return 1;4131}4132}41334134int PNGAPI4135png_image_finish_read(png_imagep image, png_const_colorp background,4136void *buffer, png_int_32 row_stride, void *colormap)4137{4138if (image != NULL && image->version == PNG_IMAGE_VERSION)4139{4140/* Check for row_stride overflow. This check is not performed on the4141* original PNG format because it may not occur in the output PNG format4142* and libpng deals with the issues of reading the original.4143*/4144unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);41454146/* The following checks just the 'row_stride' calculation to ensure it4147* fits in a signed 32-bit value. Because channels/components can be4148* either 1 or 2 bytes in size the length of a row can still overflow 324149* bits; this is just to verify that the 'row_stride' argument can be4150* represented.4151*/4152if (image->width <= 0x7fffffffU/channels) /* no overflow */4153{4154png_uint_32 check;4155png_uint_32 png_row_stride = image->width * channels;41564157if (row_stride == 0)4158row_stride = (png_int_32)/*SAFE*/png_row_stride;41594160if (row_stride < 0)4161check = (png_uint_32)(-row_stride);41624163else4164check = (png_uint_32)row_stride;41654166/* This verifies 'check', the absolute value of the actual stride4167* passed in and detects overflow in the application calculation (i.e.4168* if the app did actually pass in a non-zero 'row_stride'.4169*/4170if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)4171{4172/* Now check for overflow of the image buffer calculation; this4173* limits the whole image size to 32 bits for API compatibility with4174* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.4175*4176* The PNG_IMAGE_BUFFER_SIZE macro is:4177*4178* (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride))4179*4180* And the component size is always 1 or 2, so make sure that the4181* number of *bytes* that the application is saying are available4182* does actually fit into a 32-bit number.4183*4184* NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE4185* will be changed to use png_alloc_size_t; bigger images can be4186* accommodated on 64-bit systems.4187*/4188if (image->height <=41890xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)4190{4191if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||4192(image->colormap_entries > 0 && colormap != NULL))4193{4194int result;4195png_image_read_control display;41964197memset(&display, 0, (sizeof display));4198display.image = image;4199display.buffer = buffer;4200display.row_stride = row_stride;4201display.colormap = colormap;4202display.background = background;4203display.local_row = NULL;42044205/* Choose the correct 'end' routine; for the color-map case4206* all the setup has already been done.4207*/4208if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)4209result =4210png_safe_execute(image,4211png_image_read_colormap, &display) &&4212png_safe_execute(image,4213png_image_read_colormapped, &display);42144215else4216result =4217png_safe_execute(image,4218png_image_read_direct, &display);42194220png_image_free(image);4221return result;4222}42234224else4225return png_image_error(image,4226"png_image_finish_read[color-map]: no color-map");4227}42284229else4230return png_image_error(image,4231"png_image_finish_read: image too large");4232}42334234else4235return png_image_error(image,4236"png_image_finish_read: invalid argument");4237}42384239else4240return png_image_error(image,4241"png_image_finish_read: row_stride too large");4242}42434244else if (image != NULL)4245return png_image_error(image,4246"png_image_finish_read: damaged PNG_IMAGE_VERSION");42474248return 0;4249}42504251#endif /* SIMPLIFIED_READ */4252#endif /* READ */425342544255