15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* pngrtran.c - transforms the data in a row for PNG readers
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Last changed in libpng 1.2.45 [July 7, 2011]
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 1998-2011 Glenn Randers-Pehrson
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This code is released under the libpng license.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For conditions of distribution and use, see the disclaimer
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and license in png.h
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file contains functions optionally called by an application
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in order to tell libpng how to handle data when reading a PNG.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Transformations that are used in both reading and writing are
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in pngtrans.c.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_INTERNAL
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_NO_PEDANTIC_WARNINGS
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "png.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SUPPORTED
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Set the action on getting a CRC error for an ancillary or critical chunk. */
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_crc_action");
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Tell libpng how we react to CRC errors in critical chunks */
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (crit_action)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_WARN_USE:                               /* Warn/use data */
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           PNG_FLAG_CRC_CRITICAL_IGNORE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_warning(png_ptr,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Can't discard critical data on CRC error.");
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_DEFAULT:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Tell libpng how we react to CRC errors in ancillary chunks */
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (ancil_action)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_WARN_USE:                              /* Warn/use data */
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PNG_CRC_DEFAULT:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(PNG_FLOATING_POINT_SUPPORTED)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Handle alpha and tRNS via a background color */
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_background(png_structp png_ptr,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_color_16p background_color, int background_gamma_code,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int need_expand, double background_gamma)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_background");
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_warning(png_ptr, "Application must supply a known background gamma");
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= PNG_BACKGROUND;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_memcpy(&(png_ptr->background), background_color,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_sizeof(png_color_16));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->background_gamma = (float)background_gamma;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_16_TO_8_SUPPORTED
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Strip 16 bit depth files to 8 bit depth */
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_strip_16(png_structp png_ptr)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_strip_16");
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= PNG_16_TO_8;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_strip_alpha(png_structp png_ptr)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_strip_alpha");
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_DITHER_SUPPORTED
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Dither file to 8 bit.  Supply a palette, the current number
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of elements in the palette, the maximum number of elements
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * allowed, and a histogram if possible.  If the current number
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of colors is greater then the maximum number, the palette will be
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modified to fit in the maximum number.  "full_dither" indicates
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * whether we need a dithering cube set up for RGB images, or if we
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * simply are reducing the number of colors in a paletted image.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct png_dsort_struct
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct png_dsort_struct FAR * next;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_byte left;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_byte right;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} png_dsort;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef png_dsort FAR *       png_dsortp;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef png_dsort FAR * FAR * png_dsortpp;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_dither(png_structp png_ptr, png_colorp palette,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int num_palette, int maximum_colors, png_uint_16p histogram,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int full_dither)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_dither");
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= PNG_DITHER;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!full_dither)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (png_uint_32)(num_palette * png_sizeof(png_byte)));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < num_palette; i++)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->dither_index[i] = (png_byte)i;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (num_palette > maximum_colors)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (histogram != NULL)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This is easy enough, just throw out the least used colors.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * Perhaps not the best solution, but good enough.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int i;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Initialize an array to sort colors */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_uint_32)(num_palette * png_sizeof(png_byte)));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Initialize the dither_sort array */
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < num_palette; i++)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->dither_sort[i] = (png_byte)i;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Find the least used palette entries by starting a
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * bubble sort, and running it until we have sorted
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * out enough colors.  Note that we don't care about
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * sorting all the colors, just finding which are
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * least used.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = num_palette - 1; i >= maximum_colors; i--)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int done; /* To stop early if the list is pre-sorted */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int j;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            done = 1;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (j = 0; j < i; j++)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (histogram[png_ptr->dither_sort[j]]
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   < histogram[png_ptr->dither_sort[j + 1]])
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte t;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  t = png_ptr->dither_sort[j];
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->dither_sort[j + 1] = t;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  done = 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (done)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Swap the palette around, and set up a table, if necessary */
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (full_dither)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int j = num_palette;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Put all the useful colors within the max, but don't
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * move the others.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             */
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < maximum_colors; i++)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  do
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     j--;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  palette[i] = palette[j];
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int j = num_palette;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Move all the used colors inside the max limit, and
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * develop a translation table.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             */
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < maximum_colors; i++)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* Only move the colors we need to */
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_color tmp_color;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  do
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     j--;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  tmp_color = palette[j];
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  palette[j] = palette[i];
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  palette[i] = tmp_color;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  /* Indicate where the color went */
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->dither_index[j] = (png_byte)i;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->dither_index[i] = (png_byte)j;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Find closest color for those colors we are not using */
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < num_palette; i++)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if ((int)png_ptr->dither_index[i] >= maximum_colors)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int min_d, k, min_k, d_index;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  /* Find the closest color to one we threw out */
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  d_index = png_ptr->dither_index[i];
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (k = 1, min_k = 0; k < maximum_colors; k++)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int d;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (d < min_d)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        min_d = d;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        min_k = k;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  /* Point to closest color */
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->dither_index[i] = (png_byte)min_k;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_free(png_ptr, png_ptr->dither_sort);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->dither_sort = NULL;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This is much harder to do simply (and quickly).  Perhaps
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * we need to go through a median cut routine, but those
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * don't always behave themselves with only a few colors
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * as input.  So we will just find the closest two colors,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * and throw out one of them (chosen somewhat randomly).
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * [We don't understand this at all, so if someone wants to
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *  work on improving it, be our guest - AED, GRP]
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int i;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int max_d;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int num_new_palette;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_dsortp t;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_dsortpp hash;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         t = NULL;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Initialize palette index arrays */
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_uint_32)(num_palette * png_sizeof(png_byte)));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_uint_32)(num_palette * png_sizeof(png_byte)));
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Initialize the sort array */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < num_palette; i++)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->index_to_palette[i] = (png_byte)i;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->palette_to_index[i] = (png_byte)i;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_sizeof(png_dsortp)));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         num_new_palette = num_palette;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Initial wild guess at how far apart the farthest pixel
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * pair we will be eliminating will be.  Larger
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * numbers mean more areas will be allocated, Smaller
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * numbers run the risk of not saving enough data, and
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * having to do this all over again.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * I have not done extensive checking on this number.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         max_d = 96;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         while (num_new_palette > maximum_colors)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < num_new_palette - 1; i++)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int j;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (j = i + 1; j < num_new_palette; j++)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int d;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  d = PNG_COLOR_DIST(palette[i], palette[j]);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (d <= max_d)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     t = (png_dsortp)png_malloc_warn(png_ptr,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         (png_uint_32)(png_sizeof(png_dsort)));
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (t == NULL)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         break;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     t->next = hash[d];
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     t->left = (png_byte)i;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     t->right = (png_byte)j;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     hash[d] = t;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (t == NULL)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (t != NULL)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i <= max_d; i++)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (hash[i] != NULL)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_dsortp p;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (p = hash[i]; p; p = p->next)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if ((int)png_ptr->index_to_palette[p->left]
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        < num_new_palette &&
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        (int)png_ptr->index_to_palette[p->right]
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        < num_new_palette)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int j, next_j;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (num_new_palette & 0x01)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           j = p->left;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           next_j = p->right;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           j = p->right;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           next_j = p->left;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        num_new_palette--;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        palette[png_ptr->index_to_palette[j]]
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          = palette[num_new_palette];
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (!full_dither)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int k;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           for (k = 0; k < num_palette; k++)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              if (png_ptr->dither_index[k] ==
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 png_ptr->index_to_palette[j])
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 png_ptr->dither_index[k] =
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    png_ptr->index_to_palette[next_j];
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              if ((int)png_ptr->dither_index[k] ==
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 num_new_palette)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 png_ptr->dither_index[k] =
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    png_ptr->index_to_palette[j];
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_ptr->index_to_palette[png_ptr->palette_to_index
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           [num_new_palette]] = png_ptr->index_to_palette[j];
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           = png_ptr->palette_to_index[num_new_palette];
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_ptr->index_to_palette[j] =
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            (png_byte)num_new_palette;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_ptr->palette_to_index[num_new_palette] =
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            (png_byte)j;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (num_new_palette <= maximum_colors)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (num_new_palette <= maximum_colors)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     break;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < 769; i++)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (hash[i] != NULL)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_dsortp p = hash[i];
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  while (p)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     t = p->next;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_free(png_ptr, p);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     p = t;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               hash[i] = 0;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            max_d += 96;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_free(png_ptr, hash);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_free(png_ptr, png_ptr->palette_to_index);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_free(png_ptr, png_ptr->index_to_palette);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->palette_to_index = NULL;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->index_to_palette = NULL;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_palette = maximum_colors;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->palette == NULL)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->palette = palette;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->num_palette = (png_uint_16)num_palette;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (full_dither)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_bytep distance;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         PNG_DITHER_BLUE_BITS;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int num_red = (1 << PNG_DITHER_RED_BITS);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int num_green = (1 << PNG_DITHER_GREEN_BITS);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_size_t num_entries = ((png_size_t)1 << total_bits);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (png_uint_32)(num_entries * png_sizeof(png_byte)));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_sizeof(png_byte)));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < num_palette; i++)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int ir, ig, ib;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (ir = 0; ir < num_red; ir++)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* int dr = abs(ir - r); */
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int dr = ((ir > r) ? ir - r : r - ir);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int index_r = (ir << (PNG_DITHER_BLUE_BITS +
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PNG_DITHER_GREEN_BITS));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (ig = 0; ig < num_green; ig++)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* int dg = abs(ig - g); */
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int dg = ((ig > g) ? ig - g : g - ig);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int dt = dr + dg;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int dm = ((dr > dg) ? dr : dg);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (ib = 0; ib < num_blue; ib++)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int d_index = index_g | ib;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  /* int db = abs(ib - b); */
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int db = ((ib > b) ? ib - b : b - ib);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int dmax = ((dm > db) ? dm : db);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int d = dmax + dt + db;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (d < (int)distance[d_index])
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     distance[d_index] = (png_byte)d;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_ptr->palette_lookup[d_index] = (png_byte)i;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_free(png_ptr, distance);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Transform the image from the file_gamma to the screen_gamma.  We
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * only do transformations on images where the file_gamma and screen_gamma
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are not close reciprocals, otherwise it slows things down slightly, and
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * also needlessly introduces small errors.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We will turn off gamma transformation later if no semitransparent entries
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are present in the tRNS array for palette images.  We can't do it here
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * because we don't necessarily have the tRNS chunk yet.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_gamma");
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     png_ptr->transformations |= PNG_GAMMA;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->gamma = (float)file_gamma;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->screen_gamma = (float)scrn_gamma;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_EXPAND_SUPPORTED
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expand paletted images to RGB, expand grayscale images of
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to alpha channels.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_expand(png_structp png_ptr)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_expand");
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* GRR 19990627:  the following three functions currently are identical
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  to png_set_expand().  However, it is entirely reasonable that someone
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  might wish to expand an indexed image to RGB but *not* expand a single,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  fully transparent palette entry to a full alpha channel--perhaps instead
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  the transparent color with a particular RGB value, or drop tRNS entirely.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  IOW, a future version of the library may make the transformations flag
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  a bit more fine-grained, with separate bits for each of these three
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  functions.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  More to the point, these functions make it obvious what libpng will be
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  doing, whereas "expand" can (and does) mean any number of things.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  to expand only the sample depth but not to expand the tRNS to alpha
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expand paletted images to RGB. */
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_palette_to_rgb(png_structp png_ptr)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_palette_to_rgb");
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PNG_1_0_X
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expand grayscale images of less than 8-bit depth to 8 bits. */
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= PNG_EXPAND;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expand grayscale images of less than 8-bit depth to 8 bits. */
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Deprecated as of libpng-1.2.9 */
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_gray_1_2_4_to_8(png_structp png_ptr)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_gray_1_2_4_to_8");
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expand tRNS chunks to alpha channels. */
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_tRNS_to_alpha(png_structp png_ptr)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_tRNS_to_alpha");
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_gray_to_rgb(png_structp png_ptr)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_gray_to_rgb");
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= PNG_GRAY_TO_RGB;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FLOATING_POINT_SUPPORTED
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Convert a RGB image to a grayscale of the same width.  This allows us,
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   double green)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int red_fixed, green_fixed;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (red > 21474.83647 || red < -21474.83648 ||
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       green > 21474.83647 || green < -21474.83648)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      red_fixed = -1;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      green_fixed = -1;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      red_fixed = (int)((float)red*100000.0 + 0.5);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      green_fixed = (int)((float)green*100000.0 + 0.5);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_fixed_point red, png_fixed_point green)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_rgb_to_gray");
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch(error_action)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              break;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              break;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_EXPAND_SUPPORTED
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->transformations |= PNG_EXPAND;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_warning(png_ptr,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_16 red_int, green_int;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (red < 0 || green < 0)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         red_int   =  6968; /* .212671 * 32768 + .5 */
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         green_int = 23434; /* .715160 * 32768 + .5 */
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (red + green < 100000L)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         red_int   =  6968;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         green_int = 23434;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->rgb_to_gray_red_coeff   = red_int;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->rgb_to_gray_green_coeff = green_int;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->rgb_to_gray_blue_coeff  =
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (png_uint_16)(32768 - red_int - green_int);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(PNG_LEGACY_SUPPORTED) || \
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   read_user_transform_fn)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_set_read_user_transform_fn");
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->transformations |= PNG_USER_TRANSFORM;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->read_user_transform_fn = read_user_transform_fn;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_LEGACY_SUPPORTED
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (read_user_transform_fn)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_warning(png_ptr,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "This version of libpng does not support user transforms");
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Initialize everything needed for the read.  This includes modifying
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the palette.
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_init_read_transformations(png_structp png_ptr)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_init_read_transformations");
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (png_ptr != NULL)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(PNG_READ_SHIFT_SUPPORTED) || \
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(PNG_READ_GAMMA_SUPPORTED)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int color_type = png_ptr->color_type;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Detect gray background and attempt to enable optimization
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * for gray --> RGB case
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * background color might actually be gray yet not be flagged as such.
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * This is not a problem for the current code, which uses
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * png_do_gray_to_rgb() transformation.
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !(color_type & PNG_COLOR_MASK_COLOR))
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              png_ptr->background.red == png_ptr->background.green &&
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              png_ptr->background.red == png_ptr->background.blue)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          png_ptr->background.gray = png_ptr->background.red;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (png_ptr->transformations & PNG_EXPAND))
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Expand background and tRNS chunks */
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         switch (png_ptr->bit_depth)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 1:
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.gray *= (png_uint_16)0xff;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.red = png_ptr->background.green
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 =  png_ptr->background.blue = png_ptr->background.gray;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans_values.gray *= (png_uint_16)0xff;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans_values.red = png_ptr->trans_values.green
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 2:
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.gray *= (png_uint_16)0x55;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.red = png_ptr->background.green
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 = png_ptr->background.blue = png_ptr->background.gray;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans_values.gray *= (png_uint_16)0x55;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans_values.red = png_ptr->trans_values.green
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 4:
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.gray *= (png_uint_16)0x11;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.red = png_ptr->background.green
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 = png_ptr->background.blue = png_ptr->background.gray;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans_values.gray *= (png_uint_16)0x11;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans_values.red = png_ptr->trans_values.green
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 8:
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 16:
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.red = png_ptr->background.green
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 = png_ptr->background.blue = png_ptr->background.gray;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (color_type == PNG_COLOR_TYPE_PALETTE)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->background.red   =
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->palette[png_ptr->background.index].red;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->background.green =
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->palette[png_ptr->background.index].green;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->background.blue  =
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->palette[png_ptr->background.index].blue;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (png_ptr->transformations & PNG_INVERT_ALPHA)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_EXPAND_SUPPORTED
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           /* Invert the alpha channel (in tRNS) unless the pixels are
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            * going to be expanded, in which case leave it for later
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            */
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              int i, istop;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              istop=(int)png_ptr->num_trans;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              for (i=0; i<istop; i++)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           }
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_ptr->background_1 = png_ptr->background;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         < PNG_GAMMA_THRESHOLD))
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i, k;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k=0;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i=0; i<png_ptr->num_trans; i++)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        k=1; /* Partial transparency is present */
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (k == 0)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->transformations &= ~PNG_GAMMA;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_ptr->gamma != 0.0)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_build_gamma_table(png_ptr);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->transformations & PNG_BACKGROUND)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (color_type == PNG_COLOR_TYPE_PALETTE)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           /* Could skip if no transparency */
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_color back, back_1;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_colorp palette = png_ptr->palette;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int num_palette = png_ptr->num_palette;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int i;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back.red = png_ptr->gamma_table[png_ptr->background.red];
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back.green = png_ptr->gamma_table[png_ptr->background.green];
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               double g, gs;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               switch (png_ptr->background_gamma_type)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  case PNG_BACKGROUND_GAMMA_SCREEN:
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     g = (png_ptr->screen_gamma);
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     gs = 1.0;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     break;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  case PNG_BACKGROUND_GAMMA_FILE:
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     g = 1.0 / (png_ptr->gamma);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     break;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  case PNG_BACKGROUND_GAMMA_UNIQUE:
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     g = 1.0 / (png_ptr->background_gamma);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     gs = 1.0 / (png_ptr->background_gamma *
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 png_ptr->screen_gamma);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     break;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  default:
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     g = 1.0;    /* back_1 */
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     gs = 1.0;   /* back */
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  back.red   = (png_byte)png_ptr->background.red;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  back.green = (png_byte)png_ptr->background.green;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  back.blue  = (png_byte)png_ptr->background.blue;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  back.red = (png_byte)(pow(
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  back.green = (png_byte)(pow(
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     (double)png_ptr->background.green/255, gs) * 255.0
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         + .5);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  back.blue = (png_byte)(pow(
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back_1.red = (png_byte)(pow(
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.red/255, g) * 255.0 + .5);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back_1.green = (png_byte)(pow(
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.green/255, g) * 255.0 + .5);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               back_1.blue = (png_byte)(pow(
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.blue/255, g) * 255.0 + .5);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < num_palette; i++)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (png_ptr->trans[i] == 0)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     palette[i] = back;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else /* if (png_ptr->trans[i] != 0xff) */
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_byte v, w;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     v = png_ptr->gamma_to_1[palette[i].red];
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_composite(w, v, png_ptr->trans[i], back_1.red);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     palette[i].red = png_ptr->gamma_from_1[w];
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     v = png_ptr->gamma_to_1[palette[i].green];
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_composite(w, v, png_ptr->trans[i], back_1.green);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     palette[i].green = png_ptr->gamma_from_1[w];
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     v = png_ptr->gamma_to_1[palette[i].blue];
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_composite(w, v, png_ptr->trans[i], back_1.blue);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     palette[i].blue = png_ptr->gamma_from_1[w];
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  palette[i].red = png_ptr->gamma_table[palette[i].red];
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  palette[i].green = png_ptr->gamma_table[palette[i].green];
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Prevent the transformations being done again, and make sure
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * that the now spurious alpha channel is stripped - the code
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * has just reduced background composition and gamma correction
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * to a simple alpha channel strip.
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             */
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->transformations &= ~PNG_BACKGROUND;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->transformations &= ~PNG_GAMMA;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->transformations |= PNG_STRIP_ALPHA;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* color_type != PNG_COLOR_TYPE_PALETTE */
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            double g = 1.0;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            double gs = 1.0;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            switch (png_ptr->background_gamma_type)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case PNG_BACKGROUND_GAMMA_SCREEN:
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  g = (png_ptr->screen_gamma);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gs = 1.0;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case PNG_BACKGROUND_GAMMA_FILE:
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  g = 1.0 / (png_ptr->gamma);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case PNG_BACKGROUND_GAMMA_UNIQUE:
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  g = 1.0 / (png_ptr->background_gamma);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gs = 1.0 / (png_ptr->background_gamma *
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_ptr->screen_gamma);
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->background_1.gray = (png_uint_16)(pow(
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (double)png_ptr->background.gray / m, g) * m + .5);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->background.gray = (png_uint_16)(pow(
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (double)png_ptr->background.gray / m, gs) * m + .5);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((png_ptr->background.red != png_ptr->background.green) ||
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (png_ptr->background.red != png_ptr->background.blue) ||
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (png_ptr->background.red != png_ptr->background.gray))
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* RGB or RGBA with color background */
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background_1.red = (png_uint_16)(pow(
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.red / m, g) * m + .5);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background_1.green = (png_uint_16)(pow(
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.green / m, g) * m + .5);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background_1.blue = (png_uint_16)(pow(
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.blue / m, g) * m + .5);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.red = (png_uint_16)(pow(
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.red / m, gs) * m + .5);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.green = (png_uint_16)(pow(
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.green / m, gs) * m + .5);
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.blue = (png_uint_16)(pow(
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (double)png_ptr->background.blue / m, gs) * m + .5);
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background_1.red = png_ptr->background_1.green
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 = png_ptr->background_1.blue = png_ptr->background_1.gray;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->background.red = png_ptr->background.green
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 = png_ptr->background.blue = png_ptr->background.gray;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Transformation does not include PNG_BACKGROUND */
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_READ_BACKGROUND_SUPPORTED */
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (color_type == PNG_COLOR_TYPE_PALETTE)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_colorp palette = png_ptr->palette;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int num_palette = png_ptr->num_palette;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int i;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < num_palette; i++)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            palette[i].red = png_ptr->gamma_table[palette[i].red];
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            palette[i].green = png_ptr->gamma_table[palette[i].green];
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Done the gamma correction. */
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->transformations &= ~PNG_GAMMA;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* No GAMMA transformation */
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_BACKGROUND) &&
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (color_type == PNG_COLOR_TYPE_PALETTE))
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int istop = (int)png_ptr->num_trans;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_color back;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_colorp palette = png_ptr->palette;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      back.red   = (png_byte)png_ptr->background.red;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      back.green = (png_byte)png_ptr->background.green;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      back.blue  = (png_byte)png_ptr->background.blue;
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < istop; i++)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (png_ptr->trans[i] == 0)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            palette[i] = back;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (png_ptr->trans[i] != 0xff)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* The png_composite() macro is defined in png.h */
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_composite(palette[i].red, palette[i].red,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->trans[i], back.red);
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_composite(palette[i].green, palette[i].green,
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->trans[i], back.green);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_composite(palette[i].blue, palette[i].blue,
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->trans[i], back.blue);
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Handled alpha, still need to strip the channel. */
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->transformations &= ~PNG_BACKGROUND;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->transformations |= PNG_STRIP_ALPHA;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_READ_BACKGROUND_SUPPORTED */
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SHIFT_SUPPORTED
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_SHIFT) &&
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (color_type == PNG_COLOR_TYPE_PALETTE))
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_16 i;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_16 istop = png_ptr->num_palette;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int sr = 8 - png_ptr->sig_bit.red;
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int sg = 8 - png_ptr->sig_bit.green;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int sb = 8 - png_ptr->sig_bit.blue;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sr < 0 || sr > 8)
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sr = 0;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sg < 0 || sg > 8)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sg = 0;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sb < 0 || sb > 8)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sb = 0;
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < istop; i++)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->palette[i].red >>= sr;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->palette[i].green >>= sg;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->palette[i].blue >>= sb;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  /* PNG_READ_SHIFT_SUPPORTED */
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && !defined(PNG_READ_BACKGROUND_SUPPORTED)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr)
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Modify the info structure to reflect the transformations.  The
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * info should be updated so a PNG file could be written with it,
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * assuming the transformations result in valid PNG data.
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_read_transform_info");
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_EXPAND_SUPPORTED
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_EXPAND)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (png_ptr->num_trans)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         info_ptr->bit_depth = 8;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         info_ptr->num_trans = 0;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (png_ptr->num_trans)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->transformations & PNG_EXPAND_tRNS)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (info_ptr->bit_depth < 8)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            info_ptr->bit_depth = 8;
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         info_ptr->num_trans = 0;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_BACKGROUND)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->num_trans = 0;
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->background = png_ptr->background;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_GAMMA)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FLOATING_POINT_SUPPORTED
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->gamma = png_ptr->gamma;
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FIXED_POINT_SUPPORTED
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->int_gamma = png_ptr->int_gamma;
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_16_TO_8_SUPPORTED
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->bit_depth = 8;
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_DITHER_SUPPORTED
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_DITHER)
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_PACK_SUPPORTED
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->bit_depth = 8;
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->channels = 1;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->channels = 3;
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->channels = 1;
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->channels++;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_FILLER_SUPPORTED
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_FILLER) &&
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->channels++;
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If adding a true alpha channel not just filler */
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PNG_1_0_X
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->transformations & PNG_ADD_ALPHA)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_USER_TRANSFORM)
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       if (info_ptr->bit_depth < png_ptr->user_transform_depth)
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         info_ptr->bit_depth = png_ptr->user_transform_depth;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       if (info_ptr->channels < png_ptr->user_transform_channels)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         info_ptr->channels = png_ptr->user_transform_channels;
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_ptr->bit_depth);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PNG_READ_EXPAND_SUPPORTED
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr)
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Transform the row.  The order of transformations is significant,
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and is very touchy.  If you add a transformation, take care to
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decide how it fits in with the other transformations here.
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_read_transformations(png_structp png_ptr)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_read_transformations");
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->row_buf == NULL)
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char msg[50];
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_snprintf2(msg, 50,
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->pass);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_error(png_ptr, msg);
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_error(png_ptr, "NULL row buffer");
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WARN_UNINITIALIZED_ROW
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Application has failed to call either png_read_start_image()
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * or png_read_update_info() after setting transforms that expand
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * pixels.  This check added to libpng-1.2.19
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (PNG_WARN_UNINITIALIZED_ROW==1)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_error(png_ptr, "Uninitialized row");
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_warning(png_ptr, "Uninitialized row");
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_EXPAND_SUPPORTED
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_EXPAND)
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (png_ptr->num_trans &&
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             (png_ptr->transformations & PNG_EXPAND_tRNS))
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               &(png_ptr->trans_values));
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               NULL);
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rgb_error =
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             png_ptr->row_buf + 1);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rgb_error)
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->rgb_to_gray_status=1;
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             PNG_RGB_TO_GRAY_WARN)
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             PNG_RGB_TO_GRAY_ERR)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   In most cases, the "simple transparency" should be done prior to doing
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   pixel is transparent.  You would also need to make sure that the
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   transparency information is upgraded to RGB.
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   To summarize, the current flow is:
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   with background "in place" if transparent,
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   convert to RGB if necessary
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   - Gray + alpha -> composite with gray background and remove alpha bytes,
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   convert to RGB if necessary
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   To support RGB backgrounds for gray images we need:
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   - Gray + simple transparency -> convert to RGB + simple transparency,
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   compare 3 or 6 bytes and composite with
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   background "in place" if transparent
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   (3x compare/pixel compared to doing
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   composite with gray bkgrnd)
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   - Gray + alpha -> convert to RGB + alpha, composite with background and
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   remove alpha bytes (3x float
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   operations/pixel compared with composite
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                                   on gray background)
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Greg's change will do this.  The reason it wasn't done before is for
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  performance, as this increases the per-pixel operations.  If we would check
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  in advance if the background was gray or RGB, and position the gray-to-RGB
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  transform appropriately, then it would save a lot of work/time.
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* If gray -> RGB, do so now only if background is non-gray; else do later
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * for performance reasons
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_BACKGROUND) &&
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((png_ptr->num_trans != 0 ) ||
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         &(png_ptr->trans_values), &(png_ptr->background)
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         , &(png_ptr->background_1),
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->gamma_table, png_ptr->gamma_from_1,
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->gamma_shift
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles));
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_GAMMA) &&
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !((png_ptr->transformations & PNG_BACKGROUND) &&
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((png_ptr->num_trans != 0) ||
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          png_ptr->gamma_table, png_ptr->gamma_16_table,
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          png_ptr->gamma_shift);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_16_TO_8_SUPPORTED
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_16_TO_8)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_DITHER_SUPPORTED
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_DITHER)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->palette_lookup, png_ptr->dither_index);
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->row_info.rowbytes == (png_uint_32)0)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_error(png_ptr, "png_do_dither returned rowbytes=0");
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_INVERT_SUPPORTED
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_INVERT_MONO)
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SHIFT_SUPPORTED
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_SHIFT)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         &(png_ptr->shift));
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_PACK_SUPPORTED
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_PACK)
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BGR_SUPPORTED
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_BGR)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_PACKSWAP_SUPPORTED
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_PACKSWAP)
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* If gray -> RGB, do so now only if we did not do so above */
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_FILLER_SUPPORTED
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_FILLER)
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (png_uint_32)png_ptr->filler, png_ptr->flags);
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_INVERT_ALPHA)
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_SWAP_ALPHA)
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SWAP_SUPPORTED
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_SWAP_BYTES)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_USER_TRANSFORM)
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->read_user_transform_fn != NULL)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_ptr,                    /* png_ptr */
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               &(png_ptr->row_info),     /* row_info: */
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /*  png_uint_32 width;       width of row */
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /*  png_uint_32 rowbytes;    number of bytes in row */
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /*  png_byte color_type;     color type of pixels */
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /*  png_byte bit_depth;      bit depth of samples */
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /*  png_byte channels;       number of channels (1-4) */
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_ptr->row_buf + 1);    /* start of pixel data for row */
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->user_transform_depth)
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->user_transform_channels)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->row_info.channels = png_ptr->user_transform_channels;
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->row_info.channels);
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->row_info.width);
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_PACK_SUPPORTED
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without changing the actual values.  Thus, if you had a row with
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a bit depth of 1, you would end up with bytes that only contained
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * png_do_shift() after this.
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_unpack(png_row_infop row_info, png_bytep row)
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_unpack");
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row_info->bit_depth < 8)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 i;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 row_width=row_info->width;
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (row_info->bit_depth)
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 1:
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = row + (png_size_t)row_width - 1;
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp = (png_byte)((*sp >> shift) & 0x01);
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (shift == 7)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 0;
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp--;
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift++;
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp--;
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 2:
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = row + (png_size_t)row_width - 1;
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp = (png_byte)((*sp >> shift) & 0x03);
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (shift == 6)
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 0;
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp--;
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift += 2;
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp--;
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 4:
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = row + (png_size_t)row_width - 1;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp = (png_byte)((*sp >> shift) & 0x0f);
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (shift == 4)
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 0;
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp--;
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 4;
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp--;
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->bit_depth = 8;
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->rowbytes = row_width * row_info->channels;
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SHIFT_SUPPORTED
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Reverse the effects of png_do_shift.  This routine merely shifts the
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pixels back to their significant bits values.  Thus, if you have
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a row of bit depth 8, but only 5 are significant, this will shift
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the values back to 0 through 31.
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_unshift");
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL && sig_bits != NULL &&
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int shift[4];
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int channels = 0;
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int c;
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_16 value = 0;
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 row_width = row_info->width;
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift[channels++] = row_info->bit_depth - sig_bits->red;
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift[channels++] = row_info->bit_depth - sig_bits->green;
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift[channels++] = row_info->bit_depth - sig_bits->blue;
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift[channels++] = row_info->bit_depth - sig_bits->gray;
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (c = 0; c < channels; c++)
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (shift[c] <= 0)
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            shift[c] = 0;
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            value = 1;
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!value)
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (row_info->bit_depth)
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 2:
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep bp;
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 istop = row_info->rowbytes;
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (bp = row, i = 0; i < istop; i++)
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp >>= 1;
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp++ &= 0x55;
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 4:
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep bp = row;
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 istop = row_info->rowbytes;
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (png_byte)((int)0xf >> shift[0]));
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < istop; i++)
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp >>= shift[0];
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp++ &= mask;
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 8:
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep bp = row;
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 istop = row_width * channels;
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < istop; i++)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp++ >>= shift[i%channels];
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 16:
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep bp = row;
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 istop = channels * row_width;
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < istop; i++)
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               value = (png_uint_16)((*bp << 8) + *(bp + 1));
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               value >>= shift[i%channels];
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp++ = (png_byte)(value >> 8);
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *bp++ = (png_byte)(value & 0xff);
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_16_TO_8_SUPPORTED
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Chop rows of bit depth 16 down to 8 */
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_chop(png_row_infop row_info, png_bytep row)
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_chop");
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row_info->bit_depth == 16)
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_bytep sp = row;
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_bytep dp = row;
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 i;
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 istop = row_info->width * row_info->channels;
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i<istop; i++, sp += 2, dp++)
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* This does a more accurate scaling of the 16-bit color
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * value, rather than a simple low-byte truncation.
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * What the ideal calculation should be:
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *   *dp = (((((png_uint_32)(*sp) << 8) |
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *          (png_uint_32)(*(sp + 1))) * 255 + 127)
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *          / (png_uint_32)65535L;
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * GRR: no, I think this is what it really should be:
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *   *dp = (((((png_uint_32)(*sp) << 8) |
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *           (png_uint_32)(*(sp + 1))) + 128L)
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *           / (png_uint_32)257L;
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * GRR: here's the exact calculation with shifts:
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *   temp = (((png_uint_32)(*sp) << 8) |
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *           (png_uint_32)(*(sp + 1))) + 128L;
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *   *dp = (temp - (temp >> 8)) >> 8;
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * Approximate calculation with shift/add instead of multiply/divide:
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *   *dp = ((((png_uint_32)(*sp) << 8) |
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * What we actually do to avoid extra shifting and conversion:
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       /* Simply discard the low order byte */
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *dp = *sp;
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->bit_depth = 8;
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->rowbytes = row_info->width * row_info->channels;
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_read_swap_alpha");
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL)
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 row_width = row_info->width;
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from RGBA to ARGB */
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte save;
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save = *(--sp);
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = save;
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from RRGGBBAA to AARRGGBB */
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte save[2];
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[0] = *(--sp);
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[1] = *(--sp);
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = save[0];
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = save[1];
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from GA to AG */
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte save;
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save = *(--sp);
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = save;
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from GGAA to AAGG */
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte save[2];
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[0] = *(--sp);
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[1] = *(--sp);
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = save[0];
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = save[1];
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_read_invert_alpha");
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL)
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 row_width = row_info->width;
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in RGBA */
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = (png_byte)(255 - *(--sp));
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*             This does nothing:
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               We can replace it with:
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp-=3;
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp=sp;
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in RRGGBBAA */
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = (png_byte)(255 - *(--sp));
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = (png_byte)(255 - *(--sp));
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*             This does nothing:
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               We can replace it with:
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp-=6;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp=sp;
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in GA */
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + row_info->rowbytes;
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = (png_byte)(255 - *(--sp));
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in GGAA */
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp  = row + row_info->rowbytes;
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp;
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = (png_byte)(255 - *(--sp));
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = (png_byte)(255 - *(--sp));
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp-=2;
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp=sp;
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_FILLER_SUPPORTED
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Add filler channel if we have RGB color */
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_read_filler(png_row_infop row_info, png_bytep row,
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 filler, png_uint_32 flags)
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width = row_info->width;
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_byte lo_filler = (png_byte)(filler & 0xff);
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_read_filler");
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL  && row_info != NULL &&
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row_info->color_type == PNG_COLOR_TYPE_GRAY)
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->bit_depth == 8)
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This changes the data from G to GX */
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (flags & PNG_FLAG_FILLER_AFTER)
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width;
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp =  sp + (png_size_t)row_width;
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 1; i < row_width; i++)
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(--dp) = lo_filler;
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 2;
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 16;
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 2;
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* This changes the data from G to XG */
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width;
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width;
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 2;
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 16;
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 2;
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->bit_depth == 16)
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This changes the data from GG to GGXX */
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (flags & PNG_FLAG_FILLER_AFTER)
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 2;
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 2;
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 1; i < row_width; i++)
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = hi_filler;
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(--dp) = hi_filler;
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(--dp) = lo_filler;
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 2;
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 32;
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 4;
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This changes the data from GG to XXGG */
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 2;
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 2;
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = hi_filler;
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 2;
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 32;
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 4;
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   } /* COLOR_TYPE == GRAY */
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->bit_depth == 8)
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This changes the data from RGB to RGBX */
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (flags & PNG_FLAG_FILLER_AFTER)
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 3;
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width;
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 1; i < row_width; i++)
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(--dp) = lo_filler;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 4;
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 32;
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 4;
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* This changes the data from RGB to XRGB */
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 3;
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp + (png_size_t)row_width;
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 4;
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 32;
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 4;
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->bit_depth == 16)
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This changes the data from RRGGBB to RRGGBBXX */
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (flags & PNG_FLAG_FILLER_AFTER)
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 6;
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 2;
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 1; i < row_width; i++)
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = hi_filler;
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(--dp) = hi_filler;
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(--dp) = lo_filler;
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 4;
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 64;
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 8;
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This changes the data from RRGGBB to XXRRGGBB */
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 6;
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 2;
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = *(--sp);
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = hi_filler;
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(--dp) = lo_filler;
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 4;
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 64;
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width * 8;
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   } /* COLOR_TYPE == RGB */
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expand grayscale files to RGB, with or without alpha */
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width = row_info->width;
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_gray_to_rgb");
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row_info->bit_depth >= 8 &&
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width - 1;
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 2;
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 4;
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp - 1);
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp - 1);
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 2;
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep dp = sp  + (png_size_t)row_width * 4;
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp - 1);
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *sp;
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp - 1);
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp--) = *(sp--);
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->channels += (png_byte)2;
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->color_type |= PNG_COLOR_MASK_COLOR;
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->pixel_depth = (png_byte)(row_info->channels *
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->bit_depth);
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Reduce RGB files to grayscale, with or without alpha
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * using the equation given in Poynton's ColorFAQ at
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * New link:
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * <http://www.poynton.com/notes/colour_and_gamma/>
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Charles Poynton poynton at poynton.com
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  We approximate this with
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  which can be expressed with integers as
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  The calculation is to be done in a linear colorspace.
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Other integer coefficents can be used via png_set_rgb_to_gray().
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int /* PRIVATE */
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width = row_info->width;
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int rgb_error = 0;
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_rgb_to_gray");
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (row_info->color_type & PNG_COLOR_MASK_COLOR))
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red != green || red != blue)
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *(dp++) = png_ptr->gamma_from_1[
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       (rc*red + gc*green + bc*blue)>>15];
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *(dp++) = *(sp - 1);
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte red   = *(sp++);
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte green = *(sp++);
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte blue  = *(sp++);
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red != green || red != blue)
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *(dp++) = *(sp - 1);
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else /* RGB bit_depth == 16 */
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->gamma_16_to_1 != NULL &&
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                png_ptr->gamma_16_from_1 != NULL)
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 red, green, blue, w;
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red == green && red == blue)
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     w = red;
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  png_ptr->gamma_shift][red>>8];
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 green_1 =
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_16_to_1[(green&0xff) >>
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  png_ptr->gamma_shift][green>>8];
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  png_ptr->gamma_shift][blue>>8];
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  + bc*blue_1)>>15);
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_shift][gray16 >> 8];
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)((w>>8) & 0xff);
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)(w & 0xff);
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 red, green, blue, gray16;
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red != green || red != blue)
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)(gray16 & 0xff);
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red != green || red != blue)
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) =  png_ptr->gamma_from_1
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             [(rc*red + gc*green + bc*blue)>>15];
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = *(sp++);  /* alpha */
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte red   = *(sp++);
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte green = *(sp++);
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_byte blue  = *(sp++);
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red != green || red != blue)
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = *(sp++);  /* alpha */
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else /* RGBA bit_depth == 16 */
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->gamma_16_to_1 != NULL &&
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                png_ptr->gamma_16_from_1 != NULL)
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 red, green, blue, w;
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red == green && red == blue)
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     w = red;
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_shift][red>>8];
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 green_1 =
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_16_to_1[(green&0xff) >>
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_shift][green>>8];
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_shift][blue>>8];
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         + gc * green_1 + bc * blue_1)>>15);
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         png_ptr->gamma_shift][gray16 >> 8];
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)((w>>8) & 0xff);
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)(w & 0xff);
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = *(sp++);  /* alpha */
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = *(sp++);
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep sp = row;
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_bytep dp = row;
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 red, green, blue, gray16;
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (red != green || red != blue)
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     rgb_error |= 1;
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = (png_byte)(gray16 & 0xff);
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = *(sp++);  /* alpha */
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(dp++) = *(sp++);
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   row_info->channels -= (png_byte)2;
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->pixel_depth = (png_byte)(row_info->channels *
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->bit_depth);
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return rgb_error;
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * large of png_color.  This lets grayscale images be treated as
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * paletted.  Most useful for gamma correction and simplification
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of code.
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_build_grayscale_palette(int bit_depth, png_colorp palette)
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int num_palette;
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int color_inc;
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int i;
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int v;
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_build_grayscale_palette");
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (palette == NULL)
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (bit_depth)
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1:
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         num_palette = 2;
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         color_inc = 0xff;
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2:
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         num_palette = 4;
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         color_inc = 0x55;
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 4:
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         num_palette = 16;
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         color_inc = 0x11;
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 8:
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         num_palette = 256;
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         color_inc = 1;
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         num_palette = 0;
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         color_inc = 0;
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      palette[i].red = (png_byte)v;
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      palette[i].green = (png_byte)v;
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      palette[i].blue = (png_byte)v;
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This function is currently unused.  Do we really need it? */
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_DITHER_SUPPORTED) && \
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  defined(PNG_CORRECT_PALETTE_SUPPORTED)
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_correct_palette(png_structp png_ptr, png_colorp palette,
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int num_palette)
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_correct_palette");
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(PNG_READ_GAMMA_SUPPORTED) && \
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  defined(PNG_FLOATING_POINT_SUPPORTED)
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_color back, back_1;
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back.red = png_ptr->gamma_table[png_ptr->background.red];
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back.green = png_ptr->gamma_table[png_ptr->background.green];
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back.blue = png_ptr->gamma_table[png_ptr->background.blue];
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         double g;
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             || fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            back.red = png_ptr->background.red;
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            back.green = png_ptr->background.green;
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            back.blue = png_ptr->background.blue;
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            back.red =
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (png_byte)(pow((double)png_ptr->background.red/255, g) *
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                255.0 + 0.5);
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            back.green =
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (png_byte)(pow((double)png_ptr->background.green/255, g) *
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                255.0 + 0.5);
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            back.blue =
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (png_byte)(pow((double)png_ptr->background.blue/255, g) *
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                255.0 + 0.5);
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         g = 1.0 / png_ptr->background_gamma;
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back_1.red =
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_byte)(pow((double)png_ptr->background.red/255, g) *
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             255.0 + 0.5);
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back_1.green =
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_byte)(pow((double)png_ptr->background.green/255, g) *
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             255.0 + 0.5);
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back_1.blue =
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (png_byte)(pow((double)png_ptr->background.blue/255, g) *
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             255.0 + 0.5);
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < (png_uint_32)num_palette; i++)
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i] = back;
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte v, w;
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_composite(w, v, png_ptr->trans[i], back_1.red);
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].red = png_ptr->gamma_from_1[w];
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_composite(w, v, png_ptr->trans[i], back_1.green);
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].green = png_ptr->gamma_from_1[w];
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_composite(w, v, png_ptr->trans[i], back_1.blue);
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].blue = png_ptr->gamma_from_1[w];
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].red = png_ptr->gamma_table[palette[i].red];
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].green = png_ptr->gamma_table[palette[i].green];
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int i;
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < num_palette; i++)
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i] = back;
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].red = png_ptr->gamma_table[palette[i].red];
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].green = png_ptr->gamma_table[palette[i].green];
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_GAMMA)
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < num_palette; i++)
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         palette[i].red = png_ptr->gamma_table[palette[i].red];
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         palette[i].green = png_ptr->gamma_table[palette[i].green];
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         palette[i].blue = png_ptr->gamma_table[palette[i].blue];
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_BACKGROUND)
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_color back;
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back.red   = (png_byte)png_ptr->background.red;
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back.green = (png_byte)png_ptr->background.green;
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         back.blue  = (png_byte)png_ptr->background.blue;
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < (int)png_ptr->num_trans; i++)
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (png_ptr->trans[i] == 0)
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].red = back.red;
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].green = back.green;
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].blue = back.blue;
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (png_ptr->trans[i] != 0xff)
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_composite(palette[i].red, png_ptr->palette[i].red,
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->trans[i], back.red);
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_composite(palette[i].green, png_ptr->palette[i].green,
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->trans[i], back.green);
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_composite(palette[i].blue, png_ptr->palette[i].blue,
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_ptr->trans[i], back.blue);
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else /* Assume grayscale palette (what else could it be?) */
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int i;
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < num_palette; i++)
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (i == (png_byte)png_ptr->trans_values.gray)
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].red = (png_byte)png_ptr->background.red;
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].green = (png_byte)png_ptr->background.green;
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               palette[i].blue = (png_byte)png_ptr->background.blue;
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_BACKGROUND_SUPPORTED
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Replace any alpha or transparency with the supplied background color.
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "background" is already in the screen gamma, while "background_1" is
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * at a gamma of 1.0.  Paletted files have already been taken care of.
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_background(png_row_infop row_info, png_bytep row,
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_color_16p trans_values, png_color_16p background
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   , png_color_16p background_1,
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_16pp gamma_16_to_1, int gamma_shift
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   )
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep sp, dp;
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width=row_info->width;
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int shift;
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_background");
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (background != NULL &&
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (row_info->color_type)
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_GRAY:
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            switch (row_info->bit_depth)
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 1:
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 7;
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++)
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if ((png_uint_16)((*sp >> shift) & 0x01)
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        == trans_values->gray)
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp |= (png_byte)(background->gray << shift);
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (!shift)
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift = 7;
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sp++;
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift--;
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 2:
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (gamma_table != NULL)
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 6;
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++)
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if ((png_uint_16)((*sp >> shift) & 0x03)
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            == trans_values->gray)
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp |= (png_byte)(background->gray << shift);
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               (p << 4) | (p << 6)] >> 6) & 0x03);
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp |= (png_byte)(g << shift);
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (!shift)
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift = 6;
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sp++;
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift -= 2;
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 6;
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++)
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if ((png_uint_16)((*sp >> shift) & 0x03)
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            == trans_values->gray)
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp |= (png_byte)(background->gray << shift);
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (!shift)
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift = 6;
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sp++;
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift -= 2;
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 4:
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (gamma_table != NULL)
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 4;
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++)
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if ((png_uint_16)((*sp >> shift) & 0x0f)
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            == trans_values->gray)
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp |= (png_byte)(background->gray << shift);
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           png_byte g = (png_byte)((gamma_table[p |
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (p << 4)] >> 4) & 0x0f);
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp |= (png_byte)(g << shift);
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (!shift)
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift = 4;
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sp++;
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift -= 4;
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 4;
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++)
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if ((png_uint_16)((*sp >> shift) & 0x0f)
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            == trans_values->gray)
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp |= (png_byte)(background->gray << shift);
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (!shift)
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift = 4;
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sp++;
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           shift -= 4;
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 8:
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (gamma_table != NULL)
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++, sp++)
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (*sp == trans_values->gray)
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp = (png_byte)background->gray;
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp = gamma_table[*sp];
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++, sp++)
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (*sp == trans_values->gray)
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp = (png_byte)background->gray;
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 16:
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (gamma_16 != NULL)
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++, sp += 2)
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v;
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (v == trans_values->gray)
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           /* Background is already in screen gamma */
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp = (png_byte)((background->gray >> 8) & 0xff);
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *(sp + 1) = (png_byte)(background->gray & 0xff);
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp = (png_byte)((v >> 8) & 0xff);
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *(sp + 1) = (png_byte)(v & 0xff);
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp = row;
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     for (i = 0; i < row_width; i++, sp += 2)
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v;
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if (v == trans_values->gray)
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        {
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *sp = (png_byte)((background->gray >> 8) & 0xff);
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           *(sp + 1) = (png_byte)(background->gray & 0xff);
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        }
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_RGB:
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (gamma_table != NULL)
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 3)
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (*sp == trans_values->red &&
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) == trans_values->green &&
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) == trans_values->blue)
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp = (png_byte)background->red;
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) = (png_byte)background->green;
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) = (png_byte)background->blue;
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp = gamma_table[*sp];
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) = gamma_table[*(sp + 1)];
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) = gamma_table[*(sp + 2)];
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 3)
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (*sp == trans_values->red &&
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) == trans_values->green &&
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) == trans_values->blue)
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp = (png_byte)background->red;
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) = (png_byte)background->green;
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) = (png_byte)background->blue;
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else /* if (row_info->bit_depth == 16) */
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (gamma_16 != NULL)
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 6)
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (r == trans_values->red && g == trans_values->green &&
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        b == trans_values->blue)
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        /* Background is already in screen gamma */
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp = (png_byte)((background->red >> 8) & 0xff);
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) = (png_byte)(background->red & 0xff);
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 3) = (png_byte)(background->green & 0xff);
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 5) = (png_byte)(background->blue & 0xff);
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp = (png_byte)((v >> 8) & 0xff);
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) = (png_byte)(v & 0xff);
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 3) = (png_byte)(v & 0xff);
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 5) = (png_byte)(v & 0xff);
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 6)
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (r == trans_values->red && g == trans_values->green &&
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        b == trans_values->blue)
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *sp = (png_byte)((background->red >> 8) & 0xff);
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 1) = (png_byte)(background->red & 0xff);
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 3) = (png_byte)(background->green & 0xff);
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(sp + 5) = (png_byte)(background->blue & 0xff);
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_GRAY_ALPHA:
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   gamma_table != NULL)
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 2, dp++)
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 a = *(sp + 1);
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == 0xff)
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = gamma_table[*sp];
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        /* Background is already in screen gamma */
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)background->gray;
31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_byte v, w;
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_to_1[*sp];
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(w, v, a, background_1->gray);
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = gamma_from_1[w];
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 2, dp++)
31995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_byte a = *(sp + 1);
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == 0xff)
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = *sp;
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)background->gray;
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(*dp, *sp, a, background_1->gray);
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp = (png_byte)background->gray;
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else /* if (png_ptr->bit_depth == 16) */
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   gamma_16_to_1 != NULL)
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == (png_uint_16)0xffff)
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v;
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((v >> 8) & 0xff);
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(v & 0xff);
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        /* Background is already in screen gamma */
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((background->gray >> 8) & 0xff);
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(background->gray & 0xff);
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 g, v, w;
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(v, g, a, background_1->gray);
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((w >> 8) & 0xff);
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(w & 0xff);
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == (png_uint_16)0xffff)
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_memcpy(dp, sp, 2);
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((background->gray >> 8) & 0xff);
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(background->gray & 0xff);
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 g, v;
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(v, g, a, background_1->gray);
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((v >> 8) & 0xff);
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(v & 0xff);
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_RGB_ALPHA:
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   gamma_table != NULL)
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_byte a = *(sp + 3);
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == 0xff)
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = gamma_table[*sp];
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = gamma_table[*(sp + 1)];
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = gamma_table[*(sp + 2)];
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        /* Background is already in screen gamma */
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)background->red;
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)background->green;
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)background->blue;
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_byte v, w;
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_to_1[*sp];
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(w, v, a, background_1->red);
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = gamma_from_1[w];
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_to_1[*(sp + 1)];
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(w, v, a, background_1->green);
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = gamma_from_1[w];
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_to_1[*(sp + 2)];
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(w, v, a, background_1->blue);
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = gamma_from_1[w];
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_byte a = *(sp + 3);
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == 0xff)
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = *sp;
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = *(sp + 1);
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = *(sp + 2);
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)background->red;
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)background->green;
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)background->blue;
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(*dp, *sp, a, background->red);
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(*(dp + 1), *(sp + 1), a,
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           background->green);
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite(*(dp + 2), *(sp + 2), a,
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           background->blue);
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else /* if (row_info->bit_depth == 16) */
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   gamma_16_to_1 != NULL)
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         << 8) + (png_uint_16)(*(sp + 7)));
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == (png_uint_16)0xffff)
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v;
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((v >> 8) & 0xff);
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(v & 0xff);
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 3) = (png_byte)(v & 0xff);
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 5) = (png_byte)(v & 0xff);
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        /* Background is already in screen gamma */
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((background->red >> 8) & 0xff);
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(background->red & 0xff);
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 3) = (png_byte)(background->green & 0xff);
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 5) = (png_byte)(background->blue & 0xff);
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v, w, x;
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(w, v, a, background_1->red);
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((x >> 8) & 0xff);
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(x & 0xff);
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(w, v, a, background_1->green);
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)((x >> 8) & 0xff);
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 3) = (png_byte)(x & 0xff);
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(w, v, a, background_1->blue);
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 4) = (png_byte)((x >> 8) & 0xff);
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 5) = (png_byte)(x & 0xff);
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row;
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row;
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        << 8) + (png_uint_16)(*(sp + 7)));
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (a == (png_uint_16)0xffff)
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_memcpy(dp, sp, 6);
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else if (a == 0)
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((background->red >> 8) & 0xff);
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(background->red & 0xff);
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 3) = (png_byte)(background->green & 0xff);
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 5) = (png_byte)(background->blue & 0xff);
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 v;
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            + *(sp + 3));
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            + *(sp + 5));
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(v, r, a, background->red);
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = (png_byte)((v >> 8) & 0xff);
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 1) = (png_byte)(v & 0xff);
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(v, g, a, background->green);
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 3) = (png_byte)(v & 0xff);
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        png_composite_16(v, b, a, background->blue);
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *(dp + 5) = (png_byte)(v & 0xff);
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->channels--;
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->pixel_depth = (png_byte)(row_info->channels *
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->bit_depth);
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Gamma correct the image, avoiding the alpha channel.  Make sure
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * you do this after you deal with the transparency issue on grayscale
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or RGB images. If your bit depth is 8, use gamma_table, if it
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is 16, use gamma_16_table and gamma_shift.  Build these with
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * build_gamma_table().
35035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
35045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
35055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_gamma(png_row_infop row_info, png_bytep row,
35065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep gamma_table, png_uint_16pp gamma_16_table,
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int gamma_shift)
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep sp;
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width=row_info->width;
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_gamma");
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
35165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
35175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
35185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
35195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
35205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
35215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
35225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (row_info->color_type)
35235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
35245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_RGB:
35255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else /* if (row_info->bit_depth == 16) */
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
35435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 v;
35455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
35525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
35615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
35625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_RGB_ALPHA:
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
35735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else /* if (row_info->bit_depth == 16) */
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
35825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
35845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
35855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
35875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
35895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
35905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
35915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
35925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
35935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
35945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 4;
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
35995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
36005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_GRAY_ALPHA:
36025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
36035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
36045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
36055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
36065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
36075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
36085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
36095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
36105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
36115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
36125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else /* if (row_info->bit_depth == 16) */
36135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
36145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
36155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
36165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
36195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
36205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 4;
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
36225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
36235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
36245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
36255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PNG_COLOR_TYPE_GRAY:
36275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
36285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 2)
36295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
36305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
36315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i += 4)
36325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
36335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int a = *sp & 0xc0;
36345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int b = *sp & 0x30;
36355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int c = *sp & 0x0c;
36365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int d = *sp & 0x03;
36375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)(
36395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
36405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
36415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
36425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
36435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
36445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
36455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
36465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 4)
36485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
36495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
36505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i += 2)
36515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
36525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int msb = *sp & 0xf0;
36535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int lsb = *sp & 0x0f;
36545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
36565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
36605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (row_info->bit_depth == 8)
36625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
36645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
36655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = gamma_table[*sp];
36675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp++;
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
36695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
36705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (row_info->bit_depth == 16)
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row;
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *sp = (png_byte)((v >> 8) & 0xff);
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp + 1) = (png_byte)(v & 0xff);
36795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp += 2;
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_EXPAND_SUPPORTED
36905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Expands a palette row to an RGB or RGBA row depending
36915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * upon whether you supply trans and num_trans.
36925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
36935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
36945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_expand_palette(png_row_infop row_info, png_bytep row,
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_colorp palette, png_bytep trans, int num_trans)
36965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
36975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int shift, value;
36985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep sp, dp;
36995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width=row_info->width;
37015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_expand_palette");
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
37075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
37085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
37095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
37105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->bit_depth < 8)
37115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
37125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         switch (row_info->bit_depth)
37135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 1:
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
37165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + (png_size_t)((row_width - 1) >> 3);
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (png_size_t)row_width - 1;
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               shift = 7 - (int)((row_width + 7) & 0x07);
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
37215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if ((*sp >> shift) & 0x01)
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp = 1;
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp = 0;
37255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (shift == 7)
37265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
37275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 0;
37285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp--;
37295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
37305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
37315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift++;
37325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp--;
37345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
37355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
37365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
37375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 2:
37395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
37405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + (png_size_t)((row_width - 1) >> 2);
37415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (png_size_t)row_width - 1;
37425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
37435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
37445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
37455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  value = (*sp >> shift) & 0x03;
37465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp = (png_byte)value;
37475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (shift == 6)
37485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
37495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 0;
37505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp--;
37515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
37525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
37535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift += 2;
37545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp--;
37565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
37575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
37585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
37595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case 4:
37615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
37625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + (png_size_t)((row_width - 1) >> 1);
37635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (png_size_t)row_width - 1;
37645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               shift = (int)((row_width & 0x01) << 2);
37655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
37665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
37675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  value = (*sp >> shift) & 0x0f;
37685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp = (png_byte)value;
37695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (shift == 4)
37705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
37715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift = 0;
37725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     sp--;
37735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
37745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
37755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     shift += 4;
37765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp--;
37785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
37795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               break;
37805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
37815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
37825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->bit_depth = 8;
37835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->pixel_depth = 8;
37845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->rowbytes = row_width;
37855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
37865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (row_info->bit_depth)
37875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
37885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 8:
37895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
37905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (trans != NULL)
37915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
37925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + (png_size_t)row_width - 1;
37935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (png_size_t)(row_width << 2) - 1;
37945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
37965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
37975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if ((int)(*sp) >= num_trans)
37985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0xff;
37995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
38005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = trans[*sp];
38015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = palette[*sp].blue;
38025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = palette[*sp].green;
38035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = palette[*sp].red;
38045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp--;
38055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
38065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->bit_depth = 8;
38075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->pixel_depth = 32;
38085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->rowbytes = row_width * 4;
38095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->color_type = 6;
38105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->channels = 4;
38115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
38125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
38135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
38145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + (png_size_t)row_width - 1;
38155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (png_size_t)(row_width * 3) - 1;
38165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
38185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
38195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = palette[*sp].blue;
38205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = palette[*sp].green;
38215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = palette[*sp].red;
38225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp--;
38235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
38245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->bit_depth = 8;
38265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->pixel_depth = 24;
38275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->rowbytes = row_width * 3;
38285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->color_type = 2;
38295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_info->channels = 3;
38305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
38315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
38325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
38335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
38355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
38365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* If the bit depth < 8, it is expanded to 8.  Also, if the already
38385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * expanded transparency value is supplied, an alpha channel is built.
38395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
38405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
38415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_expand(png_row_infop row_info, png_bytep row,
38425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_color_16p trans_value)
38435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
38445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int shift, value;
38455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep sp, dp;
38465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
38475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width=row_info->width;
38485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_expand");
38505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
38525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL)
38535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
38545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
38555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
38565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
38575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
38585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth < 8)
38605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
38615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            switch (row_info->bit_depth)
38625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
38635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 1:
38645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
38655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gray = (png_uint_16)((gray&0x01)*0xff);
38665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row + (png_size_t)((row_width - 1) >> 3);
38675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row + (png_size_t)row_width - 1;
38685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 7 - (int)((row_width + 7) & 0x07);
38695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++)
38705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
38715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if ((*sp >> shift) & 0x01)
38725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = 0xff;
38735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
38745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        *dp = 0;
38755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (shift == 7)
38765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
38775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift = 0;
38785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sp--;
38795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
38805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
38815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift++;
38825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     dp--;
38845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
38855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
38865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
38875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 2:
38895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
38905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gray = (png_uint_16)((gray&0x03)*0x55);
38915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row + (png_size_t)((row_width - 1) >> 2);
38925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row + (png_size_t)row_width - 1;
38935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
38945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++)
38955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
38965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     value = (*sp >> shift) & 0x03;
38975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
38985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        (value << 6));
38995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (shift == 6)
39005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
39015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift = 0;
39025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sp--;
39035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
39045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
39055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift += 2;
39065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     dp--;
39085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
39095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
39105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
39115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               case 4:
39135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
39145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  gray = (png_uint_16)((gray&0x0f)*0x11);
39155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  sp = row + (png_size_t)((row_width - 1) >> 1);
39165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp = row + (png_size_t)row_width - 1;
39175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
39185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  for (i = 0; i < row_width; i++)
39195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
39205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     value = (*sp >> shift) & 0x0f;
39215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp = (png_byte)(value | (value << 4));
39225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     if (shift == 4)
39235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     {
39245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift = 0;
39255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sp--;
39265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     }
39275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     else
39285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        shift = 4;
39295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     dp--;
39315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
39325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  break;
39335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
39345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
39355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->bit_depth = 8;
39375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = 8;
39385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = row_width;
39395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
39405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (trans_value != NULL)
39425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
39435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (row_info->bit_depth == 8)
39445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
39455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               gray = gray & 0xff;
39465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + (png_size_t)row_width - 1;
39475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (png_size_t)(row_width << 1) - 1;
39485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
39495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
39505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (*sp == gray)
39515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0;
39525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
39535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0xff;
39545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = *sp--;
39555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
39565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
39575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (row_info->bit_depth == 16)
39595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
39605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte gray_high = (gray >> 8) & 0xff;
39615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte gray_low = gray & 0xff;
39625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp = row + row_info->rowbytes - 1;
39635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               dp = row + (row_info->rowbytes << 1) - 1;
39645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               for (i = 0; i < row_width; i++)
39655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
39665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
39675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
39685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0;
39695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0;
39705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
39715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  else
39725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  {
39735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0xff;
39745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     *dp-- = 0xff;
39755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  }
39765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = *sp--;
39775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = *sp--;
39785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
39795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
39805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
39825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->channels = 2;
39835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
39845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
39855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               row_width);
39865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
39875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
39885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
39895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
39905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
39915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
39925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte red = trans_value->red & 0xff;
39935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte green = trans_value->green & 0xff;
39945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte blue = trans_value->blue & 0xff;
39955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sp = row + (png_size_t)row_info->rowbytes - 1;
39965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dp = row + (png_size_t)(row_width << 2) - 1;
39975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
39985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
39995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
40005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = 0;
40015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
40025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = 0xff;
40035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
40075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
40085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (row_info->bit_depth == 16)
40095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
40105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte red_high = (trans_value->red >> 8) & 0xff;
40115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte green_high = (trans_value->green >> 8) & 0xff;
40125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte blue_high = (trans_value->blue >> 8) & 0xff;
40135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte red_low = trans_value->red & 0xff;
40145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte green_low = trans_value->green & 0xff;
40155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_byte blue_low = trans_value->blue & 0xff;
40165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sp = row + row_info->rowbytes - 1;
40175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dp = row + (png_size_t)(row_width << 3) - 1;
40185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
40195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
40205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (*(sp - 5) == red_high &&
40215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp - 4) == red_low &&
40225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp - 3) == green_high &&
40235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp - 2) == green_low &&
40245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp - 1) == blue_high &&
40255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *(sp    ) == blue_low)
40265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
40275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = 0;
40285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = 0;
40295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
40305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
40315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
40325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = 0xff;
40335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp-- = 0xff;
40345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
40355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp-- = *sp--;
40415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
40425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
40435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
40445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->channels = 4;
40455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
40465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
40475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
40485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
40495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
40515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_DITHER_SUPPORTED
40535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
40545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_dither(png_row_infop row_info, png_bytep row,
40555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    png_bytep palette_lookup, png_bytep dither_lookup)
40565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
40575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_bytep sp, dp;
40585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 i;
40595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_uint_32 row_width=row_info->width;
40605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_dither");
40625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
40645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL)
40655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
40665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
40675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
40685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         palette_lookup && row_info->bit_depth == 8)
40695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
40705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int r, g, b, p;
40715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sp = row;
40725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         dp = row;
40735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < row_width; i++)
40745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
40755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            r = *sp++;
40765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            g = *sp++;
40775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            b = *sp++;
40785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* This looks real messy, but the compiler will reduce
40805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * it down to a reasonable formula.  For example, with
40815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * 5 bits per color, we get:
40825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * p = (((r >> 3) & 0x1f) << 10) |
40835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             *    (((g >> 3) & 0x1f) << 5) |
40845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             *    ((b >> 3) & 0x1f);
40855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             */
40865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
40875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
40885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
40895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
40905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
40915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (PNG_DITHER_BLUE_BITS)) |
40925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
40935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((1 << PNG_DITHER_BLUE_BITS) - 1));
40945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *dp++ = palette_lookup[p];
40965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
40975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
40985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->channels = 1;
40995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->pixel_depth = row_info->bit_depth;
41005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
41015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
41025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
41035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         palette_lookup != NULL && row_info->bit_depth == 8)
41045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
41055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int r, g, b, p;
41065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sp = row;
41075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         dp = row;
41085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < row_width; i++)
41095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
41105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            r = *sp++;
41115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            g = *sp++;
41125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            b = *sp++;
41135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sp++;
41145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
41165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
41175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
41185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
41195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
41205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (PNG_DITHER_BLUE_BITS)) |
41215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
41225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((1 << PNG_DITHER_BLUE_BITS) - 1));
41235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *dp++ = palette_lookup[p];
41255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
41265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
41275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->channels = 1;
41285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->pixel_depth = row_info->bit_depth;
41295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
41305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
41315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
41325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         dither_lookup && row_info->bit_depth == 8)
41335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
41345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sp = row;
41355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < row_width; i++, sp++)
41365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
41375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *sp = dither_lookup[*sp];
41385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
41395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
41405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
41415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
41435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FLOATING_POINT_SUPPORTED
41455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_READ_GAMMA_SUPPORTED
41465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PNG_CONST int png_gamma_shift[] =
41475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
41485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
41505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * tables, we don't make a full table if we are reducing to 8-bit in
41515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the future.  Note also how the gamma_16 tables are segmented so that
41525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we don't need to allocate > 64K chunks for a full 16-bit table.
41535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the PNG extensions document for an integer algorithm for creating
41555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the gamma tables.  Maybe we will implement that here someday.
41565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We should only reach this point if
41585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      the file_gamma is known (i.e., the gAMA or sRGB chunk is present,
41605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      or the application has provided a file_gamma)
41615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   AND
41635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      {
41645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         the screen_gamma is known
41655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      OR
41665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         RGB_to_gray transformation is being performed
41685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      }
41695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   AND
41715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      {
41725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         the screen_gamma is different from the reciprocal of the
41735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         file_gamma by more than the specified threshold
41745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      OR
41765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
41775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         a background color has been specified and the file_gamma
41785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         and screen_gamma are not 1.0, within the specified threshold.
41795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      }
41805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
41815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
41835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_build_gamma_table(png_structp png_ptr)
41845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
41855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  png_debug(1, "in png_build_gamma_table");
41865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (png_ptr->bit_depth <= 8)
41885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
41895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     int i;
41905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     double g;
41915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->screen_gamma > .000001)
41935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
41945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     else
41965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0;
41975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
41995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (png_uint_32)256);
42005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     for (i = 0; i < 256; i++)
42025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
42035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
42045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           g) * 255.0 + .5);
42055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
42065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
42085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
42095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
42105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
42115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0 / (png_ptr->gamma);
42135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
42155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (png_uint_32)256);
42165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < 256; i++)
42185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
42195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
42205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              g) * 255.0 + .5);
42215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
42225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
42255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (png_uint_32)256);
42265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (png_ptr->screen_gamma > 0.000001)
42285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           g = 1.0 / png_ptr->screen_gamma;
42295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
42315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
42325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < 256; i++)
42345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
42355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
42365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              g) * 255.0 + .5);
42375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
42395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
42405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
42415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
42435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
42445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     double g;
42455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     int i, j, shift, num;
42465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     int sig_bit;
42475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     png_uint_32 ig;
42485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
42505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
42515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sig_bit = (int)png_ptr->sig_bit.red;
42525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((int)png_ptr->sig_bit.green > sig_bit)
42545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           sig_bit = png_ptr->sig_bit.green;
42555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((int)png_ptr->sig_bit.blue > sig_bit)
42575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           sig_bit = png_ptr->sig_bit.blue;
42585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
42595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     else
42605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
42615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sig_bit = (int)png_ptr->sig_bit.gray;
42625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
42635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (sig_bit > 0)
42655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shift = 16 - sig_bit;
42665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     else
42685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shift = 0;
42695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->transformations & PNG_16_TO_8)
42715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
42725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (shift < (16 - PNG_MAX_GAMMA_8))
42735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           shift = (16 - PNG_MAX_GAMMA_8);
42745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
42755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (shift > 8)
42775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shift = 8;
42785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (shift < 0)
42805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shift = 0;
42815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     png_ptr->gamma_shift = (png_byte)shift;
42835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     num = (1 << (8 - shift));
42855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->screen_gamma > .000001)
42875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
42885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     else
42895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0;
42905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr,
42925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (png_uint_32)(num * png_sizeof(png_uint_16p)));
42935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
42955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
42965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double fin, fout;
42975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_uint_32 last, max;
42985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < num; i++)
43005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
43015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
43025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_uint_32)(256 * png_sizeof(png_uint_16)));
43035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
43045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0 / g;
43065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last = 0;
43075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < 256; i++)
43085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
43095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           fout = ((double)i + 0.5) / 256.0;
43105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           fin = pow(fout, g);
43115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
43125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           while (last <= max)
43135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           {
43145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
43155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 [(int)(last >> (8 - shift))] = (png_uint_16)(
43165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (png_uint_16)i | ((png_uint_16)i << 8));
43175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              last++;
43185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           }
43195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
43205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (last < ((png_uint_32)num << 8))
43215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
43225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
43235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
43245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           last++;
43255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
43265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
43275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     else
43285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
43295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < num; i++)
43305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
43315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
43325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_uint_32)(256 * png_sizeof(png_uint_16)));
43335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
43355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           for (j = 0; j < 256; j++)
43375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           {
43385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              png_ptr->gamma_16_table[i][j] =
43395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
43405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    65535.0, g) * 65535.0 + .5);
43415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           }
43425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
43435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
43445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
43465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
43475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
43485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     {
43495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g = 1.0 / (png_ptr->gamma);
43515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr,
43535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (png_uint_32)(num * png_sizeof(png_uint_16p )));
43545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < num; i++)
43565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
43575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
43585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_uint_32)(256 * png_sizeof(png_uint_16)));
43595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ig = (((png_uint_32)i *
43615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_uint_32)png_gamma_shift[shift]) >> 4);
43625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           for (j = 0; j < 256; j++)
43635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           {
43645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              png_ptr->gamma_16_to_1[i][j] =
43655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
43665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    65535.0, g) * 65535.0 + .5);
43675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           }
43685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
43695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (png_ptr->screen_gamma > 0.000001)
43715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           g = 1.0 / png_ptr->screen_gamma;
43725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
43745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
43755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr,
43775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (png_uint_32)(num * png_sizeof(png_uint_16p)));
43785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < num; i++)
43805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
43815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
43825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_uint_32)(256 * png_sizeof(png_uint_16)));
43835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ig = (((png_uint_32)i *
43855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (png_uint_32)png_gamma_shift[shift]) >> 4);
43865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           for (j = 0; j < 256; j++)
43885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           {
43895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              png_ptr->gamma_16_from_1[i][j] =
43905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
43915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    65535.0, g) * 65535.0 + .5);
43925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           }
43935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
43945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
43955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
43965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
43985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
43995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* To do: install integer version of png_build_gamma_table here */
44005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
44015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_MNG_FEATURES_SUPPORTED
44035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Undoes intrapixel differencing  */
44045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
44055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
44065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
44075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_read_intrapixel");
44085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
44105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
44115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
44125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
44135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (row_info->color_type & PNG_COLOR_MASK_COLOR))
44145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
44155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int bytes_per_pixel;
44165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 row_width = row_info->width;
44175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->bit_depth == 8)
44185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
44195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep rp;
44205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
44215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
44235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 3;
44245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
44265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 4;
44275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
44295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
44305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
44325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
44335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
44345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
44355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
44365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
44375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->bit_depth == 16)
44385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
44395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep rp;
44405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
44415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
44435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 6;
44445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
44465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 8;
44475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
44495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
44505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
44525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
44535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
44545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
44555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
44565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 red  = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
44575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
44585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp  ) = (png_byte)((red >> 8) & 0xff);
44595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+1) = (png_byte)(red & 0xff);
44605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+4) = (png_byte)((blue >> 8) & 0xff);
44615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+5) = (png_byte)(blue & 0xff);
44625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
44635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
44645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
44655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_MNG_FEATURES_SUPPORTED */
44675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_READ_SUPPORTED */
4468