Path: blob/master/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
41154 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/* pngrtran.c - transforms the data in a row for PNG readers25*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 functions optionally called by an application41* in order to tell libpng how to handle data when reading a PNG.42* Transformations that are used in both reading and writing are43* in pngtrans.c.44*/4546#include "pngpriv.h"4748#ifdef PNG_ARM_NEON_IMPLEMENTATION49# if PNG_ARM_NEON_IMPLEMENTATION == 150# define PNG_ARM_NEON_INTRINSICS_AVAILABLE51# if defined(_MSC_VER) && defined(_M_ARM64)52# include <arm64_neon.h>53# else54# include <arm_neon.h>55# endif56# endif57#endif5859#ifdef PNG_READ_SUPPORTED6061/* Set the action on getting a CRC error for an ancillary or critical chunk. */62void PNGAPI63png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)64{65png_debug(1, "in png_set_crc_action");6667if (png_ptr == NULL)68return;6970/* Tell libpng how we react to CRC errors in critical chunks */71switch (crit_action)72{73case PNG_CRC_NO_CHANGE: /* Leave setting as is */74break;7576case PNG_CRC_WARN_USE: /* Warn/use data */77png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;78png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;79break;8081case PNG_CRC_QUIET_USE: /* Quiet/use data */82png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;83png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |84PNG_FLAG_CRC_CRITICAL_IGNORE;85break;8687case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */88png_warning(png_ptr,89"Can't discard critical data on CRC error");90/* FALLTHROUGH */91case PNG_CRC_ERROR_QUIT: /* Error/quit */9293case PNG_CRC_DEFAULT:94default:95png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;96break;97}9899/* Tell libpng how we react to CRC errors in ancillary chunks */100switch (ancil_action)101{102case PNG_CRC_NO_CHANGE: /* Leave setting as is */103break;104105case PNG_CRC_WARN_USE: /* Warn/use data */106png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;107png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;108break;109110case PNG_CRC_QUIET_USE: /* Quiet/use data */111png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;112png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |113PNG_FLAG_CRC_ANCILLARY_NOWARN;114break;115116case PNG_CRC_ERROR_QUIT: /* Error/quit */117png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;118png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;119break;120121case PNG_CRC_WARN_DISCARD: /* Warn/discard data */122123case PNG_CRC_DEFAULT:124default:125png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;126break;127}128}129130#ifdef PNG_READ_TRANSFORMS_SUPPORTED131/* Is it OK to set a transformation now? Only if png_start_read_image or132* png_read_update_info have not been called. It is not necessary for the IHDR133* to have been read in all cases; the need_IHDR parameter allows for this134* check too.135*/136static int137png_rtran_ok(png_structrp png_ptr, int need_IHDR)138{139if (png_ptr != NULL)140{141if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)142png_app_error(png_ptr,143"invalid after png_start_read_image or png_read_update_info");144145else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)146png_app_error(png_ptr, "invalid before the PNG header has been read");147148else149{150/* Turn on failure to initialize correctly for all transforms. */151png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;152153return 1; /* Ok */154}155}156157return 0; /* no png_error possible! */158}159#endif160161#ifdef PNG_READ_BACKGROUND_SUPPORTED162/* Handle alpha and tRNS via a background color */163void PNGFAPI164png_set_background_fixed(png_structrp png_ptr,165png_const_color_16p background_color, int background_gamma_code,166int need_expand, png_fixed_point background_gamma)167{168png_debug(1, "in png_set_background_fixed");169170if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)171return;172173if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)174{175png_warning(png_ptr, "Application must supply a known background gamma");176return;177}178179png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;180png_ptr->transformations &= ~PNG_ENCODE_ALPHA;181png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;182183png_ptr->background = *background_color;184png_ptr->background_gamma = background_gamma;185png_ptr->background_gamma_type = (png_byte)(background_gamma_code);186if (need_expand != 0)187png_ptr->transformations |= PNG_BACKGROUND_EXPAND;188else189png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;190}191192# ifdef PNG_FLOATING_POINT_SUPPORTED193void PNGAPI194png_set_background(png_structrp png_ptr,195png_const_color_16p background_color, int background_gamma_code,196int need_expand, double background_gamma)197{198png_set_background_fixed(png_ptr, background_color, background_gamma_code,199need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));200}201# endif /* FLOATING_POINT */202#endif /* READ_BACKGROUND */203204/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the205* one that pngrtran does first (scale) happens. This is necessary to allow the206* TRANSFORM and API behavior to be somewhat consistent, and it's simpler.207*/208#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED209void PNGAPI210png_set_scale_16(png_structrp png_ptr)211{212png_debug(1, "in png_set_scale_16");213214if (png_rtran_ok(png_ptr, 0) == 0)215return;216217png_ptr->transformations |= PNG_SCALE_16_TO_8;218}219#endif220221#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED222/* Chop 16-bit depth files to 8-bit depth */223void PNGAPI224png_set_strip_16(png_structrp png_ptr)225{226png_debug(1, "in png_set_strip_16");227228if (png_rtran_ok(png_ptr, 0) == 0)229return;230231png_ptr->transformations |= PNG_16_TO_8;232}233#endif234235#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED236void PNGAPI237png_set_strip_alpha(png_structrp png_ptr)238{239png_debug(1, "in png_set_strip_alpha");240241if (png_rtran_ok(png_ptr, 0) == 0)242return;243244png_ptr->transformations |= PNG_STRIP_ALPHA;245}246#endif247248#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)249static png_fixed_point250translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,251int is_screen)252{253/* Check for flag values. The main reason for having the old Mac value as a254* flag is that it is pretty near impossible to work out what the correct255* value is from Apple documentation - a working Mac system is needed to256* discover the value!257*/258if (output_gamma == PNG_DEFAULT_sRGB ||259output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)260{261/* If there is no sRGB support this just sets the gamma to the standard262* sRGB value. (This is a side effect of using this function!)263*/264# ifdef PNG_READ_sRGB_SUPPORTED265png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;266# else267PNG_UNUSED(png_ptr)268# endif269if (is_screen != 0)270output_gamma = PNG_GAMMA_sRGB;271else272output_gamma = PNG_GAMMA_sRGB_INVERSE;273}274275else if (output_gamma == PNG_GAMMA_MAC_18 ||276output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)277{278if (is_screen != 0)279output_gamma = PNG_GAMMA_MAC_OLD;280else281output_gamma = PNG_GAMMA_MAC_INVERSE;282}283284return output_gamma;285}286287# ifdef PNG_FLOATING_POINT_SUPPORTED288static png_fixed_point289convert_gamma_value(png_structrp png_ptr, double output_gamma)290{291/* The following silently ignores cases where fixed point (times 100,000)292* gamma values are passed to the floating point API. This is safe and it293* means the fixed point constants work just fine with the floating point294* API. The alternative would just lead to undetected errors and spurious295* bug reports. Negative values fail inside the _fixed API unless they296* correspond to the flag values.297*/298if (output_gamma > 0 && output_gamma < 128)299output_gamma *= PNG_FP_1;300301/* This preserves -1 and -2 exactly: */302output_gamma = floor(output_gamma + .5);303304if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)305png_fixed_error(png_ptr, "gamma value");306307return (png_fixed_point)output_gamma;308}309# endif310#endif /* READ_ALPHA_MODE || READ_GAMMA */311312#ifdef PNG_READ_ALPHA_MODE_SUPPORTED313void PNGFAPI314png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,315png_fixed_point output_gamma)316{317int compose = 0;318png_fixed_point file_gamma;319320png_debug(1, "in png_set_alpha_mode");321322if (png_rtran_ok(png_ptr, 0) == 0)323return;324325output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);326327/* Validate the value to ensure it is in a reasonable range. The value328* is expected to be 1 or greater, but this range test allows for some329* viewing correction values. The intent is to weed out users of this API330* who use the inverse of the gamma value accidentally! Since some of these331* values are reasonable this may have to be changed:332*333* 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit334* gamma of 36, and its reciprocal.)335*/336if (output_gamma < 1000 || output_gamma > 10000000)337png_error(png_ptr, "output gamma out of expected range");338339/* The default file gamma is the inverse of the output gamma; the output340* gamma may be changed below so get the file value first:341*/342file_gamma = png_reciprocal(output_gamma);343344/* There are really 8 possibilities here, composed of any combination345* of:346*347* premultiply the color channels348* do not encode non-opaque pixels349* encode the alpha as well as the color channels350*351* The differences disappear if the input/output ('screen') gamma is 1.0,352* because then the encoding is a no-op and there is only the choice of353* premultiplying the color channels or not.354*355* png_set_alpha_mode and png_set_background interact because both use356* png_compose to do the work. Calling both is only useful when357* png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along358* with a default gamma value. Otherwise PNG_COMPOSE must not be set.359*/360switch (mode)361{362case PNG_ALPHA_PNG: /* default: png standard */363/* No compose, but it may be set by png_set_background! */364png_ptr->transformations &= ~PNG_ENCODE_ALPHA;365png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;366break;367368case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */369compose = 1;370png_ptr->transformations &= ~PNG_ENCODE_ALPHA;371png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;372/* The output is linear: */373output_gamma = PNG_FP_1;374break;375376case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */377compose = 1;378png_ptr->transformations &= ~PNG_ENCODE_ALPHA;379png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;380/* output_gamma records the encoding of opaque pixels! */381break;382383case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */384compose = 1;385png_ptr->transformations |= PNG_ENCODE_ALPHA;386png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;387break;388389default:390png_error(png_ptr, "invalid alpha mode");391}392393/* Only set the default gamma if the file gamma has not been set (this has394* the side effect that the gamma in a second call to png_set_alpha_mode will395* be ignored.)396*/397if (png_ptr->colorspace.gamma == 0)398{399png_ptr->colorspace.gamma = file_gamma;400png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;401}402403/* But always set the output gamma: */404png_ptr->screen_gamma = output_gamma;405406/* Finally, if pre-multiplying, set the background fields to achieve the407* desired result.408*/409if (compose != 0)410{411/* And obtain alpha pre-multiplication by composing on black: */412memset(&png_ptr->background, 0, (sizeof png_ptr->background));413png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */414png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;415png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;416417if ((png_ptr->transformations & PNG_COMPOSE) != 0)418png_error(png_ptr,419"conflicting calls to set alpha mode and background");420421png_ptr->transformations |= PNG_COMPOSE;422}423}424425# ifdef PNG_FLOATING_POINT_SUPPORTED426void PNGAPI427png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)428{429png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,430output_gamma));431}432# endif433#endif434435#ifdef PNG_READ_QUANTIZE_SUPPORTED436/* Dither file to 8-bit. Supply a palette, the current number437* of elements in the palette, the maximum number of elements438* allowed, and a histogram if possible. If the current number439* of colors is greater than the maximum number, the palette will be440* modified to fit in the maximum number. "full_quantize" indicates441* whether we need a quantizing cube set up for RGB images, or if we442* simply are reducing the number of colors in a paletted image.443*/444445typedef struct png_dsort_struct446{447struct png_dsort_struct * next;448png_byte left;449png_byte right;450} png_dsort;451typedef png_dsort * png_dsortp;452typedef png_dsort * * png_dsortpp;453454void PNGAPI455png_set_quantize(png_structrp png_ptr, png_colorp palette,456int num_palette, int maximum_colors, png_const_uint_16p histogram,457int full_quantize)458{459png_debug(1, "in png_set_quantize");460461if (png_rtran_ok(png_ptr, 0) == 0)462return;463464png_ptr->transformations |= PNG_QUANTIZE;465466if (full_quantize == 0)467{468int i;469470png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,471(png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));472for (i = 0; i < num_palette; i++)473png_ptr->quantize_index[i] = (png_byte)i;474}475476if (num_palette > maximum_colors)477{478if (histogram != NULL)479{480/* This is easy enough, just throw out the least used colors.481* Perhaps not the best solution, but good enough.482*/483484int i;485486/* Initialize an array to sort colors */487png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,488(png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));489490/* Initialize the quantize_sort array */491for (i = 0; i < num_palette; i++)492png_ptr->quantize_sort[i] = (png_byte)i;493494/* Find the least used palette entries by starting a495* bubble sort, and running it until we have sorted496* out enough colors. Note that we don't care about497* sorting all the colors, just finding which are498* least used.499*/500501for (i = num_palette - 1; i >= maximum_colors; i--)502{503int done; /* To stop early if the list is pre-sorted */504int j;505506done = 1;507for (j = 0; j < i; j++)508{509if (histogram[png_ptr->quantize_sort[j]]510< histogram[png_ptr->quantize_sort[j + 1]])511{512png_byte t;513514t = png_ptr->quantize_sort[j];515png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];516png_ptr->quantize_sort[j + 1] = t;517done = 0;518}519}520521if (done != 0)522break;523}524525/* Swap the palette around, and set up a table, if necessary */526if (full_quantize != 0)527{528int j = num_palette;529530/* Put all the useful colors within the max, but don't531* move the others.532*/533for (i = 0; i < maximum_colors; i++)534{535if ((int)png_ptr->quantize_sort[i] >= maximum_colors)536{537do538j--;539while ((int)png_ptr->quantize_sort[j] >= maximum_colors);540541palette[i] = palette[j];542}543}544}545else546{547int j = num_palette;548549/* Move all the used colors inside the max limit, and550* develop a translation table.551*/552for (i = 0; i < maximum_colors; i++)553{554/* Only move the colors we need to */555if ((int)png_ptr->quantize_sort[i] >= maximum_colors)556{557png_color tmp_color;558559do560j--;561while ((int)png_ptr->quantize_sort[j] >= maximum_colors);562563tmp_color = palette[j];564palette[j] = palette[i];565palette[i] = tmp_color;566/* Indicate where the color went */567png_ptr->quantize_index[j] = (png_byte)i;568png_ptr->quantize_index[i] = (png_byte)j;569}570}571572/* Find closest color for those colors we are not using */573for (i = 0; i < num_palette; i++)574{575if ((int)png_ptr->quantize_index[i] >= maximum_colors)576{577int min_d, k, min_k, d_index;578579/* Find the closest color to one we threw out */580d_index = png_ptr->quantize_index[i];581min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);582for (k = 1, min_k = 0; k < maximum_colors; k++)583{584int d;585586d = PNG_COLOR_DIST(palette[d_index], palette[k]);587588if (d < min_d)589{590min_d = d;591min_k = k;592}593}594/* Point to closest color */595png_ptr->quantize_index[i] = (png_byte)min_k;596}597}598}599png_free(png_ptr, png_ptr->quantize_sort);600png_ptr->quantize_sort = NULL;601}602else603{604/* This is much harder to do simply (and quickly). Perhaps605* we need to go through a median cut routine, but those606* don't always behave themselves with only a few colors607* as input. So we will just find the closest two colors,608* and throw out one of them (chosen somewhat randomly).609* [We don't understand this at all, so if someone wants to610* work on improving it, be our guest - AED, GRP]611*/612int i;613int max_d;614int num_new_palette;615png_dsortp t;616png_dsortpp hash;617618t = NULL;619620/* Initialize palette index arrays */621png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,622(png_alloc_size_t)((png_uint_32)num_palette *623(sizeof (png_byte))));624png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,625(png_alloc_size_t)((png_uint_32)num_palette *626(sizeof (png_byte))));627628/* Initialize the sort array */629for (i = 0; i < num_palette; i++)630{631png_ptr->index_to_palette[i] = (png_byte)i;632png_ptr->palette_to_index[i] = (png_byte)i;633}634635hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *636(sizeof (png_dsortp))));637638num_new_palette = num_palette;639640/* Initial wild guess at how far apart the farthest pixel641* pair we will be eliminating will be. Larger642* numbers mean more areas will be allocated, Smaller643* numbers run the risk of not saving enough data, and644* having to do this all over again.645*646* I have not done extensive checking on this number.647*/648max_d = 96;649650while (num_new_palette > maximum_colors)651{652for (i = 0; i < num_new_palette - 1; i++)653{654int j;655656for (j = i + 1; j < num_new_palette; j++)657{658int d;659660d = PNG_COLOR_DIST(palette[i], palette[j]);661662if (d <= max_d)663{664665t = (png_dsortp)png_malloc_warn(png_ptr,666(png_alloc_size_t)(sizeof (png_dsort)));667668if (t == NULL)669break;670671t->next = hash[d];672t->left = (png_byte)i;673t->right = (png_byte)j;674hash[d] = t;675}676}677if (t == NULL)678break;679}680681if (t != NULL)682for (i = 0; i <= max_d; i++)683{684if (hash[i] != NULL)685{686png_dsortp p;687688for (p = hash[i]; p; p = p->next)689{690if ((int)png_ptr->index_to_palette[p->left]691< num_new_palette &&692(int)png_ptr->index_to_palette[p->right]693< num_new_palette)694{695int j, next_j;696697if (num_new_palette & 0x01)698{699j = p->left;700next_j = p->right;701}702else703{704j = p->right;705next_j = p->left;706}707708num_new_palette--;709palette[png_ptr->index_to_palette[j]]710= palette[num_new_palette];711if (full_quantize == 0)712{713int k;714715for (k = 0; k < num_palette; k++)716{717if (png_ptr->quantize_index[k] ==718png_ptr->index_to_palette[j])719png_ptr->quantize_index[k] =720png_ptr->index_to_palette[next_j];721722if ((int)png_ptr->quantize_index[k] ==723num_new_palette)724png_ptr->quantize_index[k] =725png_ptr->index_to_palette[j];726}727}728729png_ptr->index_to_palette[png_ptr->palette_to_index730[num_new_palette]] = png_ptr->index_to_palette[j];731732png_ptr->palette_to_index[png_ptr->index_to_palette[j]]733= png_ptr->palette_to_index[num_new_palette];734735png_ptr->index_to_palette[j] =736(png_byte)num_new_palette;737738png_ptr->palette_to_index[num_new_palette] =739(png_byte)j;740}741if (num_new_palette <= maximum_colors)742break;743}744if (num_new_palette <= maximum_colors)745break;746}747}748749for (i = 0; i < 769; i++)750{751if (hash[i] != NULL)752{753png_dsortp p = hash[i];754while (p)755{756t = p->next;757png_free(png_ptr, p);758p = t;759}760}761hash[i] = 0;762}763max_d += 96;764}765png_free(png_ptr, hash);766png_free(png_ptr, png_ptr->palette_to_index);767png_free(png_ptr, png_ptr->index_to_palette);768png_ptr->palette_to_index = NULL;769png_ptr->index_to_palette = NULL;770}771num_palette = maximum_colors;772}773if (png_ptr->palette == NULL)774{775png_ptr->palette = palette;776}777png_ptr->num_palette = (png_uint_16)num_palette;778779if (full_quantize != 0)780{781int i;782png_bytep distance;783int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +784PNG_QUANTIZE_BLUE_BITS;785int num_red = (1 << PNG_QUANTIZE_RED_BITS);786int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);787int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);788size_t num_entries = ((size_t)1 << total_bits);789790png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,791(png_alloc_size_t)(num_entries * (sizeof (png_byte))));792793distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *794(sizeof (png_byte))));795796memset(distance, 0xff, num_entries * (sizeof (png_byte)));797798for (i = 0; i < num_palette; i++)799{800int ir, ig, ib;801int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));802int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));803int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));804805for (ir = 0; ir < num_red; ir++)806{807/* int dr = abs(ir - r); */808int dr = ((ir > r) ? ir - r : r - ir);809int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +810PNG_QUANTIZE_GREEN_BITS));811812for (ig = 0; ig < num_green; ig++)813{814/* int dg = abs(ig - g); */815int dg = ((ig > g) ? ig - g : g - ig);816int dt = dr + dg;817int dm = ((dr > dg) ? dr : dg);818int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);819820for (ib = 0; ib < num_blue; ib++)821{822int d_index = index_g | ib;823/* int db = abs(ib - b); */824int db = ((ib > b) ? ib - b : b - ib);825int dmax = ((dm > db) ? dm : db);826int d = dmax + dt + db;827828if (d < (int)distance[d_index])829{830distance[d_index] = (png_byte)d;831png_ptr->palette_lookup[d_index] = (png_byte)i;832}833}834}835}836}837838png_free(png_ptr, distance);839}840}841#endif /* READ_QUANTIZE */842843#ifdef PNG_READ_GAMMA_SUPPORTED844void PNGFAPI845png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,846png_fixed_point file_gamma)847{848png_debug(1, "in png_set_gamma_fixed");849850if (png_rtran_ok(png_ptr, 0) == 0)851return;852853/* New in libpng-1.5.4 - reserve particular negative values as flags. */854scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);855file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);856857/* Checking the gamma values for being >0 was added in 1.5.4 along with the858* premultiplied alpha support; this actually hides an undocumented feature859* of the previous implementation which allowed gamma processing to be860* disabled in background handling. There is no evidence (so far) that this861* was being used; however, png_set_background itself accepted and must still862* accept '0' for the gamma value it takes, because it isn't always used.863*864* Since this is an API change (albeit a very minor one that removes an865* undocumented API feature) the following checks were only enabled in866* libpng-1.6.0.867*/868if (file_gamma <= 0)869png_error(png_ptr, "invalid file gamma in png_set_gamma");870871if (scrn_gamma <= 0)872png_error(png_ptr, "invalid screen gamma in png_set_gamma");873874/* Set the gamma values unconditionally - this overrides the value in the PNG875* file if a gAMA chunk was present. png_set_alpha_mode provides a876* different, easier, way to default the file gamma.877*/878png_ptr->colorspace.gamma = file_gamma;879png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;880png_ptr->screen_gamma = scrn_gamma;881}882883# ifdef PNG_FLOATING_POINT_SUPPORTED884void PNGAPI885png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)886{887png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),888convert_gamma_value(png_ptr, file_gamma));889}890# endif /* FLOATING_POINT */891#endif /* READ_GAMMA */892893#ifdef PNG_READ_EXPAND_SUPPORTED894/* Expand paletted images to RGB, expand grayscale images of895* less than 8-bit depth to 8-bit depth, and expand tRNS chunks896* to alpha channels.897*/898void PNGAPI899png_set_expand(png_structrp png_ptr)900{901png_debug(1, "in png_set_expand");902903if (png_rtran_ok(png_ptr, 0) == 0)904return;905906png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);907}908909/* GRR 19990627: the following three functions currently are identical910* to png_set_expand(). However, it is entirely reasonable that someone911* might wish to expand an indexed image to RGB but *not* expand a single,912* fully transparent palette entry to a full alpha channel--perhaps instead913* convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace914* the transparent color with a particular RGB value, or drop tRNS entirely.915* IOW, a future version of the library may make the transformations flag916* a bit more fine-grained, with separate bits for each of these three917* functions.918*919* More to the point, these functions make it obvious what libpng will be920* doing, whereas "expand" can (and does) mean any number of things.921*922* GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified923* to expand only the sample depth but not to expand the tRNS to alpha924* and its name was changed to png_set_expand_gray_1_2_4_to_8().925*/926927/* Expand paletted images to RGB. */928void PNGAPI929png_set_palette_to_rgb(png_structrp png_ptr)930{931png_debug(1, "in png_set_palette_to_rgb");932933if (png_rtran_ok(png_ptr, 0) == 0)934return;935936png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);937}938939/* Expand grayscale images of less than 8-bit depth to 8 bits. */940void PNGAPI941png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)942{943png_debug(1, "in png_set_expand_gray_1_2_4_to_8");944945if (png_rtran_ok(png_ptr, 0) == 0)946return;947948png_ptr->transformations |= PNG_EXPAND;949}950951/* Expand tRNS chunks to alpha channels. */952void PNGAPI953png_set_tRNS_to_alpha(png_structrp png_ptr)954{955png_debug(1, "in png_set_tRNS_to_alpha");956957if (png_rtran_ok(png_ptr, 0) == 0)958return;959960png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);961}962#endif /* READ_EXPAND */963964#ifdef PNG_READ_EXPAND_16_SUPPORTED965/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise966* it may not work correctly.)967*/968void PNGAPI969png_set_expand_16(png_structrp png_ptr)970{971png_debug(1, "in png_set_expand_16");972973if (png_rtran_ok(png_ptr, 0) == 0)974return;975976png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);977}978#endif979980#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED981void PNGAPI982png_set_gray_to_rgb(png_structrp png_ptr)983{984png_debug(1, "in png_set_gray_to_rgb");985986if (png_rtran_ok(png_ptr, 0) == 0)987return;988989/* Because rgb must be 8 bits or more: */990png_set_expand_gray_1_2_4_to_8(png_ptr);991png_ptr->transformations |= PNG_GRAY_TO_RGB;992}993#endif994995#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED996void PNGFAPI997png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,998png_fixed_point red, png_fixed_point green)999{1000png_debug(1, "in png_set_rgb_to_gray");10011002/* Need the IHDR here because of the check on color_type below. */1003/* TODO: fix this */1004if (png_rtran_ok(png_ptr, 1) == 0)1005return;10061007switch (error_action)1008{1009case PNG_ERROR_ACTION_NONE:1010png_ptr->transformations |= PNG_RGB_TO_GRAY;1011break;10121013case PNG_ERROR_ACTION_WARN:1014png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;1015break;10161017case PNG_ERROR_ACTION_ERROR:1018png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;1019break;10201021default:1022png_error(png_ptr, "invalid error action to rgb_to_gray");1023}10241025if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)1026#ifdef PNG_READ_EXPAND_SUPPORTED1027png_ptr->transformations |= PNG_EXPAND;1028#else1029{1030/* Make this an error in 1.6 because otherwise the application may assume1031* that it just worked and get a memory overwrite.1032*/1033png_error(png_ptr,1034"Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");10351036/* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */1037}1038#endif1039{1040if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)1041{1042png_uint_16 red_int, green_int;10431044/* NOTE: this calculation does not round, but this behavior is retained1045* for consistency; the inaccuracy is very small. The code here always1046* overwrites the coefficients, regardless of whether they have been1047* defaulted or set already.1048*/1049red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);1050green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);10511052png_ptr->rgb_to_gray_red_coeff = red_int;1053png_ptr->rgb_to_gray_green_coeff = green_int;1054png_ptr->rgb_to_gray_coefficients_set = 1;1055}10561057else1058{1059if (red >= 0 && green >= 0)1060png_app_warning(png_ptr,1061"ignoring out of range rgb_to_gray coefficients");10621063/* Use the defaults, from the cHRM chunk if set, else the historical1064* values which are close to the sRGB/HDTV/ITU-Rec 709 values. See1065* png_do_rgb_to_gray for more discussion of the values. In this case1066* the coefficients are not marked as 'set' and are not overwritten if1067* something has already provided a default.1068*/1069if (png_ptr->rgb_to_gray_red_coeff == 0 &&1070png_ptr->rgb_to_gray_green_coeff == 0)1071{1072png_ptr->rgb_to_gray_red_coeff = 6968;1073png_ptr->rgb_to_gray_green_coeff = 23434;1074/* png_ptr->rgb_to_gray_blue_coeff = 2366; */1075}1076}1077}1078}10791080#ifdef PNG_FLOATING_POINT_SUPPORTED1081/* Convert a RGB image to a grayscale of the same width. This allows us,1082* for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.1083*/10841085void PNGAPI1086png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,1087double green)1088{1089png_set_rgb_to_gray_fixed(png_ptr, error_action,1090png_fixed(png_ptr, red, "rgb to gray red coefficient"),1091png_fixed(png_ptr, green, "rgb to gray green coefficient"));1092}1093#endif /* FLOATING POINT */10941095#endif /* RGB_TO_GRAY */10961097#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \1098defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)1099void PNGAPI1100png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr1101read_user_transform_fn)1102{1103png_debug(1, "in png_set_read_user_transform_fn");11041105#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED1106png_ptr->transformations |= PNG_USER_TRANSFORM;1107png_ptr->read_user_transform_fn = read_user_transform_fn;1108#endif1109}1110#endif11111112#ifdef PNG_READ_TRANSFORMS_SUPPORTED1113#ifdef PNG_READ_GAMMA_SUPPORTED1114/* In the case of gamma transformations only do transformations on images where1115* the [file] gamma and screen_gamma are not close reciprocals, otherwise it1116* slows things down slightly, and also needlessly introduces small errors.1117*/1118static int /* PRIVATE */1119png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)1120{1121/* PNG_GAMMA_THRESHOLD is the threshold for performing gamma1122* correction as a difference of the overall transform from 1.01123*1124* We want to compare the threshold with s*f - 1, if we get1125* overflow here it is because of wacky gamma values so we1126* turn on processing anyway.1127*/1128png_fixed_point gtest;1129return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) ||1130png_gamma_significant(gtest);1131}1132#endif11331134/* Initialize everything needed for the read. This includes modifying1135* the palette.1136*/11371138/* For the moment 'png_init_palette_transformations' and1139* 'png_init_rgb_transformations' only do some flag canceling optimizations.1140* The intent is that these two routines should have palette or rgb operations1141* extracted from 'png_init_read_transformations'.1142*/1143static void /* PRIVATE */1144png_init_palette_transformations(png_structrp png_ptr)1145{1146/* Called to handle the (input) palette case. In png_do_read_transformations1147* the first step is to expand the palette if requested, so this code must1148* take care to only make changes that are invariant with respect to the1149* palette expansion, or only do them if there is no expansion.1150*1151* STRIP_ALPHA has already been handled in the caller (by setting num_trans1152* to 0.)1153*/1154int input_has_alpha = 0;1155int input_has_transparency = 0;11561157if (png_ptr->num_trans > 0)1158{1159int i;11601161/* Ignore if all the entries are opaque (unlikely!) */1162for (i=0; i<png_ptr->num_trans; ++i)1163{1164if (png_ptr->trans_alpha[i] == 255)1165continue;1166else if (png_ptr->trans_alpha[i] == 0)1167input_has_transparency = 1;1168else1169{1170input_has_transparency = 1;1171input_has_alpha = 1;1172break;1173}1174}1175}11761177/* If no alpha we can optimize. */1178if (input_has_alpha == 0)1179{1180/* Any alpha means background and associative alpha processing is1181* required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA1182* and ENCODE_ALPHA are irrelevant.1183*/1184png_ptr->transformations &= ~PNG_ENCODE_ALPHA;1185png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;11861187if (input_has_transparency == 0)1188png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);1189}11901191#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)1192/* png_set_background handling - deals with the complexity of whether the1193* background color is in the file format or the screen format in the case1194* where an 'expand' will happen.1195*/11961197/* The following code cannot be entered in the alpha pre-multiplication case1198* because PNG_BACKGROUND_EXPAND is cancelled below.1199*/1200if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&1201(png_ptr->transformations & PNG_EXPAND) != 0)1202{1203{1204png_ptr->background.red =1205png_ptr->palette[png_ptr->background.index].red;1206png_ptr->background.green =1207png_ptr->palette[png_ptr->background.index].green;1208png_ptr->background.blue =1209png_ptr->palette[png_ptr->background.index].blue;12101211#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED1212if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)1213{1214if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)1215{1216/* Invert the alpha channel (in tRNS) unless the pixels are1217* going to be expanded, in which case leave it for later1218*/1219int i, istop = png_ptr->num_trans;12201221for (i = 0; i < istop; i++)1222png_ptr->trans_alpha[i] =1223(png_byte)(255 - png_ptr->trans_alpha[i]);1224}1225}1226#endif /* READ_INVERT_ALPHA */1227}1228} /* background expand and (therefore) no alpha association. */1229#endif /* READ_EXPAND && READ_BACKGROUND */1230}12311232static void /* PRIVATE */1233png_init_rgb_transformations(png_structrp png_ptr)1234{1235/* Added to libpng-1.5.4: check the color type to determine whether there1236* is any alpha or transparency in the image and simply cancel the1237* background and alpha mode stuff if there isn't.1238*/1239int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;1240int input_has_transparency = png_ptr->num_trans > 0;12411242/* If no alpha we can optimize. */1243if (input_has_alpha == 0)1244{1245/* Any alpha means background and associative alpha processing is1246* required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA1247* and ENCODE_ALPHA are irrelevant.1248*/1249# ifdef PNG_READ_ALPHA_MODE_SUPPORTED1250png_ptr->transformations &= ~PNG_ENCODE_ALPHA;1251png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;1252# endif12531254if (input_has_transparency == 0)1255png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);1256}12571258#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)1259/* png_set_background handling - deals with the complexity of whether the1260* background color is in the file format or the screen format in the case1261* where an 'expand' will happen.1262*/12631264/* The following code cannot be entered in the alpha pre-multiplication case1265* because PNG_BACKGROUND_EXPAND is cancelled below.1266*/1267if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&1268(png_ptr->transformations & PNG_EXPAND) != 0 &&1269(png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)1270/* i.e., GRAY or GRAY_ALPHA */1271{1272{1273/* Expand background and tRNS chunks */1274int gray = png_ptr->background.gray;1275int trans_gray = png_ptr->trans_color.gray;12761277switch (png_ptr->bit_depth)1278{1279case 1:1280gray *= 0xff;1281trans_gray *= 0xff;1282break;12831284case 2:1285gray *= 0x55;1286trans_gray *= 0x55;1287break;12881289case 4:1290gray *= 0x11;1291trans_gray *= 0x11;1292break;12931294default:12951296case 8:1297/* FALLTHROUGH */ /* (Already 8 bits) */12981299case 16:1300/* Already a full 16 bits */1301break;1302}13031304png_ptr->background.red = png_ptr->background.green =1305png_ptr->background.blue = (png_uint_16)gray;13061307if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)1308{1309png_ptr->trans_color.red = png_ptr->trans_color.green =1310png_ptr->trans_color.blue = (png_uint_16)trans_gray;1311}1312}1313} /* background expand and (therefore) no alpha association. */1314#endif /* READ_EXPAND && READ_BACKGROUND */1315}13161317void /* PRIVATE */1318png_init_read_transformations(png_structrp png_ptr)1319{1320png_debug(1, "in png_init_read_transformations");13211322/* This internal function is called from png_read_start_row in pngrutil.c1323* and it is called before the 'rowbytes' calculation is done, so the code1324* in here can change or update the transformations flags.1325*1326* First do updates that do not depend on the details of the PNG image data1327* being processed.1328*/13291330#ifdef PNG_READ_GAMMA_SUPPORTED1331/* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds1332* png_set_alpha_mode and this is another source for a default file gamma so1333* the test needs to be performed later - here. In addition prior to 1.5.41334* the tests were repeated for the PALETTE color type here - this is no1335* longer necessary (and doesn't seem to have been necessary before.)1336*/1337{1338/* The following temporary indicates if overall gamma correction is1339* required.1340*/1341int gamma_correction = 0;13421343if (png_ptr->colorspace.gamma != 0) /* has been set */1344{1345if (png_ptr->screen_gamma != 0) /* screen set too */1346gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,1347png_ptr->screen_gamma);13481349else1350/* Assume the output matches the input; a long time default behavior1351* of libpng, although the standard has nothing to say about this.1352*/1353png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);1354}13551356else if (png_ptr->screen_gamma != 0)1357/* The converse - assume the file matches the screen, note that this1358* perhaps undesirable default can (from 1.5.4) be changed by calling1359* png_set_alpha_mode (even if the alpha handling mode isn't required1360* or isn't changed from the default.)1361*/1362png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);13631364else /* neither are set */1365/* Just in case the following prevents any processing - file and screen1366* are both assumed to be linear and there is no way to introduce a1367* third gamma value other than png_set_background with 'UNIQUE', and,1368* prior to 1.5.41369*/1370png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;13711372/* We have a gamma value now. */1373png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;13741375/* Now turn the gamma transformation on or off as appropriate. Notice1376* that PNG_GAMMA just refers to the file->screen correction. Alpha1377* composition may independently cause gamma correction because it needs1378* linear data (e.g. if the file has a gAMA chunk but the screen gamma1379* hasn't been specified.) In any case this flag may get turned off in1380* the code immediately below if the transform can be handled outside the1381* row loop.1382*/1383if (gamma_correction != 0)1384png_ptr->transformations |= PNG_GAMMA;13851386else1387png_ptr->transformations &= ~PNG_GAMMA;1388}1389#endif13901391/* Certain transformations have the effect of preventing other1392* transformations that happen afterward in png_do_read_transformations;1393* resolve the interdependencies here. From the code of1394* png_do_read_transformations the order is:1395*1396* 1) PNG_EXPAND (including PNG_EXPAND_tRNS)1397* 2) PNG_STRIP_ALPHA (if no compose)1398* 3) PNG_RGB_TO_GRAY1399* 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY1400* 5) PNG_COMPOSE1401* 6) PNG_GAMMA1402* 7) PNG_STRIP_ALPHA (if compose)1403* 8) PNG_ENCODE_ALPHA1404* 9) PNG_SCALE_16_TO_81405* 10) PNG_16_TO_81406* 11) PNG_QUANTIZE (converts to palette)1407* 12) PNG_EXPAND_161408* 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY1409* 14) PNG_INVERT_MONO1410* 15) PNG_INVERT_ALPHA1411* 16) PNG_SHIFT1412* 17) PNG_PACK1413* 18) PNG_BGR1414* 19) PNG_PACKSWAP1415* 20) PNG_FILLER (includes PNG_ADD_ALPHA)1416* 21) PNG_SWAP_ALPHA1417* 22) PNG_SWAP_BYTES1418* 23) PNG_USER_TRANSFORM [must be last]1419*/1420#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED1421if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&1422(png_ptr->transformations & PNG_COMPOSE) == 0)1423{1424/* Stripping the alpha channel happens immediately after the 'expand'1425* transformations, before all other transformation, so it cancels out1426* the alpha handling. It has the side effect negating the effect of1427* PNG_EXPAND_tRNS too:1428*/1429png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |1430PNG_EXPAND_tRNS);1431png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;14321433/* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen1434* so transparency information would remain just so long as it wasn't1435* expanded. This produces unexpected API changes if the set of things1436* that do PNG_EXPAND_tRNS changes (perfectly possible given the1437* documentation - which says ask for what you want, accept what you1438* get.) This makes the behavior consistent from 1.5.4:1439*/1440png_ptr->num_trans = 0;1441}1442#endif /* STRIP_ALPHA supported, no COMPOSE */14431444#ifdef PNG_READ_ALPHA_MODE_SUPPORTED1445/* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA1446* settings will have no effect.1447*/1448if (png_gamma_significant(png_ptr->screen_gamma) == 0)1449{1450png_ptr->transformations &= ~PNG_ENCODE_ALPHA;1451png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;1452}1453#endif14541455#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED1456/* Make sure the coefficients for the rgb to gray conversion are set1457* appropriately.1458*/1459if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)1460png_colorspace_set_rgb_coefficients(png_ptr);1461#endif14621463#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED1464#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)1465/* Detect gray background and attempt to enable optimization for1466* gray --> RGB case.1467*1468* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or1469* RGB_ALPHA (in which case need_expand is superfluous anyway), the1470* background color might actually be gray yet not be flagged as such.1471* This is not a problem for the current code, which uses1472* PNG_BACKGROUND_IS_GRAY only to decide when to do the1473* png_do_gray_to_rgb() transformation.1474*1475* TODO: this code needs to be revised to avoid the complexity and1476* interdependencies. The color type of the background should be recorded in1477* png_set_background, along with the bit depth, then the code has a record1478* of exactly what color space the background is currently in.1479*/1480if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)1481{1482/* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if1483* the file was grayscale the background value is gray.1484*/1485if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)1486png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;1487}14881489else if ((png_ptr->transformations & PNG_COMPOSE) != 0)1490{1491/* PNG_COMPOSE: png_set_background was called with need_expand false,1492* so the color is in the color space of the output or png_set_alpha_mode1493* was called and the color is black. Ignore RGB_TO_GRAY because that1494* happens before GRAY_TO_RGB.1495*/1496if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)1497{1498if (png_ptr->background.red == png_ptr->background.green &&1499png_ptr->background.red == png_ptr->background.blue)1500{1501png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;1502png_ptr->background.gray = png_ptr->background.red;1503}1504}1505}1506#endif /* READ_EXPAND && READ_BACKGROUND */1507#endif /* READ_GRAY_TO_RGB */15081509/* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations1510* can be performed directly on the palette, and some (such as rgb to gray)1511* can be optimized inside the palette. This is particularly true of the1512* composite (background and alpha) stuff, which can be pretty much all done1513* in the palette even if the result is expanded to RGB or gray afterward.1514*1515* NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and1516* earlier and the palette stuff is actually handled on the first row. This1517* leads to the reported bug that the palette returned by png_get_PLTE is not1518* updated.1519*/1520if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)1521png_init_palette_transformations(png_ptr);15221523else1524png_init_rgb_transformations(png_ptr);15251526#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \1527defined(PNG_READ_EXPAND_16_SUPPORTED)1528if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&1529(png_ptr->transformations & PNG_COMPOSE) != 0 &&1530(png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&1531png_ptr->bit_depth != 16)1532{1533/* TODO: fix this. Because the expand_16 operation is after the compose1534* handling the background color must be 8, not 16, bits deep, but the1535* application will supply a 16-bit value so reduce it here.1536*1537* The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at1538* present, so that case is ok (until do_expand_16 is moved.)1539*1540* NOTE: this discards the low 16 bits of the user supplied background1541* color, but until expand_16 works properly there is no choice!1542*/1543# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))1544CHOP(png_ptr->background.red);1545CHOP(png_ptr->background.green);1546CHOP(png_ptr->background.blue);1547CHOP(png_ptr->background.gray);1548# undef CHOP1549}1550#endif /* READ_BACKGROUND && READ_EXPAND_16 */15511552#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \1553(defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \1554defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))1555if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&1556(png_ptr->transformations & PNG_COMPOSE) != 0 &&1557(png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&1558png_ptr->bit_depth == 16)1559{1560/* On the other hand, if a 16-bit file is to be reduced to 8-bits per1561* component this will also happen after PNG_COMPOSE and so the background1562* color must be pre-expanded here.1563*1564* TODO: fix this too.1565*/1566png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);1567png_ptr->background.green =1568(png_uint_16)(png_ptr->background.green * 257);1569png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);1570png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);1571}1572#endif15731574/* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the1575* background support (see the comments in scripts/pnglibconf.dfa), this1576* allows pre-multiplication of the alpha channel to be implemented as1577* compositing on black. This is probably sub-optimal and has been done in1578* 1.5.4 betas simply to enable external critique and testing (i.e. to1579* implement the new API quickly, without lots of internal changes.)1580*/15811582#ifdef PNG_READ_GAMMA_SUPPORTED1583# ifdef PNG_READ_BACKGROUND_SUPPORTED1584/* Includes ALPHA_MODE */1585png_ptr->background_1 = png_ptr->background;1586# endif15871588/* This needs to change - in the palette image case a whole set of tables are1589* built when it would be quicker to just calculate the correct value for1590* each palette entry directly. Also, the test is too tricky - why check1591* PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that1592* PNG_GAMMA is cancelled even if the gamma is known? The test excludes the1593* PNG_COMPOSE case, so apparently if there is no *overall* gamma correction1594* the gamma tables will not be built even if composition is required on a1595* gamma encoded value.1596*1597* In 1.5.4 this is addressed below by an additional check on the individual1598* file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the1599* tables.1600*/1601if ((png_ptr->transformations & PNG_GAMMA) != 0 ||1602((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&1603(png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||1604png_gamma_significant(png_ptr->screen_gamma) != 0)) ||1605((png_ptr->transformations & PNG_COMPOSE) != 0 &&1606(png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||1607png_gamma_significant(png_ptr->screen_gamma) != 01608# ifdef PNG_READ_BACKGROUND_SUPPORTED1609|| (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&1610png_gamma_significant(png_ptr->background_gamma) != 0)1611# endif1612)) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&1613png_gamma_significant(png_ptr->screen_gamma) != 0))1614{1615png_build_gamma_table(png_ptr, png_ptr->bit_depth);16161617#ifdef PNG_READ_BACKGROUND_SUPPORTED1618if ((png_ptr->transformations & PNG_COMPOSE) != 0)1619{1620/* Issue a warning about this combination: because RGB_TO_GRAY is1621* optimized to do the gamma transform if present yet do_background has1622* to do the same thing if both options are set a1623* double-gamma-correction happens. This is true in all versions of1624* libpng to date.1625*/1626if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)1627png_warning(png_ptr,1628"libpng does not support gamma+background+rgb_to_gray");16291630if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)1631{1632/* We don't get to here unless there is a tRNS chunk with non-opaque1633* entries - see the checking code at the start of this function.1634*/1635png_color back, back_1;1636png_colorp palette = png_ptr->palette;1637int num_palette = png_ptr->num_palette;1638int i;1639if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)1640{16411642back.red = png_ptr->gamma_table[png_ptr->background.red];1643back.green = png_ptr->gamma_table[png_ptr->background.green];1644back.blue = png_ptr->gamma_table[png_ptr->background.blue];16451646back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];1647back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];1648back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];1649}1650else1651{1652png_fixed_point g, gs;16531654switch (png_ptr->background_gamma_type)1655{1656case PNG_BACKGROUND_GAMMA_SCREEN:1657g = (png_ptr->screen_gamma);1658gs = PNG_FP_1;1659break;16601661case PNG_BACKGROUND_GAMMA_FILE:1662g = png_reciprocal(png_ptr->colorspace.gamma);1663gs = png_reciprocal2(png_ptr->colorspace.gamma,1664png_ptr->screen_gamma);1665break;16661667case PNG_BACKGROUND_GAMMA_UNIQUE:1668g = png_reciprocal(png_ptr->background_gamma);1669gs = png_reciprocal2(png_ptr->background_gamma,1670png_ptr->screen_gamma);1671break;1672default:1673g = PNG_FP_1; /* back_1 */1674gs = PNG_FP_1; /* back */1675break;1676}16771678if (png_gamma_significant(gs) != 0)1679{1680back.red = png_gamma_8bit_correct(png_ptr->background.red,1681gs);1682back.green = png_gamma_8bit_correct(png_ptr->background.green,1683gs);1684back.blue = png_gamma_8bit_correct(png_ptr->background.blue,1685gs);1686}16871688else1689{1690back.red = (png_byte)png_ptr->background.red;1691back.green = (png_byte)png_ptr->background.green;1692back.blue = (png_byte)png_ptr->background.blue;1693}16941695if (png_gamma_significant(g) != 0)1696{1697back_1.red = png_gamma_8bit_correct(png_ptr->background.red,1698g);1699back_1.green = png_gamma_8bit_correct(1700png_ptr->background.green, g);1701back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,1702g);1703}17041705else1706{1707back_1.red = (png_byte)png_ptr->background.red;1708back_1.green = (png_byte)png_ptr->background.green;1709back_1.blue = (png_byte)png_ptr->background.blue;1710}1711}17121713for (i = 0; i < num_palette; i++)1714{1715if (i < (int)png_ptr->num_trans &&1716png_ptr->trans_alpha[i] != 0xff)1717{1718if (png_ptr->trans_alpha[i] == 0)1719{1720palette[i] = back;1721}1722else /* if (png_ptr->trans_alpha[i] != 0xff) */1723{1724png_byte v, w;17251726v = png_ptr->gamma_to_1[palette[i].red];1727png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);1728palette[i].red = png_ptr->gamma_from_1[w];17291730v = png_ptr->gamma_to_1[palette[i].green];1731png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);1732palette[i].green = png_ptr->gamma_from_1[w];17331734v = png_ptr->gamma_to_1[palette[i].blue];1735png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);1736palette[i].blue = png_ptr->gamma_from_1[w];1737}1738}1739else1740{1741palette[i].red = png_ptr->gamma_table[palette[i].red];1742palette[i].green = png_ptr->gamma_table[palette[i].green];1743palette[i].blue = png_ptr->gamma_table[palette[i].blue];1744}1745}17461747/* Prevent the transformations being done again.1748*1749* NOTE: this is highly dubious; it removes the transformations in1750* place. This seems inconsistent with the general treatment of the1751* transformations elsewhere.1752*/1753png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);1754} /* color_type == PNG_COLOR_TYPE_PALETTE */17551756/* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */1757else /* color_type != PNG_COLOR_TYPE_PALETTE */1758{1759int gs_sig, g_sig;1760png_fixed_point g = PNG_FP_1; /* Correction to linear */1761png_fixed_point gs = PNG_FP_1; /* Correction to screen */17621763switch (png_ptr->background_gamma_type)1764{1765case PNG_BACKGROUND_GAMMA_SCREEN:1766g = png_ptr->screen_gamma;1767/* gs = PNG_FP_1; */1768break;17691770case PNG_BACKGROUND_GAMMA_FILE:1771g = png_reciprocal(png_ptr->colorspace.gamma);1772gs = png_reciprocal2(png_ptr->colorspace.gamma,1773png_ptr->screen_gamma);1774break;17751776case PNG_BACKGROUND_GAMMA_UNIQUE:1777g = png_reciprocal(png_ptr->background_gamma);1778gs = png_reciprocal2(png_ptr->background_gamma,1779png_ptr->screen_gamma);1780break;17811782default:1783png_error(png_ptr, "invalid background gamma type");1784}17851786g_sig = png_gamma_significant(g);1787gs_sig = png_gamma_significant(gs);17881789if (g_sig != 0)1790png_ptr->background_1.gray = png_gamma_correct(png_ptr,1791png_ptr->background.gray, g);17921793if (gs_sig != 0)1794png_ptr->background.gray = png_gamma_correct(png_ptr,1795png_ptr->background.gray, gs);17961797if ((png_ptr->background.red != png_ptr->background.green) ||1798(png_ptr->background.red != png_ptr->background.blue) ||1799(png_ptr->background.red != png_ptr->background.gray))1800{1801/* RGB or RGBA with color background */1802if (g_sig != 0)1803{1804png_ptr->background_1.red = png_gamma_correct(png_ptr,1805png_ptr->background.red, g);18061807png_ptr->background_1.green = png_gamma_correct(png_ptr,1808png_ptr->background.green, g);18091810png_ptr->background_1.blue = png_gamma_correct(png_ptr,1811png_ptr->background.blue, g);1812}18131814if (gs_sig != 0)1815{1816png_ptr->background.red = png_gamma_correct(png_ptr,1817png_ptr->background.red, gs);18181819png_ptr->background.green = png_gamma_correct(png_ptr,1820png_ptr->background.green, gs);18211822png_ptr->background.blue = png_gamma_correct(png_ptr,1823png_ptr->background.blue, gs);1824}1825}18261827else1828{1829/* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */1830png_ptr->background_1.red = png_ptr->background_1.green1831= png_ptr->background_1.blue = png_ptr->background_1.gray;18321833png_ptr->background.red = png_ptr->background.green1834= png_ptr->background.blue = png_ptr->background.gray;1835}18361837/* The background is now in screen gamma: */1838png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;1839} /* color_type != PNG_COLOR_TYPE_PALETTE */1840}/* png_ptr->transformations & PNG_BACKGROUND */18411842else1843/* Transformation does not include PNG_BACKGROUND */1844#endif /* READ_BACKGROUND */1845if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE1846#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED1847/* RGB_TO_GRAY needs to have non-gamma-corrected values! */1848&& ((png_ptr->transformations & PNG_EXPAND) == 0 ||1849(png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)1850#endif1851)1852{1853png_colorp palette = png_ptr->palette;1854int num_palette = png_ptr->num_palette;1855int i;18561857/* NOTE: there are other transformations that should probably be in1858* here too.1859*/1860for (i = 0; i < num_palette; i++)1861{1862palette[i].red = png_ptr->gamma_table[palette[i].red];1863palette[i].green = png_ptr->gamma_table[palette[i].green];1864palette[i].blue = png_ptr->gamma_table[palette[i].blue];1865}18661867/* Done the gamma correction. */1868png_ptr->transformations &= ~PNG_GAMMA;1869} /* color_type == PALETTE && !PNG_BACKGROUND transformation */1870}1871#ifdef PNG_READ_BACKGROUND_SUPPORTED1872else1873#endif1874#endif /* READ_GAMMA */18751876#ifdef PNG_READ_BACKGROUND_SUPPORTED1877/* No GAMMA transformation (see the hanging else 4 lines above) */1878if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&1879(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))1880{1881int i;1882int istop = (int)png_ptr->num_trans;1883png_color back;1884png_colorp palette = png_ptr->palette;18851886back.red = (png_byte)png_ptr->background.red;1887back.green = (png_byte)png_ptr->background.green;1888back.blue = (png_byte)png_ptr->background.blue;18891890for (i = 0; i < istop; i++)1891{1892if (png_ptr->trans_alpha[i] == 0)1893{1894palette[i] = back;1895}18961897else if (png_ptr->trans_alpha[i] != 0xff)1898{1899/* The png_composite() macro is defined in png.h */1900png_composite(palette[i].red, palette[i].red,1901png_ptr->trans_alpha[i], back.red);19021903png_composite(palette[i].green, palette[i].green,1904png_ptr->trans_alpha[i], back.green);19051906png_composite(palette[i].blue, palette[i].blue,1907png_ptr->trans_alpha[i], back.blue);1908}1909}19101911png_ptr->transformations &= ~PNG_COMPOSE;1912}1913#endif /* READ_BACKGROUND */19141915#ifdef PNG_READ_SHIFT_SUPPORTED1916if ((png_ptr->transformations & PNG_SHIFT) != 0 &&1917(png_ptr->transformations & PNG_EXPAND) == 0 &&1918(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))1919{1920int i;1921int istop = png_ptr->num_palette;1922int shift = 8 - png_ptr->sig_bit.red;19231924png_ptr->transformations &= ~PNG_SHIFT;19251926/* significant bits can be in the range 1 to 7 for a meaningful result, if1927* the number of significant bits is 0 then no shift is done (this is an1928* error condition which is silently ignored.)1929*/1930if (shift > 0 && shift < 8)1931for (i=0; i<istop; ++i)1932{1933int component = png_ptr->palette[i].red;19341935component >>= shift;1936png_ptr->palette[i].red = (png_byte)component;1937}19381939shift = 8 - png_ptr->sig_bit.green;1940if (shift > 0 && shift < 8)1941for (i=0; i<istop; ++i)1942{1943int component = png_ptr->palette[i].green;19441945component >>= shift;1946png_ptr->palette[i].green = (png_byte)component;1947}19481949shift = 8 - png_ptr->sig_bit.blue;1950if (shift > 0 && shift < 8)1951for (i=0; i<istop; ++i)1952{1953int component = png_ptr->palette[i].blue;19541955component >>= shift;1956png_ptr->palette[i].blue = (png_byte)component;1957}1958}1959#endif /* READ_SHIFT */1960}19611962/* Modify the info structure to reflect the transformations. The1963* info should be updated so a PNG file could be written with it,1964* assuming the transformations result in valid PNG data.1965*/1966void /* PRIVATE */1967png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)1968{1969png_debug(1, "in png_read_transform_info");19701971#ifdef PNG_READ_EXPAND_SUPPORTED1972if ((png_ptr->transformations & PNG_EXPAND) != 0)1973{1974if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)1975{1976/* This check must match what actually happens in1977* png_do_expand_palette; if it ever checks the tRNS chunk to see if1978* it is all opaque we must do the same (at present it does not.)1979*/1980if (png_ptr->num_trans > 0)1981info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;19821983else1984info_ptr->color_type = PNG_COLOR_TYPE_RGB;19851986info_ptr->bit_depth = 8;1987info_ptr->num_trans = 0;19881989if (png_ptr->palette == NULL)1990png_error (png_ptr, "Palette is NULL in indexed image");1991}1992else1993{1994if (png_ptr->num_trans != 0)1995{1996if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)1997info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;1998}1999if (info_ptr->bit_depth < 8)2000info_ptr->bit_depth = 8;20012002info_ptr->num_trans = 0;2003}2004}2005#endif20062007#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\2008defined(PNG_READ_ALPHA_MODE_SUPPORTED)2009/* The following is almost certainly wrong unless the background value is in2010* the screen space!2011*/2012if ((png_ptr->transformations & PNG_COMPOSE) != 0)2013info_ptr->background = png_ptr->background;2014#endif20152016#ifdef PNG_READ_GAMMA_SUPPORTED2017/* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),2018* however it seems that the code in png_init_read_transformations, which has2019* been called before this from png_read_update_info->png_read_start_row2020* sometimes does the gamma transform and cancels the flag.2021*2022* TODO: this looks wrong; the info_ptr should end up with a gamma equal to2023* the screen_gamma value. The following probably results in weirdness if2024* the info_ptr is used by the app after the rows have been read.2025*/2026info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;2027#endif20282029if (info_ptr->bit_depth == 16)2030{2031# ifdef PNG_READ_16BIT_SUPPORTED2032# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED2033if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)2034info_ptr->bit_depth = 8;2035# endif20362037# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED2038if ((png_ptr->transformations & PNG_16_TO_8) != 0)2039info_ptr->bit_depth = 8;2040# endif20412042# else2043/* No 16-bit support: force chopping 16-bit input down to 8, in this case2044* the app program can chose if both APIs are available by setting the2045* correct scaling to use.2046*/2047# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED2048/* For compatibility with previous versions use the strip method by2049* default. This code works because if PNG_SCALE_16_TO_8 is already2050* set the code below will do that in preference to the chop.2051*/2052png_ptr->transformations |= PNG_16_TO_8;2053info_ptr->bit_depth = 8;2054# else20552056# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED2057png_ptr->transformations |= PNG_SCALE_16_TO_8;2058info_ptr->bit_depth = 8;2059# else20602061CONFIGURATION ERROR: you must enable at least one 16 to 8 method2062# endif2063# endif2064#endif /* !READ_16BIT */2065}20662067#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED2068if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)2069info_ptr->color_type = (png_byte)(info_ptr->color_type |2070PNG_COLOR_MASK_COLOR);2071#endif20722073#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED2074if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)2075info_ptr->color_type = (png_byte)(info_ptr->color_type &2076~PNG_COLOR_MASK_COLOR);2077#endif20782079#ifdef PNG_READ_QUANTIZE_SUPPORTED2080if ((png_ptr->transformations & PNG_QUANTIZE) != 0)2081{2082if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||2083(info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&2084png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)2085{2086info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;2087}2088}2089#endif20902091#ifdef PNG_READ_EXPAND_16_SUPPORTED2092if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&2093info_ptr->bit_depth == 8 &&2094info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)2095{2096info_ptr->bit_depth = 16;2097}2098#endif20992100#ifdef PNG_READ_PACK_SUPPORTED2101if ((png_ptr->transformations & PNG_PACK) != 0 &&2102(info_ptr->bit_depth < 8))2103info_ptr->bit_depth = 8;2104#endif21052106if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)2107info_ptr->channels = 1;21082109else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)2110info_ptr->channels = 3;21112112else2113info_ptr->channels = 1;21142115#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED2116if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)2117{2118info_ptr->color_type = (png_byte)(info_ptr->color_type &2119~PNG_COLOR_MASK_ALPHA);2120info_ptr->num_trans = 0;2121}2122#endif21232124if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)2125info_ptr->channels++;21262127#ifdef PNG_READ_FILLER_SUPPORTED2128/* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */2129if ((png_ptr->transformations & PNG_FILLER) != 0 &&2130(info_ptr->color_type == PNG_COLOR_TYPE_RGB ||2131info_ptr->color_type == PNG_COLOR_TYPE_GRAY))2132{2133info_ptr->channels++;2134/* If adding a true alpha channel not just filler */2135if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)2136info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;2137}2138#endif21392140#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \2141defined(PNG_READ_USER_TRANSFORM_SUPPORTED)2142if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)2143{2144if (png_ptr->user_transform_depth != 0)2145info_ptr->bit_depth = png_ptr->user_transform_depth;21462147if (png_ptr->user_transform_channels != 0)2148info_ptr->channels = png_ptr->user_transform_channels;2149}2150#endif21512152info_ptr->pixel_depth = (png_byte)(info_ptr->channels *2153info_ptr->bit_depth);21542155info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);21562157/* Adding in 1.5.4: cache the above value in png_struct so that we can later2158* check in png_rowbytes that the user buffer won't get overwritten. Note2159* that the field is not always set - if png_read_update_info isn't called2160* the application has to either not do any transforms or get the calculation2161* right itself.2162*/2163png_ptr->info_rowbytes = info_ptr->rowbytes;21642165#ifndef PNG_READ_EXPAND_SUPPORTED2166if (png_ptr != NULL)2167return;2168#endif2169}21702171#ifdef PNG_READ_PACK_SUPPORTED2172/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,2173* without changing the actual values. Thus, if you had a row with2174* a bit depth of 1, you would end up with bytes that only contained2175* the numbers 0 or 1. If you would rather they contain 0 and 255, use2176* png_do_shift() after this.2177*/2178static void2179png_do_unpack(png_row_infop row_info, png_bytep row)2180{2181png_debug(1, "in png_do_unpack");21822183if (row_info->bit_depth < 8)2184{2185png_uint_32 i;2186png_uint_32 row_width=row_info->width;21872188switch (row_info->bit_depth)2189{2190case 1:2191{2192png_bytep sp = row + (size_t)((row_width - 1) >> 3);2193png_bytep dp = row + (size_t)row_width - 1;2194png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);2195for (i = 0; i < row_width; i++)2196{2197*dp = (png_byte)((*sp >> shift) & 0x01);21982199if (shift == 7)2200{2201shift = 0;2202sp--;2203}22042205else2206shift++;22072208dp--;2209}2210break;2211}22122213case 2:2214{22152216png_bytep sp = row + (size_t)((row_width - 1) >> 2);2217png_bytep dp = row + (size_t)row_width - 1;2218png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);2219for (i = 0; i < row_width; i++)2220{2221*dp = (png_byte)((*sp >> shift) & 0x03);22222223if (shift == 6)2224{2225shift = 0;2226sp--;2227}22282229else2230shift += 2;22312232dp--;2233}2234break;2235}22362237case 4:2238{2239png_bytep sp = row + (size_t)((row_width - 1) >> 1);2240png_bytep dp = row + (size_t)row_width - 1;2241png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);2242for (i = 0; i < row_width; i++)2243{2244*dp = (png_byte)((*sp >> shift) & 0x0f);22452246if (shift == 4)2247{2248shift = 0;2249sp--;2250}22512252else2253shift = 4;22542255dp--;2256}2257break;2258}22592260default:2261break;2262}2263row_info->bit_depth = 8;2264row_info->pixel_depth = (png_byte)(8 * row_info->channels);2265row_info->rowbytes = row_width * row_info->channels;2266}2267}2268#endif22692270#ifdef PNG_READ_SHIFT_SUPPORTED2271/* Reverse the effects of png_do_shift. This routine merely shifts the2272* pixels back to their significant bits values. Thus, if you have2273* a row of bit depth 8, but only 5 are significant, this will shift2274* the values back to 0 through 31.2275*/2276static void2277png_do_unshift(png_row_infop row_info, png_bytep row,2278png_const_color_8p sig_bits)2279{2280int color_type;22812282png_debug(1, "in png_do_unshift");22832284/* The palette case has already been handled in the _init routine. */2285color_type = row_info->color_type;22862287if (color_type != PNG_COLOR_TYPE_PALETTE)2288{2289int shift[4];2290int channels = 0;2291int bit_depth = row_info->bit_depth;22922293if ((color_type & PNG_COLOR_MASK_COLOR) != 0)2294{2295shift[channels++] = bit_depth - sig_bits->red;2296shift[channels++] = bit_depth - sig_bits->green;2297shift[channels++] = bit_depth - sig_bits->blue;2298}22992300else2301{2302shift[channels++] = bit_depth - sig_bits->gray;2303}23042305if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)2306{2307shift[channels++] = bit_depth - sig_bits->alpha;2308}23092310{2311int c, have_shift;23122313for (c = have_shift = 0; c < channels; ++c)2314{2315/* A shift of more than the bit depth is an error condition but it2316* gets ignored here.2317*/2318if (shift[c] <= 0 || shift[c] >= bit_depth)2319shift[c] = 0;23202321else2322have_shift = 1;2323}23242325if (have_shift == 0)2326return;2327}23282329switch (bit_depth)2330{2331default:2332/* Must be 1bpp gray: should not be here! */2333/* NOTREACHED */2334break;23352336case 2:2337/* Must be 2bpp gray */2338/* assert(channels == 1 && shift[0] == 1) */2339{2340png_bytep bp = row;2341png_bytep bp_end = bp + row_info->rowbytes;23422343while (bp < bp_end)2344{2345int b = (*bp >> 1) & 0x55;2346*bp++ = (png_byte)b;2347}2348break;2349}23502351case 4:2352/* Must be 4bpp gray */2353/* assert(channels == 1) */2354{2355png_bytep bp = row;2356png_bytep bp_end = bp + row_info->rowbytes;2357int gray_shift = shift[0];2358int mask = 0xf >> gray_shift;23592360mask |= mask << 4;23612362while (bp < bp_end)2363{2364int b = (*bp >> gray_shift) & mask;2365*bp++ = (png_byte)b;2366}2367break;2368}23692370case 8:2371/* Single byte components, G, GA, RGB, RGBA */2372{2373png_bytep bp = row;2374png_bytep bp_end = bp + row_info->rowbytes;2375int channel = 0;23762377while (bp < bp_end)2378{2379int b = *bp >> shift[channel];2380if (++channel >= channels)2381channel = 0;2382*bp++ = (png_byte)b;2383}2384break;2385}23862387#ifdef PNG_READ_16BIT_SUPPORTED2388case 16:2389/* Double byte components, G, GA, RGB, RGBA */2390{2391png_bytep bp = row;2392png_bytep bp_end = bp + row_info->rowbytes;2393int channel = 0;23942395while (bp < bp_end)2396{2397int value = (bp[0] << 8) + bp[1];23982399value >>= shift[channel];2400if (++channel >= channels)2401channel = 0;2402*bp++ = (png_byte)(value >> 8);2403*bp++ = (png_byte)value;2404}2405break;2406}2407#endif2408}2409}2410}2411#endif24122413#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED2414/* Scale rows of bit depth 16 down to 8 accurately */2415static void2416png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)2417{2418png_debug(1, "in png_do_scale_16_to_8");24192420if (row_info->bit_depth == 16)2421{2422png_bytep sp = row; /* source */2423png_bytep dp = row; /* destination */2424png_bytep ep = sp + row_info->rowbytes; /* end+1 */24252426while (sp < ep)2427{2428/* The input is an array of 16-bit components, these must be scaled to2429* 8 bits each. For a 16-bit value V the required value (from the PNG2430* specification) is:2431*2432* (V * 255) / 655352433*2434* This reduces to round(V / 257), or floor((V + 128.5)/257)2435*2436* Represent V as the two byte value vhi.vlo. Make a guess that the2437* result is the top byte of V, vhi, then the correction to this value2438* is:2439*2440* error = floor(((V-vhi.vhi) + 128.5) / 257)2441* = floor(((vlo-vhi) + 128.5) / 257)2442*2443* This can be approximated using integer arithmetic (and a signed2444* shift):2445*2446* error = (vlo-vhi+128) >> 8;2447*2448* The approximate differs from the exact answer only when (vlo-vhi) is2449* 128; it then gives a correction of +1 when the exact correction is2450* 0. This gives 128 errors. The exact answer (correct for all 16-bit2451* input values) is:2452*2453* error = (vlo-vhi+128)*65535 >> 24;2454*2455* An alternative arithmetic calculation which also gives no errors is:2456*2457* (V * 255 + 32895) >> 162458*/24592460png_int_32 tmp = *sp++; /* must be signed! */2461tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;2462*dp++ = (png_byte)tmp;2463}24642465row_info->bit_depth = 8;2466row_info->pixel_depth = (png_byte)(8 * row_info->channels);2467row_info->rowbytes = row_info->width * row_info->channels;2468}2469}2470#endif24712472#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED2473static void2474/* Simply discard the low byte. This was the default behavior prior2475* to libpng-1.5.4.2476*/2477png_do_chop(png_row_infop row_info, png_bytep row)2478{2479png_debug(1, "in png_do_chop");24802481if (row_info->bit_depth == 16)2482{2483png_bytep sp = row; /* source */2484png_bytep dp = row; /* destination */2485png_bytep ep = sp + row_info->rowbytes; /* end+1 */24862487while (sp < ep)2488{2489*dp++ = *sp;2490sp += 2; /* skip low byte */2491}24922493row_info->bit_depth = 8;2494row_info->pixel_depth = (png_byte)(8 * row_info->channels);2495row_info->rowbytes = row_info->width * row_info->channels;2496}2497}2498#endif24992500#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED2501static void2502png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)2503{2504png_uint_32 row_width = row_info->width;25052506png_debug(1, "in png_do_read_swap_alpha");25072508if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)2509{2510/* This converts from RGBA to ARGB */2511if (row_info->bit_depth == 8)2512{2513png_bytep sp = row + row_info->rowbytes;2514png_bytep dp = sp;2515png_byte save;2516png_uint_32 i;25172518for (i = 0; i < row_width; i++)2519{2520save = *(--sp);2521*(--dp) = *(--sp);2522*(--dp) = *(--sp);2523*(--dp) = *(--sp);2524*(--dp) = save;2525}2526}25272528#ifdef PNG_READ_16BIT_SUPPORTED2529/* This converts from RRGGBBAA to AARRGGBB */2530else2531{2532png_bytep sp = row + row_info->rowbytes;2533png_bytep dp = sp;2534png_byte save[2];2535png_uint_32 i;25362537for (i = 0; i < row_width; i++)2538{2539save[0] = *(--sp);2540save[1] = *(--sp);2541*(--dp) = *(--sp);2542*(--dp) = *(--sp);2543*(--dp) = *(--sp);2544*(--dp) = *(--sp);2545*(--dp) = *(--sp);2546*(--dp) = *(--sp);2547*(--dp) = save[0];2548*(--dp) = save[1];2549}2550}2551#endif2552}25532554else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)2555{2556/* This converts from GA to AG */2557if (row_info->bit_depth == 8)2558{2559png_bytep sp = row + row_info->rowbytes;2560png_bytep dp = sp;2561png_byte save;2562png_uint_32 i;25632564for (i = 0; i < row_width; i++)2565{2566save = *(--sp);2567*(--dp) = *(--sp);2568*(--dp) = save;2569}2570}25712572#ifdef PNG_READ_16BIT_SUPPORTED2573/* This converts from GGAA to AAGG */2574else2575{2576png_bytep sp = row + row_info->rowbytes;2577png_bytep dp = sp;2578png_byte save[2];2579png_uint_32 i;25802581for (i = 0; i < row_width; i++)2582{2583save[0] = *(--sp);2584save[1] = *(--sp);2585*(--dp) = *(--sp);2586*(--dp) = *(--sp);2587*(--dp) = save[0];2588*(--dp) = save[1];2589}2590}2591#endif2592}2593}2594#endif25952596#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED2597static void2598png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)2599{2600png_uint_32 row_width;2601png_debug(1, "in png_do_read_invert_alpha");26022603row_width = row_info->width;2604if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)2605{2606if (row_info->bit_depth == 8)2607{2608/* This inverts the alpha channel in RGBA */2609png_bytep sp = row + row_info->rowbytes;2610png_bytep dp = sp;2611png_uint_32 i;26122613for (i = 0; i < row_width; i++)2614{2615*(--dp) = (png_byte)(255 - *(--sp));26162617/* This does nothing:2618*(--dp) = *(--sp);2619*(--dp) = *(--sp);2620*(--dp) = *(--sp);2621We can replace it with:2622*/2623sp-=3;2624dp=sp;2625}2626}26272628#ifdef PNG_READ_16BIT_SUPPORTED2629/* This inverts the alpha channel in RRGGBBAA */2630else2631{2632png_bytep sp = row + row_info->rowbytes;2633png_bytep dp = sp;2634png_uint_32 i;26352636for (i = 0; i < row_width; i++)2637{2638*(--dp) = (png_byte)(255 - *(--sp));2639*(--dp) = (png_byte)(255 - *(--sp));26402641/* This does nothing:2642*(--dp) = *(--sp);2643*(--dp) = *(--sp);2644*(--dp) = *(--sp);2645*(--dp) = *(--sp);2646*(--dp) = *(--sp);2647*(--dp) = *(--sp);2648We can replace it with:2649*/2650sp-=6;2651dp=sp;2652}2653}2654#endif2655}2656else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)2657{2658if (row_info->bit_depth == 8)2659{2660/* This inverts the alpha channel in GA */2661png_bytep sp = row + row_info->rowbytes;2662png_bytep dp = sp;2663png_uint_32 i;26642665for (i = 0; i < row_width; i++)2666{2667*(--dp) = (png_byte)(255 - *(--sp));2668*(--dp) = *(--sp);2669}2670}26712672#ifdef PNG_READ_16BIT_SUPPORTED2673else2674{2675/* This inverts the alpha channel in GGAA */2676png_bytep sp = row + row_info->rowbytes;2677png_bytep dp = sp;2678png_uint_32 i;26792680for (i = 0; i < row_width; i++)2681{2682*(--dp) = (png_byte)(255 - *(--sp));2683*(--dp) = (png_byte)(255 - *(--sp));2684/*2685*(--dp) = *(--sp);2686*(--dp) = *(--sp);2687*/2688sp-=2;2689dp=sp;2690}2691}2692#endif2693}2694}2695#endif26962697#ifdef PNG_READ_FILLER_SUPPORTED2698/* Add filler channel if we have RGB color */2699static void2700png_do_read_filler(png_row_infop row_info, png_bytep row,2701png_uint_32 filler, png_uint_32 flags)2702{2703png_uint_32 i;2704png_uint_32 row_width = row_info->width;27052706#ifdef PNG_READ_16BIT_SUPPORTED2707png_byte hi_filler = (png_byte)(filler>>8);2708#endif2709png_byte lo_filler = (png_byte)filler;27102711png_debug(1, "in png_do_read_filler");27122713if (2714row_info->color_type == PNG_COLOR_TYPE_GRAY)2715{2716if (row_info->bit_depth == 8)2717{2718if ((flags & PNG_FLAG_FILLER_AFTER) != 0)2719{2720/* This changes the data from G to GX */2721png_bytep sp = row + (size_t)row_width;2722png_bytep dp = sp + (size_t)row_width;2723for (i = 1; i < row_width; i++)2724{2725*(--dp) = lo_filler;2726*(--dp) = *(--sp);2727}2728*(--dp) = lo_filler;2729row_info->channels = 2;2730row_info->pixel_depth = 16;2731row_info->rowbytes = row_width * 2;2732}27332734else2735{2736/* This changes the data from G to XG */2737png_bytep sp = row + (size_t)row_width;2738png_bytep dp = sp + (size_t)row_width;2739for (i = 0; i < row_width; i++)2740{2741*(--dp) = *(--sp);2742*(--dp) = lo_filler;2743}2744row_info->channels = 2;2745row_info->pixel_depth = 16;2746row_info->rowbytes = row_width * 2;2747}2748}27492750#ifdef PNG_READ_16BIT_SUPPORTED2751else if (row_info->bit_depth == 16)2752{2753if ((flags & PNG_FLAG_FILLER_AFTER) != 0)2754{2755/* This changes the data from GG to GGXX */2756png_bytep sp = row + (size_t)row_width * 2;2757png_bytep dp = sp + (size_t)row_width * 2;2758for (i = 1; i < row_width; i++)2759{2760*(--dp) = lo_filler;2761*(--dp) = hi_filler;2762*(--dp) = *(--sp);2763*(--dp) = *(--sp);2764}2765*(--dp) = lo_filler;2766*(--dp) = hi_filler;2767row_info->channels = 2;2768row_info->pixel_depth = 32;2769row_info->rowbytes = row_width * 4;2770}27712772else2773{2774/* This changes the data from GG to XXGG */2775png_bytep sp = row + (size_t)row_width * 2;2776png_bytep dp = sp + (size_t)row_width * 2;2777for (i = 0; i < row_width; i++)2778{2779*(--dp) = *(--sp);2780*(--dp) = *(--sp);2781*(--dp) = lo_filler;2782*(--dp) = hi_filler;2783}2784row_info->channels = 2;2785row_info->pixel_depth = 32;2786row_info->rowbytes = row_width * 4;2787}2788}2789#endif2790} /* COLOR_TYPE == GRAY */2791else if (row_info->color_type == PNG_COLOR_TYPE_RGB)2792{2793if (row_info->bit_depth == 8)2794{2795if ((flags & PNG_FLAG_FILLER_AFTER) != 0)2796{2797/* This changes the data from RGB to RGBX */2798png_bytep sp = row + (size_t)row_width * 3;2799png_bytep dp = sp + (size_t)row_width;2800for (i = 1; i < row_width; i++)2801{2802*(--dp) = lo_filler;2803*(--dp) = *(--sp);2804*(--dp) = *(--sp);2805*(--dp) = *(--sp);2806}2807*(--dp) = lo_filler;2808row_info->channels = 4;2809row_info->pixel_depth = 32;2810row_info->rowbytes = row_width * 4;2811}28122813else2814{2815/* This changes the data from RGB to XRGB */2816png_bytep sp = row + (size_t)row_width * 3;2817png_bytep dp = sp + (size_t)row_width;2818for (i = 0; i < row_width; i++)2819{2820*(--dp) = *(--sp);2821*(--dp) = *(--sp);2822*(--dp) = *(--sp);2823*(--dp) = lo_filler;2824}2825row_info->channels = 4;2826row_info->pixel_depth = 32;2827row_info->rowbytes = row_width * 4;2828}2829}28302831#ifdef PNG_READ_16BIT_SUPPORTED2832else if (row_info->bit_depth == 16)2833{2834if ((flags & PNG_FLAG_FILLER_AFTER) != 0)2835{2836/* This changes the data from RRGGBB to RRGGBBXX */2837png_bytep sp = row + (size_t)row_width * 6;2838png_bytep dp = sp + (size_t)row_width * 2;2839for (i = 1; i < row_width; i++)2840{2841*(--dp) = lo_filler;2842*(--dp) = hi_filler;2843*(--dp) = *(--sp);2844*(--dp) = *(--sp);2845*(--dp) = *(--sp);2846*(--dp) = *(--sp);2847*(--dp) = *(--sp);2848*(--dp) = *(--sp);2849}2850*(--dp) = lo_filler;2851*(--dp) = hi_filler;2852row_info->channels = 4;2853row_info->pixel_depth = 64;2854row_info->rowbytes = row_width * 8;2855}28562857else2858{2859/* This changes the data from RRGGBB to XXRRGGBB */2860png_bytep sp = row + (size_t)row_width * 6;2861png_bytep dp = sp + (size_t)row_width * 2;2862for (i = 0; i < row_width; i++)2863{2864*(--dp) = *(--sp);2865*(--dp) = *(--sp);2866*(--dp) = *(--sp);2867*(--dp) = *(--sp);2868*(--dp) = *(--sp);2869*(--dp) = *(--sp);2870*(--dp) = lo_filler;2871*(--dp) = hi_filler;2872}28732874row_info->channels = 4;2875row_info->pixel_depth = 64;2876row_info->rowbytes = row_width * 8;2877}2878}2879#endif2880} /* COLOR_TYPE == RGB */2881}2882#endif28832884#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED2885/* Expand grayscale files to RGB, with or without alpha */2886static void2887png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)2888{2889png_uint_32 i;2890png_uint_32 row_width = row_info->width;28912892png_debug(1, "in png_do_gray_to_rgb");28932894if (row_info->bit_depth >= 8 &&2895(row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)2896{2897if (row_info->color_type == PNG_COLOR_TYPE_GRAY)2898{2899if (row_info->bit_depth == 8)2900{2901/* This changes G to RGB */2902png_bytep sp = row + (size_t)row_width - 1;2903png_bytep dp = sp + (size_t)row_width * 2;2904for (i = 0; i < row_width; i++)2905{2906*(dp--) = *sp;2907*(dp--) = *sp;2908*(dp--) = *(sp--);2909}2910}29112912else2913{2914/* This changes GG to RRGGBB */2915png_bytep sp = row + (size_t)row_width * 2 - 1;2916png_bytep dp = sp + (size_t)row_width * 4;2917for (i = 0; i < row_width; i++)2918{2919*(dp--) = *sp;2920*(dp--) = *(sp - 1);2921*(dp--) = *sp;2922*(dp--) = *(sp - 1);2923*(dp--) = *(sp--);2924*(dp--) = *(sp--);2925}2926}2927}29282929else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)2930{2931if (row_info->bit_depth == 8)2932{2933/* This changes GA to RGBA */2934png_bytep sp = row + (size_t)row_width * 2 - 1;2935png_bytep dp = sp + (size_t)row_width * 2;2936for (i = 0; i < row_width; i++)2937{2938*(dp--) = *(sp--);2939*(dp--) = *sp;2940*(dp--) = *sp;2941*(dp--) = *(sp--);2942}2943}29442945else2946{2947/* This changes GGAA to RRGGBBAA */2948png_bytep sp = row + (size_t)row_width * 4 - 1;2949png_bytep dp = sp + (size_t)row_width * 4;2950for (i = 0; i < row_width; i++)2951{2952*(dp--) = *(sp--);2953*(dp--) = *(sp--);2954*(dp--) = *sp;2955*(dp--) = *(sp - 1);2956*(dp--) = *sp;2957*(dp--) = *(sp - 1);2958*(dp--) = *(sp--);2959*(dp--) = *(sp--);2960}2961}2962}2963row_info->channels = (png_byte)(row_info->channels + 2);2964row_info->color_type |= PNG_COLOR_MASK_COLOR;2965row_info->pixel_depth = (png_byte)(row_info->channels *2966row_info->bit_depth);2967row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);2968}2969}2970#endif29712972#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED2973/* Reduce RGB files to grayscale, with or without alpha2974* using the equation given in Poynton's ColorFAQ of 1998-01-04 at2975* <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but2976* versions dated 1998 through November 2002 have been archived at2977* https://web.archive.org/web/20000816232553/www.inforamp.net/2978* ~poynton/notes/colour_and_gamma/ColorFAQ.txt )2979* Charles Poynton poynton at poynton.com2980*2981* Y = 0.212671 * R + 0.715160 * G + 0.072169 * B2982*2983* which can be expressed with integers as2984*2985* Y = (6969 * R + 23434 * G + 2365 * B)/327682986*2987* Poynton's current link (as of January 2003 through July 2011):2988* <http://www.poynton.com/notes/colour_and_gamma/>2989* has changed the numbers slightly:2990*2991* Y = 0.2126*R + 0.7152*G + 0.0722*B2992*2993* which can be expressed with integers as2994*2995* Y = (6966 * R + 23436 * G + 2366 * B)/327682996*2997* Historically, however, libpng uses numbers derived from the ITU-R Rec 7092998* end point chromaticities and the D65 white point. Depending on the2999* precision used for the D65 white point this produces a variety of different3000* numbers, however if the four decimal place value used in ITU-R Rec 709 is3001* used (0.3127,0.3290) the Y calculation would be:3002*3003* Y = (6968 * R + 23435 * G + 2366 * B)/327683004*3005* While this is correct the rounding results in an overflow for white, because3006* the sum of the rounded coefficients is 32769, not 32768. Consequently3007* libpng uses, instead, the closest non-overflowing approximation:3008*3009* Y = (6968 * R + 23434 * G + 2366 * B)/327683010*3011* Starting with libpng-1.5.5, if the image being converted has a cHRM chunk3012* (including an sRGB chunk) then the chromaticities are used to calculate the3013* coefficients. See the chunk handling in pngrutil.c for more information.3014*3015* In all cases the calculation is to be done in a linear colorspace. If no3016* gamma information is available to correct the encoding of the original RGB3017* values this results in an implicit assumption that the original PNG RGB3018* values were linear.3019*3020* Other integer coefficients can be used via png_set_rgb_to_gray(). Because3021* the API takes just red and green coefficients the blue coefficient is3022* calculated to make the sum 32768. This will result in different rounding3023* to that used above.3024*/3025static int3026png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)3027{3028int rgb_error = 0;30293030png_debug(1, "in png_do_rgb_to_gray");30313032if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&3033(row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)3034{3035png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;3036png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;3037png_uint_32 bc = 32768 - rc - gc;3038png_uint_32 row_width = row_info->width;3039int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;30403041if (row_info->bit_depth == 8)3042{3043#ifdef PNG_READ_GAMMA_SUPPORTED3044/* Notice that gamma to/from 1 are not necessarily inverses (if3045* there is an overall gamma correction). Prior to 1.5.5 this code3046* checked the linearized values for equality; this doesn't match3047* the documentation, the original values must be checked.3048*/3049if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)3050{3051png_bytep sp = row;3052png_bytep dp = row;3053png_uint_32 i;30543055for (i = 0; i < row_width; i++)3056{3057png_byte red = *(sp++);3058png_byte green = *(sp++);3059png_byte blue = *(sp++);30603061if (red != green || red != blue)3062{3063red = png_ptr->gamma_to_1[red];3064green = png_ptr->gamma_to_1[green];3065blue = png_ptr->gamma_to_1[blue];30663067rgb_error |= 1;3068*(dp++) = png_ptr->gamma_from_1[3069(rc*red + gc*green + bc*blue + 16384)>>15];3070}30713072else3073{3074/* If there is no overall correction the table will not be3075* set.3076*/3077if (png_ptr->gamma_table != NULL)3078red = png_ptr->gamma_table[red];30793080*(dp++) = red;3081}30823083if (have_alpha != 0)3084*(dp++) = *(sp++);3085}3086}3087else3088#endif3089{3090png_bytep sp = row;3091png_bytep dp = row;3092png_uint_32 i;30933094for (i = 0; i < row_width; i++)3095{3096png_byte red = *(sp++);3097png_byte green = *(sp++);3098png_byte blue = *(sp++);30993100if (red != green || red != blue)3101{3102rgb_error |= 1;3103/* NOTE: this is the historical approach which simply3104* truncates the results.3105*/3106*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);3107}31083109else3110*(dp++) = red;31113112if (have_alpha != 0)3113*(dp++) = *(sp++);3114}3115}3116}31173118else /* RGB bit_depth == 16 */3119{3120#ifdef PNG_READ_GAMMA_SUPPORTED3121if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)3122{3123png_bytep sp = row;3124png_bytep dp = row;3125png_uint_32 i;31263127for (i = 0; i < row_width; i++)3128{3129png_uint_16 red, green, blue, w;3130png_byte hi,lo;31313132hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));3133hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));3134hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));31353136if (red == green && red == blue)3137{3138if (png_ptr->gamma_16_table != NULL)3139w = png_ptr->gamma_16_table[(red & 0xff)3140>> png_ptr->gamma_shift][red >> 8];31413142else3143w = red;3144}31453146else3147{3148png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red & 0xff)3149>> png_ptr->gamma_shift][red>>8];3150png_uint_16 green_1 =3151png_ptr->gamma_16_to_1[(green & 0xff) >>3152png_ptr->gamma_shift][green>>8];3153png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue & 0xff)3154>> png_ptr->gamma_shift][blue>>8];3155png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_13156+ bc*blue_1 + 16384)>>15);3157w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>3158png_ptr->gamma_shift][gray16 >> 8];3159rgb_error |= 1;3160}31613162*(dp++) = (png_byte)((w>>8) & 0xff);3163*(dp++) = (png_byte)(w & 0xff);31643165if (have_alpha != 0)3166{3167*(dp++) = *(sp++);3168*(dp++) = *(sp++);3169}3170}3171}3172else3173#endif3174{3175png_bytep sp = row;3176png_bytep dp = row;3177png_uint_32 i;31783179for (i = 0; i < row_width; i++)3180{3181png_uint_16 red, green, blue, gray16;3182png_byte hi,lo;31833184hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));3185hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));3186hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));31873188if (red != green || red != blue)3189rgb_error |= 1;31903191/* From 1.5.5 in the 16-bit case do the accurate conversion even3192* in the 'fast' case - this is because this is where the code3193* ends up when handling linear 16-bit data.3194*/3195gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>319615);3197*(dp++) = (png_byte)((gray16 >> 8) & 0xff);3198*(dp++) = (png_byte)(gray16 & 0xff);31993200if (have_alpha != 0)3201{3202*(dp++) = *(sp++);3203*(dp++) = *(sp++);3204}3205}3206}3207}32083209row_info->channels = (png_byte)(row_info->channels - 2);3210row_info->color_type = (png_byte)(row_info->color_type &3211~PNG_COLOR_MASK_COLOR);3212row_info->pixel_depth = (png_byte)(row_info->channels *3213row_info->bit_depth);3214row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);3215}3216return rgb_error;3217}3218#endif32193220#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\3221defined(PNG_READ_ALPHA_MODE_SUPPORTED)3222/* Replace any alpha or transparency with the supplied background color.3223* "background" is already in the screen gamma, while "background_1" is3224* at a gamma of 1.0. Paletted files have already been taken care of.3225*/3226static void3227png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)3228{3229#ifdef PNG_READ_GAMMA_SUPPORTED3230png_const_bytep gamma_table = png_ptr->gamma_table;3231png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;3232png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;3233png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;3234png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;3235png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;3236int gamma_shift = png_ptr->gamma_shift;3237int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;3238#endif32393240png_bytep sp;3241png_uint_32 i;3242png_uint_32 row_width = row_info->width;3243int shift;32443245png_debug(1, "in png_do_compose");32463247switch (row_info->color_type)3248{3249case PNG_COLOR_TYPE_GRAY:3250{3251switch (row_info->bit_depth)3252{3253case 1:3254{3255sp = row;3256shift = 7;3257for (i = 0; i < row_width; i++)3258{3259if ((png_uint_16)((*sp >> shift) & 0x01)3260== png_ptr->trans_color.gray)3261{3262unsigned int tmp = *sp & (0x7f7f >> (7 - shift));3263tmp |=3264(unsigned int)(png_ptr->background.gray << shift);3265*sp = (png_byte)(tmp & 0xff);3266}32673268if (shift == 0)3269{3270shift = 7;3271sp++;3272}32733274else3275shift--;3276}3277break;3278}32793280case 2:3281{3282#ifdef PNG_READ_GAMMA_SUPPORTED3283if (gamma_table != NULL)3284{3285sp = row;3286shift = 6;3287for (i = 0; i < row_width; i++)3288{3289if ((png_uint_16)((*sp >> shift) & 0x03)3290== png_ptr->trans_color.gray)3291{3292unsigned int tmp = *sp & (0x3f3f >> (6 - shift));3293tmp |=3294(unsigned int)png_ptr->background.gray << shift;3295*sp = (png_byte)(tmp & 0xff);3296}32973298else3299{3300unsigned int p = (*sp >> shift) & 0x03;3301unsigned int g = (gamma_table [p | (p << 2) |3302(p << 4) | (p << 6)] >> 6) & 0x03;3303unsigned int tmp = *sp & (0x3f3f >> (6 - shift));3304tmp |= (unsigned int)(g << shift);3305*sp = (png_byte)(tmp & 0xff);3306}33073308if (shift == 0)3309{3310shift = 6;3311sp++;3312}33133314else3315shift -= 2;3316}3317}33183319else3320#endif3321{3322sp = row;3323shift = 6;3324for (i = 0; i < row_width; i++)3325{3326if ((png_uint_16)((*sp >> shift) & 0x03)3327== png_ptr->trans_color.gray)3328{3329unsigned int tmp = *sp & (0x3f3f >> (6 - shift));3330tmp |=3331(unsigned int)png_ptr->background.gray << shift;3332*sp = (png_byte)(tmp & 0xff);3333}33343335if (shift == 0)3336{3337shift = 6;3338sp++;3339}33403341else3342shift -= 2;3343}3344}3345break;3346}33473348case 4:3349{3350#ifdef PNG_READ_GAMMA_SUPPORTED3351if (gamma_table != NULL)3352{3353sp = row;3354shift = 4;3355for (i = 0; i < row_width; i++)3356{3357if ((png_uint_16)((*sp >> shift) & 0x0f)3358== png_ptr->trans_color.gray)3359{3360unsigned int tmp = *sp & (0x0f0f >> (4 - shift));3361tmp |=3362(unsigned int)(png_ptr->background.gray << shift);3363*sp = (png_byte)(tmp & 0xff);3364}33653366else3367{3368unsigned int p = (*sp >> shift) & 0x0f;3369unsigned int g = (gamma_table[p | (p << 4)] >> 4) &33700x0f;3371unsigned int tmp = *sp & (0x0f0f >> (4 - shift));3372tmp |= (unsigned int)(g << shift);3373*sp = (png_byte)(tmp & 0xff);3374}33753376if (shift == 0)3377{3378shift = 4;3379sp++;3380}33813382else3383shift -= 4;3384}3385}33863387else3388#endif3389{3390sp = row;3391shift = 4;3392for (i = 0; i < row_width; i++)3393{3394if ((png_uint_16)((*sp >> shift) & 0x0f)3395== png_ptr->trans_color.gray)3396{3397unsigned int tmp = *sp & (0x0f0f >> (4 - shift));3398tmp |=3399(unsigned int)(png_ptr->background.gray << shift);3400*sp = (png_byte)(tmp & 0xff);3401}34023403if (shift == 0)3404{3405shift = 4;3406sp++;3407}34083409else3410shift -= 4;3411}3412}3413break;3414}34153416case 8:3417{3418#ifdef PNG_READ_GAMMA_SUPPORTED3419if (gamma_table != NULL)3420{3421sp = row;3422for (i = 0; i < row_width; i++, sp++)3423{3424if (*sp == png_ptr->trans_color.gray)3425*sp = (png_byte)png_ptr->background.gray;34263427else3428*sp = gamma_table[*sp];3429}3430}3431else3432#endif3433{3434sp = row;3435for (i = 0; i < row_width; i++, sp++)3436{3437if (*sp == png_ptr->trans_color.gray)3438*sp = (png_byte)png_ptr->background.gray;3439}3440}3441break;3442}34433444case 16:3445{3446#ifdef PNG_READ_GAMMA_SUPPORTED3447if (gamma_16 != NULL)3448{3449sp = row;3450for (i = 0; i < row_width; i++, sp += 2)3451{3452png_uint_16 v;34533454v = (png_uint_16)(((*sp) << 8) + *(sp + 1));34553456if (v == png_ptr->trans_color.gray)3457{3458/* Background is already in screen gamma */3459*sp = (png_byte)((png_ptr->background.gray >> 8)3460& 0xff);3461*(sp + 1) = (png_byte)(png_ptr->background.gray3462& 0xff);3463}34643465else3466{3467v = gamma_16[*(sp + 1) >> gamma_shift][*sp];3468*sp = (png_byte)((v >> 8) & 0xff);3469*(sp + 1) = (png_byte)(v & 0xff);3470}3471}3472}3473else3474#endif3475{3476sp = row;3477for (i = 0; i < row_width; i++, sp += 2)3478{3479png_uint_16 v;34803481v = (png_uint_16)(((*sp) << 8) + *(sp + 1));34823483if (v == png_ptr->trans_color.gray)3484{3485*sp = (png_byte)((png_ptr->background.gray >> 8)3486& 0xff);3487*(sp + 1) = (png_byte)(png_ptr->background.gray3488& 0xff);3489}3490}3491}3492break;3493}34943495default:3496break;3497}3498break;3499}35003501case PNG_COLOR_TYPE_RGB:3502{3503if (row_info->bit_depth == 8)3504{3505#ifdef PNG_READ_GAMMA_SUPPORTED3506if (gamma_table != NULL)3507{3508sp = row;3509for (i = 0; i < row_width; i++, sp += 3)3510{3511if (*sp == png_ptr->trans_color.red &&3512*(sp + 1) == png_ptr->trans_color.green &&3513*(sp + 2) == png_ptr->trans_color.blue)3514{3515*sp = (png_byte)png_ptr->background.red;3516*(sp + 1) = (png_byte)png_ptr->background.green;3517*(sp + 2) = (png_byte)png_ptr->background.blue;3518}35193520else3521{3522*sp = gamma_table[*sp];3523*(sp + 1) = gamma_table[*(sp + 1)];3524*(sp + 2) = gamma_table[*(sp + 2)];3525}3526}3527}3528else3529#endif3530{3531sp = row;3532for (i = 0; i < row_width; i++, sp += 3)3533{3534if (*sp == png_ptr->trans_color.red &&3535*(sp + 1) == png_ptr->trans_color.green &&3536*(sp + 2) == png_ptr->trans_color.blue)3537{3538*sp = (png_byte)png_ptr->background.red;3539*(sp + 1) = (png_byte)png_ptr->background.green;3540*(sp + 2) = (png_byte)png_ptr->background.blue;3541}3542}3543}3544}3545else /* if (row_info->bit_depth == 16) */3546{3547#ifdef PNG_READ_GAMMA_SUPPORTED3548if (gamma_16 != NULL)3549{3550sp = row;3551for (i = 0; i < row_width; i++, sp += 6)3552{3553png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));35543555png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)3556+ *(sp + 3));35573558png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)3559+ *(sp + 5));35603561if (r == png_ptr->trans_color.red &&3562g == png_ptr->trans_color.green &&3563b == png_ptr->trans_color.blue)3564{3565/* Background is already in screen gamma */3566*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);3567*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);3568*(sp + 2) = (png_byte)((png_ptr->background.green >> 8)3569& 0xff);3570*(sp + 3) = (png_byte)(png_ptr->background.green3571& 0xff);3572*(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)3573& 0xff);3574*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);3575}35763577else3578{3579png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];3580*sp = (png_byte)((v >> 8) & 0xff);3581*(sp + 1) = (png_byte)(v & 0xff);35823583v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];3584*(sp + 2) = (png_byte)((v >> 8) & 0xff);3585*(sp + 3) = (png_byte)(v & 0xff);35863587v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];3588*(sp + 4) = (png_byte)((v >> 8) & 0xff);3589*(sp + 5) = (png_byte)(v & 0xff);3590}3591}3592}35933594else3595#endif3596{3597sp = row;3598for (i = 0; i < row_width; i++, sp += 6)3599{3600png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));36013602png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)3603+ *(sp + 3));36043605png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)3606+ *(sp + 5));36073608if (r == png_ptr->trans_color.red &&3609g == png_ptr->trans_color.green &&3610b == png_ptr->trans_color.blue)3611{3612*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);3613*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);3614*(sp + 2) = (png_byte)((png_ptr->background.green >> 8)3615& 0xff);3616*(sp + 3) = (png_byte)(png_ptr->background.green3617& 0xff);3618*(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)3619& 0xff);3620*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);3621}3622}3623}3624}3625break;3626}36273628case PNG_COLOR_TYPE_GRAY_ALPHA:3629{3630if (row_info->bit_depth == 8)3631{3632#ifdef PNG_READ_GAMMA_SUPPORTED3633if (gamma_to_1 != NULL && gamma_from_1 != NULL &&3634gamma_table != NULL)3635{3636sp = row;3637for (i = 0; i < row_width; i++, sp += 2)3638{3639png_uint_16 a = *(sp + 1);36403641if (a == 0xff)3642*sp = gamma_table[*sp];36433644else if (a == 0)3645{3646/* Background is already in screen gamma */3647*sp = (png_byte)png_ptr->background.gray;3648}36493650else3651{3652png_byte v, w;36533654v = gamma_to_1[*sp];3655png_composite(w, v, a, png_ptr->background_1.gray);3656if (optimize == 0)3657w = gamma_from_1[w];3658*sp = w;3659}3660}3661}3662else3663#endif3664{3665sp = row;3666for (i = 0; i < row_width; i++, sp += 2)3667{3668png_byte a = *(sp + 1);36693670if (a == 0)3671*sp = (png_byte)png_ptr->background.gray;36723673else if (a < 0xff)3674png_composite(*sp, *sp, a, png_ptr->background.gray);3675}3676}3677}3678else /* if (png_ptr->bit_depth == 16) */3679{3680#ifdef PNG_READ_GAMMA_SUPPORTED3681if (gamma_16 != NULL && gamma_16_from_1 != NULL &&3682gamma_16_to_1 != NULL)3683{3684sp = row;3685for (i = 0; i < row_width; i++, sp += 4)3686{3687png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)3688+ *(sp + 3));36893690if (a == (png_uint_16)0xffff)3691{3692png_uint_16 v;36933694v = gamma_16[*(sp + 1) >> gamma_shift][*sp];3695*sp = (png_byte)((v >> 8) & 0xff);3696*(sp + 1) = (png_byte)(v & 0xff);3697}36983699else if (a == 0)3700{3701/* Background is already in screen gamma */3702*sp = (png_byte)((png_ptr->background.gray >> 8)3703& 0xff);3704*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);3705}37063707else3708{3709png_uint_16 g, v, w;37103711g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];3712png_composite_16(v, g, a, png_ptr->background_1.gray);3713if (optimize != 0)3714w = v;3715else3716w = gamma_16_from_1[(v & 0xff) >>3717gamma_shift][v >> 8];3718*sp = (png_byte)((w >> 8) & 0xff);3719*(sp + 1) = (png_byte)(w & 0xff);3720}3721}3722}3723else3724#endif3725{3726sp = row;3727for (i = 0; i < row_width; i++, sp += 4)3728{3729png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)3730+ *(sp + 3));37313732if (a == 0)3733{3734*sp = (png_byte)((png_ptr->background.gray >> 8)3735& 0xff);3736*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);3737}37383739else if (a < 0xffff)3740{3741png_uint_16 g, v;37423743g = (png_uint_16)(((*sp) << 8) + *(sp + 1));3744png_composite_16(v, g, a, png_ptr->background.gray);3745*sp = (png_byte)((v >> 8) & 0xff);3746*(sp + 1) = (png_byte)(v & 0xff);3747}3748}3749}3750}3751break;3752}37533754case PNG_COLOR_TYPE_RGB_ALPHA:3755{3756if (row_info->bit_depth == 8)3757{3758#ifdef PNG_READ_GAMMA_SUPPORTED3759if (gamma_to_1 != NULL && gamma_from_1 != NULL &&3760gamma_table != NULL)3761{3762sp = row;3763for (i = 0; i < row_width; i++, sp += 4)3764{3765png_byte a = *(sp + 3);37663767if (a == 0xff)3768{3769*sp = gamma_table[*sp];3770*(sp + 1) = gamma_table[*(sp + 1)];3771*(sp + 2) = gamma_table[*(sp + 2)];3772}37733774else if (a == 0)3775{3776/* Background is already in screen gamma */3777*sp = (png_byte)png_ptr->background.red;3778*(sp + 1) = (png_byte)png_ptr->background.green;3779*(sp + 2) = (png_byte)png_ptr->background.blue;3780}37813782else3783{3784png_byte v, w;37853786v = gamma_to_1[*sp];3787png_composite(w, v, a, png_ptr->background_1.red);3788if (optimize == 0) w = gamma_from_1[w];3789*sp = w;37903791v = gamma_to_1[*(sp + 1)];3792png_composite(w, v, a, png_ptr->background_1.green);3793if (optimize == 0) w = gamma_from_1[w];3794*(sp + 1) = w;37953796v = gamma_to_1[*(sp + 2)];3797png_composite(w, v, a, png_ptr->background_1.blue);3798if (optimize == 0) w = gamma_from_1[w];3799*(sp + 2) = w;3800}3801}3802}3803else3804#endif3805{3806sp = row;3807for (i = 0; i < row_width; i++, sp += 4)3808{3809png_byte a = *(sp + 3);38103811if (a == 0)3812{3813*sp = (png_byte)png_ptr->background.red;3814*(sp + 1) = (png_byte)png_ptr->background.green;3815*(sp + 2) = (png_byte)png_ptr->background.blue;3816}38173818else if (a < 0xff)3819{3820png_composite(*sp, *sp, a, png_ptr->background.red);38213822png_composite(*(sp + 1), *(sp + 1), a,3823png_ptr->background.green);38243825png_composite(*(sp + 2), *(sp + 2), a,3826png_ptr->background.blue);3827}3828}3829}3830}3831else /* if (row_info->bit_depth == 16) */3832{3833#ifdef PNG_READ_GAMMA_SUPPORTED3834if (gamma_16 != NULL && gamma_16_from_1 != NULL &&3835gamma_16_to_1 != NULL)3836{3837sp = row;3838for (i = 0; i < row_width; i++, sp += 8)3839{3840png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))3841<< 8) + (png_uint_16)(*(sp + 7)));38423843if (a == (png_uint_16)0xffff)3844{3845png_uint_16 v;38463847v = gamma_16[*(sp + 1) >> gamma_shift][*sp];3848*sp = (png_byte)((v >> 8) & 0xff);3849*(sp + 1) = (png_byte)(v & 0xff);38503851v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];3852*(sp + 2) = (png_byte)((v >> 8) & 0xff);3853*(sp + 3) = (png_byte)(v & 0xff);38543855v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];3856*(sp + 4) = (png_byte)((v >> 8) & 0xff);3857*(sp + 5) = (png_byte)(v & 0xff);3858}38593860else if (a == 0)3861{3862/* Background is already in screen gamma */3863*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);3864*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);3865*(sp + 2) = (png_byte)((png_ptr->background.green >> 8)3866& 0xff);3867*(sp + 3) = (png_byte)(png_ptr->background.green3868& 0xff);3869*(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)3870& 0xff);3871*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);3872}38733874else3875{3876png_uint_16 v, w;38773878v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];3879png_composite_16(w, v, a, png_ptr->background_1.red);3880if (optimize == 0)3881w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>38828];3883*sp = (png_byte)((w >> 8) & 0xff);3884*(sp + 1) = (png_byte)(w & 0xff);38853886v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];3887png_composite_16(w, v, a, png_ptr->background_1.green);3888if (optimize == 0)3889w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>38908];38913892*(sp + 2) = (png_byte)((w >> 8) & 0xff);3893*(sp + 3) = (png_byte)(w & 0xff);38943895v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];3896png_composite_16(w, v, a, png_ptr->background_1.blue);3897if (optimize == 0)3898w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>38998];39003901*(sp + 4) = (png_byte)((w >> 8) & 0xff);3902*(sp + 5) = (png_byte)(w & 0xff);3903}3904}3905}39063907else3908#endif3909{3910sp = row;3911for (i = 0; i < row_width; i++, sp += 8)3912{3913png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))3914<< 8) + (png_uint_16)(*(sp + 7)));39153916if (a == 0)3917{3918*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);3919*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);3920*(sp + 2) = (png_byte)((png_ptr->background.green >> 8)3921& 0xff);3922*(sp + 3) = (png_byte)(png_ptr->background.green3923& 0xff);3924*(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)3925& 0xff);3926*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);3927}39283929else if (a < 0xffff)3930{3931png_uint_16 v;39323933png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));3934png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)3935+ *(sp + 3));3936png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)3937+ *(sp + 5));39383939png_composite_16(v, r, a, png_ptr->background.red);3940*sp = (png_byte)((v >> 8) & 0xff);3941*(sp + 1) = (png_byte)(v & 0xff);39423943png_composite_16(v, g, a, png_ptr->background.green);3944*(sp + 2) = (png_byte)((v >> 8) & 0xff);3945*(sp + 3) = (png_byte)(v & 0xff);39463947png_composite_16(v, b, a, png_ptr->background.blue);3948*(sp + 4) = (png_byte)((v >> 8) & 0xff);3949*(sp + 5) = (png_byte)(v & 0xff);3950}3951}3952}3953}3954break;3955}39563957default:3958break;3959}3960}3961#endif /* READ_BACKGROUND || READ_ALPHA_MODE */39623963#ifdef PNG_READ_GAMMA_SUPPORTED3964/* Gamma correct the image, avoiding the alpha channel. Make sure3965* you do this after you deal with the transparency issue on grayscale3966* or RGB images. If your bit depth is 8, use gamma_table, if it3967* is 16, use gamma_16_table and gamma_shift. Build these with3968* build_gamma_table().3969*/3970static void3971png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)3972{3973png_const_bytep gamma_table = png_ptr->gamma_table;3974png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;3975int gamma_shift = png_ptr->gamma_shift;39763977png_bytep sp;3978png_uint_32 i;3979png_uint_32 row_width=row_info->width;39803981png_debug(1, "in png_do_gamma");39823983if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||3984(row_info->bit_depth == 16 && gamma_16_table != NULL)))3985{3986switch (row_info->color_type)3987{3988case PNG_COLOR_TYPE_RGB:3989{3990if (row_info->bit_depth == 8)3991{3992sp = row;3993for (i = 0; i < row_width; i++)3994{3995*sp = gamma_table[*sp];3996sp++;3997*sp = gamma_table[*sp];3998sp++;3999*sp = gamma_table[*sp];4000sp++;4001}4002}40034004else /* if (row_info->bit_depth == 16) */4005{4006sp = row;4007for (i = 0; i < row_width; i++)4008{4009png_uint_16 v;40104011v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4012*sp = (png_byte)((v >> 8) & 0xff);4013*(sp + 1) = (png_byte)(v & 0xff);4014sp += 2;40154016v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4017*sp = (png_byte)((v >> 8) & 0xff);4018*(sp + 1) = (png_byte)(v & 0xff);4019sp += 2;40204021v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4022*sp = (png_byte)((v >> 8) & 0xff);4023*(sp + 1) = (png_byte)(v & 0xff);4024sp += 2;4025}4026}4027break;4028}40294030case PNG_COLOR_TYPE_RGB_ALPHA:4031{4032if (row_info->bit_depth == 8)4033{4034sp = row;4035for (i = 0; i < row_width; i++)4036{4037*sp = gamma_table[*sp];4038sp++;40394040*sp = gamma_table[*sp];4041sp++;40424043*sp = gamma_table[*sp];4044sp++;40454046sp++;4047}4048}40494050else /* if (row_info->bit_depth == 16) */4051{4052sp = row;4053for (i = 0; i < row_width; i++)4054{4055png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4056*sp = (png_byte)((v >> 8) & 0xff);4057*(sp + 1) = (png_byte)(v & 0xff);4058sp += 2;40594060v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4061*sp = (png_byte)((v >> 8) & 0xff);4062*(sp + 1) = (png_byte)(v & 0xff);4063sp += 2;40644065v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4066*sp = (png_byte)((v >> 8) & 0xff);4067*(sp + 1) = (png_byte)(v & 0xff);4068sp += 4;4069}4070}4071break;4072}40734074case PNG_COLOR_TYPE_GRAY_ALPHA:4075{4076if (row_info->bit_depth == 8)4077{4078sp = row;4079for (i = 0; i < row_width; i++)4080{4081*sp = gamma_table[*sp];4082sp += 2;4083}4084}40854086else /* if (row_info->bit_depth == 16) */4087{4088sp = row;4089for (i = 0; i < row_width; i++)4090{4091png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4092*sp = (png_byte)((v >> 8) & 0xff);4093*(sp + 1) = (png_byte)(v & 0xff);4094sp += 4;4095}4096}4097break;4098}40994100case PNG_COLOR_TYPE_GRAY:4101{4102if (row_info->bit_depth == 2)4103{4104sp = row;4105for (i = 0; i < row_width; i += 4)4106{4107int a = *sp & 0xc0;4108int b = *sp & 0x30;4109int c = *sp & 0x0c;4110int d = *sp & 0x03;41114112*sp = (png_byte)(4113((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|4114((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|4115((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|4116((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));4117sp++;4118}4119}41204121if (row_info->bit_depth == 4)4122{4123sp = row;4124for (i = 0; i < row_width; i += 2)4125{4126int msb = *sp & 0xf0;4127int lsb = *sp & 0x0f;41284129*sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)4130| (((int)gamma_table[(lsb << 4) | lsb]) >> 4));4131sp++;4132}4133}41344135else if (row_info->bit_depth == 8)4136{4137sp = row;4138for (i = 0; i < row_width; i++)4139{4140*sp = gamma_table[*sp];4141sp++;4142}4143}41444145else if (row_info->bit_depth == 16)4146{4147sp = row;4148for (i = 0; i < row_width; i++)4149{4150png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];4151*sp = (png_byte)((v >> 8) & 0xff);4152*(sp + 1) = (png_byte)(v & 0xff);4153sp += 2;4154}4155}4156break;4157}41584159default:4160break;4161}4162}4163}4164#endif41654166#ifdef PNG_READ_ALPHA_MODE_SUPPORTED4167/* Encode the alpha channel to the output gamma (the input channel is always4168* linear.) Called only with color types that have an alpha channel. Needs the4169* from_1 tables.4170*/4171static void4172png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)4173{4174png_uint_32 row_width = row_info->width;41754176png_debug(1, "in png_do_encode_alpha");41774178if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)4179{4180if (row_info->bit_depth == 8)4181{4182png_bytep table = png_ptr->gamma_from_1;41834184if (table != NULL)4185{4186int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;41874188/* The alpha channel is the last component: */4189row += step - 1;41904191for (; row_width > 0; --row_width, row += step)4192*row = table[*row];41934194return;4195}4196}41974198else if (row_info->bit_depth == 16)4199{4200png_uint_16pp table = png_ptr->gamma_16_from_1;4201int gamma_shift = png_ptr->gamma_shift;42024203if (table != NULL)4204{4205int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;42064207/* The alpha channel is the last component: */4208row += step - 2;42094210for (; row_width > 0; --row_width, row += step)4211{4212png_uint_16 v;42134214v = table[*(row + 1) >> gamma_shift][*row];4215*row = (png_byte)((v >> 8) & 0xff);4216*(row + 1) = (png_byte)(v & 0xff);4217}42184219return;4220}4221}4222}42234224/* Only get to here if called with a weird row_info; no harm has been done,4225* so just issue a warning.4226*/4227png_warning(png_ptr, "png_do_encode_alpha: unexpected call");4228}4229#endif42304231#ifdef PNG_READ_EXPAND_SUPPORTED4232/* Expands a palette row to an RGB or RGBA row depending4233* upon whether you supply trans and num_trans.4234*/4235static void4236png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,4237png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,4238int num_trans)4239{4240int shift, value;4241png_bytep sp, dp;4242png_uint_32 i;4243png_uint_32 row_width=row_info->width;42444245png_debug(1, "in png_do_expand_palette");42464247if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)4248{4249if (row_info->bit_depth < 8)4250{4251switch (row_info->bit_depth)4252{4253case 1:4254{4255sp = row + (size_t)((row_width - 1) >> 3);4256dp = row + (size_t)row_width - 1;4257shift = 7 - (int)((row_width + 7) & 0x07);4258for (i = 0; i < row_width; i++)4259{4260if ((*sp >> shift) & 0x01)4261*dp = 1;42624263else4264*dp = 0;42654266if (shift == 7)4267{4268shift = 0;4269sp--;4270}42714272else4273shift++;42744275dp--;4276}4277break;4278}42794280case 2:4281{4282sp = row + (size_t)((row_width - 1) >> 2);4283dp = row + (size_t)row_width - 1;4284shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);4285for (i = 0; i < row_width; i++)4286{4287value = (*sp >> shift) & 0x03;4288*dp = (png_byte)value;4289if (shift == 6)4290{4291shift = 0;4292sp--;4293}42944295else4296shift += 2;42974298dp--;4299}4300break;4301}43024303case 4:4304{4305sp = row + (size_t)((row_width - 1) >> 1);4306dp = row + (size_t)row_width - 1;4307shift = (int)((row_width & 0x01) << 2);4308for (i = 0; i < row_width; i++)4309{4310value = (*sp >> shift) & 0x0f;4311*dp = (png_byte)value;4312if (shift == 4)4313{4314shift = 0;4315sp--;4316}43174318else4319shift += 4;43204321dp--;4322}4323break;4324}43254326default:4327break;4328}4329row_info->bit_depth = 8;4330row_info->pixel_depth = 8;4331row_info->rowbytes = row_width;4332}43334334if (row_info->bit_depth == 8)4335{4336{4337if (num_trans > 0)4338{4339sp = row + (size_t)row_width - 1;4340dp = row + ((size_t)row_width << 2) - 1;43414342i = 0;4343#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE4344if (png_ptr->riffled_palette != NULL)4345{4346/* The RGBA optimization works with png_ptr->bit_depth == 84347* but sometimes row_info->bit_depth has been changed to 8.4348* In these cases, the palette hasn't been riffled.4349*/4350i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,4351&sp, &dp);4352}4353#else4354PNG_UNUSED(png_ptr)4355#endif43564357for (; i < row_width; i++)4358{4359if ((int)(*sp) >= num_trans)4360*dp-- = 0xff;4361else4362*dp-- = trans_alpha[*sp];4363*dp-- = palette[*sp].blue;4364*dp-- = palette[*sp].green;4365*dp-- = palette[*sp].red;4366sp--;4367}4368row_info->bit_depth = 8;4369row_info->pixel_depth = 32;4370row_info->rowbytes = row_width * 4;4371row_info->color_type = 6;4372row_info->channels = 4;4373}43744375else4376{4377sp = row + (size_t)row_width - 1;4378dp = row + (size_t)(row_width * 3) - 1;4379i = 0;4380#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE4381i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,4382&sp, &dp);4383#else4384PNG_UNUSED(png_ptr)4385#endif43864387for (; i < row_width; i++)4388{4389*dp-- = palette[*sp].blue;4390*dp-- = palette[*sp].green;4391*dp-- = palette[*sp].red;4392sp--;4393}43944395row_info->bit_depth = 8;4396row_info->pixel_depth = 24;4397row_info->rowbytes = row_width * 3;4398row_info->color_type = 2;4399row_info->channels = 3;4400}4401}4402}4403}4404}44054406/* If the bit depth < 8, it is expanded to 8. Also, if the already4407* expanded transparency value is supplied, an alpha channel is built.4408*/4409static void4410png_do_expand(png_row_infop row_info, png_bytep row,4411png_const_color_16p trans_color)4412{4413int shift, value;4414png_bytep sp, dp;4415png_uint_32 i;4416png_uint_32 row_width=row_info->width;44174418png_debug(1, "in png_do_expand");44194420if (row_info->color_type == PNG_COLOR_TYPE_GRAY)4421{4422unsigned int gray = trans_color != NULL ? trans_color->gray : 0;44234424if (row_info->bit_depth < 8)4425{4426switch (row_info->bit_depth)4427{4428case 1:4429{4430gray = (gray & 0x01) * 0xff;4431sp = row + (size_t)((row_width - 1) >> 3);4432dp = row + (size_t)row_width - 1;4433shift = 7 - (int)((row_width + 7) & 0x07);4434for (i = 0; i < row_width; i++)4435{4436if ((*sp >> shift) & 0x01)4437*dp = 0xff;44384439else4440*dp = 0;44414442if (shift == 7)4443{4444shift = 0;4445sp--;4446}44474448else4449shift++;44504451dp--;4452}4453break;4454}44554456case 2:4457{4458gray = (gray & 0x03) * 0x55;4459sp = row + (size_t)((row_width - 1) >> 2);4460dp = row + (size_t)row_width - 1;4461shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);4462for (i = 0; i < row_width; i++)4463{4464value = (*sp >> shift) & 0x03;4465*dp = (png_byte)(value | (value << 2) | (value << 4) |4466(value << 6));4467if (shift == 6)4468{4469shift = 0;4470sp--;4471}44724473else4474shift += 2;44754476dp--;4477}4478break;4479}44804481case 4:4482{4483gray = (gray & 0x0f) * 0x11;4484sp = row + (size_t)((row_width - 1) >> 1);4485dp = row + (size_t)row_width - 1;4486shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);4487for (i = 0; i < row_width; i++)4488{4489value = (*sp >> shift) & 0x0f;4490*dp = (png_byte)(value | (value << 4));4491if (shift == 4)4492{4493shift = 0;4494sp--;4495}44964497else4498shift = 4;44994500dp--;4501}4502break;4503}45044505default:4506break;4507}45084509row_info->bit_depth = 8;4510row_info->pixel_depth = 8;4511row_info->rowbytes = row_width;4512}45134514if (trans_color != NULL)4515{4516if (row_info->bit_depth == 8)4517{4518gray = gray & 0xff;4519sp = row + (size_t)row_width - 1;4520dp = row + ((size_t)row_width << 1) - 1;45214522for (i = 0; i < row_width; i++)4523{4524if ((*sp & 0xffU) == gray)4525*dp-- = 0;45264527else4528*dp-- = 0xff;45294530*dp-- = *sp--;4531}4532}45334534else if (row_info->bit_depth == 16)4535{4536unsigned int gray_high = (gray >> 8) & 0xff;4537unsigned int gray_low = gray & 0xff;4538sp = row + row_info->rowbytes - 1;4539dp = row + (row_info->rowbytes << 1) - 1;4540for (i = 0; i < row_width; i++)4541{4542if ((*(sp - 1) & 0xffU) == gray_high &&4543(*(sp) & 0xffU) == gray_low)4544{4545*dp-- = 0;4546*dp-- = 0;4547}45484549else4550{4551*dp-- = 0xff;4552*dp-- = 0xff;4553}45544555*dp-- = *sp--;4556*dp-- = *sp--;4557}4558}45594560row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;4561row_info->channels = 2;4562row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);4563row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,4564row_width);4565}4566}4567else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&4568trans_color != NULL)4569{4570if (row_info->bit_depth == 8)4571{4572png_byte red = (png_byte)(trans_color->red & 0xff);4573png_byte green = (png_byte)(trans_color->green & 0xff);4574png_byte blue = (png_byte)(trans_color->blue & 0xff);4575sp = row + (size_t)row_info->rowbytes - 1;4576dp = row + ((size_t)row_width << 2) - 1;4577for (i = 0; i < row_width; i++)4578{4579if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)4580*dp-- = 0;45814582else4583*dp-- = 0xff;45844585*dp-- = *sp--;4586*dp-- = *sp--;4587*dp-- = *sp--;4588}4589}4590else if (row_info->bit_depth == 16)4591{4592png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);4593png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);4594png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);4595png_byte red_low = (png_byte)(trans_color->red & 0xff);4596png_byte green_low = (png_byte)(trans_color->green & 0xff);4597png_byte blue_low = (png_byte)(trans_color->blue & 0xff);4598sp = row + row_info->rowbytes - 1;4599dp = row + ((size_t)row_width << 3) - 1;4600for (i = 0; i < row_width; i++)4601{4602if (*(sp - 5) == red_high &&4603*(sp - 4) == red_low &&4604*(sp - 3) == green_high &&4605*(sp - 2) == green_low &&4606*(sp - 1) == blue_high &&4607*(sp ) == blue_low)4608{4609*dp-- = 0;4610*dp-- = 0;4611}46124613else4614{4615*dp-- = 0xff;4616*dp-- = 0xff;4617}46184619*dp-- = *sp--;4620*dp-- = *sp--;4621*dp-- = *sp--;4622*dp-- = *sp--;4623*dp-- = *sp--;4624*dp-- = *sp--;4625}4626}4627row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;4628row_info->channels = 4;4629row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);4630row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);4631}4632}4633#endif46344635#ifdef PNG_READ_EXPAND_16_SUPPORTED4636/* If the bit depth is 8 and the color type is not a palette type expand the4637* whole row to 16 bits. Has no effect otherwise.4638*/4639static void4640png_do_expand_16(png_row_infop row_info, png_bytep row)4641{4642if (row_info->bit_depth == 8 &&4643row_info->color_type != PNG_COLOR_TYPE_PALETTE)4644{4645/* The row have a sequence of bytes containing [0..255] and we need4646* to turn it into another row containing [0..65535], to do this we4647* calculate:4648*4649* (input / 255) * 655354650*4651* Which happens to be exactly input * 257 and this can be achieved4652* simply by byte replication in place (copying backwards).4653*/4654png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */4655png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */4656while (dp > sp)4657{4658dp[-2] = dp[-1] = *--sp; dp -= 2;4659}46604661row_info->rowbytes *= 2;4662row_info->bit_depth = 16;4663row_info->pixel_depth = (png_byte)(row_info->channels * 16);4664}4665}4666#endif46674668#ifdef PNG_READ_QUANTIZE_SUPPORTED4669static void4670png_do_quantize(png_row_infop row_info, png_bytep row,4671png_const_bytep palette_lookup, png_const_bytep quantize_lookup)4672{4673png_bytep sp, dp;4674png_uint_32 i;4675png_uint_32 row_width=row_info->width;46764677png_debug(1, "in png_do_quantize");46784679if (row_info->bit_depth == 8)4680{4681if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)4682{4683int r, g, b, p;4684sp = row;4685dp = row;4686for (i = 0; i < row_width; i++)4687{4688r = *sp++;4689g = *sp++;4690b = *sp++;46914692/* This looks real messy, but the compiler will reduce4693* it down to a reasonable formula. For example, with4694* 5 bits per color, we get:4695* p = (((r >> 3) & 0x1f) << 10) |4696* (((g >> 3) & 0x1f) << 5) |4697* ((b >> 3) & 0x1f);4698*/4699p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &4700((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<4701(PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |4702(((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &4703((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<4704(PNG_QUANTIZE_BLUE_BITS)) |4705((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &4706((1 << PNG_QUANTIZE_BLUE_BITS) - 1));47074708*dp++ = palette_lookup[p];4709}47104711row_info->color_type = PNG_COLOR_TYPE_PALETTE;4712row_info->channels = 1;4713row_info->pixel_depth = row_info->bit_depth;4714row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);4715}47164717else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&4718palette_lookup != NULL)4719{4720int r, g, b, p;4721sp = row;4722dp = row;4723for (i = 0; i < row_width; i++)4724{4725r = *sp++;4726g = *sp++;4727b = *sp++;4728sp++;47294730p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &4731((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<4732(PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |4733(((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &4734((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<4735(PNG_QUANTIZE_BLUE_BITS)) |4736((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &4737((1 << PNG_QUANTIZE_BLUE_BITS) - 1));47384739*dp++ = palette_lookup[p];4740}47414742row_info->color_type = PNG_COLOR_TYPE_PALETTE;4743row_info->channels = 1;4744row_info->pixel_depth = row_info->bit_depth;4745row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);4746}47474748else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&4749quantize_lookup)4750{4751sp = row;47524753for (i = 0; i < row_width; i++, sp++)4754{4755*sp = quantize_lookup[*sp];4756}4757}4758}4759}4760#endif /* READ_QUANTIZE */47614762/* Transform the row. The order of transformations is significant,4763* and is very touchy. If you add a transformation, take care to4764* decide how it fits in with the other transformations here.4765*/4766void /* PRIVATE */4767png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)4768{4769png_debug(1, "in png_do_read_transformations");47704771if (png_ptr->row_buf == NULL)4772{4773/* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this4774* error is incredibly rare and incredibly easy to debug without this4775* information.4776*/4777png_error(png_ptr, "NULL row buffer");4778}47794780/* The following is debugging; prior to 1.5.4 the code was never compiled in;4781* in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro4782* PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for4783* all transformations, however in practice the ROW_INIT always gets done on4784* demand, if necessary.4785*/4786if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&4787(png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)4788{4789/* Application has failed to call either png_read_start_image() or4790* png_read_update_info() after setting transforms that expand pixels.4791* This check added to libpng-1.2.19 (but not enabled until 1.5.4).4792*/4793png_error(png_ptr, "Uninitialized row");4794}47954796#ifdef PNG_READ_EXPAND_SUPPORTED4797if ((png_ptr->transformations & PNG_EXPAND) != 0)4798{4799if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)4800{4801#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE4802if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))4803{4804if (png_ptr->riffled_palette == NULL)4805{4806/* Initialize the accelerated palette expansion. */4807png_ptr->riffled_palette =4808(png_bytep)png_malloc(png_ptr, 256 * 4);4809png_riffle_palette_neon(png_ptr);4810}4811}4812#endif4813png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,4814png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);4815}48164817else4818{4819if (png_ptr->num_trans != 0 &&4820(png_ptr->transformations & PNG_EXPAND_tRNS) != 0)4821png_do_expand(row_info, png_ptr->row_buf + 1,4822&(png_ptr->trans_color));48234824else4825png_do_expand(row_info, png_ptr->row_buf + 1, NULL);4826}4827}4828#endif48294830#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED4831if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&4832(png_ptr->transformations & PNG_COMPOSE) == 0 &&4833(row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||4834row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))4835png_do_strip_channel(row_info, png_ptr->row_buf + 1,48360 /* at_start == false, because SWAP_ALPHA happens later */);4837#endif48384839#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED4840if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)4841{4842int rgb_error =4843png_do_rgb_to_gray(png_ptr, row_info,4844png_ptr->row_buf + 1);48454846if (rgb_error != 0)4847{4848png_ptr->rgb_to_gray_status=1;4849if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==4850PNG_RGB_TO_GRAY_WARN)4851png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");48524853if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==4854PNG_RGB_TO_GRAY_ERR)4855png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");4856}4857}4858#endif48594860/* From Andreas Dilger e-mail to png-implement, 26 March 1998:4861*4862* In most cases, the "simple transparency" should be done prior to doing4863* gray-to-RGB, or you will have to test 3x as many bytes to check if a4864* pixel is transparent. You would also need to make sure that the4865* transparency information is upgraded to RGB.4866*4867* To summarize, the current flow is:4868* - Gray + simple transparency -> compare 1 or 2 gray bytes and composite4869* with background "in place" if transparent,4870* convert to RGB if necessary4871* - Gray + alpha -> composite with gray background and remove alpha bytes,4872* convert to RGB if necessary4873*4874* To support RGB backgrounds for gray images we need:4875* - Gray + simple transparency -> convert to RGB + simple transparency,4876* compare 3 or 6 bytes and composite with4877* background "in place" if transparent4878* (3x compare/pixel compared to doing4879* composite with gray bkgrnd)4880* - Gray + alpha -> convert to RGB + alpha, composite with background and4881* remove alpha bytes (3x float4882* operations/pixel compared with composite4883* on gray background)4884*4885* Greg's change will do this. The reason it wasn't done before is for4886* performance, as this increases the per-pixel operations. If we would check4887* in advance if the background was gray or RGB, and position the gray-to-RGB4888* transform appropriately, then it would save a lot of work/time.4889*/48904891#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED4892/* If gray -> RGB, do so now only if background is non-gray; else do later4893* for performance reasons4894*/4895if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&4896(png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)4897png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);4898#endif48994900#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\4901defined(PNG_READ_ALPHA_MODE_SUPPORTED)4902if ((png_ptr->transformations & PNG_COMPOSE) != 0)4903png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);4904#endif49054906#ifdef PNG_READ_GAMMA_SUPPORTED4907if ((png_ptr->transformations & PNG_GAMMA) != 0 &&4908#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED4909/* Because RGB_TO_GRAY does the gamma transform. */4910(png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&4911#endif4912#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\4913defined(PNG_READ_ALPHA_MODE_SUPPORTED)4914/* Because PNG_COMPOSE does the gamma transform if there is something to4915* do (if there is an alpha channel or transparency.)4916*/4917!((png_ptr->transformations & PNG_COMPOSE) != 0 &&4918((png_ptr->num_trans != 0) ||4919(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&4920#endif4921/* Because png_init_read_transformations transforms the palette, unless4922* RGB_TO_GRAY will do the transform.4923*/4924(png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))4925png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);4926#endif49274928#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED4929if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&4930(png_ptr->transformations & PNG_COMPOSE) != 0 &&4931(row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||4932row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))4933png_do_strip_channel(row_info, png_ptr->row_buf + 1,49340 /* at_start == false, because SWAP_ALPHA happens later */);4935#endif49364937#ifdef PNG_READ_ALPHA_MODE_SUPPORTED4938if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&4939(row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)4940png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);4941#endif49424943#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED4944if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)4945png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);4946#endif49474948#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED4949/* There is no harm in doing both of these because only one has any effect,4950* by putting the 'scale' option first if the app asks for scale (either by4951* calling the API or in a TRANSFORM flag) this is what happens.4952*/4953if ((png_ptr->transformations & PNG_16_TO_8) != 0)4954png_do_chop(row_info, png_ptr->row_buf + 1);4955#endif49564957#ifdef PNG_READ_QUANTIZE_SUPPORTED4958if ((png_ptr->transformations & PNG_QUANTIZE) != 0)4959{4960png_do_quantize(row_info, png_ptr->row_buf + 1,4961png_ptr->palette_lookup, png_ptr->quantize_index);49624963if (row_info->rowbytes == 0)4964png_error(png_ptr, "png_do_quantize returned rowbytes=0");4965}4966#endif /* READ_QUANTIZE */49674968#ifdef PNG_READ_EXPAND_16_SUPPORTED4969/* Do the expansion now, after all the arithmetic has been done. Notice4970* that previous transformations can handle the PNG_EXPAND_16 flag if this4971* is efficient (particularly true in the case of gamma correction, where4972* better accuracy results faster!)4973*/4974if ((png_ptr->transformations & PNG_EXPAND_16) != 0)4975png_do_expand_16(row_info, png_ptr->row_buf + 1);4976#endif49774978#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED4979/* NOTE: moved here in 1.5.4 (from much later in this list.) */4980if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&4981(png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)4982png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);4983#endif49844985#ifdef PNG_READ_INVERT_SUPPORTED4986if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)4987png_do_invert(row_info, png_ptr->row_buf + 1);4988#endif49894990#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED4991if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)4992png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);4993#endif49944995#ifdef PNG_READ_SHIFT_SUPPORTED4996if ((png_ptr->transformations & PNG_SHIFT) != 0)4997png_do_unshift(row_info, png_ptr->row_buf + 1,4998&(png_ptr->shift));4999#endif50005001#ifdef PNG_READ_PACK_SUPPORTED5002if ((png_ptr->transformations & PNG_PACK) != 0)5003png_do_unpack(row_info, png_ptr->row_buf + 1);5004#endif50055006#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED5007/* Added at libpng-1.5.10 */5008if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&5009png_ptr->num_palette_max >= 0)5010png_do_check_palette_indexes(png_ptr, row_info);5011#endif50125013#ifdef PNG_READ_BGR_SUPPORTED5014if ((png_ptr->transformations & PNG_BGR) != 0)5015png_do_bgr(row_info, png_ptr->row_buf + 1);5016#endif50175018#ifdef PNG_READ_PACKSWAP_SUPPORTED5019if ((png_ptr->transformations & PNG_PACKSWAP) != 0)5020png_do_packswap(row_info, png_ptr->row_buf + 1);5021#endif50225023#ifdef PNG_READ_FILLER_SUPPORTED5024if ((png_ptr->transformations & PNG_FILLER) != 0)5025png_do_read_filler(row_info, png_ptr->row_buf + 1,5026(png_uint_32)png_ptr->filler, png_ptr->flags);5027#endif50285029#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED5030if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)5031png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);5032#endif50335034#ifdef PNG_READ_16BIT_SUPPORTED5035#ifdef PNG_READ_SWAP_SUPPORTED5036if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)5037png_do_swap(row_info, png_ptr->row_buf + 1);5038#endif5039#endif50405041#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED5042if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)5043{5044if (png_ptr->read_user_transform_fn != NULL)5045(*(png_ptr->read_user_transform_fn)) /* User read transform function */5046(png_ptr, /* png_ptr */5047row_info, /* row_info: */5048/* png_uint_32 width; width of row */5049/* size_t rowbytes; number of bytes in row */5050/* png_byte color_type; color type of pixels */5051/* png_byte bit_depth; bit depth of samples */5052/* png_byte channels; number of channels (1-4) */5053/* png_byte pixel_depth; bits per pixel (depth*channels) */5054png_ptr->row_buf + 1); /* start of pixel data for row */5055#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED5056if (png_ptr->user_transform_depth != 0)5057row_info->bit_depth = png_ptr->user_transform_depth;50585059if (png_ptr->user_transform_channels != 0)5060row_info->channels = png_ptr->user_transform_channels;5061#endif5062row_info->pixel_depth = (png_byte)(row_info->bit_depth *5063row_info->channels);50645065row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);5066}5067#endif5068}50695070#endif /* READ_TRANSFORMS */5071#endif /* READ */507250735074