pngrtran.c revision f9a51917495bc8ba8b60632219652a7b122c1190
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* pngrtran.c - transforms the data in a row for PNG readers
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * libpng version 1.2.8 - December 3, 2004
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * For conditions of distribution and use, see copyright notice in png.h
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Copyright (c) 1998-2004 Glenn Randers-Pehrson
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * This file contains functions optionally called by an application
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * in order to tell libpng how to handle data when reading a PNG.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Transformations that are used in both reading and writing are
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Set the action on getting a CRC error for an ancillary or critical chunk. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Tell libpng how we react to CRC errors in critical chunks */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_warning(png_ptr, "Can't discard critical data on CRC error.");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* handle alpha and tRNS via a background color */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_color_16p background_color, int background_gamma_code,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_warning(png_ptr, "Application must supply a known background gamma");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_memcpy(&(png_ptr->background), background_color,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background_gamma = (float)background_gamma;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (in which case need_expand is superfluous anyway), the background color
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * might actually be gray yet not be flagged as such. This is not a problem
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * decide when to do the png_do_gray_to_rgb() transformation.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (!need_expand && background_color->red == background_color->green &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* strip 16 bit depth files to 8 bit depth */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Dither file to 8 bit. Supply a palette, the current number
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * of elements in the palette, the maximum number of elements
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * allowed, and a histogram if possible. If the current number
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * of colors is greater then the maximum number, the palette will be
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * modified to fit in the maximum number. "full_dither" indicates
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * whether we need a dithering cube set up for RGB images, or if we
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * simply are reducing the number of colors in a paletted image.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_set_dither(png_structp png_ptr, png_colorp palette,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int num_palette, int maximum_colors, png_uint_16p histogram,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_32)(num_palette * png_sizeof (png_byte)));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This is easy enough, just throw out the least used colors.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Perhaps not the best solution, but good enough. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* initialize an array to sort colors */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_32)(num_palette * png_sizeof (png_byte)));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* initialize the dither_sort array */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Find the least used palette entries by starting a
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bubble sort, and running it until we have sorted
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync out enough colors. Note that we don't care about
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync sorting all the colors, just finding which are
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync least used. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = num_palette - 1; i >= maximum_colors; i--)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int done; /* to stop early if the list is pre-sorted */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (j = 0; j < i; j++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* swap the palette around, and set up a table, if necessary */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* put all the useful colors within the max, but don't
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync move the others */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < maximum_colors; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((int)png_ptr->dither_sort[i] >= maximum_colors)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync while ((int)png_ptr->dither_sort[j] >= maximum_colors);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* move all the used colors inside the max limit, and
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync develop a translation table */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < maximum_colors; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* only move the colors we need to */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((int)png_ptr->dither_sort[i] >= maximum_colors)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync while ((int)png_ptr->dither_sort[j] >= maximum_colors);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* indicate where the color went */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* find closest color for those colors we are not using */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((int)png_ptr->dither_index[i] >= maximum_colors)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* find the closest color to one we threw out */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* point to closest color */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This is much harder to do simply (and quickly). Perhaps
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync we need to go through a median cut routine, but those
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync don't always behave themselves with only a few colors
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync as input. So we will just find the closest two colors,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync and throw out one of them (chosen somewhat randomly).
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync [We don't understand this at all, so if someone wants to
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync work on improving it, be our guest - AED, GRP]
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* initialize palette index arrays */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_32)(num_palette * png_sizeof (png_byte)));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_32)(num_palette * png_sizeof (png_byte)));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* initialize the sort array */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < 769; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* initial wild guess at how far apart the farthest pixel
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pair we will be eliminating will be. Larger
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync numbers mean more areas will be allocated, Smaller
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync numbers run the risk of not saving enough data, and
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync having to do this all over again.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync I have not done extensive checking on this number.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i <= max_d; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (k = 0; k < num_palette; k++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->index_to_palette[png_ptr->palette_to_index
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < 769; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_size_t num_entries = ((png_size_t)1 << total_bits);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_32)(num_entries * png_sizeof (png_byte)));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_memset(png_ptr->palette_lookup, 0, num_entries *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* int dr = abs(ir - r); */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* int dg = abs(ig - g); */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* int db = abs(ib - b); */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Transform the image from the file_gamma to the screen_gamma. We
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * only do transformations on images where the file_gamma and screen_gamma
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * are not close reciprocals, otherwise it slows things down slightly, and
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * also needlessly introduces small errors.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * We will turn off gamma transformation later if no semitransparent entries
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * are present in the tRNS array for palette images. We can't do it here
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * because we don't necessarily have the tRNS chunk yet.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Expand paletted images to RGB, expand grayscale images of
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * to alpha channels.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* GRR 19990627: the following three functions currently are identical
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * to png_set_expand(). However, it is entirely reasonable that someone
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * might wish to expand an indexed image to RGB but *not* expand a single,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * fully transparent palette entry to a full alpha channel--perhaps instead
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * the transparent color with a particular RGB value, or drop tRNS entirely.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * IOW, a future version of the library may make the transformations flag
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * a bit more fine-grained, with separate bits for each of these three
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * functions.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * More to the point, these functions make it obvious what libpng will be
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * doing, whereas "expand" can (and does) mean any number of things.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Expand paletted images to RGB. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Expand grayscale images of less than 8-bit depth to 8 bits. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Expand tRNS chunks to alpha channels. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Convert a RGB image to a grayscale of the same width. This allows us,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int green_fixed = (int)((float)green*100000.0 + 0.5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_debug(1, "in png_set_read_user_transform_fn\n");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->read_user_transform_fn = read_user_transform_fn;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync "This version of libpng does not support user transforms");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Initialize everything needed for the read. This includes modifying
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * the palette.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_debug(1, "in png_init_read_transformations\n");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* expand background chunk. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background.red = png_ptr->background.green
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync = png_ptr->background.blue = png_ptr->background.gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background.red = png_ptr->background.green
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync = png_ptr->background.blue = png_ptr->background.gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background.red = png_ptr->background.green
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync = png_ptr->background.blue = png_ptr->background.gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background.red = png_ptr->background.green
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync = png_ptr->background.blue = png_ptr->background.gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* invert the alpha channel (in tRNS) unless the pixels are
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync going to be expanded, in which case leave it for later */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i=0; i<istop; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (k == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* could skip if no transparency and
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back.red = png_ptr->gamma_table[png_ptr->background.red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back.green = png_ptr->gamma_table[png_ptr->background.green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back.blue = png_ptr->gamma_table[png_ptr->background.blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.red/255, gs) * 255.0 + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.green/255, gs) * 255.0 + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.red/255, g) * 255.0 + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.green/255, g) * 255.0 + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.blue/255, g) * 255.0 + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (png_ptr->trans[i] != 0xff) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(w, v, png_ptr->trans[i], back_1.red);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(w, v, png_ptr->trans[i], back_1.green);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(w, v, png_ptr->trans[i], back_1.blue);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].red = png_ptr->gamma_table[palette[i].red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].green = png_ptr->gamma_table[palette[i].green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].blue = png_ptr->gamma_table[palette[i].blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* color_type != PNG_COLOR_TYPE_PALETTE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync double g = 1.0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.gray / m, g) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.gray / m, gs) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((png_ptr->background.red != png_ptr->background.green) ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_ptr->background.red != png_ptr->background.blue) ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_ptr->background.red != png_ptr->background.gray))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* RGB or RGBA with color background */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.green / m, g) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.blue / m, g) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.red / m, gs) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.green / m, gs) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (double)png_ptr->background.blue / m, gs) * m + .5);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background_1.red = png_ptr->background_1.green
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync = png_ptr->background_1.blue = png_ptr->background_1.gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->background.red = png_ptr->background.green
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync = png_ptr->background.blue = png_ptr->background.gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* transformation does not include PNG_BACKGROUND */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_READ_BACKGROUND_SUPPORTED */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].red = png_ptr->gamma_table[palette[i].red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].green = png_ptr->gamma_table[palette[i].green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].blue = png_ptr->gamma_table[palette[i].blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* No GAMMA transformation */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < istop; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* The png_composite() macro is defined in png.h */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_READ_BACKGROUND_SUPPORTED */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < istop; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_READ_SHIFT_SUPPORTED */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Modify the info structure to reflect the transformations. The
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * info should be updated so a PNG file could be written with it,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * assuming the transformations result in valid PNG data.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_read_transform_info(png_structp png_ptr, png_infop info_ptr)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->palette_lookup && info_ptr->bit_depth == 8)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* if adding a true alpha channel not just filler */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if(info_ptr->bit_depth < png_ptr->user_transform_depth)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync info_ptr->bit_depth = png_ptr->user_transform_depth;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if(info_ptr->channels < png_ptr->user_transform_channels)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync info_ptr->channels = png_ptr->user_transform_channels;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Transform the row. The order of transformations is significant,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * and is very touchy. If you add a transformation, take care to
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * decide how it fits in with the other transformations here.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncFrom Andreas Dilger e-mail to png-implement, 26 March 1998:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync In most cases, the "simple transparency" should be done prior to doing
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync gray-to-RGB, or you will have to test 3x as many bytes to check if a
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pixel is transparent. You would also need to make sure that the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync transparency information is upgraded to RGB.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync To summarize, the current flow is:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync with background "in place" if transparent,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync convert to RGB if necessary
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync - Gray + alpha -> composite with gray background and remove alpha bytes,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync convert to RGB if necessary
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync To support RGB backgrounds for gray images we need:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync - Gray + simple transparency -> convert to RGB + simple transparency, compare
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync 3 or 6 bytes and composite with background
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync "in place" if transparent (3x compare/pixel
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync compared to doing composite with gray bkgrnd)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync - Gray + alpha -> convert to RGB + alpha, composite with background and
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync remove alpha bytes (3x float operations/pixel
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync compared with composite on gray background)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Greg's change will do this. The reason it wasn't done before is for
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync performance, as this increases the per-pixel operations. If we would check
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync in advance if the background was gray or RGB, and position the gray-to-RGB
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync transform appropriately, then it would save a lot of work/time.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* if gray -> RGB, do so now only if background is non-gray; else do later
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * for performance reasons */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_error(png_ptr, "png_do_dither returned rowbytes=0");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* if gray -> RGB, do so now only if we did not do so above */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (*(png_ptr->read_user_transform_fn)) /* user read transform function */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* png_uint_32 width; width of row */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* png_uint_32 rowbytes; number of bytes in row */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* png_byte color_type; color type of pixels */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* png_byte bit_depth; bit depth of samples */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* png_byte channels; number of channels (1-4) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* png_byte pixel_depth; bits per pixel (depth*channels) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->row_buf + 1); /* start of pixel data for row */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->row_info.channels = png_ptr->user_transform_channels;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * without changing the actual values. Thus, if you had a row with
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * a bit depth of 1, you would end up with bytes that only contained
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * the numbers 0 or 1. If you would rather they contain 0 and 255, use
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * png_do_shift() after this.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_unpack(png_row_infop row_info, png_bytep row)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(8 * row_info->channels);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = row_width * row_info->channels;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Reverse the effects of png_do_shift. This routine merely shifts the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * pixels back to their significant bits values. Thus, if you have
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * a row of bit depth 8, but only 5 are significant, this will shift
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * the values back to 0 through 31.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row != NULL && row_info != NULL && sig_bits != NULL &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift[channels++] = row_info->bit_depth - sig_bits->red;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift[channels++] = row_info->bit_depth - sig_bits->green;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift[channels++] = row_info->bit_depth - sig_bits->blue;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift[channels++] = row_info->bit_depth - sig_bits->gray;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift[channels++] = row_info->bit_depth - sig_bits->alpha;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (c = 0; c < channels; c++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (shift[c] <= 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < istop; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < istop; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < istop; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* chop rows of bit depth 16 down to 8 */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_32 istop = row_info->width * row_info->channels;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This does a more accurate scaling of the 16-bit color
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * value, rather than a simple low-byte truncation.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * What the ideal calculation should be:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * *dp = (((((png_uint_32)(*sp) << 8) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * GRR: no, I think this is what it really should be:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * *dp = (((((png_uint_32)(*sp) << 8) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * GRR: here's the exact calculation with shifts:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * *dp = (temp - (temp >> 8)) >> 8;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Approximate calculation with shift/add instead of multiply/divide:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * *dp = ((((png_uint_32)(*sp) << 8) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * What we actually do to avoid extra shifting and conversion:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Simply discard the low order byte */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(8 * row_info->channels);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = row_info->width * row_info->channels;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This converts from RGBA to ARGB */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This converts from RRGGBBAA to AARRGGBB */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This converts from GA to AG */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This converts from GGAA to AAGG */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This inverts the alpha channel in RGBA */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* This does nothing:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync We can replace it with:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This inverts the alpha channel in RRGGBBAA */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* This does nothing:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync We can replace it with:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This inverts the alpha channel in GA */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This inverts the alpha channel in GGAA */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(--dp) = *(--sp);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Add filler channel if we have RGB color */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_read_filler(png_row_infop row_info, png_bytep row,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from G to GX */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from G to XG */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from GG to GGXX */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from GG to XXGG */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync } /* COLOR_TYPE == GRAY */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from RGB to RGBX */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from RGB to XRGB */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from RRGGBB to RRGGBBXX */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This changes the data from RRGGBB to XXRRGGBB */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync } /* COLOR_TYPE == RGB */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* expand grayscale files to RGB, with or without alpha */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep sp = row + (png_size_t)row_width * 2 - 1;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep sp = row + (png_size_t)row_width * 2 - 1;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep sp = row + (png_size_t)row_width * 4 - 1;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(row_info->channels *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* reduce RGB files to grayscale, with or without alpha
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * using the equation given in Poynton's ColorFAQ at
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * We approximate this with
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * which can be expressed with integers as
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Y = (6969 * R + 23434 * G + 2365 * B)/32768
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * The calculation is to be done in a linear colorspace.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Other integer coefficents can be used via png_set_rgb_to_gray().
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* RGB bit_depth == 16 */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* RGBA bit_depth == 16 */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(row_info->channels *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * large of png_color. This lets grayscale images be treated as
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * paletted. Most useful for gamma correction and simplification
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_build_grayscale_palette(int bit_depth, png_colorp palette)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_debug(1, "in png_do_build_grayscale_palette\n");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* This function is currently unused. Do we really need it? */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_correct_palette(png_structp png_ptr, png_colorp palette,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back.red = png_ptr->gamma_table[png_ptr->background.red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back.green = png_ptr->gamma_table[png_ptr->background.green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back.blue = png_ptr->gamma_table[png_ptr->background.blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_byte)(pow((double)png_ptr->background.red/255, g) *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_byte)(pow((double)png_ptr->background.green/255, g) *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_byte)(pow((double)png_ptr->background.blue/255, g) *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_byte)(pow((double)png_ptr->background.red/255, g) *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_byte)(pow((double)png_ptr->background.green/255, g) *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_byte)(pow((double)png_ptr->background.blue/255, g) *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(w, v, png_ptr->trans[i], back_1.red);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(w, v, png_ptr->trans[i], back_1.green);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(w, v, png_ptr->trans[i], back_1.blue);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].red = png_ptr->gamma_table[palette[i].red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].green = png_ptr->gamma_table[palette[i].green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].blue = png_ptr->gamma_table[palette[i].blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].red = png_ptr->gamma_table[palette[i].red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].green = png_ptr->gamma_table[palette[i].green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].blue = png_ptr->gamma_table[palette[i].blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].red = png_ptr->gamma_table[palette[i].red];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].green = png_ptr->gamma_table[palette[i].green];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].blue = png_ptr->gamma_table[palette[i].blue];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(palette[i].red, png_ptr->palette[i].red,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(palette[i].green, png_ptr->palette[i].green,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_composite(palette[i].blue, png_ptr->palette[i].blue,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* assume grayscale palette (what else could it be?) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num_palette; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].red = (png_byte)png_ptr->background.red;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].green = (png_byte)png_ptr->background.green;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette[i].blue = (png_byte)png_ptr->background.blue;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Replace any alpha or transparency with the supplied background color.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * "background" is already in the screen gamma, while "background_1" is
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * at a gamma of 1.0. Paletted files have already been taken care of.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_background(png_row_infop row_info, png_bytep row,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_color_16p trans_values, png_color_16p background
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_byte g = (png_byte)((gamma_table [p | (p << 2) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* background is already in screen gamma */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (row_info->bit_depth == 16) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (r == trans_values->red && g == trans_values->green &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* background is already in screen gamma */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (r == trans_values->red && g == trans_values->green &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (a == 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* background is already in screen gamma */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (a == 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (png_ptr->bit_depth == 16) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* background is already in screen gamma */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (a == 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* background is already in screen gamma */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (a == 0xff)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (row_info->bit_depth == 16) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* background is already in screen gamma */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (a == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(row_info->channels *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Gamma correct the image, avoiding the alpha channel. Make sure
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * you do this after you deal with the transparency issue on grayscale
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * or RGB images. If your bit depth is 8, use gamma_table, if it
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * is 16, use gamma_16_table and gamma_shift. Build these with
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * build_gamma_table().
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_bytep gamma_table, png_uint_16pp gamma_16_table,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (row_info->bit_depth == 16 && gamma_16_table != NULL)))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (row_info->bit_depth == 16) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (row_info->bit_depth == 16) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* if (row_info->bit_depth == 16) */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Expands a palette row to an RGB or RGBA row depending
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * upon whether you supply trans and num_trans.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_expand_palette(png_row_infop row_info, png_bytep row,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_colorp palette, png_bytep trans, int num_trans)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* If the bit depth < 8, it is expanded to 8. Also, if the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * transparency value is supplied, an alpha channel is built.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_expand(png_row_infop row_info, png_bytep row,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *dp = (png_byte)(value | (value << 2) | (value << 4) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_dither(png_row_infop row_info, png_bytep row,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int r, g, b, p;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* this looks real messy, but the compiler will reduce
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync it down to a reasonable formula. For example, with
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync 5 bits per color, we get:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync p = (((r >> 3) & 0x1f) << 10) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (((g >> 3) & 0x1f) << 5) |
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ((b >> 3) & 0x1f);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync palette_lookup != NULL && row_info->bit_depth == 8)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int r, g, b, p;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < row_width; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * tables, we don't make a full table if we are reducing to 8-bit in
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * the future. Note also how the gamma_16 tables are segmented so that
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * we don't need to allocate > 64K chunks for a full 16-bit table.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < 256; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < 256; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync g = png_ptr->gamma; /* probably doing rgb_to_gray */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < 256; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync g = 1.0 / g;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < 256; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (j = 0; j < 256; j++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (j = 0; j < 256; j++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync g = png_ptr->gamma; /* probably doing rgb_to_gray */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0; i < num; i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (j = 0; j < 256; j++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* To do: install integer version of png_build_gamma_table here */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* undoes intrapixel differencing */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid /* PRIVATE */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpng_do_read_intrapixel(png_row_infop row_info, png_bytep row)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* PNG_MNG_FEATURES_SUPPORTED */