xref: /plan9/sys/src/cmd/gs/libpng/pngrtran.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier 
27dd7cddfSDavid du Colombier /* pngrtran.c - transforms the data in a row for PNG readers
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * libpng version  1.2.8 - December 3, 2004
57dd7cddfSDavid du Colombier  * For conditions of distribution and use, see copyright notice in png.h
6*593dc095SDavid du Colombier  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7*593dc095SDavid du Colombier  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8*593dc095SDavid du Colombier  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
97dd7cddfSDavid du Colombier  *
107dd7cddfSDavid du Colombier  * This file contains functions optionally called by an application
117dd7cddfSDavid du Colombier  * in order to tell libpng how to handle data when reading a PNG.
12*593dc095SDavid du Colombier  * Transformations that are used in both reading and writing are
137dd7cddfSDavid du Colombier  * in pngtrans.c.
147dd7cddfSDavid du Colombier  */
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier #define PNG_INTERNAL
177dd7cddfSDavid du Colombier #include "png.h"
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier /* Set the action on getting a CRC error for an ancillary or critical chunk. */
20*593dc095SDavid du Colombier void PNGAPI
png_set_crc_action(png_structp png_ptr,int crit_action,int ancil_action)217dd7cddfSDavid du Colombier png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
227dd7cddfSDavid du Colombier {
237dd7cddfSDavid du Colombier    png_debug(1, "in png_set_crc_action\n");
247dd7cddfSDavid du Colombier    /* Tell libpng how we react to CRC errors in critical chunks */
257dd7cddfSDavid du Colombier    switch (crit_action)
267dd7cddfSDavid du Colombier    {
277dd7cddfSDavid du Colombier       case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
287dd7cddfSDavid du Colombier          break;
297dd7cddfSDavid du Colombier       case PNG_CRC_WARN_USE:                               /* warn/use data */
307dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
317dd7cddfSDavid du Colombier          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
327dd7cddfSDavid du Colombier          break;
337dd7cddfSDavid du Colombier       case PNG_CRC_QUIET_USE:                             /* quiet/use data */
347dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
357dd7cddfSDavid du Colombier          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
367dd7cddfSDavid du Colombier                            PNG_FLAG_CRC_CRITICAL_IGNORE;
377dd7cddfSDavid du Colombier          break;
387dd7cddfSDavid du Colombier       case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
397dd7cddfSDavid du Colombier          png_warning(png_ptr, "Can't discard critical data on CRC error.");
407dd7cddfSDavid du Colombier       case PNG_CRC_ERROR_QUIT:                                /* error/quit */
417dd7cddfSDavid du Colombier       case PNG_CRC_DEFAULT:
427dd7cddfSDavid du Colombier       default:
437dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
447dd7cddfSDavid du Colombier          break;
457dd7cddfSDavid du Colombier    }
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier    switch (ancil_action)
487dd7cddfSDavid du Colombier    {
497dd7cddfSDavid du Colombier       case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
507dd7cddfSDavid du Colombier          break;
517dd7cddfSDavid du Colombier       case PNG_CRC_WARN_USE:                              /* warn/use data */
527dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
537dd7cddfSDavid du Colombier          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
547dd7cddfSDavid du Colombier          break;
557dd7cddfSDavid du Colombier       case PNG_CRC_QUIET_USE:                            /* quiet/use data */
567dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
577dd7cddfSDavid du Colombier          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
587dd7cddfSDavid du Colombier                            PNG_FLAG_CRC_ANCILLARY_NOWARN;
597dd7cddfSDavid du Colombier          break;
607dd7cddfSDavid du Colombier       case PNG_CRC_ERROR_QUIT:                               /* error/quit */
617dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
627dd7cddfSDavid du Colombier          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
637dd7cddfSDavid du Colombier          break;
647dd7cddfSDavid du Colombier       case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
657dd7cddfSDavid du Colombier       case PNG_CRC_DEFAULT:
667dd7cddfSDavid du Colombier       default:
677dd7cddfSDavid du Colombier          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
687dd7cddfSDavid du Colombier          break;
697dd7cddfSDavid du Colombier    }
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier 
72*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
73*593dc095SDavid du Colombier     defined(PNG_FLOATING_POINT_SUPPORTED)
747dd7cddfSDavid du Colombier /* handle alpha and tRNS via a background color */
75*593dc095SDavid du Colombier void PNGAPI
png_set_background(png_structp png_ptr,png_color_16p background_color,int background_gamma_code,int need_expand,double background_gamma)767dd7cddfSDavid du Colombier png_set_background(png_structp png_ptr,
777dd7cddfSDavid du Colombier    png_color_16p background_color, int background_gamma_code,
787dd7cddfSDavid du Colombier    int need_expand, double background_gamma)
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier    png_debug(1, "in png_set_background\n");
817dd7cddfSDavid du Colombier    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
827dd7cddfSDavid du Colombier    {
837dd7cddfSDavid du Colombier       png_warning(png_ptr, "Application must supply a known background gamma");
847dd7cddfSDavid du Colombier       return;
857dd7cddfSDavid du Colombier    }
867dd7cddfSDavid du Colombier 
877dd7cddfSDavid du Colombier    png_ptr->transformations |= PNG_BACKGROUND;
887dd7cddfSDavid du Colombier    png_memcpy(&(png_ptr->background), background_color,
89*593dc095SDavid du Colombier       png_sizeof(png_color_16));
907dd7cddfSDavid du Colombier    png_ptr->background_gamma = (float)background_gamma;
917dd7cddfSDavid du Colombier    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
927dd7cddfSDavid du Colombier    png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
93*593dc095SDavid du Colombier 
94*593dc095SDavid du Colombier    /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
95*593dc095SDavid du Colombier     * (in which case need_expand is superfluous anyway), the background color
96*593dc095SDavid du Colombier     * might actually be gray yet not be flagged as such. This is not a problem
97*593dc095SDavid du Colombier     * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
98*593dc095SDavid du Colombier     * decide when to do the png_do_gray_to_rgb() transformation.
99*593dc095SDavid du Colombier     */
100*593dc095SDavid du Colombier    if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
101*593dc095SDavid du Colombier        (!need_expand && background_color->red == background_color->green &&
102*593dc095SDavid du Colombier         background_color->red == background_color->blue))
103*593dc095SDavid du Colombier       png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier #endif
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier #if defined(PNG_READ_16_TO_8_SUPPORTED)
1087dd7cddfSDavid du Colombier /* strip 16 bit depth files to 8 bit depth */
109*593dc095SDavid du Colombier void PNGAPI
png_set_strip_16(png_structp png_ptr)1107dd7cddfSDavid du Colombier png_set_strip_16(png_structp png_ptr)
1117dd7cddfSDavid du Colombier {
1127dd7cddfSDavid du Colombier    png_debug(1, "in png_set_strip_16\n");
1137dd7cddfSDavid du Colombier    png_ptr->transformations |= PNG_16_TO_8;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier #endif
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
118*593dc095SDavid du Colombier void PNGAPI
png_set_strip_alpha(png_structp png_ptr)1197dd7cddfSDavid du Colombier png_set_strip_alpha(png_structp png_ptr)
1207dd7cddfSDavid du Colombier {
1217dd7cddfSDavid du Colombier    png_debug(1, "in png_set_strip_alpha\n");
122*593dc095SDavid du Colombier    png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
1237dd7cddfSDavid du Colombier }
1247dd7cddfSDavid du Colombier #endif
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier #if defined(PNG_READ_DITHER_SUPPORTED)
1277dd7cddfSDavid du Colombier /* Dither file to 8 bit.  Supply a palette, the current number
1287dd7cddfSDavid du Colombier  * of elements in the palette, the maximum number of elements
1297dd7cddfSDavid du Colombier  * allowed, and a histogram if possible.  If the current number
1307dd7cddfSDavid du Colombier  * of colors is greater then the maximum number, the palette will be
1317dd7cddfSDavid du Colombier  * modified to fit in the maximum number.  "full_dither" indicates
1327dd7cddfSDavid du Colombier  * whether we need a dithering cube set up for RGB images, or if we
1337dd7cddfSDavid du Colombier  * simply are reducing the number of colors in a paletted image.
1347dd7cddfSDavid du Colombier  */
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier typedef struct png_dsort_struct
1377dd7cddfSDavid du Colombier {
1387dd7cddfSDavid du Colombier    struct png_dsort_struct FAR * next;
1397dd7cddfSDavid du Colombier    png_byte left;
1407dd7cddfSDavid du Colombier    png_byte right;
1417dd7cddfSDavid du Colombier } png_dsort;
1427dd7cddfSDavid du Colombier typedef png_dsort FAR *       png_dsortp;
1437dd7cddfSDavid du Colombier typedef png_dsort FAR * FAR * png_dsortpp;
1447dd7cddfSDavid du Colombier 
145*593dc095SDavid du Colombier void PNGAPI
png_set_dither(png_structp png_ptr,png_colorp palette,int num_palette,int maximum_colors,png_uint_16p histogram,int full_dither)1467dd7cddfSDavid du Colombier png_set_dither(png_structp png_ptr, png_colorp palette,
1477dd7cddfSDavid du Colombier    int num_palette, int maximum_colors, png_uint_16p histogram,
1487dd7cddfSDavid du Colombier    int full_dither)
1497dd7cddfSDavid du Colombier {
1507dd7cddfSDavid du Colombier    png_debug(1, "in png_set_dither\n");
1517dd7cddfSDavid du Colombier    png_ptr->transformations |= PNG_DITHER;
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier    if (!full_dither)
1547dd7cddfSDavid du Colombier    {
1557dd7cddfSDavid du Colombier       int i;
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier       png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
158*593dc095SDavid du Colombier          (png_uint_32)(num_palette * png_sizeof (png_byte)));
1597dd7cddfSDavid du Colombier       for (i = 0; i < num_palette; i++)
1607dd7cddfSDavid du Colombier          png_ptr->dither_index[i] = (png_byte)i;
1617dd7cddfSDavid du Colombier    }
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier    if (num_palette > maximum_colors)
1647dd7cddfSDavid du Colombier    {
1657dd7cddfSDavid du Colombier       if (histogram != NULL)
1667dd7cddfSDavid du Colombier       {
1677dd7cddfSDavid du Colombier          /* This is easy enough, just throw out the least used colors.
1687dd7cddfSDavid du Colombier             Perhaps not the best solution, but good enough. */
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier          int i;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier          /* initialize an array to sort colors */
173*593dc095SDavid du Colombier          png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
174*593dc095SDavid du Colombier             (png_uint_32)(num_palette * png_sizeof (png_byte)));
1757dd7cddfSDavid du Colombier 
176*593dc095SDavid du Colombier          /* initialize the dither_sort array */
1777dd7cddfSDavid du Colombier          for (i = 0; i < num_palette; i++)
178*593dc095SDavid du Colombier             png_ptr->dither_sort[i] = (png_byte)i;
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier          /* Find the least used palette entries by starting a
1817dd7cddfSDavid du Colombier             bubble sort, and running it until we have sorted
1827dd7cddfSDavid du Colombier             out enough colors.  Note that we don't care about
1837dd7cddfSDavid du Colombier             sorting all the colors, just finding which are
1847dd7cddfSDavid du Colombier             least used. */
1857dd7cddfSDavid du Colombier 
1867dd7cddfSDavid du Colombier          for (i = num_palette - 1; i >= maximum_colors; i--)
1877dd7cddfSDavid du Colombier          {
1887dd7cddfSDavid du Colombier             int done; /* to stop early if the list is pre-sorted */
1897dd7cddfSDavid du Colombier             int j;
1907dd7cddfSDavid du Colombier 
1917dd7cddfSDavid du Colombier             done = 1;
1927dd7cddfSDavid du Colombier             for (j = 0; j < i; j++)
1937dd7cddfSDavid du Colombier             {
194*593dc095SDavid du Colombier                if (histogram[png_ptr->dither_sort[j]]
195*593dc095SDavid du Colombier                    < histogram[png_ptr->dither_sort[j + 1]])
1967dd7cddfSDavid du Colombier                {
1977dd7cddfSDavid du Colombier                   png_byte t;
1987dd7cddfSDavid du Colombier 
199*593dc095SDavid du Colombier                   t = png_ptr->dither_sort[j];
200*593dc095SDavid du Colombier                   png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
201*593dc095SDavid du Colombier                   png_ptr->dither_sort[j + 1] = t;
2027dd7cddfSDavid du Colombier                   done = 0;
2037dd7cddfSDavid du Colombier                }
2047dd7cddfSDavid du Colombier             }
2057dd7cddfSDavid du Colombier             if (done)
2067dd7cddfSDavid du Colombier                break;
2077dd7cddfSDavid du Colombier          }
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier          /* swap the palette around, and set up a table, if necessary */
2107dd7cddfSDavid du Colombier          if (full_dither)
2117dd7cddfSDavid du Colombier          {
212*593dc095SDavid du Colombier             int j = num_palette;
2137dd7cddfSDavid du Colombier 
2147dd7cddfSDavid du Colombier             /* put all the useful colors within the max, but don't
2157dd7cddfSDavid du Colombier                move the others */
216*593dc095SDavid du Colombier             for (i = 0; i < maximum_colors; i++)
2177dd7cddfSDavid du Colombier             {
218*593dc095SDavid du Colombier                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
2197dd7cddfSDavid du Colombier                {
2207dd7cddfSDavid du Colombier                   do
2217dd7cddfSDavid du Colombier                      j--;
222*593dc095SDavid du Colombier                   while ((int)png_ptr->dither_sort[j] >= maximum_colors);
2237dd7cddfSDavid du Colombier                   palette[i] = palette[j];
2247dd7cddfSDavid du Colombier                }
2257dd7cddfSDavid du Colombier             }
2267dd7cddfSDavid du Colombier          }
2277dd7cddfSDavid du Colombier          else
2287dd7cddfSDavid du Colombier          {
229*593dc095SDavid du Colombier             int j = num_palette;
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier             /* move all the used colors inside the max limit, and
2327dd7cddfSDavid du Colombier                develop a translation table */
233*593dc095SDavid du Colombier             for (i = 0; i < maximum_colors; i++)
2347dd7cddfSDavid du Colombier             {
2357dd7cddfSDavid du Colombier                /* only move the colors we need to */
236*593dc095SDavid du Colombier                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
2377dd7cddfSDavid du Colombier                {
2387dd7cddfSDavid du Colombier                   png_color tmp_color;
2397dd7cddfSDavid du Colombier 
2407dd7cddfSDavid du Colombier                   do
2417dd7cddfSDavid du Colombier                      j--;
242*593dc095SDavid du Colombier                   while ((int)png_ptr->dither_sort[j] >= maximum_colors);
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier                   tmp_color = palette[j];
2457dd7cddfSDavid du Colombier                   palette[j] = palette[i];
2467dd7cddfSDavid du Colombier                   palette[i] = tmp_color;
2477dd7cddfSDavid du Colombier                   /* indicate where the color went */
2487dd7cddfSDavid du Colombier                   png_ptr->dither_index[j] = (png_byte)i;
2497dd7cddfSDavid du Colombier                   png_ptr->dither_index[i] = (png_byte)j;
2507dd7cddfSDavid du Colombier                }
2517dd7cddfSDavid du Colombier             }
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier             /* find closest color for those colors we are not using */
2547dd7cddfSDavid du Colombier             for (i = 0; i < num_palette; i++)
2557dd7cddfSDavid du Colombier             {
256*593dc095SDavid du Colombier                if ((int)png_ptr->dither_index[i] >= maximum_colors)
2577dd7cddfSDavid du Colombier                {
2587dd7cddfSDavid du Colombier                   int min_d, k, min_k, d_index;
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier                   /* find the closest color to one we threw out */
2617dd7cddfSDavid du Colombier                   d_index = png_ptr->dither_index[i];
2627dd7cddfSDavid du Colombier                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
2637dd7cddfSDavid du Colombier                   for (k = 1, min_k = 0; k < maximum_colors; k++)
2647dd7cddfSDavid du Colombier                   {
2657dd7cddfSDavid du Colombier                      int d;
2667dd7cddfSDavid du Colombier 
2677dd7cddfSDavid du Colombier                      d = PNG_COLOR_DIST(palette[d_index], palette[k]);
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier                      if (d < min_d)
2707dd7cddfSDavid du Colombier                      {
2717dd7cddfSDavid du Colombier                         min_d = d;
2727dd7cddfSDavid du Colombier                         min_k = k;
2737dd7cddfSDavid du Colombier                      }
2747dd7cddfSDavid du Colombier                   }
2757dd7cddfSDavid du Colombier                   /* point to closest color */
2767dd7cddfSDavid du Colombier                   png_ptr->dither_index[i] = (png_byte)min_k;
2777dd7cddfSDavid du Colombier                }
2787dd7cddfSDavid du Colombier             }
2797dd7cddfSDavid du Colombier          }
280*593dc095SDavid du Colombier          png_free(png_ptr, png_ptr->dither_sort);
281*593dc095SDavid du Colombier          png_ptr->dither_sort=NULL;
2827dd7cddfSDavid du Colombier       }
2837dd7cddfSDavid du Colombier       else
2847dd7cddfSDavid du Colombier       {
2857dd7cddfSDavid du Colombier          /* This is much harder to do simply (and quickly).  Perhaps
2867dd7cddfSDavid du Colombier             we need to go through a median cut routine, but those
2877dd7cddfSDavid du Colombier             don't always behave themselves with only a few colors
2887dd7cddfSDavid du Colombier             as input.  So we will just find the closest two colors,
2897dd7cddfSDavid du Colombier             and throw out one of them (chosen somewhat randomly).
290*593dc095SDavid du Colombier             [We don't understand this at all, so if someone wants to
291*593dc095SDavid du Colombier              work on improving it, be our guest - AED, GRP]
2927dd7cddfSDavid du Colombier             */
2937dd7cddfSDavid du Colombier          int i;
2947dd7cddfSDavid du Colombier          int max_d;
2957dd7cddfSDavid du Colombier          int num_new_palette;
296*593dc095SDavid du Colombier          png_dsortp t;
2977dd7cddfSDavid du Colombier          png_dsortpp hash;
298*593dc095SDavid du Colombier 
299*593dc095SDavid du Colombier          t=NULL;
3007dd7cddfSDavid du Colombier 
3017dd7cddfSDavid du Colombier          /* initialize palette index arrays */
302*593dc095SDavid du Colombier          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
303*593dc095SDavid du Colombier             (png_uint_32)(num_palette * png_sizeof (png_byte)));
304*593dc095SDavid du Colombier          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
305*593dc095SDavid du Colombier             (png_uint_32)(num_palette * png_sizeof (png_byte)));
3067dd7cddfSDavid du Colombier 
3077dd7cddfSDavid du Colombier          /* initialize the sort array */
3087dd7cddfSDavid du Colombier          for (i = 0; i < num_palette; i++)
3097dd7cddfSDavid du Colombier          {
310*593dc095SDavid du Colombier             png_ptr->index_to_palette[i] = (png_byte)i;
311*593dc095SDavid du Colombier             png_ptr->palette_to_index[i] = (png_byte)i;
3127dd7cddfSDavid du Colombier          }
3137dd7cddfSDavid du Colombier 
3147dd7cddfSDavid du Colombier          hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
315*593dc095SDavid du Colombier             png_sizeof (png_dsortp)));
3167dd7cddfSDavid du Colombier          for (i = 0; i < 769; i++)
3177dd7cddfSDavid du Colombier             hash[i] = NULL;
318*593dc095SDavid du Colombier /*         png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
3197dd7cddfSDavid du Colombier 
3207dd7cddfSDavid du Colombier          num_new_palette = num_palette;
3217dd7cddfSDavid du Colombier 
3227dd7cddfSDavid du Colombier          /* initial wild guess at how far apart the farthest pixel
3237dd7cddfSDavid du Colombier             pair we will be eliminating will be.  Larger
3247dd7cddfSDavid du Colombier             numbers mean more areas will be allocated, Smaller
3257dd7cddfSDavid du Colombier             numbers run the risk of not saving enough data, and
3267dd7cddfSDavid du Colombier             having to do this all over again.
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier             I have not done extensive checking on this number.
3297dd7cddfSDavid du Colombier             */
3307dd7cddfSDavid du Colombier          max_d = 96;
3317dd7cddfSDavid du Colombier 
3327dd7cddfSDavid du Colombier          while (num_new_palette > maximum_colors)
3337dd7cddfSDavid du Colombier          {
3347dd7cddfSDavid du Colombier             for (i = 0; i < num_new_palette - 1; i++)
3357dd7cddfSDavid du Colombier             {
3367dd7cddfSDavid du Colombier                int j;
3377dd7cddfSDavid du Colombier 
3387dd7cddfSDavid du Colombier                for (j = i + 1; j < num_new_palette; j++)
3397dd7cddfSDavid du Colombier                {
3407dd7cddfSDavid du Colombier                   int d;
3417dd7cddfSDavid du Colombier 
3427dd7cddfSDavid du Colombier                   d = PNG_COLOR_DIST(palette[i], palette[j]);
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier                   if (d <= max_d)
3457dd7cddfSDavid du Colombier                   {
3467dd7cddfSDavid du Colombier 
347*593dc095SDavid du Colombier                      t = (png_dsortp)png_malloc_warn(png_ptr,
348*593dc095SDavid du Colombier                          (png_uint_32)(png_sizeof(png_dsort)));
349*593dc095SDavid du Colombier                      if (t == NULL)
350*593dc095SDavid du Colombier                          break;
3517dd7cddfSDavid du Colombier                      t->next = hash[d];
3527dd7cddfSDavid du Colombier                      t->left = (png_byte)i;
3537dd7cddfSDavid du Colombier                      t->right = (png_byte)j;
3547dd7cddfSDavid du Colombier                      hash[d] = t;
3557dd7cddfSDavid du Colombier                   }
3567dd7cddfSDavid du Colombier                }
357*593dc095SDavid du Colombier                if (t == NULL)
358*593dc095SDavid du Colombier                   break;
3597dd7cddfSDavid du Colombier             }
3607dd7cddfSDavid du Colombier 
361*593dc095SDavid du Colombier             if (t != NULL)
3627dd7cddfSDavid du Colombier             for (i = 0; i <= max_d; i++)
3637dd7cddfSDavid du Colombier             {
3647dd7cddfSDavid du Colombier                if (hash[i] != NULL)
3657dd7cddfSDavid du Colombier                {
3667dd7cddfSDavid du Colombier                   png_dsortp p;
3677dd7cddfSDavid du Colombier 
3687dd7cddfSDavid du Colombier                   for (p = hash[i]; p; p = p->next)
3697dd7cddfSDavid du Colombier                   {
370*593dc095SDavid du Colombier                      if ((int)png_ptr->index_to_palette[p->left]
371*593dc095SDavid du Colombier                         < num_new_palette &&
372*593dc095SDavid du Colombier                         (int)png_ptr->index_to_palette[p->right]
373*593dc095SDavid du Colombier                         < num_new_palette)
3747dd7cddfSDavid du Colombier                      {
3757dd7cddfSDavid du Colombier                         int j, next_j;
3767dd7cddfSDavid du Colombier 
377*593dc095SDavid du Colombier                         if (num_new_palette & 0x01)
3787dd7cddfSDavid du Colombier                         {
3797dd7cddfSDavid du Colombier                            j = p->left;
3807dd7cddfSDavid du Colombier                            next_j = p->right;
3817dd7cddfSDavid du Colombier                         }
3827dd7cddfSDavid du Colombier                         else
3837dd7cddfSDavid du Colombier                         {
3847dd7cddfSDavid du Colombier                            j = p->right;
3857dd7cddfSDavid du Colombier                            next_j = p->left;
3867dd7cddfSDavid du Colombier                         }
3877dd7cddfSDavid du Colombier 
3887dd7cddfSDavid du Colombier                         num_new_palette--;
389*593dc095SDavid du Colombier                         palette[png_ptr->index_to_palette[j]]
390*593dc095SDavid du Colombier                           = palette[num_new_palette];
3917dd7cddfSDavid du Colombier                         if (!full_dither)
3927dd7cddfSDavid du Colombier                         {
3937dd7cddfSDavid du Colombier                            int k;
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier                            for (k = 0; k < num_palette; k++)
3967dd7cddfSDavid du Colombier                            {
3977dd7cddfSDavid du Colombier                               if (png_ptr->dither_index[k] ==
398*593dc095SDavid du Colombier                                  png_ptr->index_to_palette[j])
3997dd7cddfSDavid du Colombier                                  png_ptr->dither_index[k] =
400*593dc095SDavid du Colombier                                     png_ptr->index_to_palette[next_j];
4017dd7cddfSDavid du Colombier                               if ((int)png_ptr->dither_index[k] ==
4027dd7cddfSDavid du Colombier                                  num_new_palette)
4037dd7cddfSDavid du Colombier                                  png_ptr->dither_index[k] =
404*593dc095SDavid du Colombier                                     png_ptr->index_to_palette[j];
4057dd7cddfSDavid du Colombier                            }
4067dd7cddfSDavid du Colombier                         }
4077dd7cddfSDavid du Colombier 
408*593dc095SDavid du Colombier                         png_ptr->index_to_palette[png_ptr->palette_to_index
409*593dc095SDavid du Colombier                            [num_new_palette]] = png_ptr->index_to_palette[j];
410*593dc095SDavid du Colombier                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
411*593dc095SDavid du Colombier                            = png_ptr->palette_to_index[num_new_palette];
4127dd7cddfSDavid du Colombier 
413*593dc095SDavid du Colombier                         png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
414*593dc095SDavid du Colombier                         png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
4157dd7cddfSDavid du Colombier                      }
4167dd7cddfSDavid du Colombier                      if (num_new_palette <= maximum_colors)
4177dd7cddfSDavid du Colombier                         break;
4187dd7cddfSDavid du Colombier                   }
4197dd7cddfSDavid du Colombier                   if (num_new_palette <= maximum_colors)
4207dd7cddfSDavid du Colombier                      break;
4217dd7cddfSDavid du Colombier                }
4227dd7cddfSDavid du Colombier             }
4237dd7cddfSDavid du Colombier 
4247dd7cddfSDavid du Colombier             for (i = 0; i < 769; i++)
4257dd7cddfSDavid du Colombier             {
4267dd7cddfSDavid du Colombier                if (hash[i] != NULL)
4277dd7cddfSDavid du Colombier                {
428*593dc095SDavid du Colombier                   png_dsortp p = hash[i];
4297dd7cddfSDavid du Colombier                   while (p)
4307dd7cddfSDavid du Colombier                   {
4317dd7cddfSDavid du Colombier                      t = p->next;
4327dd7cddfSDavid du Colombier                      png_free(png_ptr, p);
4337dd7cddfSDavid du Colombier                      p = t;
4347dd7cddfSDavid du Colombier                   }
4357dd7cddfSDavid du Colombier                }
4367dd7cddfSDavid du Colombier                hash[i] = 0;
4377dd7cddfSDavid du Colombier             }
4387dd7cddfSDavid du Colombier             max_d += 96;
4397dd7cddfSDavid du Colombier          }
4407dd7cddfSDavid du Colombier          png_free(png_ptr, hash);
441*593dc095SDavid du Colombier          png_free(png_ptr, png_ptr->palette_to_index);
442*593dc095SDavid du Colombier          png_free(png_ptr, png_ptr->index_to_palette);
443*593dc095SDavid du Colombier          png_ptr->palette_to_index=NULL;
444*593dc095SDavid du Colombier          png_ptr->index_to_palette=NULL;
4457dd7cddfSDavid du Colombier       }
4467dd7cddfSDavid du Colombier       num_palette = maximum_colors;
4477dd7cddfSDavid du Colombier    }
4487dd7cddfSDavid du Colombier    if (png_ptr->palette == NULL)
4497dd7cddfSDavid du Colombier    {
4507dd7cddfSDavid du Colombier       png_ptr->palette = palette;
4517dd7cddfSDavid du Colombier    }
4527dd7cddfSDavid du Colombier    png_ptr->num_palette = (png_uint_16)num_palette;
4537dd7cddfSDavid du Colombier 
4547dd7cddfSDavid du Colombier    if (full_dither)
4557dd7cddfSDavid du Colombier    {
4567dd7cddfSDavid du Colombier       int i;
4577dd7cddfSDavid du Colombier       png_bytep distance;
458*593dc095SDavid du Colombier       int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
4597dd7cddfSDavid du Colombier          PNG_DITHER_BLUE_BITS;
460*593dc095SDavid du Colombier       int num_red = (1 << PNG_DITHER_RED_BITS);
461*593dc095SDavid du Colombier       int num_green = (1 << PNG_DITHER_GREEN_BITS);
462*593dc095SDavid du Colombier       int num_blue = (1 << PNG_DITHER_BLUE_BITS);
463*593dc095SDavid du Colombier       png_size_t num_entries = ((png_size_t)1 << total_bits);
4647dd7cddfSDavid du Colombier 
4657dd7cddfSDavid du Colombier       png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
466*593dc095SDavid du Colombier          (png_uint_32)(num_entries * png_sizeof (png_byte)));
4677dd7cddfSDavid du Colombier 
468*593dc095SDavid du Colombier       png_memset(png_ptr->palette_lookup, 0, num_entries *
469*593dc095SDavid du Colombier          png_sizeof (png_byte));
4707dd7cddfSDavid du Colombier 
4717dd7cddfSDavid du Colombier       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
472*593dc095SDavid du Colombier          png_sizeof(png_byte)));
4737dd7cddfSDavid du Colombier 
474*593dc095SDavid du Colombier       png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
4757dd7cddfSDavid du Colombier 
4767dd7cddfSDavid du Colombier       for (i = 0; i < num_palette; i++)
4777dd7cddfSDavid du Colombier       {
478*593dc095SDavid du Colombier          int ir, ig, ib;
479*593dc095SDavid du Colombier          int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
480*593dc095SDavid du Colombier          int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
481*593dc095SDavid du Colombier          int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
4827dd7cddfSDavid du Colombier 
4837dd7cddfSDavid du Colombier          for (ir = 0; ir < num_red; ir++)
4847dd7cddfSDavid du Colombier          {
485*593dc095SDavid du Colombier             /* int dr = abs(ir - r); */
486*593dc095SDavid du Colombier             int dr = ((ir > r) ? ir - r : r - ir);
487*593dc095SDavid du Colombier             int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
4887dd7cddfSDavid du Colombier 
4897dd7cddfSDavid du Colombier             for (ig = 0; ig < num_green; ig++)
4907dd7cddfSDavid du Colombier             {
491*593dc095SDavid du Colombier                /* int dg = abs(ig - g); */
492*593dc095SDavid du Colombier                int dg = ((ig > g) ? ig - g : g - ig);
493*593dc095SDavid du Colombier                int dt = dr + dg;
494*593dc095SDavid du Colombier                int dm = ((dr > dg) ? dr : dg);
495*593dc095SDavid du Colombier                int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
4967dd7cddfSDavid du Colombier 
4977dd7cddfSDavid du Colombier                for (ib = 0; ib < num_blue; ib++)
4987dd7cddfSDavid du Colombier                {
499*593dc095SDavid du Colombier                   int d_index = index_g | ib;
500*593dc095SDavid du Colombier                   /* int db = abs(ib - b); */
501*593dc095SDavid du Colombier                   int db = ((ib > b) ? ib - b : b - ib);
502*593dc095SDavid du Colombier                   int dmax = ((dm > db) ? dm : db);
503*593dc095SDavid du Colombier                   int d = dmax + dt + db;
5047dd7cddfSDavid du Colombier 
5057dd7cddfSDavid du Colombier                   if (d < (int)distance[d_index])
5067dd7cddfSDavid du Colombier                   {
5077dd7cddfSDavid du Colombier                      distance[d_index] = (png_byte)d;
5087dd7cddfSDavid du Colombier                      png_ptr->palette_lookup[d_index] = (png_byte)i;
5097dd7cddfSDavid du Colombier                   }
5107dd7cddfSDavid du Colombier                }
5117dd7cddfSDavid du Colombier             }
5127dd7cddfSDavid du Colombier          }
5137dd7cddfSDavid du Colombier       }
5147dd7cddfSDavid du Colombier 
5157dd7cddfSDavid du Colombier       png_free(png_ptr, distance);
5167dd7cddfSDavid du Colombier    }
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier #endif
5197dd7cddfSDavid du Colombier 
520*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
5217dd7cddfSDavid du Colombier /* Transform the image from the file_gamma to the screen_gamma.  We
5227dd7cddfSDavid du Colombier  * only do transformations on images where the file_gamma and screen_gamma
5237dd7cddfSDavid du Colombier  * are not close reciprocals, otherwise it slows things down slightly, and
5247dd7cddfSDavid du Colombier  * also needlessly introduces small errors.
525*593dc095SDavid du Colombier  *
526*593dc095SDavid du Colombier  * We will turn off gamma transformation later if no semitransparent entries
527*593dc095SDavid du Colombier  * are present in the tRNS array for palette images.  We can't do it here
528*593dc095SDavid du Colombier  * because we don't necessarily have the tRNS chunk yet.
5297dd7cddfSDavid du Colombier  */
530*593dc095SDavid du Colombier void PNGAPI
png_set_gamma(png_structp png_ptr,double scrn_gamma,double file_gamma)5317dd7cddfSDavid du Colombier png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
5327dd7cddfSDavid du Colombier {
5337dd7cddfSDavid du Colombier    png_debug(1, "in png_set_gamma\n");
534*593dc095SDavid du Colombier    if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
535*593dc095SDavid du Colombier        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
536*593dc095SDavid du Colombier        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
5377dd7cddfSDavid du Colombier      png_ptr->transformations |= PNG_GAMMA;
5387dd7cddfSDavid du Colombier    png_ptr->gamma = (float)file_gamma;
5397dd7cddfSDavid du Colombier    png_ptr->screen_gamma = (float)scrn_gamma;
5407dd7cddfSDavid du Colombier }
5417dd7cddfSDavid du Colombier #endif
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
544*593dc095SDavid du Colombier /* Expand paletted images to RGB, expand grayscale images of
545*593dc095SDavid du Colombier  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
5467dd7cddfSDavid du Colombier  * to alpha channels.
5477dd7cddfSDavid du Colombier  */
548*593dc095SDavid du Colombier void PNGAPI
png_set_expand(png_structp png_ptr)5497dd7cddfSDavid du Colombier png_set_expand(png_structp png_ptr)
5507dd7cddfSDavid du Colombier {
5517dd7cddfSDavid du Colombier    png_debug(1, "in png_set_expand\n");
5527dd7cddfSDavid du Colombier    png_ptr->transformations |= PNG_EXPAND;
5537dd7cddfSDavid du Colombier }
554*593dc095SDavid du Colombier 
555*593dc095SDavid du Colombier /* GRR 19990627:  the following three functions currently are identical
556*593dc095SDavid du Colombier  *  to png_set_expand().  However, it is entirely reasonable that someone
557*593dc095SDavid du Colombier  *  might wish to expand an indexed image to RGB but *not* expand a single,
558*593dc095SDavid du Colombier  *  fully transparent palette entry to a full alpha channel--perhaps instead
559*593dc095SDavid du Colombier  *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
560*593dc095SDavid du Colombier  *  the transparent color with a particular RGB value, or drop tRNS entirely.
561*593dc095SDavid du Colombier  *  IOW, a future version of the library may make the transformations flag
562*593dc095SDavid du Colombier  *  a bit more fine-grained, with separate bits for each of these three
563*593dc095SDavid du Colombier  *  functions.
564*593dc095SDavid du Colombier  *
565*593dc095SDavid du Colombier  *  More to the point, these functions make it obvious what libpng will be
566*593dc095SDavid du Colombier  *  doing, whereas "expand" can (and does) mean any number of things.
567*593dc095SDavid du Colombier  */
568*593dc095SDavid du Colombier 
569*593dc095SDavid du Colombier /* Expand paletted images to RGB. */
570*593dc095SDavid du Colombier void PNGAPI
png_set_palette_to_rgb(png_structp png_ptr)571*593dc095SDavid du Colombier png_set_palette_to_rgb(png_structp png_ptr)
572*593dc095SDavid du Colombier {
573*593dc095SDavid du Colombier    png_debug(1, "in png_set_expand\n");
574*593dc095SDavid du Colombier    png_ptr->transformations |= PNG_EXPAND;
575*593dc095SDavid du Colombier }
576*593dc095SDavid du Colombier 
577*593dc095SDavid du Colombier /* Expand grayscale images of less than 8-bit depth to 8 bits. */
578*593dc095SDavid du Colombier void PNGAPI
png_set_gray_1_2_4_to_8(png_structp png_ptr)579*593dc095SDavid du Colombier png_set_gray_1_2_4_to_8(png_structp png_ptr)
580*593dc095SDavid du Colombier {
581*593dc095SDavid du Colombier    png_debug(1, "in png_set_expand\n");
582*593dc095SDavid du Colombier    png_ptr->transformations |= PNG_EXPAND;
583*593dc095SDavid du Colombier }
584*593dc095SDavid du Colombier 
585*593dc095SDavid du Colombier /* Expand tRNS chunks to alpha channels. */
586*593dc095SDavid du Colombier void PNGAPI
png_set_tRNS_to_alpha(png_structp png_ptr)587*593dc095SDavid du Colombier png_set_tRNS_to_alpha(png_structp png_ptr)
588*593dc095SDavid du Colombier {
589*593dc095SDavid du Colombier    png_debug(1, "in png_set_expand\n");
590*593dc095SDavid du Colombier    png_ptr->transformations |= PNG_EXPAND;
591*593dc095SDavid du Colombier }
592*593dc095SDavid du Colombier #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
5937dd7cddfSDavid du Colombier 
5947dd7cddfSDavid du Colombier #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
595*593dc095SDavid du Colombier void PNGAPI
png_set_gray_to_rgb(png_structp png_ptr)5967dd7cddfSDavid du Colombier png_set_gray_to_rgb(png_structp png_ptr)
5977dd7cddfSDavid du Colombier {
5987dd7cddfSDavid du Colombier    png_debug(1, "in png_set_gray_to_rgb\n");
5997dd7cddfSDavid du Colombier    png_ptr->transformations |= PNG_GRAY_TO_RGB;
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier #endif
6027dd7cddfSDavid du Colombier 
6037dd7cddfSDavid du Colombier #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
604*593dc095SDavid du Colombier #if defined(PNG_FLOATING_POINT_SUPPORTED)
605*593dc095SDavid du Colombier /* Convert a RGB image to a grayscale of the same width.  This allows us,
606*593dc095SDavid du Colombier  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
6077dd7cddfSDavid du Colombier  */
608*593dc095SDavid du Colombier 
609*593dc095SDavid du Colombier void PNGAPI
png_set_rgb_to_gray(png_structp png_ptr,int error_action,double red,double green)610*593dc095SDavid du Colombier png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
611*593dc095SDavid du Colombier    double green)
612*593dc095SDavid du Colombier {
613*593dc095SDavid du Colombier       int red_fixed = (int)((float)red*100000.0 + 0.5);
614*593dc095SDavid du Colombier       int green_fixed = (int)((float)green*100000.0 + 0.5);
615*593dc095SDavid du Colombier       png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
616*593dc095SDavid du Colombier }
617*593dc095SDavid du Colombier #endif
618*593dc095SDavid du Colombier 
619*593dc095SDavid du Colombier void PNGAPI
png_set_rgb_to_gray_fixed(png_structp png_ptr,int error_action,png_fixed_point red,png_fixed_point green)620*593dc095SDavid du Colombier png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
621*593dc095SDavid du Colombier    png_fixed_point red, png_fixed_point green)
6227dd7cddfSDavid du Colombier {
6237dd7cddfSDavid du Colombier    png_debug(1, "in png_set_rgb_to_gray\n");
624*593dc095SDavid du Colombier    switch(error_action)
625*593dc095SDavid du Colombier    {
626*593dc095SDavid du Colombier       case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
627*593dc095SDavid du Colombier               break;
628*593dc095SDavid du Colombier       case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
629*593dc095SDavid du Colombier               break;
630*593dc095SDavid du Colombier       case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
631*593dc095SDavid du Colombier    }
632*593dc095SDavid du Colombier    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
633*593dc095SDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
634*593dc095SDavid du Colombier       png_ptr->transformations |= PNG_EXPAND;
635*593dc095SDavid du Colombier #else
636*593dc095SDavid du Colombier    {
637*593dc095SDavid du Colombier       png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
638*593dc095SDavid du Colombier       png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
639*593dc095SDavid du Colombier    }
640*593dc095SDavid du Colombier #endif
641*593dc095SDavid du Colombier    {
642*593dc095SDavid du Colombier       png_uint_16 red_int, green_int;
643*593dc095SDavid du Colombier       if(red < 0 || green < 0)
644*593dc095SDavid du Colombier       {
645*593dc095SDavid du Colombier          red_int   =  6968; /* .212671 * 32768 + .5 */
646*593dc095SDavid du Colombier          green_int = 23434; /* .715160 * 32768 + .5 */
647*593dc095SDavid du Colombier       }
648*593dc095SDavid du Colombier       else if(red + green < 100000L)
649*593dc095SDavid du Colombier       {
650*593dc095SDavid du Colombier         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
651*593dc095SDavid du Colombier         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
652*593dc095SDavid du Colombier       }
653*593dc095SDavid du Colombier       else
654*593dc095SDavid du Colombier       {
655*593dc095SDavid du Colombier          png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
656*593dc095SDavid du Colombier          red_int   =  6968;
657*593dc095SDavid du Colombier          green_int = 23434;
658*593dc095SDavid du Colombier       }
659*593dc095SDavid du Colombier       png_ptr->rgb_to_gray_red_coeff   = red_int;
660*593dc095SDavid du Colombier       png_ptr->rgb_to_gray_green_coeff = green_int;
661*593dc095SDavid du Colombier       png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
662*593dc095SDavid du Colombier    }
663*593dc095SDavid du Colombier }
664*593dc095SDavid du Colombier #endif
665*593dc095SDavid du Colombier 
666*593dc095SDavid du Colombier #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
667*593dc095SDavid du Colombier     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
668*593dc095SDavid du Colombier     defined(PNG_LEGACY_SUPPORTED)
669*593dc095SDavid du Colombier void PNGAPI
png_set_read_user_transform_fn(png_structp png_ptr,png_user_transform_ptr read_user_transform_fn)670*593dc095SDavid du Colombier png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
671*593dc095SDavid du Colombier    read_user_transform_fn)
672*593dc095SDavid du Colombier {
673*593dc095SDavid du Colombier    png_debug(1, "in png_set_read_user_transform_fn\n");
674*593dc095SDavid du Colombier #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
675*593dc095SDavid du Colombier    png_ptr->transformations |= PNG_USER_TRANSFORM;
676*593dc095SDavid du Colombier    png_ptr->read_user_transform_fn = read_user_transform_fn;
677*593dc095SDavid du Colombier #endif
678*593dc095SDavid du Colombier #ifdef PNG_LEGACY_SUPPORTED
679*593dc095SDavid du Colombier    if(read_user_transform_fn)
680*593dc095SDavid du Colombier       png_warning(png_ptr,
681*593dc095SDavid du Colombier         "This version of libpng does not support user transforms");
682*593dc095SDavid du Colombier #endif
6837dd7cddfSDavid du Colombier }
6847dd7cddfSDavid du Colombier #endif
6857dd7cddfSDavid du Colombier 
6867dd7cddfSDavid du Colombier /* Initialize everything needed for the read.  This includes modifying
6877dd7cddfSDavid du Colombier  * the palette.
6887dd7cddfSDavid du Colombier  */
689*593dc095SDavid du Colombier void /* PRIVATE */
png_init_read_transformations(png_structp png_ptr)6907dd7cddfSDavid du Colombier png_init_read_transformations(png_structp png_ptr)
6917dd7cddfSDavid du Colombier {
6927dd7cddfSDavid du Colombier    png_debug(1, "in png_init_read_transformations\n");
693*593dc095SDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
694*593dc095SDavid du Colombier    if(png_ptr != NULL)
695*593dc095SDavid du Colombier #endif
696*593dc095SDavid du Colombier   {
697*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
698*593dc095SDavid du Colombier  || defined(PNG_READ_GAMMA_SUPPORTED)
699*593dc095SDavid du Colombier    int color_type = png_ptr->color_type;
700*593dc095SDavid du Colombier #endif
7017dd7cddfSDavid du Colombier 
7027dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
703*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
704*593dc095SDavid du Colombier        (png_ptr->transformations & PNG_EXPAND))
7057dd7cddfSDavid du Colombier    {
706*593dc095SDavid du Colombier       if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
7077dd7cddfSDavid du Colombier       {
7087dd7cddfSDavid du Colombier          /* expand background chunk. */
7097dd7cddfSDavid du Colombier          switch (png_ptr->bit_depth)
7107dd7cddfSDavid du Colombier          {
7117dd7cddfSDavid du Colombier             case 1:
7127dd7cddfSDavid du Colombier                png_ptr->background.gray *= (png_uint_16)0xff;
713*593dc095SDavid du Colombier                png_ptr->background.red = png_ptr->background.green
714*593dc095SDavid du Colombier                  =  png_ptr->background.blue = png_ptr->background.gray;
7157dd7cddfSDavid du Colombier                break;
7167dd7cddfSDavid du Colombier             case 2:
7177dd7cddfSDavid du Colombier                png_ptr->background.gray *= (png_uint_16)0x55;
718*593dc095SDavid du Colombier                png_ptr->background.red = png_ptr->background.green
719*593dc095SDavid du Colombier                  = png_ptr->background.blue = png_ptr->background.gray;
7207dd7cddfSDavid du Colombier                break;
7217dd7cddfSDavid du Colombier             case 4:
7227dd7cddfSDavid du Colombier                png_ptr->background.gray *= (png_uint_16)0x11;
723*593dc095SDavid du Colombier                png_ptr->background.red = png_ptr->background.green
724*593dc095SDavid du Colombier                  = png_ptr->background.blue = png_ptr->background.gray;
7257dd7cddfSDavid du Colombier                break;
7267dd7cddfSDavid du Colombier             case 8:
7277dd7cddfSDavid du Colombier             case 16:
728*593dc095SDavid du Colombier                png_ptr->background.red = png_ptr->background.green
729*593dc095SDavid du Colombier                  = png_ptr->background.blue = png_ptr->background.gray;
7307dd7cddfSDavid du Colombier                break;
7317dd7cddfSDavid du Colombier          }
7327dd7cddfSDavid du Colombier       }
7337dd7cddfSDavid du Colombier       else if (color_type == PNG_COLOR_TYPE_PALETTE)
7347dd7cddfSDavid du Colombier       {
7357dd7cddfSDavid du Colombier          png_ptr->background.red   =
7367dd7cddfSDavid du Colombier             png_ptr->palette[png_ptr->background.index].red;
7377dd7cddfSDavid du Colombier          png_ptr->background.green =
7387dd7cddfSDavid du Colombier             png_ptr->palette[png_ptr->background.index].green;
7397dd7cddfSDavid du Colombier          png_ptr->background.blue  =
7407dd7cddfSDavid du Colombier             png_ptr->palette[png_ptr->background.index].blue;
7417dd7cddfSDavid du Colombier 
7427dd7cddfSDavid du Colombier #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
7437dd7cddfSDavid du Colombier         if (png_ptr->transformations & PNG_INVERT_ALPHA)
7447dd7cddfSDavid du Colombier         {
7457dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
746*593dc095SDavid du Colombier            if (!(png_ptr->transformations & PNG_EXPAND))
7477dd7cddfSDavid du Colombier #endif
7487dd7cddfSDavid du Colombier            {
7497dd7cddfSDavid du Colombier            /* invert the alpha channel (in tRNS) unless the pixels are
7507dd7cddfSDavid du Colombier               going to be expanded, in which case leave it for later */
751*593dc095SDavid du Colombier               int i,istop;
752*593dc095SDavid du Colombier               istop=(int)png_ptr->num_trans;
753*593dc095SDavid du Colombier               for (i=0; i<istop; i++)
754*593dc095SDavid du Colombier                  png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
7557dd7cddfSDavid du Colombier            }
7567dd7cddfSDavid du Colombier         }
7577dd7cddfSDavid du Colombier #endif
7587dd7cddfSDavid du Colombier 
7597dd7cddfSDavid du Colombier       }
7607dd7cddfSDavid du Colombier    }
7617dd7cddfSDavid du Colombier #endif
7627dd7cddfSDavid du Colombier 
763*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
7647dd7cddfSDavid du Colombier    png_ptr->background_1 = png_ptr->background;
7657dd7cddfSDavid du Colombier #endif
766*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
767*593dc095SDavid du Colombier 
768*593dc095SDavid du Colombier    if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
769*593dc095SDavid du Colombier        && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
770*593dc095SDavid du Colombier          < PNG_GAMMA_THRESHOLD))
771*593dc095SDavid du Colombier    {
772*593dc095SDavid du Colombier     int i,k;
773*593dc095SDavid du Colombier     k=0;
774*593dc095SDavid du Colombier     for (i=0; i<png_ptr->num_trans; i++)
775*593dc095SDavid du Colombier     {
776*593dc095SDavid du Colombier       if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
777*593dc095SDavid du Colombier         k=1; /* partial transparency is present */
778*593dc095SDavid du Colombier     }
779*593dc095SDavid du Colombier     if (k == 0)
780*593dc095SDavid du Colombier       png_ptr->transformations &= (~PNG_GAMMA);
781*593dc095SDavid du Colombier    }
782*593dc095SDavid du Colombier 
783*593dc095SDavid du Colombier    if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
7847dd7cddfSDavid du Colombier    {
7857dd7cddfSDavid du Colombier       png_build_gamma_table(png_ptr);
7867dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
7877dd7cddfSDavid du Colombier       if (png_ptr->transformations & PNG_BACKGROUND)
7887dd7cddfSDavid du Colombier       {
7897dd7cddfSDavid du Colombier          if (color_type == PNG_COLOR_TYPE_PALETTE)
7907dd7cddfSDavid du Colombier          {
791*593dc095SDavid du Colombier            /* could skip if no transparency and
792*593dc095SDavid du Colombier            */
7937dd7cddfSDavid du Colombier             png_color back, back_1;
794*593dc095SDavid du Colombier             png_colorp palette = png_ptr->palette;
795*593dc095SDavid du Colombier             int num_palette = png_ptr->num_palette;
796*593dc095SDavid du Colombier             int i;
7977dd7cddfSDavid du Colombier             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
7987dd7cddfSDavid du Colombier             {
7997dd7cddfSDavid du Colombier                back.red = png_ptr->gamma_table[png_ptr->background.red];
8007dd7cddfSDavid du Colombier                back.green = png_ptr->gamma_table[png_ptr->background.green];
8017dd7cddfSDavid du Colombier                back.blue = png_ptr->gamma_table[png_ptr->background.blue];
8027dd7cddfSDavid du Colombier 
8037dd7cddfSDavid du Colombier                back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
8047dd7cddfSDavid du Colombier                back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
8057dd7cddfSDavid du Colombier                back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
8067dd7cddfSDavid du Colombier             }
8077dd7cddfSDavid du Colombier             else
8087dd7cddfSDavid du Colombier             {
809*593dc095SDavid du Colombier                double g, gs;
8107dd7cddfSDavid du Colombier 
811*593dc095SDavid du Colombier                switch (png_ptr->background_gamma_type)
812*593dc095SDavid du Colombier                {
813*593dc095SDavid du Colombier                   case PNG_BACKGROUND_GAMMA_SCREEN:
814*593dc095SDavid du Colombier                      g = (png_ptr->screen_gamma);
815*593dc095SDavid du Colombier                      gs = 1.0;
816*593dc095SDavid du Colombier                      break;
817*593dc095SDavid du Colombier                   case PNG_BACKGROUND_GAMMA_FILE:
818*593dc095SDavid du Colombier                      g = 1.0 / (png_ptr->gamma);
819*593dc095SDavid du Colombier                      gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
820*593dc095SDavid du Colombier                      break;
821*593dc095SDavid du Colombier                   case PNG_BACKGROUND_GAMMA_UNIQUE:
822*593dc095SDavid du Colombier                      g = 1.0 / (png_ptr->background_gamma);
823*593dc095SDavid du Colombier                      gs = 1.0 / (png_ptr->background_gamma *
824*593dc095SDavid du Colombier                                  png_ptr->screen_gamma);
825*593dc095SDavid du Colombier                      break;
826*593dc095SDavid du Colombier                   default:
827*593dc095SDavid du Colombier                      g = 1.0;    /* back_1 */
828*593dc095SDavid du Colombier                      gs = 1.0;   /* back */
829*593dc095SDavid du Colombier                }
8307dd7cddfSDavid du Colombier 
831*593dc095SDavid du Colombier                if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
8327dd7cddfSDavid du Colombier                {
8337dd7cddfSDavid du Colombier                   back.red   = (png_byte)png_ptr->background.red;
8347dd7cddfSDavid du Colombier                   back.green = (png_byte)png_ptr->background.green;
8357dd7cddfSDavid du Colombier                   back.blue  = (png_byte)png_ptr->background.blue;
8367dd7cddfSDavid du Colombier                }
8377dd7cddfSDavid du Colombier                else
8387dd7cddfSDavid du Colombier                {
839*593dc095SDavid du Colombier                   back.red = (png_byte)(pow(
840*593dc095SDavid du Colombier                      (double)png_ptr->background.red/255, gs) * 255.0 + .5);
841*593dc095SDavid du Colombier                   back.green = (png_byte)(pow(
842*593dc095SDavid du Colombier                      (double)png_ptr->background.green/255, gs) * 255.0 + .5);
843*593dc095SDavid du Colombier                   back.blue = (png_byte)(pow(
844*593dc095SDavid du Colombier                      (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
8457dd7cddfSDavid du Colombier                }
8467dd7cddfSDavid du Colombier 
847*593dc095SDavid du Colombier                back_1.red = (png_byte)(pow(
848*593dc095SDavid du Colombier                   (double)png_ptr->background.red/255, g) * 255.0 + .5);
849*593dc095SDavid du Colombier                back_1.green = (png_byte)(pow(
850*593dc095SDavid du Colombier                   (double)png_ptr->background.green/255, g) * 255.0 + .5);
851*593dc095SDavid du Colombier                back_1.blue = (png_byte)(pow(
852*593dc095SDavid du Colombier                   (double)png_ptr->background.blue/255, g) * 255.0 + .5);
8537dd7cddfSDavid du Colombier             }
8547dd7cddfSDavid du Colombier             for (i = 0; i < num_palette; i++)
8557dd7cddfSDavid du Colombier             {
8567dd7cddfSDavid du Colombier                if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
8577dd7cddfSDavid du Colombier                {
8587dd7cddfSDavid du Colombier                   if (png_ptr->trans[i] == 0)
8597dd7cddfSDavid du Colombier                   {
8607dd7cddfSDavid du Colombier                      palette[i] = back;
8617dd7cddfSDavid du Colombier                   }
8627dd7cddfSDavid du Colombier                   else /* if (png_ptr->trans[i] != 0xff) */
8637dd7cddfSDavid du Colombier                   {
8647dd7cddfSDavid du Colombier                      png_byte v, w;
8657dd7cddfSDavid du Colombier 
8667dd7cddfSDavid du Colombier                      v = png_ptr->gamma_to_1[palette[i].red];
8677dd7cddfSDavid du Colombier                      png_composite(w, v, png_ptr->trans[i], back_1.red);
8687dd7cddfSDavid du Colombier                      palette[i].red = png_ptr->gamma_from_1[w];
8697dd7cddfSDavid du Colombier 
8707dd7cddfSDavid du Colombier                      v = png_ptr->gamma_to_1[palette[i].green];
8717dd7cddfSDavid du Colombier                      png_composite(w, v, png_ptr->trans[i], back_1.green);
8727dd7cddfSDavid du Colombier                      palette[i].green = png_ptr->gamma_from_1[w];
8737dd7cddfSDavid du Colombier 
8747dd7cddfSDavid du Colombier                      v = png_ptr->gamma_to_1[palette[i].blue];
8757dd7cddfSDavid du Colombier                      png_composite(w, v, png_ptr->trans[i], back_1.blue);
8767dd7cddfSDavid du Colombier                      palette[i].blue = png_ptr->gamma_from_1[w];
8777dd7cddfSDavid du Colombier                   }
8787dd7cddfSDavid du Colombier                }
8797dd7cddfSDavid du Colombier                else
8807dd7cddfSDavid du Colombier                {
8817dd7cddfSDavid du Colombier                   palette[i].red = png_ptr->gamma_table[palette[i].red];
8827dd7cddfSDavid du Colombier                   palette[i].green = png_ptr->gamma_table[palette[i].green];
8837dd7cddfSDavid du Colombier                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];
8847dd7cddfSDavid du Colombier                }
8857dd7cddfSDavid du Colombier             }
8867dd7cddfSDavid du Colombier          }
8877dd7cddfSDavid du Colombier          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
888*593dc095SDavid du Colombier          else
889*593dc095SDavid du Colombier          /* color_type != PNG_COLOR_TYPE_PALETTE */
8907dd7cddfSDavid du Colombier          {
891*593dc095SDavid du Colombier             double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
892*593dc095SDavid du Colombier             double g = 1.0;
893*593dc095SDavid du Colombier             double gs = 1.0;
8947dd7cddfSDavid du Colombier 
8957dd7cddfSDavid du Colombier             switch (png_ptr->background_gamma_type)
8967dd7cddfSDavid du Colombier             {
8977dd7cddfSDavid du Colombier                case PNG_BACKGROUND_GAMMA_SCREEN:
8987dd7cddfSDavid du Colombier                   g = (png_ptr->screen_gamma);
8997dd7cddfSDavid du Colombier                   gs = 1.0;
9007dd7cddfSDavid du Colombier                   break;
9017dd7cddfSDavid du Colombier                case PNG_BACKGROUND_GAMMA_FILE:
9027dd7cddfSDavid du Colombier                   g = 1.0 / (png_ptr->gamma);
9037dd7cddfSDavid du Colombier                   gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
9047dd7cddfSDavid du Colombier                   break;
9057dd7cddfSDavid du Colombier                case PNG_BACKGROUND_GAMMA_UNIQUE:
9067dd7cddfSDavid du Colombier                   g = 1.0 / (png_ptr->background_gamma);
9077dd7cddfSDavid du Colombier                   gs = 1.0 / (png_ptr->background_gamma *
9087dd7cddfSDavid du Colombier                      png_ptr->screen_gamma);
9097dd7cddfSDavid du Colombier                   break;
9107dd7cddfSDavid du Colombier             }
9117dd7cddfSDavid du Colombier 
912*593dc095SDavid du Colombier             png_ptr->background_1.gray = (png_uint_16)(pow(
913*593dc095SDavid du Colombier                (double)png_ptr->background.gray / m, g) * m + .5);
914*593dc095SDavid du Colombier             png_ptr->background.gray = (png_uint_16)(pow(
915*593dc095SDavid du Colombier                (double)png_ptr->background.gray / m, gs) * m + .5);
916*593dc095SDavid du Colombier 
917*593dc095SDavid du Colombier             if ((png_ptr->background.red != png_ptr->background.green) ||
918*593dc095SDavid du Colombier                 (png_ptr->background.red != png_ptr->background.blue) ||
919*593dc095SDavid du Colombier                 (png_ptr->background.red != png_ptr->background.gray))
9207dd7cddfSDavid du Colombier             {
921*593dc095SDavid du Colombier                /* RGB or RGBA with color background */
9227dd7cddfSDavid du Colombier                png_ptr->background_1.red = (png_uint_16)(pow(
9237dd7cddfSDavid du Colombier                   (double)png_ptr->background.red / m, g) * m + .5);
9247dd7cddfSDavid du Colombier                png_ptr->background_1.green = (png_uint_16)(pow(
9257dd7cddfSDavid du Colombier                   (double)png_ptr->background.green / m, g) * m + .5);
9267dd7cddfSDavid du Colombier                png_ptr->background_1.blue = (png_uint_16)(pow(
9277dd7cddfSDavid du Colombier                   (double)png_ptr->background.blue / m, g) * m + .5);
9287dd7cddfSDavid du Colombier                png_ptr->background.red = (png_uint_16)(pow(
9297dd7cddfSDavid du Colombier                   (double)png_ptr->background.red / m, gs) * m + .5);
9307dd7cddfSDavid du Colombier                png_ptr->background.green = (png_uint_16)(pow(
9317dd7cddfSDavid du Colombier                   (double)png_ptr->background.green / m, gs) * m + .5);
9327dd7cddfSDavid du Colombier                png_ptr->background.blue = (png_uint_16)(pow(
9337dd7cddfSDavid du Colombier                   (double)png_ptr->background.blue / m, gs) * m + .5);
9347dd7cddfSDavid du Colombier             }
9357dd7cddfSDavid du Colombier             else
9367dd7cddfSDavid du Colombier             {
937*593dc095SDavid du Colombier                /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
938*593dc095SDavid du Colombier                png_ptr->background_1.red = png_ptr->background_1.green
939*593dc095SDavid du Colombier                  = png_ptr->background_1.blue = png_ptr->background_1.gray;
940*593dc095SDavid du Colombier                png_ptr->background.red = png_ptr->background.green
941*593dc095SDavid du Colombier                  = png_ptr->background.blue = png_ptr->background.gray;
9427dd7cddfSDavid du Colombier             }
9437dd7cddfSDavid du Colombier          }
9447dd7cddfSDavid du Colombier       }
9457dd7cddfSDavid du Colombier       else
946*593dc095SDavid du Colombier       /* transformation does not include PNG_BACKGROUND */
947*593dc095SDavid du Colombier #endif /* PNG_READ_BACKGROUND_SUPPORTED */
9487dd7cddfSDavid du Colombier       if (color_type == PNG_COLOR_TYPE_PALETTE)
9497dd7cddfSDavid du Colombier       {
950*593dc095SDavid du Colombier          png_colorp palette = png_ptr->palette;
951*593dc095SDavid du Colombier          int num_palette = png_ptr->num_palette;
952*593dc095SDavid du Colombier          int i;
9537dd7cddfSDavid du Colombier 
9547dd7cddfSDavid du Colombier          for (i = 0; i < num_palette; i++)
9557dd7cddfSDavid du Colombier          {
9567dd7cddfSDavid du Colombier             palette[i].red = png_ptr->gamma_table[palette[i].red];
9577dd7cddfSDavid du Colombier             palette[i].green = png_ptr->gamma_table[palette[i].green];
9587dd7cddfSDavid du Colombier             palette[i].blue = png_ptr->gamma_table[palette[i].blue];
9597dd7cddfSDavid du Colombier          }
9607dd7cddfSDavid du Colombier       }
9617dd7cddfSDavid du Colombier    }
9627dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
9637dd7cddfSDavid du Colombier    else
9647dd7cddfSDavid du Colombier #endif
965*593dc095SDavid du Colombier #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
9667dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
967*593dc095SDavid du Colombier    /* No GAMMA transformation */
968*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_BACKGROUND) &&
969*593dc095SDavid du Colombier        (color_type == PNG_COLOR_TYPE_PALETTE))
9707dd7cddfSDavid du Colombier    {
9717dd7cddfSDavid du Colombier       int i;
972*593dc095SDavid du Colombier       int istop = (int)png_ptr->num_trans;
9737dd7cddfSDavid du Colombier       png_color back;
974*593dc095SDavid du Colombier       png_colorp palette = png_ptr->palette;
9757dd7cddfSDavid du Colombier 
9767dd7cddfSDavid du Colombier       back.red   = (png_byte)png_ptr->background.red;
9777dd7cddfSDavid du Colombier       back.green = (png_byte)png_ptr->background.green;
9787dd7cddfSDavid du Colombier       back.blue  = (png_byte)png_ptr->background.blue;
9797dd7cddfSDavid du Colombier 
980*593dc095SDavid du Colombier       for (i = 0; i < istop; i++)
9817dd7cddfSDavid du Colombier       {
9827dd7cddfSDavid du Colombier          if (png_ptr->trans[i] == 0)
9837dd7cddfSDavid du Colombier          {
9847dd7cddfSDavid du Colombier             palette[i] = back;
9857dd7cddfSDavid du Colombier          }
9867dd7cddfSDavid du Colombier          else if (png_ptr->trans[i] != 0xff)
9877dd7cddfSDavid du Colombier          {
988*593dc095SDavid du Colombier             /* The png_composite() macro is defined in png.h */
9897dd7cddfSDavid du Colombier             png_composite(palette[i].red, palette[i].red,
9907dd7cddfSDavid du Colombier                png_ptr->trans[i], back.red);
9917dd7cddfSDavid du Colombier             png_composite(palette[i].green, palette[i].green,
9927dd7cddfSDavid du Colombier                png_ptr->trans[i], back.green);
9937dd7cddfSDavid du Colombier             png_composite(palette[i].blue, palette[i].blue,
9947dd7cddfSDavid du Colombier                png_ptr->trans[i], back.blue);
9957dd7cddfSDavid du Colombier          }
9967dd7cddfSDavid du Colombier       }
9977dd7cddfSDavid du Colombier    }
998*593dc095SDavid du Colombier #endif /* PNG_READ_BACKGROUND_SUPPORTED */
9997dd7cddfSDavid du Colombier 
10007dd7cddfSDavid du Colombier #if defined(PNG_READ_SHIFT_SUPPORTED)
10017dd7cddfSDavid du Colombier    if ((png_ptr->transformations & PNG_SHIFT) &&
1002*593dc095SDavid du Colombier       (color_type == PNG_COLOR_TYPE_PALETTE))
10037dd7cddfSDavid du Colombier    {
10047dd7cddfSDavid du Colombier       png_uint_16 i;
1005*593dc095SDavid du Colombier       png_uint_16 istop = png_ptr->num_palette;
1006*593dc095SDavid du Colombier       int sr = 8 - png_ptr->sig_bit.red;
1007*593dc095SDavid du Colombier       int sg = 8 - png_ptr->sig_bit.green;
1008*593dc095SDavid du Colombier       int sb = 8 - png_ptr->sig_bit.blue;
10097dd7cddfSDavid du Colombier 
10107dd7cddfSDavid du Colombier       if (sr < 0 || sr > 8)
10117dd7cddfSDavid du Colombier          sr = 0;
10127dd7cddfSDavid du Colombier       if (sg < 0 || sg > 8)
10137dd7cddfSDavid du Colombier          sg = 0;
10147dd7cddfSDavid du Colombier       if (sb < 0 || sb > 8)
10157dd7cddfSDavid du Colombier          sb = 0;
1016*593dc095SDavid du Colombier       for (i = 0; i < istop; i++)
10177dd7cddfSDavid du Colombier       {
10187dd7cddfSDavid du Colombier          png_ptr->palette[i].red >>= sr;
10197dd7cddfSDavid du Colombier          png_ptr->palette[i].green >>= sg;
10207dd7cddfSDavid du Colombier          png_ptr->palette[i].blue >>= sb;
10217dd7cddfSDavid du Colombier       }
10227dd7cddfSDavid du Colombier    }
1023*593dc095SDavid du Colombier #endif  /* PNG_READ_SHIFT_SUPPORTED */
1024*593dc095SDavid du Colombier  }
1025*593dc095SDavid du Colombier #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1026*593dc095SDavid du Colombier  && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1027*593dc095SDavid du Colombier    if(png_ptr)
1028*593dc095SDavid du Colombier       return;
10297dd7cddfSDavid du Colombier #endif
10307dd7cddfSDavid du Colombier }
10317dd7cddfSDavid du Colombier 
10327dd7cddfSDavid du Colombier /* Modify the info structure to reflect the transformations.  The
10337dd7cddfSDavid du Colombier  * info should be updated so a PNG file could be written with it,
10347dd7cddfSDavid du Colombier  * assuming the transformations result in valid PNG data.
10357dd7cddfSDavid du Colombier  */
1036*593dc095SDavid du Colombier void /* PRIVATE */
png_read_transform_info(png_structp png_ptr,png_infop info_ptr)10377dd7cddfSDavid du Colombier png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
10387dd7cddfSDavid du Colombier {
10397dd7cddfSDavid du Colombier    png_debug(1, "in png_read_transform_info\n");
10407dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
10417dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_EXPAND)
10427dd7cddfSDavid du Colombier    {
10437dd7cddfSDavid du Colombier       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
10447dd7cddfSDavid du Colombier       {
10457dd7cddfSDavid du Colombier          if (png_ptr->num_trans)
10467dd7cddfSDavid du Colombier             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
10477dd7cddfSDavid du Colombier          else
10487dd7cddfSDavid du Colombier             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
10497dd7cddfSDavid du Colombier          info_ptr->bit_depth = 8;
10507dd7cddfSDavid du Colombier          info_ptr->num_trans = 0;
10517dd7cddfSDavid du Colombier       }
10527dd7cddfSDavid du Colombier       else
10537dd7cddfSDavid du Colombier       {
10547dd7cddfSDavid du Colombier          if (png_ptr->num_trans)
10557dd7cddfSDavid du Colombier             info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
10567dd7cddfSDavid du Colombier          if (info_ptr->bit_depth < 8)
10577dd7cddfSDavid du Colombier             info_ptr->bit_depth = 8;
10587dd7cddfSDavid du Colombier          info_ptr->num_trans = 0;
10597dd7cddfSDavid du Colombier       }
10607dd7cddfSDavid du Colombier    }
10617dd7cddfSDavid du Colombier #endif
10627dd7cddfSDavid du Colombier 
10637dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
10647dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_BACKGROUND)
10657dd7cddfSDavid du Colombier    {
10667dd7cddfSDavid du Colombier       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
10677dd7cddfSDavid du Colombier       info_ptr->num_trans = 0;
10687dd7cddfSDavid du Colombier       info_ptr->background = png_ptr->background;
10697dd7cddfSDavid du Colombier    }
10707dd7cddfSDavid du Colombier #endif
10717dd7cddfSDavid du Colombier 
1072*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
1073*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_GAMMA)
1074*593dc095SDavid du Colombier    {
1075*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
1076*593dc095SDavid du Colombier       info_ptr->gamma = png_ptr->gamma;
1077*593dc095SDavid du Colombier #endif
1078*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
1079*593dc095SDavid du Colombier       info_ptr->int_gamma = png_ptr->int_gamma;
1080*593dc095SDavid du Colombier #endif
1081*593dc095SDavid du Colombier    }
1082*593dc095SDavid du Colombier #endif
1083*593dc095SDavid du Colombier 
10847dd7cddfSDavid du Colombier #if defined(PNG_READ_16_TO_8_SUPPORTED)
1085*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
10867dd7cddfSDavid du Colombier       info_ptr->bit_depth = 8;
10877dd7cddfSDavid du Colombier #endif
10887dd7cddfSDavid du Colombier 
10897dd7cddfSDavid du Colombier #if defined(PNG_READ_DITHER_SUPPORTED)
10907dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_DITHER)
10917dd7cddfSDavid du Colombier    {
10927dd7cddfSDavid du Colombier       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
10937dd7cddfSDavid du Colombier          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
10947dd7cddfSDavid du Colombier          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
10957dd7cddfSDavid du Colombier       {
10967dd7cddfSDavid du Colombier          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
10977dd7cddfSDavid du Colombier       }
10987dd7cddfSDavid du Colombier    }
10997dd7cddfSDavid du Colombier #endif
11007dd7cddfSDavid du Colombier 
11017dd7cddfSDavid du Colombier #if defined(PNG_READ_PACK_SUPPORTED)
1102*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
11037dd7cddfSDavid du Colombier       info_ptr->bit_depth = 8;
11047dd7cddfSDavid du Colombier #endif
11057dd7cddfSDavid du Colombier 
11067dd7cddfSDavid du Colombier #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1107*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
11087dd7cddfSDavid du Colombier       info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
11097dd7cddfSDavid du Colombier #endif
11107dd7cddfSDavid du Colombier 
1111*593dc095SDavid du Colombier #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1112*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1113*593dc095SDavid du Colombier       info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1114*593dc095SDavid du Colombier #endif
1115*593dc095SDavid du Colombier 
11167dd7cddfSDavid du Colombier    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
11177dd7cddfSDavid du Colombier       info_ptr->channels = 1;
11187dd7cddfSDavid du Colombier    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
11197dd7cddfSDavid du Colombier       info_ptr->channels = 3;
11207dd7cddfSDavid du Colombier    else
11217dd7cddfSDavid du Colombier       info_ptr->channels = 1;
11227dd7cddfSDavid du Colombier 
11237dd7cddfSDavid du Colombier #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1124*593dc095SDavid du Colombier    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
11257dd7cddfSDavid du Colombier       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
11267dd7cddfSDavid du Colombier #endif
11277dd7cddfSDavid du Colombier 
11287dd7cddfSDavid du Colombier    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
11297dd7cddfSDavid du Colombier       info_ptr->channels++;
1130*593dc095SDavid du Colombier 
1131*593dc095SDavid du Colombier #if defined(PNG_READ_FILLER_SUPPORTED)
1132*593dc095SDavid du Colombier    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1133*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_FILLER) &&
1134*593dc095SDavid du Colombier        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1135*593dc095SDavid du Colombier        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1136*593dc095SDavid du Colombier    {
1137*593dc095SDavid du Colombier       info_ptr->channels++;
1138*593dc095SDavid du Colombier       /* if adding a true alpha channel not just filler */
1139*593dc095SDavid du Colombier #if !defined(PNG_1_0_X)
1140*593dc095SDavid du Colombier       if (png_ptr->transformations & PNG_ADD_ALPHA)
1141*593dc095SDavid du Colombier         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1142*593dc095SDavid du Colombier #endif
1143*593dc095SDavid du Colombier    }
1144*593dc095SDavid du Colombier #endif
1145*593dc095SDavid du Colombier 
1146*593dc095SDavid du Colombier #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1147*593dc095SDavid du Colombier defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1148*593dc095SDavid du Colombier    if(png_ptr->transformations & PNG_USER_TRANSFORM)
1149*593dc095SDavid du Colombier      {
1150*593dc095SDavid du Colombier        if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1151*593dc095SDavid du Colombier          info_ptr->bit_depth = png_ptr->user_transform_depth;
1152*593dc095SDavid du Colombier        if(info_ptr->channels < png_ptr->user_transform_channels)
1153*593dc095SDavid du Colombier          info_ptr->channels = png_ptr->user_transform_channels;
1154*593dc095SDavid du Colombier      }
1155*593dc095SDavid du Colombier #endif
1156*593dc095SDavid du Colombier 
11577dd7cddfSDavid du Colombier    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
11587dd7cddfSDavid du Colombier       info_ptr->bit_depth);
11597dd7cddfSDavid du Colombier 
1160*593dc095SDavid du Colombier    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
1161*593dc095SDavid du Colombier 
1162*593dc095SDavid du Colombier #if !defined(PNG_READ_EXPAND_SUPPORTED)
1163*593dc095SDavid du Colombier    if(png_ptr)
1164*593dc095SDavid du Colombier       return;
1165*593dc095SDavid du Colombier #endif
11667dd7cddfSDavid du Colombier }
11677dd7cddfSDavid du Colombier 
11687dd7cddfSDavid du Colombier /* Transform the row.  The order of transformations is significant,
11697dd7cddfSDavid du Colombier  * and is very touchy.  If you add a transformation, take care to
11707dd7cddfSDavid du Colombier  * decide how it fits in with the other transformations here.
11717dd7cddfSDavid du Colombier  */
1172*593dc095SDavid du Colombier void /* PRIVATE */
png_do_read_transformations(png_structp png_ptr)11737dd7cddfSDavid du Colombier png_do_read_transformations(png_structp png_ptr)
11747dd7cddfSDavid du Colombier {
11757dd7cddfSDavid du Colombier    png_debug(1, "in png_do_read_transformations\n");
11767dd7cddfSDavid du Colombier #if !defined(PNG_USELESS_TESTS_SUPPORTED)
11777dd7cddfSDavid du Colombier    if (png_ptr->row_buf == NULL)
11787dd7cddfSDavid du Colombier    {
1179*593dc095SDavid du Colombier #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
11807dd7cddfSDavid du Colombier       char msg[50];
11817dd7cddfSDavid du Colombier 
11827dd7cddfSDavid du Colombier       sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
11837dd7cddfSDavid du Colombier          png_ptr->pass);
11847dd7cddfSDavid du Colombier       png_error(png_ptr, msg);
11857dd7cddfSDavid du Colombier #else
11867dd7cddfSDavid du Colombier       png_error(png_ptr, "NULL row buffer");
11877dd7cddfSDavid du Colombier #endif
11887dd7cddfSDavid du Colombier    }
11897dd7cddfSDavid du Colombier #endif
11907dd7cddfSDavid du Colombier 
11917dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
11927dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_EXPAND)
11937dd7cddfSDavid du Colombier    {
11947dd7cddfSDavid du Colombier       if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
11957dd7cddfSDavid du Colombier       {
11967dd7cddfSDavid du Colombier          png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
11977dd7cddfSDavid du Colombier             png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
11987dd7cddfSDavid du Colombier       }
1199*593dc095SDavid du Colombier       else
12007dd7cddfSDavid du Colombier       {
12017dd7cddfSDavid du Colombier          if (png_ptr->num_trans)
12027dd7cddfSDavid du Colombier             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
12037dd7cddfSDavid du Colombier                &(png_ptr->trans_values));
12047dd7cddfSDavid du Colombier          else
12057dd7cddfSDavid du Colombier             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
12067dd7cddfSDavid du Colombier                NULL);
12077dd7cddfSDavid du Colombier       }
12087dd7cddfSDavid du Colombier    }
12097dd7cddfSDavid du Colombier #endif
12107dd7cddfSDavid du Colombier 
12117dd7cddfSDavid du Colombier #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1212*593dc095SDavid du Colombier    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
12137dd7cddfSDavid du Colombier       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1214*593dc095SDavid du Colombier          PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1215*593dc095SDavid du Colombier #endif
1216*593dc095SDavid du Colombier 
1217*593dc095SDavid du Colombier #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1218*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1219*593dc095SDavid du Colombier    {
1220*593dc095SDavid du Colombier       int rgb_error =
1221*593dc095SDavid du Colombier          png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1222*593dc095SDavid du Colombier       if(rgb_error)
1223*593dc095SDavid du Colombier       {
1224*593dc095SDavid du Colombier          png_ptr->rgb_to_gray_status=1;
1225*593dc095SDavid du Colombier          if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1226*593dc095SDavid du Colombier             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1227*593dc095SDavid du Colombier          if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1228*593dc095SDavid du Colombier             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1229*593dc095SDavid du Colombier       }
1230*593dc095SDavid du Colombier    }
1231*593dc095SDavid du Colombier #endif
1232*593dc095SDavid du Colombier 
1233*593dc095SDavid du Colombier /*
1234*593dc095SDavid du Colombier From Andreas Dilger e-mail to png-implement, 26 March 1998:
1235*593dc095SDavid du Colombier 
1236*593dc095SDavid du Colombier   In most cases, the "simple transparency" should be done prior to doing
1237*593dc095SDavid du Colombier   gray-to-RGB, or you will have to test 3x as many bytes to check if a
1238*593dc095SDavid du Colombier   pixel is transparent.  You would also need to make sure that the
1239*593dc095SDavid du Colombier   transparency information is upgraded to RGB.
1240*593dc095SDavid du Colombier 
1241*593dc095SDavid du Colombier   To summarize, the current flow is:
1242*593dc095SDavid du Colombier   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1243*593dc095SDavid du Colombier                                   with background "in place" if transparent,
1244*593dc095SDavid du Colombier                                   convert to RGB if necessary
1245*593dc095SDavid du Colombier   - Gray + alpha -> composite with gray background and remove alpha bytes,
1246*593dc095SDavid du Colombier                                   convert to RGB if necessary
1247*593dc095SDavid du Colombier 
1248*593dc095SDavid du Colombier   To support RGB backgrounds for gray images we need:
1249*593dc095SDavid du Colombier   - Gray + simple transparency -> convert to RGB + simple transparency, compare
1250*593dc095SDavid du Colombier                                   3 or 6 bytes and composite with background
1251*593dc095SDavid du Colombier                                   "in place" if transparent (3x compare/pixel
1252*593dc095SDavid du Colombier                                   compared to doing composite with gray bkgrnd)
1253*593dc095SDavid du Colombier   - Gray + alpha -> convert to RGB + alpha, composite with background and
1254*593dc095SDavid du Colombier                                   remove alpha bytes (3x float operations/pixel
1255*593dc095SDavid du Colombier                                   compared with composite on gray background)
1256*593dc095SDavid du Colombier 
1257*593dc095SDavid du Colombier   Greg's change will do this.  The reason it wasn't done before is for
1258*593dc095SDavid du Colombier   performance, as this increases the per-pixel operations.  If we would check
1259*593dc095SDavid du Colombier   in advance if the background was gray or RGB, and position the gray-to-RGB
1260*593dc095SDavid du Colombier   transform appropriately, then it would save a lot of work/time.
1261*593dc095SDavid du Colombier  */
1262*593dc095SDavid du Colombier 
1263*593dc095SDavid du Colombier #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1264*593dc095SDavid du Colombier    /* if gray -> RGB, do so now only if background is non-gray; else do later
1265*593dc095SDavid du Colombier     * for performance reasons */
1266*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1267*593dc095SDavid du Colombier        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1268*593dc095SDavid du Colombier       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
12697dd7cddfSDavid du Colombier #endif
12707dd7cddfSDavid du Colombier 
12717dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
12727dd7cddfSDavid du Colombier    if ((png_ptr->transformations & PNG_BACKGROUND) &&
12737dd7cddfSDavid du Colombier       ((png_ptr->num_trans != 0 ) ||
12747dd7cddfSDavid du Colombier       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
12757dd7cddfSDavid du Colombier       png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1276*593dc095SDavid du Colombier          &(png_ptr->trans_values), &(png_ptr->background)
1277*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
1278*593dc095SDavid du Colombier          , &(png_ptr->background_1),
12797dd7cddfSDavid du Colombier          png_ptr->gamma_table, png_ptr->gamma_from_1,
12807dd7cddfSDavid du Colombier          png_ptr->gamma_to_1, png_ptr->gamma_16_table,
12817dd7cddfSDavid du Colombier          png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1282*593dc095SDavid du Colombier          png_ptr->gamma_shift
1283*593dc095SDavid du Colombier #endif
1284*593dc095SDavid du Colombier );
12857dd7cddfSDavid du Colombier #endif
12867dd7cddfSDavid du Colombier 
12877dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
12887dd7cddfSDavid du Colombier    if ((png_ptr->transformations & PNG_GAMMA) &&
1289*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1290*593dc095SDavid du Colombier       !((png_ptr->transformations & PNG_BACKGROUND) &&
1291*593dc095SDavid du Colombier       ((png_ptr->num_trans != 0) ||
1292*593dc095SDavid du Colombier       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1293*593dc095SDavid du Colombier #endif
12947dd7cddfSDavid du Colombier       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
12957dd7cddfSDavid du Colombier       png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
12967dd7cddfSDavid du Colombier          png_ptr->gamma_table, png_ptr->gamma_16_table,
12977dd7cddfSDavid du Colombier          png_ptr->gamma_shift);
12987dd7cddfSDavid du Colombier #endif
12997dd7cddfSDavid du Colombier 
13007dd7cddfSDavid du Colombier #if defined(PNG_READ_16_TO_8_SUPPORTED)
13017dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_16_TO_8)
13027dd7cddfSDavid du Colombier       png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
13037dd7cddfSDavid du Colombier #endif
13047dd7cddfSDavid du Colombier 
13057dd7cddfSDavid du Colombier #if defined(PNG_READ_DITHER_SUPPORTED)
13067dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_DITHER)
13077dd7cddfSDavid du Colombier    {
13087dd7cddfSDavid du Colombier       png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
13097dd7cddfSDavid du Colombier          png_ptr->palette_lookup, png_ptr->dither_index);
1310*593dc095SDavid du Colombier       if(png_ptr->row_info.rowbytes == (png_uint_32)0)
13117dd7cddfSDavid du Colombier          png_error(png_ptr, "png_do_dither returned rowbytes=0");
13127dd7cddfSDavid du Colombier    }
13137dd7cddfSDavid du Colombier #endif
13147dd7cddfSDavid du Colombier 
13157dd7cddfSDavid du Colombier #if defined(PNG_READ_INVERT_SUPPORTED)
13167dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_INVERT_MONO)
13177dd7cddfSDavid du Colombier       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
13187dd7cddfSDavid du Colombier #endif
13197dd7cddfSDavid du Colombier 
13207dd7cddfSDavid du Colombier #if defined(PNG_READ_SHIFT_SUPPORTED)
13217dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_SHIFT)
13227dd7cddfSDavid du Colombier       png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
13237dd7cddfSDavid du Colombier          &(png_ptr->shift));
13247dd7cddfSDavid du Colombier #endif
13257dd7cddfSDavid du Colombier 
13267dd7cddfSDavid du Colombier #if defined(PNG_READ_PACK_SUPPORTED)
13277dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_PACK)
13287dd7cddfSDavid du Colombier       png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
13297dd7cddfSDavid du Colombier #endif
13307dd7cddfSDavid du Colombier 
13317dd7cddfSDavid du Colombier #if defined(PNG_READ_BGR_SUPPORTED)
13327dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_BGR)
13337dd7cddfSDavid du Colombier       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
13347dd7cddfSDavid du Colombier #endif
13357dd7cddfSDavid du Colombier 
13367dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
13377dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_PACKSWAP)
13387dd7cddfSDavid du Colombier       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
13397dd7cddfSDavid du Colombier #endif
13407dd7cddfSDavid du Colombier 
13417dd7cddfSDavid du Colombier #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1342*593dc095SDavid du Colombier    /* if gray -> RGB, do so now only if we did not do so above */
1343*593dc095SDavid du Colombier    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1344*593dc095SDavid du Colombier        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
13457dd7cddfSDavid du Colombier       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
13467dd7cddfSDavid du Colombier #endif
13477dd7cddfSDavid du Colombier 
13487dd7cddfSDavid du Colombier #if defined(PNG_READ_FILLER_SUPPORTED)
13497dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_FILLER)
13507dd7cddfSDavid du Colombier       png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
13517dd7cddfSDavid du Colombier          (png_uint_32)png_ptr->filler, png_ptr->flags);
13527dd7cddfSDavid du Colombier #endif
13537dd7cddfSDavid du Colombier 
13547dd7cddfSDavid du Colombier #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
13557dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_INVERT_ALPHA)
13567dd7cddfSDavid du Colombier       png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
13577dd7cddfSDavid du Colombier #endif
13587dd7cddfSDavid du Colombier 
1359*593dc095SDavid du Colombier #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1360*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_SWAP_ALPHA)
1361*593dc095SDavid du Colombier       png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1362*593dc095SDavid du Colombier #endif
1363*593dc095SDavid du Colombier 
13647dd7cddfSDavid du Colombier #if defined(PNG_READ_SWAP_SUPPORTED)
13657dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_SWAP_BYTES)
13667dd7cddfSDavid du Colombier       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
13677dd7cddfSDavid du Colombier #endif
1368*593dc095SDavid du Colombier 
1369*593dc095SDavid du Colombier #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1370*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_USER_TRANSFORM)
1371*593dc095SDavid du Colombier     {
1372*593dc095SDavid du Colombier       if(png_ptr->read_user_transform_fn != NULL)
1373*593dc095SDavid du Colombier         (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1374*593dc095SDavid du Colombier           (png_ptr,                    /* png_ptr */
1375*593dc095SDavid du Colombier            &(png_ptr->row_info),       /* row_info:     */
1376*593dc095SDavid du Colombier              /*  png_uint_32 width;          width of row */
1377*593dc095SDavid du Colombier              /*  png_uint_32 rowbytes;       number of bytes in row */
1378*593dc095SDavid du Colombier              /*  png_byte color_type;        color type of pixels */
1379*593dc095SDavid du Colombier              /*  png_byte bit_depth;         bit depth of samples */
1380*593dc095SDavid du Colombier              /*  png_byte channels;          number of channels (1-4) */
1381*593dc095SDavid du Colombier              /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
1382*593dc095SDavid du Colombier            png_ptr->row_buf + 1);      /* start of pixel data for row */
1383*593dc095SDavid du Colombier #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1384*593dc095SDavid du Colombier       if(png_ptr->user_transform_depth)
1385*593dc095SDavid du Colombier          png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1386*593dc095SDavid du Colombier       if(png_ptr->user_transform_channels)
1387*593dc095SDavid du Colombier          png_ptr->row_info.channels = png_ptr->user_transform_channels;
1388*593dc095SDavid du Colombier #endif
1389*593dc095SDavid du Colombier       png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1390*593dc095SDavid du Colombier          png_ptr->row_info.channels);
1391*593dc095SDavid du Colombier       png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1392*593dc095SDavid du Colombier          png_ptr->row_info.width);
1393*593dc095SDavid du Colombier    }
1394*593dc095SDavid du Colombier #endif
1395*593dc095SDavid du Colombier 
13967dd7cddfSDavid du Colombier }
13977dd7cddfSDavid du Colombier 
13987dd7cddfSDavid du Colombier #if defined(PNG_READ_PACK_SUPPORTED)
13997dd7cddfSDavid du Colombier /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
14007dd7cddfSDavid du Colombier  * without changing the actual values.  Thus, if you had a row with
14017dd7cddfSDavid du Colombier  * a bit depth of 1, you would end up with bytes that only contained
14027dd7cddfSDavid du Colombier  * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
14037dd7cddfSDavid du Colombier  * png_do_shift() after this.
14047dd7cddfSDavid du Colombier  */
1405*593dc095SDavid du Colombier void /* PRIVATE */
png_do_unpack(png_row_infop row_info,png_bytep row)14067dd7cddfSDavid du Colombier png_do_unpack(png_row_infop row_info, png_bytep row)
14077dd7cddfSDavid du Colombier {
14087dd7cddfSDavid du Colombier    png_debug(1, "in png_do_unpack\n");
14097dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
14107dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
14117dd7cddfSDavid du Colombier #else
14127dd7cddfSDavid du Colombier    if (row_info->bit_depth < 8)
14137dd7cddfSDavid du Colombier #endif
14147dd7cddfSDavid du Colombier    {
1415*593dc095SDavid du Colombier       png_uint_32 i;
1416*593dc095SDavid du Colombier       png_uint_32 row_width=row_info->width;
14177dd7cddfSDavid du Colombier 
14187dd7cddfSDavid du Colombier       switch (row_info->bit_depth)
14197dd7cddfSDavid du Colombier       {
14207dd7cddfSDavid du Colombier          case 1:
14217dd7cddfSDavid du Colombier          {
1422*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1423*593dc095SDavid du Colombier             png_bytep dp = row + (png_size_t)row_width - 1;
1424*593dc095SDavid du Colombier             png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1425*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
14267dd7cddfSDavid du Colombier             {
1427*593dc095SDavid du Colombier                *dp = (png_byte)((*sp >> shift) & 0x01);
14287dd7cddfSDavid du Colombier                if (shift == 7)
14297dd7cddfSDavid du Colombier                {
14307dd7cddfSDavid du Colombier                   shift = 0;
14317dd7cddfSDavid du Colombier                   sp--;
14327dd7cddfSDavid du Colombier                }
14337dd7cddfSDavid du Colombier                else
14347dd7cddfSDavid du Colombier                   shift++;
14357dd7cddfSDavid du Colombier 
14367dd7cddfSDavid du Colombier                dp--;
14377dd7cddfSDavid du Colombier             }
14387dd7cddfSDavid du Colombier             break;
14397dd7cddfSDavid du Colombier          }
14407dd7cddfSDavid du Colombier          case 2:
14417dd7cddfSDavid du Colombier          {
14427dd7cddfSDavid du Colombier 
1443*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1444*593dc095SDavid du Colombier             png_bytep dp = row + (png_size_t)row_width - 1;
1445*593dc095SDavid du Colombier             png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1446*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
14477dd7cddfSDavid du Colombier             {
1448*593dc095SDavid du Colombier                *dp = (png_byte)((*sp >> shift) & 0x03);
14497dd7cddfSDavid du Colombier                if (shift == 6)
14507dd7cddfSDavid du Colombier                {
14517dd7cddfSDavid du Colombier                   shift = 0;
14527dd7cddfSDavid du Colombier                   sp--;
14537dd7cddfSDavid du Colombier                }
14547dd7cddfSDavid du Colombier                else
14557dd7cddfSDavid du Colombier                   shift += 2;
14567dd7cddfSDavid du Colombier 
14577dd7cddfSDavid du Colombier                dp--;
14587dd7cddfSDavid du Colombier             }
14597dd7cddfSDavid du Colombier             break;
14607dd7cddfSDavid du Colombier          }
14617dd7cddfSDavid du Colombier          case 4:
14627dd7cddfSDavid du Colombier          {
1463*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1464*593dc095SDavid du Colombier             png_bytep dp = row + (png_size_t)row_width - 1;
1465*593dc095SDavid du Colombier             png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1466*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
14677dd7cddfSDavid du Colombier             {
1468*593dc095SDavid du Colombier                *dp = (png_byte)((*sp >> shift) & 0x0f);
14697dd7cddfSDavid du Colombier                if (shift == 4)
14707dd7cddfSDavid du Colombier                {
14717dd7cddfSDavid du Colombier                   shift = 0;
14727dd7cddfSDavid du Colombier                   sp--;
14737dd7cddfSDavid du Colombier                }
14747dd7cddfSDavid du Colombier                else
14757dd7cddfSDavid du Colombier                   shift = 4;
14767dd7cddfSDavid du Colombier 
14777dd7cddfSDavid du Colombier                dp--;
14787dd7cddfSDavid du Colombier             }
14797dd7cddfSDavid du Colombier             break;
14807dd7cddfSDavid du Colombier          }
14817dd7cddfSDavid du Colombier       }
14827dd7cddfSDavid du Colombier       row_info->bit_depth = 8;
14837dd7cddfSDavid du Colombier       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1484*593dc095SDavid du Colombier       row_info->rowbytes = row_width * row_info->channels;
14857dd7cddfSDavid du Colombier    }
14867dd7cddfSDavid du Colombier }
14877dd7cddfSDavid du Colombier #endif
14887dd7cddfSDavid du Colombier 
14897dd7cddfSDavid du Colombier #if defined(PNG_READ_SHIFT_SUPPORTED)
14907dd7cddfSDavid du Colombier /* Reverse the effects of png_do_shift.  This routine merely shifts the
14917dd7cddfSDavid du Colombier  * pixels back to their significant bits values.  Thus, if you have
14927dd7cddfSDavid du Colombier  * a row of bit depth 8, but only 5 are significant, this will shift
14937dd7cddfSDavid du Colombier  * the values back to 0 through 31.
14947dd7cddfSDavid du Colombier  */
1495*593dc095SDavid du Colombier void /* PRIVATE */
png_do_unshift(png_row_infop row_info,png_bytep row,png_color_8p sig_bits)14967dd7cddfSDavid du Colombier png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
14977dd7cddfSDavid du Colombier {
14987dd7cddfSDavid du Colombier    png_debug(1, "in png_do_unshift\n");
14997dd7cddfSDavid du Colombier    if (
15007dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
15017dd7cddfSDavid du Colombier        row != NULL && row_info != NULL && sig_bits != NULL &&
15027dd7cddfSDavid du Colombier #endif
15037dd7cddfSDavid du Colombier        row_info->color_type != PNG_COLOR_TYPE_PALETTE)
15047dd7cddfSDavid du Colombier    {
15057dd7cddfSDavid du Colombier       int shift[4];
1506*593dc095SDavid du Colombier       int channels = 0;
1507*593dc095SDavid du Colombier       int c;
1508*593dc095SDavid du Colombier       png_uint_16 value = 0;
1509*593dc095SDavid du Colombier       png_uint_32 row_width = row_info->width;
15107dd7cddfSDavid du Colombier 
15117dd7cddfSDavid du Colombier       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
15127dd7cddfSDavid du Colombier       {
15137dd7cddfSDavid du Colombier          shift[channels++] = row_info->bit_depth - sig_bits->red;
15147dd7cddfSDavid du Colombier          shift[channels++] = row_info->bit_depth - sig_bits->green;
15157dd7cddfSDavid du Colombier          shift[channels++] = row_info->bit_depth - sig_bits->blue;
15167dd7cddfSDavid du Colombier       }
15177dd7cddfSDavid du Colombier       else
15187dd7cddfSDavid du Colombier       {
15197dd7cddfSDavid du Colombier          shift[channels++] = row_info->bit_depth - sig_bits->gray;
15207dd7cddfSDavid du Colombier       }
15217dd7cddfSDavid du Colombier       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
15227dd7cddfSDavid du Colombier       {
15237dd7cddfSDavid du Colombier          shift[channels++] = row_info->bit_depth - sig_bits->alpha;
15247dd7cddfSDavid du Colombier       }
15257dd7cddfSDavid du Colombier 
15267dd7cddfSDavid du Colombier       for (c = 0; c < channels; c++)
15277dd7cddfSDavid du Colombier       {
15287dd7cddfSDavid du Colombier          if (shift[c] <= 0)
15297dd7cddfSDavid du Colombier             shift[c] = 0;
15307dd7cddfSDavid du Colombier          else
15317dd7cddfSDavid du Colombier             value = 1;
15327dd7cddfSDavid du Colombier       }
15337dd7cddfSDavid du Colombier 
15347dd7cddfSDavid du Colombier       if (!value)
15357dd7cddfSDavid du Colombier          return;
15367dd7cddfSDavid du Colombier 
15377dd7cddfSDavid du Colombier       switch (row_info->bit_depth)
15387dd7cddfSDavid du Colombier       {
15397dd7cddfSDavid du Colombier          case 2:
15407dd7cddfSDavid du Colombier          {
15417dd7cddfSDavid du Colombier             png_bytep bp;
1542*593dc095SDavid du Colombier             png_uint_32 i;
1543*593dc095SDavid du Colombier             png_uint_32 istop = row_info->rowbytes;
15447dd7cddfSDavid du Colombier 
1545*593dc095SDavid du Colombier             for (bp = row, i = 0; i < istop; i++)
15467dd7cddfSDavid du Colombier             {
15477dd7cddfSDavid du Colombier                *bp >>= 1;
1548*593dc095SDavid du Colombier                *bp++ &= 0x55;
15497dd7cddfSDavid du Colombier             }
15507dd7cddfSDavid du Colombier             break;
15517dd7cddfSDavid du Colombier          }
15527dd7cddfSDavid du Colombier          case 4:
15537dd7cddfSDavid du Colombier          {
1554*593dc095SDavid du Colombier             png_bytep bp = row;
1555*593dc095SDavid du Colombier             png_uint_32 i;
1556*593dc095SDavid du Colombier             png_uint_32 istop = row_info->rowbytes;
1557*593dc095SDavid du Colombier             png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1558*593dc095SDavid du Colombier                (png_byte)((int)0xf >> shift[0]));
15597dd7cddfSDavid du Colombier 
1560*593dc095SDavid du Colombier             for (i = 0; i < istop; i++)
15617dd7cddfSDavid du Colombier             {
15627dd7cddfSDavid du Colombier                *bp >>= shift[0];
1563*593dc095SDavid du Colombier                *bp++ &= mask;
15647dd7cddfSDavid du Colombier             }
15657dd7cddfSDavid du Colombier             break;
15667dd7cddfSDavid du Colombier          }
15677dd7cddfSDavid du Colombier          case 8:
15687dd7cddfSDavid du Colombier          {
1569*593dc095SDavid du Colombier             png_bytep bp = row;
1570*593dc095SDavid du Colombier             png_uint_32 i;
1571*593dc095SDavid du Colombier             png_uint_32 istop = row_width * channels;
15727dd7cddfSDavid du Colombier 
1573*593dc095SDavid du Colombier             for (i = 0; i < istop; i++)
15747dd7cddfSDavid du Colombier             {
1575*593dc095SDavid du Colombier                *bp++ >>= shift[i%channels];
15767dd7cddfSDavid du Colombier             }
15777dd7cddfSDavid du Colombier             break;
15787dd7cddfSDavid du Colombier          }
15797dd7cddfSDavid du Colombier          case 16:
15807dd7cddfSDavid du Colombier          {
1581*593dc095SDavid du Colombier             png_bytep bp = row;
1582*593dc095SDavid du Colombier             png_uint_32 i;
1583*593dc095SDavid du Colombier             png_uint_32 istop = channels * row_width;
15847dd7cddfSDavid du Colombier 
1585*593dc095SDavid du Colombier             for (i = 0; i < istop; i++)
15867dd7cddfSDavid du Colombier             {
15877dd7cddfSDavid du Colombier                value = (png_uint_16)((*bp << 8) + *(bp + 1));
1588*593dc095SDavid du Colombier                value >>= shift[i%channels];
1589*593dc095SDavid du Colombier                *bp++ = (png_byte)(value >> 8);
1590*593dc095SDavid du Colombier                *bp++ = (png_byte)(value & 0xff);
15917dd7cddfSDavid du Colombier             }
15927dd7cddfSDavid du Colombier             break;
15937dd7cddfSDavid du Colombier          }
15947dd7cddfSDavid du Colombier       }
15957dd7cddfSDavid du Colombier    }
15967dd7cddfSDavid du Colombier }
15977dd7cddfSDavid du Colombier #endif
15987dd7cddfSDavid du Colombier 
15997dd7cddfSDavid du Colombier #if defined(PNG_READ_16_TO_8_SUPPORTED)
16007dd7cddfSDavid du Colombier /* chop rows of bit depth 16 down to 8 */
1601*593dc095SDavid du Colombier void /* PRIVATE */
png_do_chop(png_row_infop row_info,png_bytep row)16027dd7cddfSDavid du Colombier png_do_chop(png_row_infop row_info, png_bytep row)
16037dd7cddfSDavid du Colombier {
16047dd7cddfSDavid du Colombier    png_debug(1, "in png_do_chop\n");
16057dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
16067dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
16077dd7cddfSDavid du Colombier #else
16087dd7cddfSDavid du Colombier    if (row_info->bit_depth == 16)
16097dd7cddfSDavid du Colombier #endif
16107dd7cddfSDavid du Colombier    {
1611*593dc095SDavid du Colombier       png_bytep sp = row;
1612*593dc095SDavid du Colombier       png_bytep dp = row;
16137dd7cddfSDavid du Colombier       png_uint_32 i;
1614*593dc095SDavid du Colombier       png_uint_32 istop = row_info->width * row_info->channels;
16157dd7cddfSDavid du Colombier 
1616*593dc095SDavid du Colombier       for (i = 0; i<istop; i++, sp += 2, dp++)
16177dd7cddfSDavid du Colombier       {
16187dd7cddfSDavid du Colombier #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
16197dd7cddfSDavid du Colombier       /* This does a more accurate scaling of the 16-bit color
16207dd7cddfSDavid du Colombier        * value, rather than a simple low-byte truncation.
16217dd7cddfSDavid du Colombier        *
16227dd7cddfSDavid du Colombier        * What the ideal calculation should be:
1623*593dc095SDavid du Colombier        *   *dp = (((((png_uint_32)(*sp) << 8) |
1624*593dc095SDavid du Colombier        *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1625*593dc095SDavid du Colombier        *
16267dd7cddfSDavid du Colombier        * GRR: no, I think this is what it really should be:
1627*593dc095SDavid du Colombier        *   *dp = (((((png_uint_32)(*sp) << 8) |
1628*593dc095SDavid du Colombier        *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1629*593dc095SDavid du Colombier        *
16307dd7cddfSDavid du Colombier        * GRR: here's the exact calculation with shifts:
1631*593dc095SDavid du Colombier        *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1632*593dc095SDavid du Colombier        *   *dp = (temp - (temp >> 8)) >> 8;
1633*593dc095SDavid du Colombier        *
16347dd7cddfSDavid du Colombier        * Approximate calculation with shift/add instead of multiply/divide:
1635*593dc095SDavid du Colombier        *   *dp = ((((png_uint_32)(*sp) << 8) |
1636*593dc095SDavid du Colombier        *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1637*593dc095SDavid du Colombier        *
1638*593dc095SDavid du Colombier        * What we actually do to avoid extra shifting and conversion:
1639*593dc095SDavid du Colombier        */
16407dd7cddfSDavid du Colombier 
16417dd7cddfSDavid du Colombier          *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
16427dd7cddfSDavid du Colombier #else
1643*593dc095SDavid du Colombier        /* Simply discard the low order byte */
16447dd7cddfSDavid du Colombier          *dp = *sp;
16457dd7cddfSDavid du Colombier #endif
16467dd7cddfSDavid du Colombier       }
16477dd7cddfSDavid du Colombier       row_info->bit_depth = 8;
16487dd7cddfSDavid du Colombier       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1649*593dc095SDavid du Colombier       row_info->rowbytes = row_info->width * row_info->channels;
16507dd7cddfSDavid du Colombier    }
16517dd7cddfSDavid du Colombier }
16527dd7cddfSDavid du Colombier #endif
16537dd7cddfSDavid du Colombier 
16547dd7cddfSDavid du Colombier #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1655*593dc095SDavid du Colombier void /* PRIVATE */
png_do_read_swap_alpha(png_row_infop row_info,png_bytep row)16567dd7cddfSDavid du Colombier png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
16577dd7cddfSDavid du Colombier {
16587dd7cddfSDavid du Colombier    png_debug(1, "in png_do_read_swap_alpha\n");
16597dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
16607dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL)
16617dd7cddfSDavid du Colombier #endif
16627dd7cddfSDavid du Colombier    {
1663*593dc095SDavid du Colombier       png_uint_32 row_width = row_info->width;
16647dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
16657dd7cddfSDavid du Colombier       {
16667dd7cddfSDavid du Colombier          /* This converts from RGBA to ARGB */
16677dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
16687dd7cddfSDavid du Colombier          {
1669*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1670*593dc095SDavid du Colombier             png_bytep dp = sp;
16717dd7cddfSDavid du Colombier             png_byte save;
16727dd7cddfSDavid du Colombier             png_uint_32 i;
16737dd7cddfSDavid du Colombier 
1674*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
16757dd7cddfSDavid du Colombier             {
16767dd7cddfSDavid du Colombier                save = *(--sp);
16777dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16787dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16797dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16807dd7cddfSDavid du Colombier                *(--dp) = save;
16817dd7cddfSDavid du Colombier             }
16827dd7cddfSDavid du Colombier          }
16837dd7cddfSDavid du Colombier          /* This converts from RRGGBBAA to AARRGGBB */
16847dd7cddfSDavid du Colombier          else
16857dd7cddfSDavid du Colombier          {
1686*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1687*593dc095SDavid du Colombier             png_bytep dp = sp;
16887dd7cddfSDavid du Colombier             png_byte save[2];
16897dd7cddfSDavid du Colombier             png_uint_32 i;
16907dd7cddfSDavid du Colombier 
1691*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
16927dd7cddfSDavid du Colombier             {
16937dd7cddfSDavid du Colombier                save[0] = *(--sp);
16947dd7cddfSDavid du Colombier                save[1] = *(--sp);
16957dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16967dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16977dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16987dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
16997dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17007dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17017dd7cddfSDavid du Colombier                *(--dp) = save[0];
17027dd7cddfSDavid du Colombier                *(--dp) = save[1];
17037dd7cddfSDavid du Colombier             }
17047dd7cddfSDavid du Colombier          }
17057dd7cddfSDavid du Colombier       }
17067dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
17077dd7cddfSDavid du Colombier       {
17087dd7cddfSDavid du Colombier          /* This converts from GA to AG */
17097dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
17107dd7cddfSDavid du Colombier          {
1711*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1712*593dc095SDavid du Colombier             png_bytep dp = sp;
17137dd7cddfSDavid du Colombier             png_byte save;
17147dd7cddfSDavid du Colombier             png_uint_32 i;
17157dd7cddfSDavid du Colombier 
1716*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
17177dd7cddfSDavid du Colombier             {
17187dd7cddfSDavid du Colombier                save = *(--sp);
17197dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17207dd7cddfSDavid du Colombier                *(--dp) = save;
17217dd7cddfSDavid du Colombier             }
17227dd7cddfSDavid du Colombier          }
17237dd7cddfSDavid du Colombier          /* This converts from GGAA to AAGG */
17247dd7cddfSDavid du Colombier          else
17257dd7cddfSDavid du Colombier          {
1726*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1727*593dc095SDavid du Colombier             png_bytep dp = sp;
17287dd7cddfSDavid du Colombier             png_byte save[2];
17297dd7cddfSDavid du Colombier             png_uint_32 i;
17307dd7cddfSDavid du Colombier 
1731*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
17327dd7cddfSDavid du Colombier             {
17337dd7cddfSDavid du Colombier                save[0] = *(--sp);
17347dd7cddfSDavid du Colombier                save[1] = *(--sp);
17357dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17367dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17377dd7cddfSDavid du Colombier                *(--dp) = save[0];
17387dd7cddfSDavid du Colombier                *(--dp) = save[1];
17397dd7cddfSDavid du Colombier             }
17407dd7cddfSDavid du Colombier          }
17417dd7cddfSDavid du Colombier       }
17427dd7cddfSDavid du Colombier    }
17437dd7cddfSDavid du Colombier }
17447dd7cddfSDavid du Colombier #endif
17457dd7cddfSDavid du Colombier 
17467dd7cddfSDavid du Colombier #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1747*593dc095SDavid du Colombier void /* PRIVATE */
png_do_read_invert_alpha(png_row_infop row_info,png_bytep row)17487dd7cddfSDavid du Colombier png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
17497dd7cddfSDavid du Colombier {
17507dd7cddfSDavid du Colombier    png_debug(1, "in png_do_read_invert_alpha\n");
17517dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
17527dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL)
17537dd7cddfSDavid du Colombier #endif
17547dd7cddfSDavid du Colombier    {
1755*593dc095SDavid du Colombier       png_uint_32 row_width = row_info->width;
17567dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
17577dd7cddfSDavid du Colombier       {
17587dd7cddfSDavid du Colombier          /* This inverts the alpha channel in RGBA */
17597dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
17607dd7cddfSDavid du Colombier          {
1761*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1762*593dc095SDavid du Colombier             png_bytep dp = sp;
17637dd7cddfSDavid du Colombier             png_uint_32 i;
17647dd7cddfSDavid du Colombier 
1765*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
17667dd7cddfSDavid du Colombier             {
1767*593dc095SDavid du Colombier                *(--dp) = (png_byte)(255 - *(--sp));
1768*593dc095SDavid du Colombier 
1769*593dc095SDavid du Colombier /*             This does nothing:
17707dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17717dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17727dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
1773*593dc095SDavid du Colombier                We can replace it with:
1774*593dc095SDavid du Colombier */
1775*593dc095SDavid du Colombier                sp-=3;
1776*593dc095SDavid du Colombier                dp=sp;
17777dd7cddfSDavid du Colombier             }
17787dd7cddfSDavid du Colombier          }
17797dd7cddfSDavid du Colombier          /* This inverts the alpha channel in RRGGBBAA */
17807dd7cddfSDavid du Colombier          else
17817dd7cddfSDavid du Colombier          {
1782*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1783*593dc095SDavid du Colombier             png_bytep dp = sp;
17847dd7cddfSDavid du Colombier             png_uint_32 i;
17857dd7cddfSDavid du Colombier 
1786*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
17877dd7cddfSDavid du Colombier             {
1788*593dc095SDavid du Colombier                *(--dp) = (png_byte)(255 - *(--sp));
1789*593dc095SDavid du Colombier                *(--dp) = (png_byte)(255 - *(--sp));
1790*593dc095SDavid du Colombier 
1791*593dc095SDavid du Colombier /*             This does nothing:
17927dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17937dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17947dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17957dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17967dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
17977dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
1798*593dc095SDavid du Colombier                We can replace it with:
1799*593dc095SDavid du Colombier */
1800*593dc095SDavid du Colombier                sp-=6;
1801*593dc095SDavid du Colombier                dp=sp;
18027dd7cddfSDavid du Colombier             }
18037dd7cddfSDavid du Colombier          }
18047dd7cddfSDavid du Colombier       }
18057dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
18067dd7cddfSDavid du Colombier       {
1807*593dc095SDavid du Colombier          /* This inverts the alpha channel in GA */
18087dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
18097dd7cddfSDavid du Colombier          {
1810*593dc095SDavid du Colombier             png_bytep sp = row + row_info->rowbytes;
1811*593dc095SDavid du Colombier             png_bytep dp = sp;
18127dd7cddfSDavid du Colombier             png_uint_32 i;
18137dd7cddfSDavid du Colombier 
1814*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
18157dd7cddfSDavid du Colombier             {
1816*593dc095SDavid du Colombier                *(--dp) = (png_byte)(255 - *(--sp));
18177dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
18187dd7cddfSDavid du Colombier             }
18197dd7cddfSDavid du Colombier          }
1820*593dc095SDavid du Colombier          /* This inverts the alpha channel in GGAA */
18217dd7cddfSDavid du Colombier          else
18227dd7cddfSDavid du Colombier          {
1823*593dc095SDavid du Colombier             png_bytep sp  = row + row_info->rowbytes;
1824*593dc095SDavid du Colombier             png_bytep dp = sp;
18257dd7cddfSDavid du Colombier             png_uint_32 i;
18267dd7cddfSDavid du Colombier 
1827*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
18287dd7cddfSDavid du Colombier             {
1829*593dc095SDavid du Colombier                *(--dp) = (png_byte)(255 - *(--sp));
1830*593dc095SDavid du Colombier                *(--dp) = (png_byte)(255 - *(--sp));
1831*593dc095SDavid du Colombier /*
18327dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
18337dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
1834*593dc095SDavid du Colombier */
1835*593dc095SDavid du Colombier                sp-=2;
1836*593dc095SDavid du Colombier                dp=sp;
18377dd7cddfSDavid du Colombier             }
18387dd7cddfSDavid du Colombier          }
18397dd7cddfSDavid du Colombier       }
18407dd7cddfSDavid du Colombier    }
18417dd7cddfSDavid du Colombier }
18427dd7cddfSDavid du Colombier #endif
18437dd7cddfSDavid du Colombier 
18447dd7cddfSDavid du Colombier #if defined(PNG_READ_FILLER_SUPPORTED)
18457dd7cddfSDavid du Colombier /* Add filler channel if we have RGB color */
1846*593dc095SDavid du Colombier void /* PRIVATE */
png_do_read_filler(png_row_infop row_info,png_bytep row,png_uint_32 filler,png_uint_32 flags)18477dd7cddfSDavid du Colombier png_do_read_filler(png_row_infop row_info, png_bytep row,
18487dd7cddfSDavid du Colombier    png_uint_32 filler, png_uint_32 flags)
18497dd7cddfSDavid du Colombier {
18507dd7cddfSDavid du Colombier    png_uint_32 i;
1851*593dc095SDavid du Colombier    png_uint_32 row_width = row_info->width;
1852*593dc095SDavid du Colombier 
1853*593dc095SDavid du Colombier    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1854*593dc095SDavid du Colombier    png_byte lo_filler = (png_byte)(filler & 0xff);
18557dd7cddfSDavid du Colombier 
18567dd7cddfSDavid du Colombier    png_debug(1, "in png_do_read_filler\n");
18577dd7cddfSDavid du Colombier    if (
18587dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
18597dd7cddfSDavid du Colombier        row != NULL  && row_info != NULL &&
18607dd7cddfSDavid du Colombier #endif
1861*593dc095SDavid du Colombier        row_info->color_type == PNG_COLOR_TYPE_GRAY)
1862*593dc095SDavid du Colombier    {
1863*593dc095SDavid du Colombier       if(row_info->bit_depth == 8)
1864*593dc095SDavid du Colombier       {
1865*593dc095SDavid du Colombier          /* This changes the data from G to GX */
1866*593dc095SDavid du Colombier          if (flags & PNG_FLAG_FILLER_AFTER)
1867*593dc095SDavid du Colombier          {
1868*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width;
1869*593dc095SDavid du Colombier             png_bytep dp =  sp + (png_size_t)row_width;
1870*593dc095SDavid du Colombier             for (i = 1; i < row_width; i++)
1871*593dc095SDavid du Colombier             {
1872*593dc095SDavid du Colombier                *(--dp) = lo_filler;
1873*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1874*593dc095SDavid du Colombier             }
1875*593dc095SDavid du Colombier             *(--dp) = lo_filler;
1876*593dc095SDavid du Colombier             row_info->channels = 2;
1877*593dc095SDavid du Colombier             row_info->pixel_depth = 16;
1878*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 2;
1879*593dc095SDavid du Colombier          }
1880*593dc095SDavid du Colombier       /* This changes the data from G to XG */
1881*593dc095SDavid du Colombier          else
1882*593dc095SDavid du Colombier          {
1883*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width;
1884*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width;
1885*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
1886*593dc095SDavid du Colombier             {
1887*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1888*593dc095SDavid du Colombier                *(--dp) = lo_filler;
1889*593dc095SDavid du Colombier             }
1890*593dc095SDavid du Colombier             row_info->channels = 2;
1891*593dc095SDavid du Colombier             row_info->pixel_depth = 16;
1892*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 2;
1893*593dc095SDavid du Colombier          }
1894*593dc095SDavid du Colombier       }
1895*593dc095SDavid du Colombier       else if(row_info->bit_depth == 16)
1896*593dc095SDavid du Colombier       {
1897*593dc095SDavid du Colombier          /* This changes the data from GG to GGXX */
1898*593dc095SDavid du Colombier          if (flags & PNG_FLAG_FILLER_AFTER)
1899*593dc095SDavid du Colombier          {
1900*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 2;
1901*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 2;
1902*593dc095SDavid du Colombier             for (i = 1; i < row_width; i++)
1903*593dc095SDavid du Colombier             {
1904*593dc095SDavid du Colombier                *(--dp) = hi_filler;
1905*593dc095SDavid du Colombier                *(--dp) = lo_filler;
1906*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1907*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1908*593dc095SDavid du Colombier             }
1909*593dc095SDavid du Colombier             *(--dp) = hi_filler;
1910*593dc095SDavid du Colombier             *(--dp) = lo_filler;
1911*593dc095SDavid du Colombier             row_info->channels = 2;
1912*593dc095SDavid du Colombier             row_info->pixel_depth = 32;
1913*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 4;
1914*593dc095SDavid du Colombier          }
1915*593dc095SDavid du Colombier          /* This changes the data from GG to XXGG */
1916*593dc095SDavid du Colombier          else
1917*593dc095SDavid du Colombier          {
1918*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 2;
1919*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 2;
1920*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
1921*593dc095SDavid du Colombier             {
1922*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1923*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1924*593dc095SDavid du Colombier                *(--dp) = hi_filler;
1925*593dc095SDavid du Colombier                *(--dp) = lo_filler;
1926*593dc095SDavid du Colombier             }
1927*593dc095SDavid du Colombier             row_info->channels = 2;
1928*593dc095SDavid du Colombier             row_info->pixel_depth = 32;
1929*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 4;
1930*593dc095SDavid du Colombier          }
1931*593dc095SDavid du Colombier       }
1932*593dc095SDavid du Colombier    } /* COLOR_TYPE == GRAY */
1933*593dc095SDavid du Colombier    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1934*593dc095SDavid du Colombier    {
1935*593dc095SDavid du Colombier       if(row_info->bit_depth == 8)
19367dd7cddfSDavid du Colombier       {
19377dd7cddfSDavid du Colombier          /* This changes the data from RGB to RGBX */
19387dd7cddfSDavid du Colombier          if (flags & PNG_FLAG_FILLER_AFTER)
19397dd7cddfSDavid du Colombier          {
1940*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 3;
1941*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width;
1942*593dc095SDavid du Colombier             for (i = 1; i < row_width; i++)
19437dd7cddfSDavid du Colombier             {
1944*593dc095SDavid du Colombier                *(--dp) = lo_filler;
19457dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
19467dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
19477dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
19487dd7cddfSDavid du Colombier             }
1949*593dc095SDavid du Colombier             *(--dp) = lo_filler;
19507dd7cddfSDavid du Colombier             row_info->channels = 4;
19517dd7cddfSDavid du Colombier             row_info->pixel_depth = 32;
1952*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 4;
19537dd7cddfSDavid du Colombier          }
19547dd7cddfSDavid du Colombier       /* This changes the data from RGB to XRGB */
19557dd7cddfSDavid du Colombier          else
19567dd7cddfSDavid du Colombier          {
1957*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 3;
1958*593dc095SDavid du Colombier             png_bytep dp = sp + (png_size_t)row_width;
1959*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
19607dd7cddfSDavid du Colombier             {
19617dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
19627dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
19637dd7cddfSDavid du Colombier                *(--dp) = *(--sp);
1964*593dc095SDavid du Colombier                *(--dp) = lo_filler;
19657dd7cddfSDavid du Colombier             }
19667dd7cddfSDavid du Colombier             row_info->channels = 4;
19677dd7cddfSDavid du Colombier             row_info->pixel_depth = 32;
1968*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 4;
19697dd7cddfSDavid du Colombier          }
19707dd7cddfSDavid du Colombier       }
1971*593dc095SDavid du Colombier       else if(row_info->bit_depth == 16)
1972*593dc095SDavid du Colombier       {
1973*593dc095SDavid du Colombier          /* This changes the data from RRGGBB to RRGGBBXX */
1974*593dc095SDavid du Colombier          if (flags & PNG_FLAG_FILLER_AFTER)
1975*593dc095SDavid du Colombier          {
1976*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 6;
1977*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 2;
1978*593dc095SDavid du Colombier             for (i = 1; i < row_width; i++)
1979*593dc095SDavid du Colombier             {
1980*593dc095SDavid du Colombier                *(--dp) = hi_filler;
1981*593dc095SDavid du Colombier                *(--dp) = lo_filler;
1982*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1983*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1984*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1985*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1986*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1987*593dc095SDavid du Colombier                *(--dp) = *(--sp);
1988*593dc095SDavid du Colombier             }
1989*593dc095SDavid du Colombier             *(--dp) = hi_filler;
1990*593dc095SDavid du Colombier             *(--dp) = lo_filler;
1991*593dc095SDavid du Colombier             row_info->channels = 4;
1992*593dc095SDavid du Colombier             row_info->pixel_depth = 64;
1993*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 8;
1994*593dc095SDavid du Colombier          }
1995*593dc095SDavid du Colombier          /* This changes the data from RRGGBB to XXRRGGBB */
1996*593dc095SDavid du Colombier          else
1997*593dc095SDavid du Colombier          {
1998*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 6;
1999*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 2;
2000*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
2001*593dc095SDavid du Colombier             {
2002*593dc095SDavid du Colombier                *(--dp) = *(--sp);
2003*593dc095SDavid du Colombier                *(--dp) = *(--sp);
2004*593dc095SDavid du Colombier                *(--dp) = *(--sp);
2005*593dc095SDavid du Colombier                *(--dp) = *(--sp);
2006*593dc095SDavid du Colombier                *(--dp) = *(--sp);
2007*593dc095SDavid du Colombier                *(--dp) = *(--sp);
2008*593dc095SDavid du Colombier                *(--dp) = hi_filler;
2009*593dc095SDavid du Colombier                *(--dp) = lo_filler;
2010*593dc095SDavid du Colombier             }
2011*593dc095SDavid du Colombier             row_info->channels = 4;
2012*593dc095SDavid du Colombier             row_info->pixel_depth = 64;
2013*593dc095SDavid du Colombier             row_info->rowbytes = row_width * 8;
2014*593dc095SDavid du Colombier          }
2015*593dc095SDavid du Colombier       }
2016*593dc095SDavid du Colombier    } /* COLOR_TYPE == RGB */
20177dd7cddfSDavid du Colombier }
20187dd7cddfSDavid du Colombier #endif
20197dd7cddfSDavid du Colombier 
20207dd7cddfSDavid du Colombier #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
20217dd7cddfSDavid du Colombier /* expand grayscale files to RGB, with or without alpha */
2022*593dc095SDavid du Colombier void /* PRIVATE */
png_do_gray_to_rgb(png_row_infop row_info,png_bytep row)20237dd7cddfSDavid du Colombier png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
20247dd7cddfSDavid du Colombier {
20257dd7cddfSDavid du Colombier    png_uint_32 i;
2026*593dc095SDavid du Colombier    png_uint_32 row_width = row_info->width;
20277dd7cddfSDavid du Colombier 
20287dd7cddfSDavid du Colombier    png_debug(1, "in png_do_gray_to_rgb\n");
20297dd7cddfSDavid du Colombier    if (row_info->bit_depth >= 8 &&
20307dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
20317dd7cddfSDavid du Colombier        row != NULL && row_info != NULL &&
20327dd7cddfSDavid du Colombier #endif
20337dd7cddfSDavid du Colombier       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
20347dd7cddfSDavid du Colombier    {
20357dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
20367dd7cddfSDavid du Colombier       {
20377dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
20387dd7cddfSDavid du Colombier          {
2039*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width - 1;
2040*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 2;
2041*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
20427dd7cddfSDavid du Colombier             {
20437dd7cddfSDavid du Colombier                *(dp--) = *sp;
20447dd7cddfSDavid du Colombier                *(dp--) = *sp;
2045*593dc095SDavid du Colombier                *(dp--) = *(sp--);
20467dd7cddfSDavid du Colombier             }
20477dd7cddfSDavid du Colombier          }
20487dd7cddfSDavid du Colombier          else
20497dd7cddfSDavid du Colombier          {
2050*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2051*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 4;
2052*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
20537dd7cddfSDavid du Colombier             {
20547dd7cddfSDavid du Colombier                *(dp--) = *sp;
20557dd7cddfSDavid du Colombier                *(dp--) = *(sp - 1);
20567dd7cddfSDavid du Colombier                *(dp--) = *sp;
20577dd7cddfSDavid du Colombier                *(dp--) = *(sp - 1);
2058*593dc095SDavid du Colombier                *(dp--) = *(sp--);
2059*593dc095SDavid du Colombier                *(dp--) = *(sp--);
20607dd7cddfSDavid du Colombier             }
20617dd7cddfSDavid du Colombier          }
20627dd7cddfSDavid du Colombier       }
20637dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
20647dd7cddfSDavid du Colombier       {
20657dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
20667dd7cddfSDavid du Colombier          {
2067*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2068*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 2;
2069*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
20707dd7cddfSDavid du Colombier             {
20717dd7cddfSDavid du Colombier                *(dp--) = *(sp--);
20727dd7cddfSDavid du Colombier                *(dp--) = *sp;
20737dd7cddfSDavid du Colombier                *(dp--) = *sp;
2074*593dc095SDavid du Colombier                *(dp--) = *(sp--);
20757dd7cddfSDavid du Colombier             }
20767dd7cddfSDavid du Colombier          }
20777dd7cddfSDavid du Colombier          else
20787dd7cddfSDavid du Colombier          {
2079*593dc095SDavid du Colombier             png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2080*593dc095SDavid du Colombier             png_bytep dp = sp  + (png_size_t)row_width * 4;
2081*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
20827dd7cddfSDavid du Colombier             {
20837dd7cddfSDavid du Colombier                *(dp--) = *(sp--);
20847dd7cddfSDavid du Colombier                *(dp--) = *(sp--);
20857dd7cddfSDavid du Colombier                *(dp--) = *sp;
20867dd7cddfSDavid du Colombier                *(dp--) = *(sp - 1);
20877dd7cddfSDavid du Colombier                *(dp--) = *sp;
20887dd7cddfSDavid du Colombier                *(dp--) = *(sp - 1);
2089*593dc095SDavid du Colombier                *(dp--) = *(sp--);
2090*593dc095SDavid du Colombier                *(dp--) = *(sp--);
20917dd7cddfSDavid du Colombier             }
20927dd7cddfSDavid du Colombier          }
20937dd7cddfSDavid du Colombier       }
20947dd7cddfSDavid du Colombier       row_info->channels += (png_byte)2;
20957dd7cddfSDavid du Colombier       row_info->color_type |= PNG_COLOR_MASK_COLOR;
20967dd7cddfSDavid du Colombier       row_info->pixel_depth = (png_byte)(row_info->channels *
20977dd7cddfSDavid du Colombier          row_info->bit_depth);
2098*593dc095SDavid du Colombier       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
20997dd7cddfSDavid du Colombier    }
21007dd7cddfSDavid du Colombier }
21017dd7cddfSDavid du Colombier #endif
21027dd7cddfSDavid du Colombier 
2103*593dc095SDavid du Colombier #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2104*593dc095SDavid du Colombier /* reduce RGB files to grayscale, with or without alpha
2105*593dc095SDavid du Colombier  * using the equation given in Poynton's ColorFAQ at
2106*593dc095SDavid du Colombier  * <http://www.inforamp.net/~poynton/>
2107*593dc095SDavid du Colombier  * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
2108*593dc095SDavid du Colombier  *
2109*593dc095SDavid du Colombier  *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2110*593dc095SDavid du Colombier  *
2111*593dc095SDavid du Colombier  *  We approximate this with
2112*593dc095SDavid du Colombier  *
2113*593dc095SDavid du Colombier  *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
2114*593dc095SDavid du Colombier  *
2115*593dc095SDavid du Colombier  *  which can be expressed with integers as
2116*593dc095SDavid du Colombier  *
2117*593dc095SDavid du Colombier  *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2118*593dc095SDavid du Colombier  *
2119*593dc095SDavid du Colombier  *  The calculation is to be done in a linear colorspace.
2120*593dc095SDavid du Colombier  *
2121*593dc095SDavid du Colombier  *  Other integer coefficents can be used via png_set_rgb_to_gray().
2122*593dc095SDavid du Colombier  */
2123*593dc095SDavid du Colombier int /* PRIVATE */
png_do_rgb_to_gray(png_structp png_ptr,png_row_infop row_info,png_bytep row)2124*593dc095SDavid du Colombier png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2125*593dc095SDavid du Colombier 
2126*593dc095SDavid du Colombier {
2127*593dc095SDavid du Colombier    png_uint_32 i;
2128*593dc095SDavid du Colombier 
2129*593dc095SDavid du Colombier    png_uint_32 row_width = row_info->width;
2130*593dc095SDavid du Colombier    int rgb_error = 0;
2131*593dc095SDavid du Colombier 
2132*593dc095SDavid du Colombier    png_debug(1, "in png_do_rgb_to_gray\n");
2133*593dc095SDavid du Colombier    if (
2134*593dc095SDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
2135*593dc095SDavid du Colombier        row != NULL && row_info != NULL &&
2136*593dc095SDavid du Colombier #endif
2137*593dc095SDavid du Colombier       (row_info->color_type & PNG_COLOR_MASK_COLOR))
2138*593dc095SDavid du Colombier    {
2139*593dc095SDavid du Colombier       png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2140*593dc095SDavid du Colombier       png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2141*593dc095SDavid du Colombier       png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2142*593dc095SDavid du Colombier 
2143*593dc095SDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2144*593dc095SDavid du Colombier       {
2145*593dc095SDavid du Colombier          if (row_info->bit_depth == 8)
2146*593dc095SDavid du Colombier          {
2147*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2148*593dc095SDavid du Colombier             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2149*593dc095SDavid du Colombier             {
2150*593dc095SDavid du Colombier                png_bytep sp = row;
2151*593dc095SDavid du Colombier                png_bytep dp = row;
2152*593dc095SDavid du Colombier 
2153*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2154*593dc095SDavid du Colombier                {
2155*593dc095SDavid du Colombier                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
2156*593dc095SDavid du Colombier                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
2157*593dc095SDavid du Colombier                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
2158*593dc095SDavid du Colombier                   if(red != green || red != blue)
2159*593dc095SDavid du Colombier                   {
2160*593dc095SDavid du Colombier                      rgb_error |= 1;
2161*593dc095SDavid du Colombier                      *(dp++) = png_ptr->gamma_from_1[
2162*593dc095SDavid du Colombier                        (rc*red+gc*green+bc*blue)>>15];
2163*593dc095SDavid du Colombier                   }
2164*593dc095SDavid du Colombier                   else
2165*593dc095SDavid du Colombier                      *(dp++) = *(sp-1);
2166*593dc095SDavid du Colombier                }
2167*593dc095SDavid du Colombier             }
2168*593dc095SDavid du Colombier             else
2169*593dc095SDavid du Colombier #endif
2170*593dc095SDavid du Colombier             {
2171*593dc095SDavid du Colombier                png_bytep sp = row;
2172*593dc095SDavid du Colombier                png_bytep dp = row;
2173*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2174*593dc095SDavid du Colombier                {
2175*593dc095SDavid du Colombier                   png_byte red   = *(sp++);
2176*593dc095SDavid du Colombier                   png_byte green = *(sp++);
2177*593dc095SDavid du Colombier                   png_byte blue  = *(sp++);
2178*593dc095SDavid du Colombier                   if(red != green || red != blue)
2179*593dc095SDavid du Colombier                   {
2180*593dc095SDavid du Colombier                      rgb_error |= 1;
2181*593dc095SDavid du Colombier                      *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2182*593dc095SDavid du Colombier                   }
2183*593dc095SDavid du Colombier                   else
2184*593dc095SDavid du Colombier                      *(dp++) = *(sp-1);
2185*593dc095SDavid du Colombier                }
2186*593dc095SDavid du Colombier             }
2187*593dc095SDavid du Colombier          }
2188*593dc095SDavid du Colombier 
2189*593dc095SDavid du Colombier          else /* RGB bit_depth == 16 */
2190*593dc095SDavid du Colombier          {
2191*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2192*593dc095SDavid du Colombier             if (png_ptr->gamma_16_to_1 != NULL &&
2193*593dc095SDavid du Colombier                 png_ptr->gamma_16_from_1 != NULL)
2194*593dc095SDavid du Colombier             {
2195*593dc095SDavid du Colombier                png_bytep sp = row;
2196*593dc095SDavid du Colombier                png_bytep dp = row;
2197*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2198*593dc095SDavid du Colombier                {
2199*593dc095SDavid du Colombier                   png_uint_16 red, green, blue, w;
2200*593dc095SDavid du Colombier 
2201*593dc095SDavid du Colombier                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2202*593dc095SDavid du Colombier                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2203*593dc095SDavid du Colombier                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2204*593dc095SDavid du Colombier 
2205*593dc095SDavid du Colombier                   if(red == green && red == blue)
2206*593dc095SDavid du Colombier                      w = red;
2207*593dc095SDavid du Colombier                   else
2208*593dc095SDavid du Colombier                   {
2209*593dc095SDavid du Colombier                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
2210*593dc095SDavid du Colombier                                   png_ptr->gamma_shift][red>>8];
2211*593dc095SDavid du Colombier                      png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2212*593dc095SDavid du Colombier                                   png_ptr->gamma_shift][green>>8];
2213*593dc095SDavid du Colombier                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2214*593dc095SDavid du Colombier                                   png_ptr->gamma_shift][blue>>8];
2215*593dc095SDavid du Colombier                      png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
2216*593dc095SDavid du Colombier                                   + bc*blue_1)>>15);
2217*593dc095SDavid du Colombier                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2218*593dc095SDavid du Colombier                          png_ptr->gamma_shift][gray16 >> 8];
2219*593dc095SDavid du Colombier                      rgb_error |= 1;
2220*593dc095SDavid du Colombier                   }
2221*593dc095SDavid du Colombier 
2222*593dc095SDavid du Colombier                   *(dp++) = (png_byte)((w>>8) & 0xff);
2223*593dc095SDavid du Colombier                   *(dp++) = (png_byte)(w & 0xff);
2224*593dc095SDavid du Colombier                }
2225*593dc095SDavid du Colombier             }
2226*593dc095SDavid du Colombier             else
2227*593dc095SDavid du Colombier #endif
2228*593dc095SDavid du Colombier             {
2229*593dc095SDavid du Colombier                png_bytep sp = row;
2230*593dc095SDavid du Colombier                png_bytep dp = row;
2231*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2232*593dc095SDavid du Colombier                {
2233*593dc095SDavid du Colombier                   png_uint_16 red, green, blue, gray16;
2234*593dc095SDavid du Colombier 
2235*593dc095SDavid du Colombier                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2236*593dc095SDavid du Colombier                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2237*593dc095SDavid du Colombier                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2238*593dc095SDavid du Colombier 
2239*593dc095SDavid du Colombier                   if(red != green || red != blue)
2240*593dc095SDavid du Colombier                      rgb_error |= 1;
2241*593dc095SDavid du Colombier                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2242*593dc095SDavid du Colombier                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
2243*593dc095SDavid du Colombier                   *(dp++) = (png_byte)(gray16 & 0xff);
2244*593dc095SDavid du Colombier                }
2245*593dc095SDavid du Colombier             }
2246*593dc095SDavid du Colombier          }
2247*593dc095SDavid du Colombier       }
2248*593dc095SDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2249*593dc095SDavid du Colombier       {
2250*593dc095SDavid du Colombier          if (row_info->bit_depth == 8)
2251*593dc095SDavid du Colombier          {
2252*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2253*593dc095SDavid du Colombier             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2254*593dc095SDavid du Colombier             {
2255*593dc095SDavid du Colombier                png_bytep sp = row;
2256*593dc095SDavid du Colombier                png_bytep dp = row;
2257*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2258*593dc095SDavid du Colombier                {
2259*593dc095SDavid du Colombier                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
2260*593dc095SDavid du Colombier                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
2261*593dc095SDavid du Colombier                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
2262*593dc095SDavid du Colombier                   if(red != green || red != blue)
2263*593dc095SDavid du Colombier                      rgb_error |= 1;
2264*593dc095SDavid du Colombier                   *(dp++) =  png_ptr->gamma_from_1
2265*593dc095SDavid du Colombier                              [(rc*red + gc*green + bc*blue)>>15];
2266*593dc095SDavid du Colombier                   *(dp++) = *(sp++);  /* alpha */
2267*593dc095SDavid du Colombier                }
2268*593dc095SDavid du Colombier             }
2269*593dc095SDavid du Colombier             else
2270*593dc095SDavid du Colombier #endif
2271*593dc095SDavid du Colombier             {
2272*593dc095SDavid du Colombier                png_bytep sp = row;
2273*593dc095SDavid du Colombier                png_bytep dp = row;
2274*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2275*593dc095SDavid du Colombier                {
2276*593dc095SDavid du Colombier                   png_byte red   = *(sp++);
2277*593dc095SDavid du Colombier                   png_byte green = *(sp++);
2278*593dc095SDavid du Colombier                   png_byte blue  = *(sp++);
2279*593dc095SDavid du Colombier                   if(red != green || red != blue)
2280*593dc095SDavid du Colombier                      rgb_error |= 1;
2281*593dc095SDavid du Colombier                   *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
2282*593dc095SDavid du Colombier                   *(dp++) = *(sp++);  /* alpha */
2283*593dc095SDavid du Colombier                }
2284*593dc095SDavid du Colombier             }
2285*593dc095SDavid du Colombier          }
2286*593dc095SDavid du Colombier          else /* RGBA bit_depth == 16 */
2287*593dc095SDavid du Colombier          {
2288*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2289*593dc095SDavid du Colombier             if (png_ptr->gamma_16_to_1 != NULL &&
2290*593dc095SDavid du Colombier                 png_ptr->gamma_16_from_1 != NULL)
2291*593dc095SDavid du Colombier             {
2292*593dc095SDavid du Colombier                png_bytep sp = row;
2293*593dc095SDavid du Colombier                png_bytep dp = row;
2294*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2295*593dc095SDavid du Colombier                {
2296*593dc095SDavid du Colombier                   png_uint_16 red, green, blue, w;
2297*593dc095SDavid du Colombier 
2298*593dc095SDavid du Colombier                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2299*593dc095SDavid du Colombier                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2300*593dc095SDavid du Colombier                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2301*593dc095SDavid du Colombier 
2302*593dc095SDavid du Colombier                   if(red == green && red == blue)
2303*593dc095SDavid du Colombier                      w = red;
2304*593dc095SDavid du Colombier                   else
2305*593dc095SDavid du Colombier                   {
2306*593dc095SDavid du Colombier                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
2307*593dc095SDavid du Colombier                                   png_ptr->gamma_shift][red>>8];
2308*593dc095SDavid du Colombier                      png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2309*593dc095SDavid du Colombier                                   png_ptr->gamma_shift][green>>8];
2310*593dc095SDavid du Colombier                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2311*593dc095SDavid du Colombier                                   png_ptr->gamma_shift][blue>>8];
2312*593dc095SDavid du Colombier                      png_uint_16 gray16  = (png_uint_16)((rc * red_1
2313*593dc095SDavid du Colombier                                   + gc * green_1 + bc * blue_1)>>15);
2314*593dc095SDavid du Colombier                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2315*593dc095SDavid du Colombier                          png_ptr->gamma_shift][gray16 >> 8];
2316*593dc095SDavid du Colombier                      rgb_error |= 1;
2317*593dc095SDavid du Colombier                   }
2318*593dc095SDavid du Colombier 
2319*593dc095SDavid du Colombier                   *(dp++) = (png_byte)((w>>8) & 0xff);
2320*593dc095SDavid du Colombier                   *(dp++) = (png_byte)(w & 0xff);
2321*593dc095SDavid du Colombier                   *(dp++) = *(sp++);  /* alpha */
2322*593dc095SDavid du Colombier                   *(dp++) = *(sp++);
2323*593dc095SDavid du Colombier                }
2324*593dc095SDavid du Colombier             }
2325*593dc095SDavid du Colombier             else
2326*593dc095SDavid du Colombier #endif
2327*593dc095SDavid du Colombier             {
2328*593dc095SDavid du Colombier                png_bytep sp = row;
2329*593dc095SDavid du Colombier                png_bytep dp = row;
2330*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
2331*593dc095SDavid du Colombier                {
2332*593dc095SDavid du Colombier                   png_uint_16 red, green, blue, gray16;
2333*593dc095SDavid du Colombier                   red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2334*593dc095SDavid du Colombier                   green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2335*593dc095SDavid du Colombier                   blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2336*593dc095SDavid du Colombier                   if(red != green || red != blue)
2337*593dc095SDavid du Colombier                      rgb_error |= 1;
2338*593dc095SDavid du Colombier                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2339*593dc095SDavid du Colombier                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
2340*593dc095SDavid du Colombier                   *(dp++) = (png_byte)(gray16 & 0xff);
2341*593dc095SDavid du Colombier                   *(dp++) = *(sp++);  /* alpha */
2342*593dc095SDavid du Colombier                   *(dp++) = *(sp++);
2343*593dc095SDavid du Colombier                }
2344*593dc095SDavid du Colombier             }
2345*593dc095SDavid du Colombier          }
2346*593dc095SDavid du Colombier       }
2347*593dc095SDavid du Colombier    row_info->channels -= (png_byte)2;
2348*593dc095SDavid du Colombier       row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2349*593dc095SDavid du Colombier       row_info->pixel_depth = (png_byte)(row_info->channels *
2350*593dc095SDavid du Colombier          row_info->bit_depth);
2351*593dc095SDavid du Colombier       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2352*593dc095SDavid du Colombier    }
2353*593dc095SDavid du Colombier    return rgb_error;
2354*593dc095SDavid du Colombier }
2355*593dc095SDavid du Colombier #endif
2356*593dc095SDavid du Colombier 
23577dd7cddfSDavid du Colombier /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
23587dd7cddfSDavid du Colombier  * large of png_color.  This lets grayscale images be treated as
23597dd7cddfSDavid du Colombier  * paletted.  Most useful for gamma correction and simplification
23607dd7cddfSDavid du Colombier  * of code.
23617dd7cddfSDavid du Colombier  */
2362*593dc095SDavid du Colombier void PNGAPI
png_build_grayscale_palette(int bit_depth,png_colorp palette)23637dd7cddfSDavid du Colombier png_build_grayscale_palette(int bit_depth, png_colorp palette)
23647dd7cddfSDavid du Colombier {
23657dd7cddfSDavid du Colombier    int num_palette;
23667dd7cddfSDavid du Colombier    int color_inc;
23677dd7cddfSDavid du Colombier    int i;
23687dd7cddfSDavid du Colombier    int v;
23697dd7cddfSDavid du Colombier 
23707dd7cddfSDavid du Colombier    png_debug(1, "in png_do_build_grayscale_palette\n");
23717dd7cddfSDavid du Colombier    if (palette == NULL)
23727dd7cddfSDavid du Colombier       return;
23737dd7cddfSDavid du Colombier 
23747dd7cddfSDavid du Colombier    switch (bit_depth)
23757dd7cddfSDavid du Colombier    {
23767dd7cddfSDavid du Colombier       case 1:
23777dd7cddfSDavid du Colombier          num_palette = 2;
23787dd7cddfSDavid du Colombier          color_inc = 0xff;
23797dd7cddfSDavid du Colombier          break;
23807dd7cddfSDavid du Colombier       case 2:
23817dd7cddfSDavid du Colombier          num_palette = 4;
23827dd7cddfSDavid du Colombier          color_inc = 0x55;
23837dd7cddfSDavid du Colombier          break;
23847dd7cddfSDavid du Colombier       case 4:
23857dd7cddfSDavid du Colombier          num_palette = 16;
23867dd7cddfSDavid du Colombier          color_inc = 0x11;
23877dd7cddfSDavid du Colombier          break;
23887dd7cddfSDavid du Colombier       case 8:
23897dd7cddfSDavid du Colombier          num_palette = 256;
23907dd7cddfSDavid du Colombier          color_inc = 1;
23917dd7cddfSDavid du Colombier          break;
23927dd7cddfSDavid du Colombier       default:
23937dd7cddfSDavid du Colombier          num_palette = 0;
23947dd7cddfSDavid du Colombier          color_inc = 0;
23957dd7cddfSDavid du Colombier          break;
23967dd7cddfSDavid du Colombier    }
23977dd7cddfSDavid du Colombier 
23987dd7cddfSDavid du Colombier    for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
23997dd7cddfSDavid du Colombier    {
24007dd7cddfSDavid du Colombier       palette[i].red = (png_byte)v;
24017dd7cddfSDavid du Colombier       palette[i].green = (png_byte)v;
24027dd7cddfSDavid du Colombier       palette[i].blue = (png_byte)v;
24037dd7cddfSDavid du Colombier    }
24047dd7cddfSDavid du Colombier }
24057dd7cddfSDavid du Colombier 
24067dd7cddfSDavid du Colombier /* This function is currently unused.  Do we really need it? */
24077dd7cddfSDavid du Colombier #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2408*593dc095SDavid du Colombier void /* PRIVATE */
png_correct_palette(png_structp png_ptr,png_colorp palette,int num_palette)24097dd7cddfSDavid du Colombier png_correct_palette(png_structp png_ptr, png_colorp palette,
24107dd7cddfSDavid du Colombier    int num_palette)
24117dd7cddfSDavid du Colombier {
24127dd7cddfSDavid du Colombier    png_debug(1, "in png_correct_palette\n");
2413*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2414*593dc095SDavid du Colombier     defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2415*593dc095SDavid du Colombier    if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
24167dd7cddfSDavid du Colombier    {
24177dd7cddfSDavid du Colombier       png_color back, back_1;
24187dd7cddfSDavid du Colombier 
24197dd7cddfSDavid du Colombier       if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
24207dd7cddfSDavid du Colombier       {
24217dd7cddfSDavid du Colombier          back.red = png_ptr->gamma_table[png_ptr->background.red];
24227dd7cddfSDavid du Colombier          back.green = png_ptr->gamma_table[png_ptr->background.green];
24237dd7cddfSDavid du Colombier          back.blue = png_ptr->gamma_table[png_ptr->background.blue];
24247dd7cddfSDavid du Colombier 
24257dd7cddfSDavid du Colombier          back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
24267dd7cddfSDavid du Colombier          back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
24277dd7cddfSDavid du Colombier          back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
24287dd7cddfSDavid du Colombier       }
24297dd7cddfSDavid du Colombier       else
24307dd7cddfSDavid du Colombier       {
24317dd7cddfSDavid du Colombier          double g;
24327dd7cddfSDavid du Colombier 
24337dd7cddfSDavid du Colombier          g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
24347dd7cddfSDavid du Colombier 
24357dd7cddfSDavid du Colombier          if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
24367dd7cddfSDavid du Colombier              fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
24377dd7cddfSDavid du Colombier          {
24387dd7cddfSDavid du Colombier             back.red = png_ptr->background.red;
24397dd7cddfSDavid du Colombier             back.green = png_ptr->background.green;
24407dd7cddfSDavid du Colombier             back.blue = png_ptr->background.blue;
24417dd7cddfSDavid du Colombier          }
24427dd7cddfSDavid du Colombier          else
24437dd7cddfSDavid du Colombier          {
24447dd7cddfSDavid du Colombier             back.red =
24457dd7cddfSDavid du Colombier                (png_byte)(pow((double)png_ptr->background.red/255, g) *
24467dd7cddfSDavid du Colombier                 255.0 + 0.5);
24477dd7cddfSDavid du Colombier             back.green =
24487dd7cddfSDavid du Colombier                (png_byte)(pow((double)png_ptr->background.green/255, g) *
24497dd7cddfSDavid du Colombier                 255.0 + 0.5);
24507dd7cddfSDavid du Colombier             back.blue =
24517dd7cddfSDavid du Colombier                (png_byte)(pow((double)png_ptr->background.blue/255, g) *
24527dd7cddfSDavid du Colombier                 255.0 + 0.5);
24537dd7cddfSDavid du Colombier          }
24547dd7cddfSDavid du Colombier 
24557dd7cddfSDavid du Colombier          g = 1.0 / png_ptr->background_gamma;
24567dd7cddfSDavid du Colombier 
24577dd7cddfSDavid du Colombier          back_1.red =
24587dd7cddfSDavid du Colombier             (png_byte)(pow((double)png_ptr->background.red/255, g) *
24597dd7cddfSDavid du Colombier              255.0 + 0.5);
24607dd7cddfSDavid du Colombier          back_1.green =
24617dd7cddfSDavid du Colombier             (png_byte)(pow((double)png_ptr->background.green/255, g) *
24627dd7cddfSDavid du Colombier              255.0 + 0.5);
24637dd7cddfSDavid du Colombier          back_1.blue =
24647dd7cddfSDavid du Colombier             (png_byte)(pow((double)png_ptr->background.blue/255, g) *
24657dd7cddfSDavid du Colombier              255.0 + 0.5);
24667dd7cddfSDavid du Colombier       }
24677dd7cddfSDavid du Colombier 
24687dd7cddfSDavid du Colombier       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
24697dd7cddfSDavid du Colombier       {
24707dd7cddfSDavid du Colombier          png_uint_32 i;
24717dd7cddfSDavid du Colombier 
24727dd7cddfSDavid du Colombier          for (i = 0; i < (png_uint_32)num_palette; i++)
24737dd7cddfSDavid du Colombier          {
24747dd7cddfSDavid du Colombier             if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
24757dd7cddfSDavid du Colombier             {
24767dd7cddfSDavid du Colombier                palette[i] = back;
24777dd7cddfSDavid du Colombier             }
24787dd7cddfSDavid du Colombier             else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
24797dd7cddfSDavid du Colombier             {
24807dd7cddfSDavid du Colombier                png_byte v, w;
24817dd7cddfSDavid du Colombier 
24827dd7cddfSDavid du Colombier                v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
24837dd7cddfSDavid du Colombier                png_composite(w, v, png_ptr->trans[i], back_1.red);
24847dd7cddfSDavid du Colombier                palette[i].red = png_ptr->gamma_from_1[w];
24857dd7cddfSDavid du Colombier 
24867dd7cddfSDavid du Colombier                v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
24877dd7cddfSDavid du Colombier                png_composite(w, v, png_ptr->trans[i], back_1.green);
24887dd7cddfSDavid du Colombier                palette[i].green = png_ptr->gamma_from_1[w];
24897dd7cddfSDavid du Colombier 
24907dd7cddfSDavid du Colombier                v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
24917dd7cddfSDavid du Colombier                png_composite(w, v, png_ptr->trans[i], back_1.blue);
24927dd7cddfSDavid du Colombier                palette[i].blue = png_ptr->gamma_from_1[w];
24937dd7cddfSDavid du Colombier             }
24947dd7cddfSDavid du Colombier             else
24957dd7cddfSDavid du Colombier             {
24967dd7cddfSDavid du Colombier                palette[i].red = png_ptr->gamma_table[palette[i].red];
24977dd7cddfSDavid du Colombier                palette[i].green = png_ptr->gamma_table[palette[i].green];
24987dd7cddfSDavid du Colombier                palette[i].blue = png_ptr->gamma_table[palette[i].blue];
24997dd7cddfSDavid du Colombier             }
25007dd7cddfSDavid du Colombier          }
25017dd7cddfSDavid du Colombier       }
25027dd7cddfSDavid du Colombier       else
25037dd7cddfSDavid du Colombier       {
25047dd7cddfSDavid du Colombier          int i;
25057dd7cddfSDavid du Colombier 
25067dd7cddfSDavid du Colombier          for (i = 0; i < num_palette; i++)
25077dd7cddfSDavid du Colombier          {
25087dd7cddfSDavid du Colombier             if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
25097dd7cddfSDavid du Colombier             {
25107dd7cddfSDavid du Colombier                palette[i] = back;
25117dd7cddfSDavid du Colombier             }
25127dd7cddfSDavid du Colombier             else
25137dd7cddfSDavid du Colombier             {
25147dd7cddfSDavid du Colombier                palette[i].red = png_ptr->gamma_table[palette[i].red];
25157dd7cddfSDavid du Colombier                palette[i].green = png_ptr->gamma_table[palette[i].green];
25167dd7cddfSDavid du Colombier                palette[i].blue = png_ptr->gamma_table[palette[i].blue];
25177dd7cddfSDavid du Colombier             }
25187dd7cddfSDavid du Colombier          }
25197dd7cddfSDavid du Colombier       }
25207dd7cddfSDavid du Colombier    }
25217dd7cddfSDavid du Colombier    else
25227dd7cddfSDavid du Colombier #endif
25237dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
25247dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_GAMMA)
25257dd7cddfSDavid du Colombier    {
25267dd7cddfSDavid du Colombier       int i;
25277dd7cddfSDavid du Colombier 
25287dd7cddfSDavid du Colombier       for (i = 0; i < num_palette; i++)
25297dd7cddfSDavid du Colombier       {
25307dd7cddfSDavid du Colombier          palette[i].red = png_ptr->gamma_table[palette[i].red];
25317dd7cddfSDavid du Colombier          palette[i].green = png_ptr->gamma_table[palette[i].green];
25327dd7cddfSDavid du Colombier          palette[i].blue = png_ptr->gamma_table[palette[i].blue];
25337dd7cddfSDavid du Colombier       }
25347dd7cddfSDavid du Colombier    }
25357dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
25367dd7cddfSDavid du Colombier    else
25377dd7cddfSDavid du Colombier #endif
25387dd7cddfSDavid du Colombier #endif
25397dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
25407dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_BACKGROUND)
25417dd7cddfSDavid du Colombier    {
25427dd7cddfSDavid du Colombier       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
25437dd7cddfSDavid du Colombier       {
25447dd7cddfSDavid du Colombier          png_color back;
25457dd7cddfSDavid du Colombier 
25467dd7cddfSDavid du Colombier          back.red   = (png_byte)png_ptr->background.red;
25477dd7cddfSDavid du Colombier          back.green = (png_byte)png_ptr->background.green;
25487dd7cddfSDavid du Colombier          back.blue  = (png_byte)png_ptr->background.blue;
25497dd7cddfSDavid du Colombier 
2550*593dc095SDavid du Colombier          for (i = 0; i < (int)png_ptr->num_trans; i++)
25517dd7cddfSDavid du Colombier          {
2552*593dc095SDavid du Colombier             if (png_ptr->trans[i] == 0)
25537dd7cddfSDavid du Colombier             {
25547dd7cddfSDavid du Colombier                palette[i].red = back.red;
25557dd7cddfSDavid du Colombier                palette[i].green = back.green;
25567dd7cddfSDavid du Colombier                palette[i].blue = back.blue;
25577dd7cddfSDavid du Colombier             }
2558*593dc095SDavid du Colombier             else if (png_ptr->trans[i] != 0xff)
25597dd7cddfSDavid du Colombier             {
25607dd7cddfSDavid du Colombier                png_composite(palette[i].red, png_ptr->palette[i].red,
25617dd7cddfSDavid du Colombier                   png_ptr->trans[i], back.red);
25627dd7cddfSDavid du Colombier                png_composite(palette[i].green, png_ptr->palette[i].green,
25637dd7cddfSDavid du Colombier                   png_ptr->trans[i], back.green);
25647dd7cddfSDavid du Colombier                png_composite(palette[i].blue, png_ptr->palette[i].blue,
25657dd7cddfSDavid du Colombier                   png_ptr->trans[i], back.blue);
25667dd7cddfSDavid du Colombier             }
25677dd7cddfSDavid du Colombier          }
25687dd7cddfSDavid du Colombier       }
25697dd7cddfSDavid du Colombier       else /* assume grayscale palette (what else could it be?) */
25707dd7cddfSDavid du Colombier       {
25717dd7cddfSDavid du Colombier          int i;
25727dd7cddfSDavid du Colombier 
25737dd7cddfSDavid du Colombier          for (i = 0; i < num_palette; i++)
25747dd7cddfSDavid du Colombier          {
25757dd7cddfSDavid du Colombier             if (i == (png_byte)png_ptr->trans_values.gray)
25767dd7cddfSDavid du Colombier             {
25777dd7cddfSDavid du Colombier                palette[i].red = (png_byte)png_ptr->background.red;
25787dd7cddfSDavid du Colombier                palette[i].green = (png_byte)png_ptr->background.green;
25797dd7cddfSDavid du Colombier                palette[i].blue = (png_byte)png_ptr->background.blue;
25807dd7cddfSDavid du Colombier             }
25817dd7cddfSDavid du Colombier          }
25827dd7cddfSDavid du Colombier       }
25837dd7cddfSDavid du Colombier    }
25847dd7cddfSDavid du Colombier #endif
25857dd7cddfSDavid du Colombier }
25867dd7cddfSDavid du Colombier #endif
25877dd7cddfSDavid du Colombier 
25887dd7cddfSDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED)
25897dd7cddfSDavid du Colombier /* Replace any alpha or transparency with the supplied background color.
25907dd7cddfSDavid du Colombier  * "background" is already in the screen gamma, while "background_1" is
25917dd7cddfSDavid du Colombier  * at a gamma of 1.0.  Paletted files have already been taken care of.
25927dd7cddfSDavid du Colombier  */
2593*593dc095SDavid du Colombier void /* PRIVATE */
png_do_background(png_row_infop row_info,png_bytep row,png_color_16p trans_values,png_color_16p background,png_color_16p background_1,png_bytep gamma_table,png_bytep gamma_from_1,png_bytep gamma_to_1,png_uint_16pp gamma_16,png_uint_16pp gamma_16_from_1,png_uint_16pp gamma_16_to_1,int gamma_shift)25947dd7cddfSDavid du Colombier png_do_background(png_row_infop row_info, png_bytep row,
2595*593dc095SDavid du Colombier    png_color_16p trans_values, png_color_16p background
2596*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
2597*593dc095SDavid du Colombier    , png_color_16p background_1,
25987dd7cddfSDavid du Colombier    png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
25997dd7cddfSDavid du Colombier    png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2600*593dc095SDavid du Colombier    png_uint_16pp gamma_16_to_1, int gamma_shift
2601*593dc095SDavid du Colombier #endif
2602*593dc095SDavid du Colombier    )
26037dd7cddfSDavid du Colombier {
26047dd7cddfSDavid du Colombier    png_bytep sp, dp;
26057dd7cddfSDavid du Colombier    png_uint_32 i;
2606*593dc095SDavid du Colombier    png_uint_32 row_width=row_info->width;
26077dd7cddfSDavid du Colombier    int shift;
26087dd7cddfSDavid du Colombier 
26097dd7cddfSDavid du Colombier    png_debug(1, "in png_do_background\n");
26107dd7cddfSDavid du Colombier    if (background != NULL &&
26117dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
26127dd7cddfSDavid du Colombier        row != NULL && row_info != NULL &&
26137dd7cddfSDavid du Colombier #endif
26147dd7cddfSDavid du Colombier       (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
26157dd7cddfSDavid du Colombier       (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
26167dd7cddfSDavid du Colombier    {
26177dd7cddfSDavid du Colombier       switch (row_info->color_type)
26187dd7cddfSDavid du Colombier       {
26197dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_GRAY:
26207dd7cddfSDavid du Colombier          {
26217dd7cddfSDavid du Colombier             switch (row_info->bit_depth)
26227dd7cddfSDavid du Colombier             {
26237dd7cddfSDavid du Colombier                case 1:
26247dd7cddfSDavid du Colombier                {
26257dd7cddfSDavid du Colombier                   sp = row;
26267dd7cddfSDavid du Colombier                   shift = 7;
2627*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++)
26287dd7cddfSDavid du Colombier                   {
2629*593dc095SDavid du Colombier                      if ((png_uint_16)((*sp >> shift) & 0x01)
26307dd7cddfSDavid du Colombier                         == trans_values->gray)
26317dd7cddfSDavid du Colombier                      {
26327dd7cddfSDavid du Colombier                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
26337dd7cddfSDavid du Colombier                         *sp |= (png_byte)(background->gray << shift);
26347dd7cddfSDavid du Colombier                      }
26357dd7cddfSDavid du Colombier                      if (!shift)
26367dd7cddfSDavid du Colombier                      {
26377dd7cddfSDavid du Colombier                         shift = 7;
26387dd7cddfSDavid du Colombier                         sp++;
26397dd7cddfSDavid du Colombier                      }
26407dd7cddfSDavid du Colombier                      else
26417dd7cddfSDavid du Colombier                         shift--;
26427dd7cddfSDavid du Colombier                   }
26437dd7cddfSDavid du Colombier                   break;
26447dd7cddfSDavid du Colombier                }
26457dd7cddfSDavid du Colombier                case 2:
26467dd7cddfSDavid du Colombier                {
2647*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
2648*593dc095SDavid du Colombier                   if (gamma_table != NULL)
2649*593dc095SDavid du Colombier                   {
26507dd7cddfSDavid du Colombier                      sp = row;
26517dd7cddfSDavid du Colombier                      shift = 6;
2652*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++)
26537dd7cddfSDavid du Colombier                      {
2654*593dc095SDavid du Colombier                         if ((png_uint_16)((*sp >> shift) & 0x03)
2655*593dc095SDavid du Colombier                             == trans_values->gray)
2656*593dc095SDavid du Colombier                         {
2657*593dc095SDavid du Colombier                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2658*593dc095SDavid du Colombier                            *sp |= (png_byte)(background->gray << shift);
2659*593dc095SDavid du Colombier                         }
2660*593dc095SDavid du Colombier                         else
2661*593dc095SDavid du Colombier                         {
2662*593dc095SDavid du Colombier                            png_byte p = (png_byte)((*sp >> shift) & 0x03);
2663*593dc095SDavid du Colombier                            png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2664*593dc095SDavid du Colombier                                (p << 4) | (p << 6)] >> 6) & 0x03);
2665*593dc095SDavid du Colombier                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2666*593dc095SDavid du Colombier                            *sp |= (png_byte)(g << shift);
2667*593dc095SDavid du Colombier                         }
2668*593dc095SDavid du Colombier                         if (!shift)
2669*593dc095SDavid du Colombier                         {
2670*593dc095SDavid du Colombier                            shift = 6;
2671*593dc095SDavid du Colombier                            sp++;
2672*593dc095SDavid du Colombier                         }
2673*593dc095SDavid du Colombier                         else
2674*593dc095SDavid du Colombier                            shift -= 2;
2675*593dc095SDavid du Colombier                      }
2676*593dc095SDavid du Colombier                   }
2677*593dc095SDavid du Colombier                   else
2678*593dc095SDavid du Colombier #endif
2679*593dc095SDavid du Colombier                   {
2680*593dc095SDavid du Colombier                      sp = row;
2681*593dc095SDavid du Colombier                      shift = 6;
2682*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++)
2683*593dc095SDavid du Colombier                      {
2684*593dc095SDavid du Colombier                         if ((png_uint_16)((*sp >> shift) & 0x03)
26857dd7cddfSDavid du Colombier                             == trans_values->gray)
26867dd7cddfSDavid du Colombier                         {
26877dd7cddfSDavid du Colombier                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
26887dd7cddfSDavid du Colombier                            *sp |= (png_byte)(background->gray << shift);
26897dd7cddfSDavid du Colombier                         }
26907dd7cddfSDavid du Colombier                         if (!shift)
26917dd7cddfSDavid du Colombier                         {
26927dd7cddfSDavid du Colombier                            shift = 6;
26937dd7cddfSDavid du Colombier                            sp++;
26947dd7cddfSDavid du Colombier                         }
26957dd7cddfSDavid du Colombier                         else
26967dd7cddfSDavid du Colombier                            shift -= 2;
26977dd7cddfSDavid du Colombier                      }
2698*593dc095SDavid du Colombier                   }
26997dd7cddfSDavid du Colombier                   break;
27007dd7cddfSDavid du Colombier                }
27017dd7cddfSDavid du Colombier                case 4:
27027dd7cddfSDavid du Colombier                {
2703*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
2704*593dc095SDavid du Colombier                   if (gamma_table != NULL)
2705*593dc095SDavid du Colombier                   {
27067dd7cddfSDavid du Colombier                      sp = row;
27077dd7cddfSDavid du Colombier                      shift = 4;
2708*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++)
27097dd7cddfSDavid du Colombier                      {
2710*593dc095SDavid du Colombier                         if ((png_uint_16)((*sp >> shift) & 0x0f)
2711*593dc095SDavid du Colombier                             == trans_values->gray)
2712*593dc095SDavid du Colombier                         {
2713*593dc095SDavid du Colombier                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2714*593dc095SDavid du Colombier                            *sp |= (png_byte)(background->gray << shift);
2715*593dc095SDavid du Colombier                         }
2716*593dc095SDavid du Colombier                         else
2717*593dc095SDavid du Colombier                         {
2718*593dc095SDavid du Colombier                            png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2719*593dc095SDavid du Colombier                            png_byte g = (png_byte)((gamma_table[p |
2720*593dc095SDavid du Colombier                              (p << 4)] >> 4) & 0x0f);
2721*593dc095SDavid du Colombier                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2722*593dc095SDavid du Colombier                            *sp |= (png_byte)(g << shift);
2723*593dc095SDavid du Colombier                         }
2724*593dc095SDavid du Colombier                         if (!shift)
2725*593dc095SDavid du Colombier                         {
2726*593dc095SDavid du Colombier                            shift = 4;
2727*593dc095SDavid du Colombier                            sp++;
2728*593dc095SDavid du Colombier                         }
2729*593dc095SDavid du Colombier                         else
2730*593dc095SDavid du Colombier                            shift -= 4;
2731*593dc095SDavid du Colombier                      }
2732*593dc095SDavid du Colombier                   }
2733*593dc095SDavid du Colombier                   else
2734*593dc095SDavid du Colombier #endif
2735*593dc095SDavid du Colombier                   {
2736*593dc095SDavid du Colombier                      sp = row;
2737*593dc095SDavid du Colombier                      shift = 4;
2738*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++)
2739*593dc095SDavid du Colombier                      {
2740*593dc095SDavid du Colombier                         if ((png_uint_16)((*sp >> shift) & 0x0f)
27417dd7cddfSDavid du Colombier                             == trans_values->gray)
27427dd7cddfSDavid du Colombier                         {
27437dd7cddfSDavid du Colombier                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
27447dd7cddfSDavid du Colombier                            *sp |= (png_byte)(background->gray << shift);
27457dd7cddfSDavid du Colombier                         }
27467dd7cddfSDavid du Colombier                         if (!shift)
27477dd7cddfSDavid du Colombier                         {
27487dd7cddfSDavid du Colombier                            shift = 4;
27497dd7cddfSDavid du Colombier                            sp++;
27507dd7cddfSDavid du Colombier                         }
27517dd7cddfSDavid du Colombier                         else
27527dd7cddfSDavid du Colombier                            shift -= 4;
27537dd7cddfSDavid du Colombier                      }
2754*593dc095SDavid du Colombier                   }
27557dd7cddfSDavid du Colombier                   break;
27567dd7cddfSDavid du Colombier                }
27577dd7cddfSDavid du Colombier                case 8:
27587dd7cddfSDavid du Colombier                {
27597dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
27607dd7cddfSDavid du Colombier                   if (gamma_table != NULL)
27617dd7cddfSDavid du Colombier                   {
2762*593dc095SDavid du Colombier                      sp = row;
2763*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++, sp++)
27647dd7cddfSDavid du Colombier                      {
27657dd7cddfSDavid du Colombier                         if (*sp == trans_values->gray)
27667dd7cddfSDavid du Colombier                         {
27677dd7cddfSDavid du Colombier                            *sp = (png_byte)background->gray;
27687dd7cddfSDavid du Colombier                         }
27697dd7cddfSDavid du Colombier                         else
27707dd7cddfSDavid du Colombier                         {
27717dd7cddfSDavid du Colombier                            *sp = gamma_table[*sp];
27727dd7cddfSDavid du Colombier                         }
27737dd7cddfSDavid du Colombier                      }
27747dd7cddfSDavid du Colombier                   }
27757dd7cddfSDavid du Colombier                   else
27767dd7cddfSDavid du Colombier #endif
27777dd7cddfSDavid du Colombier                   {
2778*593dc095SDavid du Colombier                      sp = row;
2779*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++, sp++)
27807dd7cddfSDavid du Colombier                      {
27817dd7cddfSDavid du Colombier                         if (*sp == trans_values->gray)
27827dd7cddfSDavid du Colombier                         {
27837dd7cddfSDavid du Colombier                            *sp = (png_byte)background->gray;
27847dd7cddfSDavid du Colombier                         }
27857dd7cddfSDavid du Colombier                      }
27867dd7cddfSDavid du Colombier                   }
27877dd7cddfSDavid du Colombier                   break;
27887dd7cddfSDavid du Colombier                }
27897dd7cddfSDavid du Colombier                case 16:
27907dd7cddfSDavid du Colombier                {
27917dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
27927dd7cddfSDavid du Colombier                   if (gamma_16 != NULL)
27937dd7cddfSDavid du Colombier                   {
2794*593dc095SDavid du Colombier                      sp = row;
2795*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++, sp += 2)
27967dd7cddfSDavid du Colombier                      {
27977dd7cddfSDavid du Colombier                         png_uint_16 v;
27987dd7cddfSDavid du Colombier 
2799*593dc095SDavid du Colombier                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
28007dd7cddfSDavid du Colombier                         if (v == trans_values->gray)
28017dd7cddfSDavid du Colombier                         {
28027dd7cddfSDavid du Colombier                            /* background is already in screen gamma */
28037dd7cddfSDavid du Colombier                            *sp = (png_byte)((background->gray >> 8) & 0xff);
28047dd7cddfSDavid du Colombier                            *(sp + 1) = (png_byte)(background->gray & 0xff);
28057dd7cddfSDavid du Colombier                         }
28067dd7cddfSDavid du Colombier                         else
28077dd7cddfSDavid du Colombier                         {
28087dd7cddfSDavid du Colombier                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
28097dd7cddfSDavid du Colombier                            *sp = (png_byte)((v >> 8) & 0xff);
28107dd7cddfSDavid du Colombier                            *(sp + 1) = (png_byte)(v & 0xff);
28117dd7cddfSDavid du Colombier                         }
28127dd7cddfSDavid du Colombier                      }
28137dd7cddfSDavid du Colombier                   }
28147dd7cddfSDavid du Colombier                   else
28157dd7cddfSDavid du Colombier #endif
28167dd7cddfSDavid du Colombier                   {
2817*593dc095SDavid du Colombier                      sp = row;
2818*593dc095SDavid du Colombier                      for (i = 0; i < row_width; i++, sp += 2)
28197dd7cddfSDavid du Colombier                      {
28207dd7cddfSDavid du Colombier                         png_uint_16 v;
28217dd7cddfSDavid du Colombier 
2822*593dc095SDavid du Colombier                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
28237dd7cddfSDavid du Colombier                         if (v == trans_values->gray)
28247dd7cddfSDavid du Colombier                         {
28257dd7cddfSDavid du Colombier                            *sp = (png_byte)((background->gray >> 8) & 0xff);
28267dd7cddfSDavid du Colombier                            *(sp + 1) = (png_byte)(background->gray & 0xff);
28277dd7cddfSDavid du Colombier                         }
28287dd7cddfSDavid du Colombier                      }
28297dd7cddfSDavid du Colombier                   }
28307dd7cddfSDavid du Colombier                   break;
28317dd7cddfSDavid du Colombier                }
28327dd7cddfSDavid du Colombier             }
28337dd7cddfSDavid du Colombier             break;
28347dd7cddfSDavid du Colombier          }
28357dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_RGB:
28367dd7cddfSDavid du Colombier          {
28377dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
28387dd7cddfSDavid du Colombier             {
28397dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
28407dd7cddfSDavid du Colombier                if (gamma_table != NULL)
28417dd7cddfSDavid du Colombier                {
2842*593dc095SDavid du Colombier                   sp = row;
2843*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 3)
28447dd7cddfSDavid du Colombier                   {
28457dd7cddfSDavid du Colombier                      if (*sp == trans_values->red &&
28467dd7cddfSDavid du Colombier                         *(sp + 1) == trans_values->green &&
28477dd7cddfSDavid du Colombier                         *(sp + 2) == trans_values->blue)
28487dd7cddfSDavid du Colombier                      {
28497dd7cddfSDavid du Colombier                         *sp = (png_byte)background->red;
28507dd7cddfSDavid du Colombier                         *(sp + 1) = (png_byte)background->green;
28517dd7cddfSDavid du Colombier                         *(sp + 2) = (png_byte)background->blue;
28527dd7cddfSDavid du Colombier                      }
28537dd7cddfSDavid du Colombier                      else
28547dd7cddfSDavid du Colombier                      {
28557dd7cddfSDavid du Colombier                         *sp = gamma_table[*sp];
28567dd7cddfSDavid du Colombier                         *(sp + 1) = gamma_table[*(sp + 1)];
28577dd7cddfSDavid du Colombier                         *(sp + 2) = gamma_table[*(sp + 2)];
28587dd7cddfSDavid du Colombier                      }
28597dd7cddfSDavid du Colombier                   }
28607dd7cddfSDavid du Colombier                }
28617dd7cddfSDavid du Colombier                else
28627dd7cddfSDavid du Colombier #endif
28637dd7cddfSDavid du Colombier                {
2864*593dc095SDavid du Colombier                   sp = row;
2865*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 3)
28667dd7cddfSDavid du Colombier                   {
28677dd7cddfSDavid du Colombier                      if (*sp == trans_values->red &&
28687dd7cddfSDavid du Colombier                         *(sp + 1) == trans_values->green &&
28697dd7cddfSDavid du Colombier                         *(sp + 2) == trans_values->blue)
28707dd7cddfSDavid du Colombier                      {
28717dd7cddfSDavid du Colombier                         *sp = (png_byte)background->red;
28727dd7cddfSDavid du Colombier                         *(sp + 1) = (png_byte)background->green;
28737dd7cddfSDavid du Colombier                         *(sp + 2) = (png_byte)background->blue;
28747dd7cddfSDavid du Colombier                      }
28757dd7cddfSDavid du Colombier                   }
28767dd7cddfSDavid du Colombier                }
28777dd7cddfSDavid du Colombier             }
28787dd7cddfSDavid du Colombier             else /* if (row_info->bit_depth == 16) */
28797dd7cddfSDavid du Colombier             {
28807dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
28817dd7cddfSDavid du Colombier                if (gamma_16 != NULL)
28827dd7cddfSDavid du Colombier                {
2883*593dc095SDavid du Colombier                   sp = row;
2884*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 6)
28857dd7cddfSDavid du Colombier                   {
2886*593dc095SDavid du Colombier                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2887*593dc095SDavid du Colombier                      png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2888*593dc095SDavid du Colombier                      png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
28897dd7cddfSDavid du Colombier                      if (r == trans_values->red && g == trans_values->green &&
28907dd7cddfSDavid du Colombier                         b == trans_values->blue)
28917dd7cddfSDavid du Colombier                      {
28927dd7cddfSDavid du Colombier                         /* background is already in screen gamma */
28937dd7cddfSDavid du Colombier                         *sp = (png_byte)((background->red >> 8) & 0xff);
28947dd7cddfSDavid du Colombier                         *(sp + 1) = (png_byte)(background->red & 0xff);
28957dd7cddfSDavid du Colombier                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
28967dd7cddfSDavid du Colombier                         *(sp + 3) = (png_byte)(background->green & 0xff);
28977dd7cddfSDavid du Colombier                         *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
28987dd7cddfSDavid du Colombier                         *(sp + 5) = (png_byte)(background->blue & 0xff);
28997dd7cddfSDavid du Colombier                      }
29007dd7cddfSDavid du Colombier                      else
29017dd7cddfSDavid du Colombier                      {
2902*593dc095SDavid du Colombier                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
29037dd7cddfSDavid du Colombier                         *sp = (png_byte)((v >> 8) & 0xff);
29047dd7cddfSDavid du Colombier                         *(sp + 1) = (png_byte)(v & 0xff);
29057dd7cddfSDavid du Colombier                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
29067dd7cddfSDavid du Colombier                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
29077dd7cddfSDavid du Colombier                         *(sp + 3) = (png_byte)(v & 0xff);
29087dd7cddfSDavid du Colombier                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
29097dd7cddfSDavid du Colombier                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
29107dd7cddfSDavid du Colombier                         *(sp + 5) = (png_byte)(v & 0xff);
29117dd7cddfSDavid du Colombier                      }
29127dd7cddfSDavid du Colombier                   }
29137dd7cddfSDavid du Colombier                }
29147dd7cddfSDavid du Colombier                else
29157dd7cddfSDavid du Colombier #endif
29167dd7cddfSDavid du Colombier                {
2917*593dc095SDavid du Colombier                   sp = row;
2918*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 6)
29197dd7cddfSDavid du Colombier                   {
2920*593dc095SDavid du Colombier                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2921*593dc095SDavid du Colombier                      png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2922*593dc095SDavid du Colombier                      png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
29237dd7cddfSDavid du Colombier 
29247dd7cddfSDavid du Colombier                      if (r == trans_values->red && g == trans_values->green &&
29257dd7cddfSDavid du Colombier                         b == trans_values->blue)
29267dd7cddfSDavid du Colombier                      {
29277dd7cddfSDavid du Colombier                         *sp = (png_byte)((background->red >> 8) & 0xff);
29287dd7cddfSDavid du Colombier                         *(sp + 1) = (png_byte)(background->red & 0xff);
29297dd7cddfSDavid du Colombier                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
29307dd7cddfSDavid du Colombier                         *(sp + 3) = (png_byte)(background->green & 0xff);
29317dd7cddfSDavid du Colombier                         *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
29327dd7cddfSDavid du Colombier                         *(sp + 5) = (png_byte)(background->blue & 0xff);
29337dd7cddfSDavid du Colombier                      }
29347dd7cddfSDavid du Colombier                   }
29357dd7cddfSDavid du Colombier                }
29367dd7cddfSDavid du Colombier             }
29377dd7cddfSDavid du Colombier             break;
29387dd7cddfSDavid du Colombier          }
29397dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_GRAY_ALPHA:
29407dd7cddfSDavid du Colombier          {
29417dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
29427dd7cddfSDavid du Colombier             {
29437dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
29447dd7cddfSDavid du Colombier                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
29457dd7cddfSDavid du Colombier                    gamma_table != NULL)
29467dd7cddfSDavid du Colombier                {
2947*593dc095SDavid du Colombier                   sp = row;
2948*593dc095SDavid du Colombier                   dp = row;
2949*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 2, dp++)
29507dd7cddfSDavid du Colombier                   {
2951*593dc095SDavid du Colombier                      png_uint_16 a = *(sp + 1);
29527dd7cddfSDavid du Colombier 
29537dd7cddfSDavid du Colombier                      if (a == 0xff)
29547dd7cddfSDavid du Colombier                      {
29557dd7cddfSDavid du Colombier                         *dp = gamma_table[*sp];
29567dd7cddfSDavid du Colombier                      }
29577dd7cddfSDavid du Colombier                      else if (a == 0)
29587dd7cddfSDavid du Colombier                      {
29597dd7cddfSDavid du Colombier                         /* background is already in screen gamma */
29607dd7cddfSDavid du Colombier                         *dp = (png_byte)background->gray;
29617dd7cddfSDavid du Colombier                      }
29627dd7cddfSDavid du Colombier                      else
29637dd7cddfSDavid du Colombier                      {
29647dd7cddfSDavid du Colombier                         png_byte v, w;
29657dd7cddfSDavid du Colombier 
29667dd7cddfSDavid du Colombier                         v = gamma_to_1[*sp];
29677dd7cddfSDavid du Colombier                         png_composite(w, v, a, background_1->gray);
29687dd7cddfSDavid du Colombier                         *dp = gamma_from_1[w];
29697dd7cddfSDavid du Colombier                      }
29707dd7cddfSDavid du Colombier                   }
29717dd7cddfSDavid du Colombier                }
29727dd7cddfSDavid du Colombier                else
29737dd7cddfSDavid du Colombier #endif
29747dd7cddfSDavid du Colombier                {
2975*593dc095SDavid du Colombier                   sp = row;
2976*593dc095SDavid du Colombier                   dp = row;
2977*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 2, dp++)
29787dd7cddfSDavid du Colombier                   {
2979*593dc095SDavid du Colombier                      png_byte a = *(sp + 1);
29807dd7cddfSDavid du Colombier 
29817dd7cddfSDavid du Colombier                      if (a == 0xff)
29827dd7cddfSDavid du Colombier                      {
29837dd7cddfSDavid du Colombier                         *dp = *sp;
29847dd7cddfSDavid du Colombier                      }
2985*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
29867dd7cddfSDavid du Colombier                      else if (a == 0)
29877dd7cddfSDavid du Colombier                      {
29887dd7cddfSDavid du Colombier                         *dp = (png_byte)background->gray;
29897dd7cddfSDavid du Colombier                      }
29907dd7cddfSDavid du Colombier                      else
29917dd7cddfSDavid du Colombier                      {
29927dd7cddfSDavid du Colombier                         png_composite(*dp, *sp, a, background_1->gray);
29937dd7cddfSDavid du Colombier                      }
2994*593dc095SDavid du Colombier #else
2995*593dc095SDavid du Colombier                      *dp = (png_byte)background->gray;
2996*593dc095SDavid du Colombier #endif
29977dd7cddfSDavid du Colombier                   }
29987dd7cddfSDavid du Colombier                }
29997dd7cddfSDavid du Colombier             }
30007dd7cddfSDavid du Colombier             else /* if (png_ptr->bit_depth == 16) */
30017dd7cddfSDavid du Colombier             {
30027dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
30037dd7cddfSDavid du Colombier                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
30047dd7cddfSDavid du Colombier                    gamma_16_to_1 != NULL)
30057dd7cddfSDavid du Colombier                {
3006*593dc095SDavid du Colombier                   sp = row;
3007*593dc095SDavid du Colombier                   dp = row;
3008*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 4, dp += 2)
30097dd7cddfSDavid du Colombier                   {
3010*593dc095SDavid du Colombier                      png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
30117dd7cddfSDavid du Colombier 
30127dd7cddfSDavid du Colombier                      if (a == (png_uint_16)0xffff)
30137dd7cddfSDavid du Colombier                      {
30147dd7cddfSDavid du Colombier                         png_uint_16 v;
30157dd7cddfSDavid du Colombier 
30167dd7cddfSDavid du Colombier                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
30177dd7cddfSDavid du Colombier                         *dp = (png_byte)((v >> 8) & 0xff);
30187dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(v & 0xff);
30197dd7cddfSDavid du Colombier                      }
3020*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
30217dd7cddfSDavid du Colombier                      else if (a == 0)
3022*593dc095SDavid du Colombier #else
3023*593dc095SDavid du Colombier                      else
3024*593dc095SDavid du Colombier #endif
30257dd7cddfSDavid du Colombier                      {
30267dd7cddfSDavid du Colombier                         /* background is already in screen gamma */
30277dd7cddfSDavid du Colombier                         *dp = (png_byte)((background->gray >> 8) & 0xff);
30287dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(background->gray & 0xff);
30297dd7cddfSDavid du Colombier                      }
3030*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
30317dd7cddfSDavid du Colombier                      else
30327dd7cddfSDavid du Colombier                      {
30337dd7cddfSDavid du Colombier                         png_uint_16 g, v, w;
30347dd7cddfSDavid du Colombier 
30357dd7cddfSDavid du Colombier                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
30367dd7cddfSDavid du Colombier                         png_composite_16(v, g, a, background_1->gray);
30377dd7cddfSDavid du Colombier                         w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
30387dd7cddfSDavid du Colombier                         *dp = (png_byte)((w >> 8) & 0xff);
30397dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(w & 0xff);
30407dd7cddfSDavid du Colombier                      }
3041*593dc095SDavid du Colombier #endif
30427dd7cddfSDavid du Colombier                   }
30437dd7cddfSDavid du Colombier                }
30447dd7cddfSDavid du Colombier                else
30457dd7cddfSDavid du Colombier #endif
30467dd7cddfSDavid du Colombier                {
3047*593dc095SDavid du Colombier                   sp = row;
3048*593dc095SDavid du Colombier                   dp = row;
3049*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 4, dp += 2)
30507dd7cddfSDavid du Colombier                   {
3051*593dc095SDavid du Colombier                      png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
30527dd7cddfSDavid du Colombier                      if (a == (png_uint_16)0xffff)
30537dd7cddfSDavid du Colombier                      {
30547dd7cddfSDavid du Colombier                         png_memcpy(dp, sp, 2);
30557dd7cddfSDavid du Colombier                      }
3056*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
30577dd7cddfSDavid du Colombier                      else if (a == 0)
3058*593dc095SDavid du Colombier #else
3059*593dc095SDavid du Colombier                      else
3060*593dc095SDavid du Colombier #endif
30617dd7cddfSDavid du Colombier                      {
30627dd7cddfSDavid du Colombier                         *dp = (png_byte)((background->gray >> 8) & 0xff);
30637dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(background->gray & 0xff);
30647dd7cddfSDavid du Colombier                      }
3065*593dc095SDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
30667dd7cddfSDavid du Colombier                      else
30677dd7cddfSDavid du Colombier                      {
30687dd7cddfSDavid du Colombier                         png_uint_16 g, v;
30697dd7cddfSDavid du Colombier 
3070*593dc095SDavid du Colombier                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
30717dd7cddfSDavid du Colombier                         png_composite_16(v, g, a, background_1->gray);
30727dd7cddfSDavid du Colombier                         *dp = (png_byte)((v >> 8) & 0xff);
30737dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(v & 0xff);
30747dd7cddfSDavid du Colombier                      }
3075*593dc095SDavid du Colombier #endif
30767dd7cddfSDavid du Colombier                   }
30777dd7cddfSDavid du Colombier                }
30787dd7cddfSDavid du Colombier             }
30797dd7cddfSDavid du Colombier             break;
30807dd7cddfSDavid du Colombier          }
30817dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_RGB_ALPHA:
30827dd7cddfSDavid du Colombier          {
30837dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
30847dd7cddfSDavid du Colombier             {
30857dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
30867dd7cddfSDavid du Colombier                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
30877dd7cddfSDavid du Colombier                    gamma_table != NULL)
30887dd7cddfSDavid du Colombier                {
3089*593dc095SDavid du Colombier                   sp = row;
3090*593dc095SDavid du Colombier                   dp = row;
3091*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 4, dp += 3)
30927dd7cddfSDavid du Colombier                   {
3093*593dc095SDavid du Colombier                      png_byte a = *(sp + 3);
30947dd7cddfSDavid du Colombier 
30957dd7cddfSDavid du Colombier                      if (a == 0xff)
30967dd7cddfSDavid du Colombier                      {
30977dd7cddfSDavid du Colombier                         *dp = gamma_table[*sp];
30987dd7cddfSDavid du Colombier                         *(dp + 1) = gamma_table[*(sp + 1)];
30997dd7cddfSDavid du Colombier                         *(dp + 2) = gamma_table[*(sp + 2)];
31007dd7cddfSDavid du Colombier                      }
31017dd7cddfSDavid du Colombier                      else if (a == 0)
31027dd7cddfSDavid du Colombier                      {
31037dd7cddfSDavid du Colombier                         /* background is already in screen gamma */
31047dd7cddfSDavid du Colombier                         *dp = (png_byte)background->red;
31057dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)background->green;
31067dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)background->blue;
31077dd7cddfSDavid du Colombier                      }
31087dd7cddfSDavid du Colombier                      else
31097dd7cddfSDavid du Colombier                      {
31107dd7cddfSDavid du Colombier                         png_byte v, w;
31117dd7cddfSDavid du Colombier 
31127dd7cddfSDavid du Colombier                         v = gamma_to_1[*sp];
31137dd7cddfSDavid du Colombier                         png_composite(w, v, a, background_1->red);
31147dd7cddfSDavid du Colombier                         *dp = gamma_from_1[w];
31157dd7cddfSDavid du Colombier                         v = gamma_to_1[*(sp + 1)];
31167dd7cddfSDavid du Colombier                         png_composite(w, v, a, background_1->green);
31177dd7cddfSDavid du Colombier                         *(dp + 1) = gamma_from_1[w];
31187dd7cddfSDavid du Colombier                         v = gamma_to_1[*(sp + 2)];
31197dd7cddfSDavid du Colombier                         png_composite(w, v, a, background_1->blue);
31207dd7cddfSDavid du Colombier                         *(dp + 2) = gamma_from_1[w];
31217dd7cddfSDavid du Colombier                      }
31227dd7cddfSDavid du Colombier                   }
31237dd7cddfSDavid du Colombier                }
31247dd7cddfSDavid du Colombier                else
31257dd7cddfSDavid du Colombier #endif
31267dd7cddfSDavid du Colombier                {
3127*593dc095SDavid du Colombier                   sp = row;
3128*593dc095SDavid du Colombier                   dp = row;
3129*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 4, dp += 3)
31307dd7cddfSDavid du Colombier                   {
3131*593dc095SDavid du Colombier                      png_byte a = *(sp + 3);
31327dd7cddfSDavid du Colombier 
31337dd7cddfSDavid du Colombier                      if (a == 0xff)
31347dd7cddfSDavid du Colombier                      {
31357dd7cddfSDavid du Colombier                         *dp = *sp;
31367dd7cddfSDavid du Colombier                         *(dp + 1) = *(sp + 1);
31377dd7cddfSDavid du Colombier                         *(dp + 2) = *(sp + 2);
31387dd7cddfSDavid du Colombier                      }
31397dd7cddfSDavid du Colombier                      else if (a == 0)
31407dd7cddfSDavid du Colombier                      {
31417dd7cddfSDavid du Colombier                         *dp = (png_byte)background->red;
31427dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)background->green;
31437dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)background->blue;
31447dd7cddfSDavid du Colombier                      }
31457dd7cddfSDavid du Colombier                      else
31467dd7cddfSDavid du Colombier                      {
31477dd7cddfSDavid du Colombier                         png_composite(*dp, *sp, a, background->red);
31487dd7cddfSDavid du Colombier                         png_composite(*(dp + 1), *(sp + 1), a,
31497dd7cddfSDavid du Colombier                            background->green);
31507dd7cddfSDavid du Colombier                         png_composite(*(dp + 2), *(sp + 2), a,
31517dd7cddfSDavid du Colombier                            background->blue);
31527dd7cddfSDavid du Colombier                      }
31537dd7cddfSDavid du Colombier                   }
31547dd7cddfSDavid du Colombier                }
31557dd7cddfSDavid du Colombier             }
31567dd7cddfSDavid du Colombier             else /* if (row_info->bit_depth == 16) */
31577dd7cddfSDavid du Colombier             {
31587dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
31597dd7cddfSDavid du Colombier                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
31607dd7cddfSDavid du Colombier                    gamma_16_to_1 != NULL)
31617dd7cddfSDavid du Colombier                {
3162*593dc095SDavid du Colombier                   sp = row;
3163*593dc095SDavid du Colombier                   dp = row;
3164*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 8, dp += 6)
31657dd7cddfSDavid du Colombier                   {
3166*593dc095SDavid du Colombier                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3167*593dc095SDavid du Colombier                          << 8) + (png_uint_16)(*(sp + 7)));
31687dd7cddfSDavid du Colombier                      if (a == (png_uint_16)0xffff)
31697dd7cddfSDavid du Colombier                      {
31707dd7cddfSDavid du Colombier                         png_uint_16 v;
31717dd7cddfSDavid du Colombier 
31727dd7cddfSDavid du Colombier                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
31737dd7cddfSDavid du Colombier                         *dp = (png_byte)((v >> 8) & 0xff);
31747dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(v & 0xff);
31757dd7cddfSDavid du Colombier                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
31767dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
31777dd7cddfSDavid du Colombier                         *(dp + 3) = (png_byte)(v & 0xff);
31787dd7cddfSDavid du Colombier                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
31797dd7cddfSDavid du Colombier                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
31807dd7cddfSDavid du Colombier                         *(dp + 5) = (png_byte)(v & 0xff);
31817dd7cddfSDavid du Colombier                      }
31827dd7cddfSDavid du Colombier                      else if (a == 0)
31837dd7cddfSDavid du Colombier                      {
31847dd7cddfSDavid du Colombier                         /* background is already in screen gamma */
31857dd7cddfSDavid du Colombier                         *dp = (png_byte)((background->red >> 8) & 0xff);
31867dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(background->red & 0xff);
31877dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
31887dd7cddfSDavid du Colombier                         *(dp + 3) = (png_byte)(background->green & 0xff);
31897dd7cddfSDavid du Colombier                         *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
31907dd7cddfSDavid du Colombier                         *(dp + 5) = (png_byte)(background->blue & 0xff);
31917dd7cddfSDavid du Colombier                      }
31927dd7cddfSDavid du Colombier                      else
31937dd7cddfSDavid du Colombier                      {
31947dd7cddfSDavid du Colombier                         png_uint_16 v, w, x;
31957dd7cddfSDavid du Colombier 
31967dd7cddfSDavid du Colombier                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3197*593dc095SDavid du Colombier                         png_composite_16(w, v, a, background_1->red);
31987dd7cddfSDavid du Colombier                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
31997dd7cddfSDavid du Colombier                         *dp = (png_byte)((x >> 8) & 0xff);
32007dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(x & 0xff);
32017dd7cddfSDavid du Colombier                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3202*593dc095SDavid du Colombier                         png_composite_16(w, v, a, background_1->green);
32037dd7cddfSDavid du Colombier                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
32047dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)((x >> 8) & 0xff);
32057dd7cddfSDavid du Colombier                         *(dp + 3) = (png_byte)(x & 0xff);
32067dd7cddfSDavid du Colombier                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3207*593dc095SDavid du Colombier                         png_composite_16(w, v, a, background_1->blue);
32087dd7cddfSDavid du Colombier                         x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
32097dd7cddfSDavid du Colombier                         *(dp + 4) = (png_byte)((x >> 8) & 0xff);
32107dd7cddfSDavid du Colombier                         *(dp + 5) = (png_byte)(x & 0xff);
32117dd7cddfSDavid du Colombier                      }
32127dd7cddfSDavid du Colombier                   }
32137dd7cddfSDavid du Colombier                }
32147dd7cddfSDavid du Colombier                else
32157dd7cddfSDavid du Colombier #endif
32167dd7cddfSDavid du Colombier                {
3217*593dc095SDavid du Colombier                   sp = row;
3218*593dc095SDavid du Colombier                   dp = row;
3219*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++, sp += 8, dp += 6)
32207dd7cddfSDavid du Colombier                   {
3221*593dc095SDavid du Colombier                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3222*593dc095SDavid du Colombier                         << 8) + (png_uint_16)(*(sp + 7)));
32237dd7cddfSDavid du Colombier                      if (a == (png_uint_16)0xffff)
32247dd7cddfSDavid du Colombier                      {
32257dd7cddfSDavid du Colombier                         png_memcpy(dp, sp, 6);
32267dd7cddfSDavid du Colombier                      }
32277dd7cddfSDavid du Colombier                      else if (a == 0)
32287dd7cddfSDavid du Colombier                      {
32297dd7cddfSDavid du Colombier                         *dp = (png_byte)((background->red >> 8) & 0xff);
32307dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(background->red & 0xff);
32317dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
32327dd7cddfSDavid du Colombier                         *(dp + 3) = (png_byte)(background->green & 0xff);
32337dd7cddfSDavid du Colombier                         *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
32347dd7cddfSDavid du Colombier                         *(dp + 5) = (png_byte)(background->blue & 0xff);
32357dd7cddfSDavid du Colombier                      }
32367dd7cddfSDavid du Colombier                      else
32377dd7cddfSDavid du Colombier                      {
3238*593dc095SDavid du Colombier                         png_uint_16 v;
32397dd7cddfSDavid du Colombier 
3240*593dc095SDavid du Colombier                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3241*593dc095SDavid du Colombier                         png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3242*593dc095SDavid du Colombier                             + *(sp + 3));
3243*593dc095SDavid du Colombier                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3244*593dc095SDavid du Colombier                             + *(sp + 5));
32457dd7cddfSDavid du Colombier 
32467dd7cddfSDavid du Colombier                         png_composite_16(v, r, a, background->red);
32477dd7cddfSDavid du Colombier                         *dp = (png_byte)((v >> 8) & 0xff);
32487dd7cddfSDavid du Colombier                         *(dp + 1) = (png_byte)(v & 0xff);
32497dd7cddfSDavid du Colombier                         png_composite_16(v, g, a, background->green);
32507dd7cddfSDavid du Colombier                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
32517dd7cddfSDavid du Colombier                         *(dp + 3) = (png_byte)(v & 0xff);
32527dd7cddfSDavid du Colombier                         png_composite_16(v, b, a, background->blue);
32537dd7cddfSDavid du Colombier                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
32547dd7cddfSDavid du Colombier                         *(dp + 5) = (png_byte)(v & 0xff);
32557dd7cddfSDavid du Colombier                      }
32567dd7cddfSDavid du Colombier                   }
32577dd7cddfSDavid du Colombier                }
32587dd7cddfSDavid du Colombier             }
32597dd7cddfSDavid du Colombier             break;
32607dd7cddfSDavid du Colombier          }
32617dd7cddfSDavid du Colombier       }
32627dd7cddfSDavid du Colombier 
32637dd7cddfSDavid du Colombier       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
32647dd7cddfSDavid du Colombier       {
32657dd7cddfSDavid du Colombier          row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
32667dd7cddfSDavid du Colombier          row_info->channels--;
32677dd7cddfSDavid du Colombier          row_info->pixel_depth = (png_byte)(row_info->channels *
32687dd7cddfSDavid du Colombier             row_info->bit_depth);
3269*593dc095SDavid du Colombier          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
32707dd7cddfSDavid du Colombier       }
32717dd7cddfSDavid du Colombier    }
32727dd7cddfSDavid du Colombier }
32737dd7cddfSDavid du Colombier #endif
32747dd7cddfSDavid du Colombier 
32757dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
32767dd7cddfSDavid du Colombier /* Gamma correct the image, avoiding the alpha channel.  Make sure
3277*593dc095SDavid du Colombier  * you do this after you deal with the transparency issue on grayscale
3278*593dc095SDavid du Colombier  * or RGB images. If your bit depth is 8, use gamma_table, if it
32797dd7cddfSDavid du Colombier  * is 16, use gamma_16_table and gamma_shift.  Build these with
32807dd7cddfSDavid du Colombier  * build_gamma_table().
32817dd7cddfSDavid du Colombier  */
3282*593dc095SDavid du Colombier void /* PRIVATE */
png_do_gamma(png_row_infop row_info,png_bytep row,png_bytep gamma_table,png_uint_16pp gamma_16_table,int gamma_shift)32837dd7cddfSDavid du Colombier png_do_gamma(png_row_infop row_info, png_bytep row,
32847dd7cddfSDavid du Colombier    png_bytep gamma_table, png_uint_16pp gamma_16_table,
32857dd7cddfSDavid du Colombier    int gamma_shift)
32867dd7cddfSDavid du Colombier {
32877dd7cddfSDavid du Colombier    png_bytep sp;
32887dd7cddfSDavid du Colombier    png_uint_32 i;
3289*593dc095SDavid du Colombier    png_uint_32 row_width=row_info->width;
32907dd7cddfSDavid du Colombier 
32917dd7cddfSDavid du Colombier    png_debug(1, "in png_do_gamma\n");
32927dd7cddfSDavid du Colombier    if (
32937dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
32947dd7cddfSDavid du Colombier        row != NULL && row_info != NULL &&
32957dd7cddfSDavid du Colombier #endif
32967dd7cddfSDavid du Colombier        ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
32977dd7cddfSDavid du Colombier         (row_info->bit_depth == 16 && gamma_16_table != NULL)))
32987dd7cddfSDavid du Colombier    {
32997dd7cddfSDavid du Colombier       switch (row_info->color_type)
33007dd7cddfSDavid du Colombier       {
33017dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_RGB:
33027dd7cddfSDavid du Colombier          {
33037dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
33047dd7cddfSDavid du Colombier             {
3305*593dc095SDavid du Colombier                sp = row;
3306*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
33077dd7cddfSDavid du Colombier                {
33087dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33097dd7cddfSDavid du Colombier                   sp++;
33107dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33117dd7cddfSDavid du Colombier                   sp++;
33127dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33137dd7cddfSDavid du Colombier                   sp++;
33147dd7cddfSDavid du Colombier                }
33157dd7cddfSDavid du Colombier             }
33167dd7cddfSDavid du Colombier             else /* if (row_info->bit_depth == 16) */
33177dd7cddfSDavid du Colombier             {
3318*593dc095SDavid du Colombier                sp = row;
3319*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
33207dd7cddfSDavid du Colombier                {
33217dd7cddfSDavid du Colombier                   png_uint_16 v;
33227dd7cddfSDavid du Colombier 
33237dd7cddfSDavid du Colombier                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33247dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33257dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33267dd7cddfSDavid du Colombier                   sp += 2;
33277dd7cddfSDavid du Colombier                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33287dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33297dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33307dd7cddfSDavid du Colombier                   sp += 2;
33317dd7cddfSDavid du Colombier                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33327dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33337dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33347dd7cddfSDavid du Colombier                   sp += 2;
33357dd7cddfSDavid du Colombier                }
33367dd7cddfSDavid du Colombier             }
33377dd7cddfSDavid du Colombier             break;
33387dd7cddfSDavid du Colombier          }
33397dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_RGB_ALPHA:
33407dd7cddfSDavid du Colombier          {
33417dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
33427dd7cddfSDavid du Colombier             {
3343*593dc095SDavid du Colombier                sp = row;
3344*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
33457dd7cddfSDavid du Colombier                {
33467dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33477dd7cddfSDavid du Colombier                   sp++;
33487dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33497dd7cddfSDavid du Colombier                   sp++;
33507dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33517dd7cddfSDavid du Colombier                   sp++;
33527dd7cddfSDavid du Colombier                   sp++;
33537dd7cddfSDavid du Colombier                }
33547dd7cddfSDavid du Colombier             }
33557dd7cddfSDavid du Colombier             else /* if (row_info->bit_depth == 16) */
33567dd7cddfSDavid du Colombier             {
3357*593dc095SDavid du Colombier                sp = row;
3358*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
33597dd7cddfSDavid du Colombier                {
3360*593dc095SDavid du Colombier                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33617dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33627dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33637dd7cddfSDavid du Colombier                   sp += 2;
33647dd7cddfSDavid du Colombier                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33657dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33667dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33677dd7cddfSDavid du Colombier                   sp += 2;
33687dd7cddfSDavid du Colombier                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33697dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33707dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33717dd7cddfSDavid du Colombier                   sp += 4;
33727dd7cddfSDavid du Colombier                }
33737dd7cddfSDavid du Colombier             }
33747dd7cddfSDavid du Colombier             break;
33757dd7cddfSDavid du Colombier          }
33767dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_GRAY_ALPHA:
33777dd7cddfSDavid du Colombier          {
33787dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
33797dd7cddfSDavid du Colombier             {
3380*593dc095SDavid du Colombier                sp = row;
3381*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
33827dd7cddfSDavid du Colombier                {
33837dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
33847dd7cddfSDavid du Colombier                   sp += 2;
33857dd7cddfSDavid du Colombier                }
33867dd7cddfSDavid du Colombier             }
33877dd7cddfSDavid du Colombier             else /* if (row_info->bit_depth == 16) */
33887dd7cddfSDavid du Colombier             {
3389*593dc095SDavid du Colombier                sp = row;
3390*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
33917dd7cddfSDavid du Colombier                {
3392*593dc095SDavid du Colombier                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
33937dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
33947dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
33957dd7cddfSDavid du Colombier                   sp += 4;
33967dd7cddfSDavid du Colombier                }
33977dd7cddfSDavid du Colombier             }
33987dd7cddfSDavid du Colombier             break;
33997dd7cddfSDavid du Colombier          }
34007dd7cddfSDavid du Colombier          case PNG_COLOR_TYPE_GRAY:
34017dd7cddfSDavid du Colombier          {
34027dd7cddfSDavid du Colombier             if (row_info->bit_depth == 2)
34037dd7cddfSDavid du Colombier             {
3404*593dc095SDavid du Colombier                sp = row;
3405*593dc095SDavid du Colombier                for (i = 0; i < row_width; i += 4)
34067dd7cddfSDavid du Colombier                {
34077dd7cddfSDavid du Colombier                   int a = *sp & 0xc0;
34087dd7cddfSDavid du Colombier                   int b = *sp & 0x30;
34097dd7cddfSDavid du Colombier                   int c = *sp & 0x0c;
34107dd7cddfSDavid du Colombier                   int d = *sp & 0x03;
34117dd7cddfSDavid du Colombier 
3412*593dc095SDavid du Colombier                   *sp = (png_byte)(
3413*593dc095SDavid du Colombier                         ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
34147dd7cddfSDavid du Colombier                         ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
34157dd7cddfSDavid du Colombier                         ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3416*593dc095SDavid du Colombier                         ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
34177dd7cddfSDavid du Colombier                   sp++;
34187dd7cddfSDavid du Colombier                }
34197dd7cddfSDavid du Colombier             }
34207dd7cddfSDavid du Colombier             if (row_info->bit_depth == 4)
34217dd7cddfSDavid du Colombier             {
3422*593dc095SDavid du Colombier                sp = row;
3423*593dc095SDavid du Colombier                for (i = 0; i < row_width; i += 2)
34247dd7cddfSDavid du Colombier                {
34257dd7cddfSDavid du Colombier                   int msb = *sp & 0xf0;
34267dd7cddfSDavid du Colombier                   int lsb = *sp & 0x0f;
34277dd7cddfSDavid du Colombier 
3428*593dc095SDavid du Colombier                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3429*593dc095SDavid du Colombier                           | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
34307dd7cddfSDavid du Colombier                   sp++;
34317dd7cddfSDavid du Colombier                }
34327dd7cddfSDavid du Colombier             }
34337dd7cddfSDavid du Colombier             else if (row_info->bit_depth == 8)
34347dd7cddfSDavid du Colombier             {
3435*593dc095SDavid du Colombier                sp = row;
3436*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
34377dd7cddfSDavid du Colombier                {
34387dd7cddfSDavid du Colombier                   *sp = gamma_table[*sp];
34397dd7cddfSDavid du Colombier                   sp++;
34407dd7cddfSDavid du Colombier                }
34417dd7cddfSDavid du Colombier             }
34427dd7cddfSDavid du Colombier             else if (row_info->bit_depth == 16)
34437dd7cddfSDavid du Colombier             {
3444*593dc095SDavid du Colombier                sp = row;
3445*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
34467dd7cddfSDavid du Colombier                {
3447*593dc095SDavid du Colombier                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
34487dd7cddfSDavid du Colombier                   *sp = (png_byte)((v >> 8) & 0xff);
34497dd7cddfSDavid du Colombier                   *(sp + 1) = (png_byte)(v & 0xff);
34507dd7cddfSDavid du Colombier                   sp += 2;
34517dd7cddfSDavid du Colombier                }
34527dd7cddfSDavid du Colombier             }
34537dd7cddfSDavid du Colombier             break;
34547dd7cddfSDavid du Colombier          }
34557dd7cddfSDavid du Colombier       }
34567dd7cddfSDavid du Colombier    }
34577dd7cddfSDavid du Colombier }
34587dd7cddfSDavid du Colombier #endif
34597dd7cddfSDavid du Colombier 
34607dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
3461*593dc095SDavid du Colombier /* Expands a palette row to an RGB or RGBA row depending
34627dd7cddfSDavid du Colombier  * upon whether you supply trans and num_trans.
34637dd7cddfSDavid du Colombier  */
3464*593dc095SDavid du Colombier void /* PRIVATE */
png_do_expand_palette(png_row_infop row_info,png_bytep row,png_colorp palette,png_bytep trans,int num_trans)34657dd7cddfSDavid du Colombier png_do_expand_palette(png_row_infop row_info, png_bytep row,
34667dd7cddfSDavid du Colombier    png_colorp palette, png_bytep trans, int num_trans)
34677dd7cddfSDavid du Colombier {
34687dd7cddfSDavid du Colombier    int shift, value;
34697dd7cddfSDavid du Colombier    png_bytep sp, dp;
34707dd7cddfSDavid du Colombier    png_uint_32 i;
3471*593dc095SDavid du Colombier    png_uint_32 row_width=row_info->width;
34727dd7cddfSDavid du Colombier 
34737dd7cddfSDavid du Colombier    png_debug(1, "in png_do_expand_palette\n");
34747dd7cddfSDavid du Colombier    if (
34757dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
34767dd7cddfSDavid du Colombier        row != NULL && row_info != NULL &&
34777dd7cddfSDavid du Colombier #endif
34787dd7cddfSDavid du Colombier        row_info->color_type == PNG_COLOR_TYPE_PALETTE)
34797dd7cddfSDavid du Colombier    {
34807dd7cddfSDavid du Colombier       if (row_info->bit_depth < 8)
34817dd7cddfSDavid du Colombier       {
34827dd7cddfSDavid du Colombier          switch (row_info->bit_depth)
34837dd7cddfSDavid du Colombier          {
34847dd7cddfSDavid du Colombier             case 1:
34857dd7cddfSDavid du Colombier             {
3486*593dc095SDavid du Colombier                sp = row + (png_size_t)((row_width - 1) >> 3);
3487*593dc095SDavid du Colombier                dp = row + (png_size_t)row_width - 1;
3488*593dc095SDavid du Colombier                shift = 7 - (int)((row_width + 7) & 0x07);
3489*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
34907dd7cddfSDavid du Colombier                {
3491*593dc095SDavid du Colombier                   if ((*sp >> shift) & 0x01)
34927dd7cddfSDavid du Colombier                      *dp = 1;
34937dd7cddfSDavid du Colombier                   else
34947dd7cddfSDavid du Colombier                      *dp = 0;
34957dd7cddfSDavid du Colombier                   if (shift == 7)
34967dd7cddfSDavid du Colombier                   {
34977dd7cddfSDavid du Colombier                      shift = 0;
34987dd7cddfSDavid du Colombier                      sp--;
34997dd7cddfSDavid du Colombier                   }
35007dd7cddfSDavid du Colombier                   else
35017dd7cddfSDavid du Colombier                      shift++;
35027dd7cddfSDavid du Colombier 
35037dd7cddfSDavid du Colombier                   dp--;
35047dd7cddfSDavid du Colombier                }
35057dd7cddfSDavid du Colombier                break;
35067dd7cddfSDavid du Colombier             }
35077dd7cddfSDavid du Colombier             case 2:
35087dd7cddfSDavid du Colombier             {
3509*593dc095SDavid du Colombier                sp = row + (png_size_t)((row_width - 1) >> 2);
3510*593dc095SDavid du Colombier                dp = row + (png_size_t)row_width - 1;
3511*593dc095SDavid du Colombier                shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3512*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
35137dd7cddfSDavid du Colombier                {
3514*593dc095SDavid du Colombier                   value = (*sp >> shift) & 0x03;
35157dd7cddfSDavid du Colombier                   *dp = (png_byte)value;
35167dd7cddfSDavid du Colombier                   if (shift == 6)
35177dd7cddfSDavid du Colombier                   {
35187dd7cddfSDavid du Colombier                      shift = 0;
35197dd7cddfSDavid du Colombier                      sp--;
35207dd7cddfSDavid du Colombier                   }
35217dd7cddfSDavid du Colombier                   else
35227dd7cddfSDavid du Colombier                      shift += 2;
35237dd7cddfSDavid du Colombier 
35247dd7cddfSDavid du Colombier                   dp--;
35257dd7cddfSDavid du Colombier                }
35267dd7cddfSDavid du Colombier                break;
35277dd7cddfSDavid du Colombier             }
35287dd7cddfSDavid du Colombier             case 4:
35297dd7cddfSDavid du Colombier             {
3530*593dc095SDavid du Colombier                sp = row + (png_size_t)((row_width - 1) >> 1);
3531*593dc095SDavid du Colombier                dp = row + (png_size_t)row_width - 1;
3532*593dc095SDavid du Colombier                shift = (int)((row_width & 0x01) << 2);
3533*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
35347dd7cddfSDavid du Colombier                {
3535*593dc095SDavid du Colombier                   value = (*sp >> shift) & 0x0f;
35367dd7cddfSDavid du Colombier                   *dp = (png_byte)value;
35377dd7cddfSDavid du Colombier                   if (shift == 4)
35387dd7cddfSDavid du Colombier                   {
35397dd7cddfSDavid du Colombier                      shift = 0;
35407dd7cddfSDavid du Colombier                      sp--;
35417dd7cddfSDavid du Colombier                   }
35427dd7cddfSDavid du Colombier                   else
35437dd7cddfSDavid du Colombier                      shift += 4;
35447dd7cddfSDavid du Colombier 
35457dd7cddfSDavid du Colombier                   dp--;
35467dd7cddfSDavid du Colombier                }
35477dd7cddfSDavid du Colombier                break;
35487dd7cddfSDavid du Colombier             }
35497dd7cddfSDavid du Colombier          }
35507dd7cddfSDavid du Colombier          row_info->bit_depth = 8;
35517dd7cddfSDavid du Colombier          row_info->pixel_depth = 8;
3552*593dc095SDavid du Colombier          row_info->rowbytes = row_width;
35537dd7cddfSDavid du Colombier       }
35547dd7cddfSDavid du Colombier       switch (row_info->bit_depth)
35557dd7cddfSDavid du Colombier       {
35567dd7cddfSDavid du Colombier          case 8:
35577dd7cddfSDavid du Colombier          {
35587dd7cddfSDavid du Colombier             if (trans != NULL)
35597dd7cddfSDavid du Colombier             {
3560*593dc095SDavid du Colombier                sp = row + (png_size_t)row_width - 1;
3561*593dc095SDavid du Colombier                dp = row + (png_size_t)(row_width << 2) - 1;
35627dd7cddfSDavid du Colombier 
3563*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
35647dd7cddfSDavid du Colombier                {
35657dd7cddfSDavid du Colombier                   if ((int)(*sp) >= num_trans)
35667dd7cddfSDavid du Colombier                      *dp-- = 0xff;
35677dd7cddfSDavid du Colombier                   else
35687dd7cddfSDavid du Colombier                      *dp-- = trans[*sp];
35697dd7cddfSDavid du Colombier                   *dp-- = palette[*sp].blue;
35707dd7cddfSDavid du Colombier                   *dp-- = palette[*sp].green;
35717dd7cddfSDavid du Colombier                   *dp-- = palette[*sp].red;
35727dd7cddfSDavid du Colombier                   sp--;
35737dd7cddfSDavid du Colombier                }
35747dd7cddfSDavid du Colombier                row_info->bit_depth = 8;
35757dd7cddfSDavid du Colombier                row_info->pixel_depth = 32;
3576*593dc095SDavid du Colombier                row_info->rowbytes = row_width * 4;
35777dd7cddfSDavid du Colombier                row_info->color_type = 6;
35787dd7cddfSDavid du Colombier                row_info->channels = 4;
35797dd7cddfSDavid du Colombier             }
35807dd7cddfSDavid du Colombier             else
35817dd7cddfSDavid du Colombier             {
3582*593dc095SDavid du Colombier                sp = row + (png_size_t)row_width - 1;
3583*593dc095SDavid du Colombier                dp = row + (png_size_t)(row_width * 3) - 1;
35847dd7cddfSDavid du Colombier 
3585*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
35867dd7cddfSDavid du Colombier                {
35877dd7cddfSDavid du Colombier                   *dp-- = palette[*sp].blue;
35887dd7cddfSDavid du Colombier                   *dp-- = palette[*sp].green;
35897dd7cddfSDavid du Colombier                   *dp-- = palette[*sp].red;
35907dd7cddfSDavid du Colombier                   sp--;
35917dd7cddfSDavid du Colombier                }
35927dd7cddfSDavid du Colombier                row_info->bit_depth = 8;
35937dd7cddfSDavid du Colombier                row_info->pixel_depth = 24;
3594*593dc095SDavid du Colombier                row_info->rowbytes = row_width * 3;
35957dd7cddfSDavid du Colombier                row_info->color_type = 2;
35967dd7cddfSDavid du Colombier                row_info->channels = 3;
35977dd7cddfSDavid du Colombier             }
35987dd7cddfSDavid du Colombier             break;
35997dd7cddfSDavid du Colombier          }
36007dd7cddfSDavid du Colombier       }
36017dd7cddfSDavid du Colombier    }
36027dd7cddfSDavid du Colombier }
36037dd7cddfSDavid du Colombier 
36047dd7cddfSDavid du Colombier /* If the bit depth < 8, it is expanded to 8.  Also, if the
36057dd7cddfSDavid du Colombier  * transparency value is supplied, an alpha channel is built.
36067dd7cddfSDavid du Colombier  */
3607*593dc095SDavid du Colombier void /* PRIVATE */
png_do_expand(png_row_infop row_info,png_bytep row,png_color_16p trans_value)36087dd7cddfSDavid du Colombier png_do_expand(png_row_infop row_info, png_bytep row,
36097dd7cddfSDavid du Colombier    png_color_16p trans_value)
36107dd7cddfSDavid du Colombier {
36117dd7cddfSDavid du Colombier    int shift, value;
36127dd7cddfSDavid du Colombier    png_bytep sp, dp;
36137dd7cddfSDavid du Colombier    png_uint_32 i;
3614*593dc095SDavid du Colombier    png_uint_32 row_width=row_info->width;
36157dd7cddfSDavid du Colombier 
36167dd7cddfSDavid du Colombier    png_debug(1, "in png_do_expand\n");
36177dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
36187dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL)
36197dd7cddfSDavid du Colombier #endif
36207dd7cddfSDavid du Colombier    {
36217dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
36227dd7cddfSDavid du Colombier       {
3623*593dc095SDavid du Colombier          png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
36247dd7cddfSDavid du Colombier 
36257dd7cddfSDavid du Colombier          if (row_info->bit_depth < 8)
36267dd7cddfSDavid du Colombier          {
36277dd7cddfSDavid du Colombier             switch (row_info->bit_depth)
36287dd7cddfSDavid du Colombier             {
36297dd7cddfSDavid du Colombier                case 1:
36307dd7cddfSDavid du Colombier                {
3631*593dc095SDavid du Colombier                   gray = (png_uint_16)(gray*0xff);
3632*593dc095SDavid du Colombier                   sp = row + (png_size_t)((row_width - 1) >> 3);
3633*593dc095SDavid du Colombier                   dp = row + (png_size_t)row_width - 1;
3634*593dc095SDavid du Colombier                   shift = 7 - (int)((row_width + 7) & 0x07);
3635*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++)
36367dd7cddfSDavid du Colombier                   {
3637*593dc095SDavid du Colombier                      if ((*sp >> shift) & 0x01)
36387dd7cddfSDavid du Colombier                         *dp = 0xff;
36397dd7cddfSDavid du Colombier                      else
36407dd7cddfSDavid du Colombier                         *dp = 0;
36417dd7cddfSDavid du Colombier                      if (shift == 7)
36427dd7cddfSDavid du Colombier                      {
36437dd7cddfSDavid du Colombier                         shift = 0;
36447dd7cddfSDavid du Colombier                         sp--;
36457dd7cddfSDavid du Colombier                      }
36467dd7cddfSDavid du Colombier                      else
36477dd7cddfSDavid du Colombier                         shift++;
36487dd7cddfSDavid du Colombier 
36497dd7cddfSDavid du Colombier                      dp--;
36507dd7cddfSDavid du Colombier                   }
36517dd7cddfSDavid du Colombier                   break;
36527dd7cddfSDavid du Colombier                }
36537dd7cddfSDavid du Colombier                case 2:
36547dd7cddfSDavid du Colombier                {
3655*593dc095SDavid du Colombier                   gray = (png_uint_16)(gray*0x55);
3656*593dc095SDavid du Colombier                   sp = row + (png_size_t)((row_width - 1) >> 2);
3657*593dc095SDavid du Colombier                   dp = row + (png_size_t)row_width - 1;
3658*593dc095SDavid du Colombier                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3659*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++)
36607dd7cddfSDavid du Colombier                   {
3661*593dc095SDavid du Colombier                      value = (*sp >> shift) & 0x03;
36627dd7cddfSDavid du Colombier                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
36637dd7cddfSDavid du Colombier                         (value << 6));
36647dd7cddfSDavid du Colombier                      if (shift == 6)
36657dd7cddfSDavid du Colombier                      {
36667dd7cddfSDavid du Colombier                         shift = 0;
36677dd7cddfSDavid du Colombier                         sp--;
36687dd7cddfSDavid du Colombier                      }
36697dd7cddfSDavid du Colombier                      else
36707dd7cddfSDavid du Colombier                         shift += 2;
36717dd7cddfSDavid du Colombier 
36727dd7cddfSDavid du Colombier                      dp--;
36737dd7cddfSDavid du Colombier                   }
36747dd7cddfSDavid du Colombier                   break;
36757dd7cddfSDavid du Colombier                }
36767dd7cddfSDavid du Colombier                case 4:
36777dd7cddfSDavid du Colombier                {
3678*593dc095SDavid du Colombier                   gray = (png_uint_16)(gray*0x11);
3679*593dc095SDavid du Colombier                   sp = row + (png_size_t)((row_width - 1) >> 1);
3680*593dc095SDavid du Colombier                   dp = row + (png_size_t)row_width - 1;
3681*593dc095SDavid du Colombier                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3682*593dc095SDavid du Colombier                   for (i = 0; i < row_width; i++)
36837dd7cddfSDavid du Colombier                   {
3684*593dc095SDavid du Colombier                      value = (*sp >> shift) & 0x0f;
36857dd7cddfSDavid du Colombier                      *dp = (png_byte)(value | (value << 4));
36867dd7cddfSDavid du Colombier                      if (shift == 4)
36877dd7cddfSDavid du Colombier                      {
36887dd7cddfSDavid du Colombier                         shift = 0;
36897dd7cddfSDavid du Colombier                         sp--;
36907dd7cddfSDavid du Colombier                      }
36917dd7cddfSDavid du Colombier                      else
36927dd7cddfSDavid du Colombier                         shift = 4;
36937dd7cddfSDavid du Colombier 
36947dd7cddfSDavid du Colombier                      dp--;
36957dd7cddfSDavid du Colombier                   }
36967dd7cddfSDavid du Colombier                   break;
36977dd7cddfSDavid du Colombier                }
36987dd7cddfSDavid du Colombier             }
36997dd7cddfSDavid du Colombier             row_info->bit_depth = 8;
37007dd7cddfSDavid du Colombier             row_info->pixel_depth = 8;
3701*593dc095SDavid du Colombier             row_info->rowbytes = row_width;
37027dd7cddfSDavid du Colombier          }
37037dd7cddfSDavid du Colombier 
37047dd7cddfSDavid du Colombier          if (trans_value != NULL)
37057dd7cddfSDavid du Colombier          {
37067dd7cddfSDavid du Colombier             if (row_info->bit_depth == 8)
37077dd7cddfSDavid du Colombier             {
3708*593dc095SDavid du Colombier                sp = row + (png_size_t)row_width - 1;
3709*593dc095SDavid du Colombier                dp = row + (png_size_t)(row_width << 1) - 1;
3710*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
37117dd7cddfSDavid du Colombier                {
37127dd7cddfSDavid du Colombier                   if (*sp == gray)
37137dd7cddfSDavid du Colombier                      *dp-- = 0;
37147dd7cddfSDavid du Colombier                   else
37157dd7cddfSDavid du Colombier                      *dp-- = 0xff;
37167dd7cddfSDavid du Colombier                   *dp-- = *sp--;
37177dd7cddfSDavid du Colombier                }
37187dd7cddfSDavid du Colombier             }
37197dd7cddfSDavid du Colombier             else if (row_info->bit_depth == 16)
37207dd7cddfSDavid du Colombier             {
37217dd7cddfSDavid du Colombier                sp = row + row_info->rowbytes - 1;
37227dd7cddfSDavid du Colombier                dp = row + (row_info->rowbytes << 1) - 1;
3723*593dc095SDavid du Colombier                for (i = 0; i < row_width; i++)
37247dd7cddfSDavid du Colombier                {
37257dd7cddfSDavid du Colombier                   if (((png_uint_16)*(sp) |
37267dd7cddfSDavid du Colombier                      ((png_uint_16)*(sp - 1) << 8)) == gray)
37277dd7cddfSDavid du Colombier                   {
37287dd7cddfSDavid du Colombier                      *dp-- = 0;
37297dd7cddfSDavid du Colombier                      *dp-- = 0;
37307dd7cddfSDavid du Colombier                   }
37317dd7cddfSDavid du Colombier                   else
37327dd7cddfSDavid du Colombier                   {
37337dd7cddfSDavid du Colombier                      *dp-- = 0xff;
37347dd7cddfSDavid du Colombier                      *dp-- = 0xff;
37357dd7cddfSDavid du Colombier                   }
37367dd7cddfSDavid du Colombier                   *dp-- = *sp--;
37377dd7cddfSDavid du Colombier                   *dp-- = *sp--;
37387dd7cddfSDavid du Colombier                }
37397dd7cddfSDavid du Colombier             }
37407dd7cddfSDavid du Colombier             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
37417dd7cddfSDavid du Colombier             row_info->channels = 2;
37427dd7cddfSDavid du Colombier             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3743*593dc095SDavid du Colombier             row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3744*593dc095SDavid du Colombier                row_width);
37457dd7cddfSDavid du Colombier          }
37467dd7cddfSDavid du Colombier       }
37477dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
37487dd7cddfSDavid du Colombier       {
37497dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
37507dd7cddfSDavid du Colombier          {
37517dd7cddfSDavid du Colombier             sp = row + (png_size_t)row_info->rowbytes - 1;
3752*593dc095SDavid du Colombier             dp = row + (png_size_t)(row_width << 2) - 1;
3753*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
37547dd7cddfSDavid du Colombier             {
37557dd7cddfSDavid du Colombier                if (*(sp - 2) == trans_value->red &&
37567dd7cddfSDavid du Colombier                   *(sp - 1) == trans_value->green &&
37577dd7cddfSDavid du Colombier                   *(sp - 0) == trans_value->blue)
37587dd7cddfSDavid du Colombier                   *dp-- = 0;
37597dd7cddfSDavid du Colombier                else
37607dd7cddfSDavid du Colombier                   *dp-- = 0xff;
37617dd7cddfSDavid du Colombier                *dp-- = *sp--;
37627dd7cddfSDavid du Colombier                *dp-- = *sp--;
37637dd7cddfSDavid du Colombier                *dp-- = *sp--;
37647dd7cddfSDavid du Colombier             }
37657dd7cddfSDavid du Colombier          }
37667dd7cddfSDavid du Colombier          else if (row_info->bit_depth == 16)
37677dd7cddfSDavid du Colombier          {
37687dd7cddfSDavid du Colombier             sp = row + row_info->rowbytes - 1;
3769*593dc095SDavid du Colombier             dp = row + (png_size_t)(row_width << 3) - 1;
3770*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
37717dd7cddfSDavid du Colombier             {
37727dd7cddfSDavid du Colombier                if ((((png_uint_16)*(sp - 4) |
37737dd7cddfSDavid du Colombier                   ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
37747dd7cddfSDavid du Colombier                   (((png_uint_16)*(sp - 2) |
37757dd7cddfSDavid du Colombier                   ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
37767dd7cddfSDavid du Colombier                   (((png_uint_16)*(sp - 0) |
37777dd7cddfSDavid du Colombier                   ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
37787dd7cddfSDavid du Colombier                {
37797dd7cddfSDavid du Colombier                   *dp-- = 0;
37807dd7cddfSDavid du Colombier                   *dp-- = 0;
37817dd7cddfSDavid du Colombier                }
37827dd7cddfSDavid du Colombier                else
37837dd7cddfSDavid du Colombier                {
37847dd7cddfSDavid du Colombier                   *dp-- = 0xff;
37857dd7cddfSDavid du Colombier                   *dp-- = 0xff;
37867dd7cddfSDavid du Colombier                }
37877dd7cddfSDavid du Colombier                *dp-- = *sp--;
37887dd7cddfSDavid du Colombier                *dp-- = *sp--;
37897dd7cddfSDavid du Colombier                *dp-- = *sp--;
37907dd7cddfSDavid du Colombier                *dp-- = *sp--;
37917dd7cddfSDavid du Colombier                *dp-- = *sp--;
37927dd7cddfSDavid du Colombier                *dp-- = *sp--;
37937dd7cddfSDavid du Colombier             }
37947dd7cddfSDavid du Colombier          }
37957dd7cddfSDavid du Colombier          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
37967dd7cddfSDavid du Colombier          row_info->channels = 4;
37977dd7cddfSDavid du Colombier          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3798*593dc095SDavid du Colombier          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
37997dd7cddfSDavid du Colombier       }
38007dd7cddfSDavid du Colombier    }
38017dd7cddfSDavid du Colombier }
38027dd7cddfSDavid du Colombier #endif
38037dd7cddfSDavid du Colombier 
38047dd7cddfSDavid du Colombier #if defined(PNG_READ_DITHER_SUPPORTED)
3805*593dc095SDavid du Colombier void /* PRIVATE */
png_do_dither(png_row_infop row_info,png_bytep row,png_bytep palette_lookup,png_bytep dither_lookup)38067dd7cddfSDavid du Colombier png_do_dither(png_row_infop row_info, png_bytep row,
38077dd7cddfSDavid du Colombier     png_bytep palette_lookup, png_bytep dither_lookup)
38087dd7cddfSDavid du Colombier {
38097dd7cddfSDavid du Colombier    png_bytep sp, dp;
38107dd7cddfSDavid du Colombier    png_uint_32 i;
3811*593dc095SDavid du Colombier    png_uint_32 row_width=row_info->width;
38127dd7cddfSDavid du Colombier 
38137dd7cddfSDavid du Colombier    png_debug(1, "in png_do_dither\n");
38147dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
38157dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL)
38167dd7cddfSDavid du Colombier #endif
38177dd7cddfSDavid du Colombier    {
38187dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
38197dd7cddfSDavid du Colombier          palette_lookup && row_info->bit_depth == 8)
38207dd7cddfSDavid du Colombier       {
38217dd7cddfSDavid du Colombier          int r, g, b, p;
38227dd7cddfSDavid du Colombier          sp = row;
38237dd7cddfSDavid du Colombier          dp = row;
3824*593dc095SDavid du Colombier          for (i = 0; i < row_width; i++)
38257dd7cddfSDavid du Colombier          {
38267dd7cddfSDavid du Colombier             r = *sp++;
38277dd7cddfSDavid du Colombier             g = *sp++;
38287dd7cddfSDavid du Colombier             b = *sp++;
38297dd7cddfSDavid du Colombier 
38307dd7cddfSDavid du Colombier             /* this looks real messy, but the compiler will reduce
38317dd7cddfSDavid du Colombier                it down to a reasonable formula.  For example, with
38327dd7cddfSDavid du Colombier                5 bits per color, we get:
38337dd7cddfSDavid du Colombier                p = (((r >> 3) & 0x1f) << 10) |
38347dd7cddfSDavid du Colombier                   (((g >> 3) & 0x1f) << 5) |
38357dd7cddfSDavid du Colombier                   ((b >> 3) & 0x1f);
38367dd7cddfSDavid du Colombier                */
38377dd7cddfSDavid du Colombier             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
38387dd7cddfSDavid du Colombier                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
38397dd7cddfSDavid du Colombier                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
38407dd7cddfSDavid du Colombier                (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
38417dd7cddfSDavid du Colombier                ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
38427dd7cddfSDavid du Colombier                (PNG_DITHER_BLUE_BITS)) |
38437dd7cddfSDavid du Colombier                ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
38447dd7cddfSDavid du Colombier                ((1 << PNG_DITHER_BLUE_BITS) - 1));
38457dd7cddfSDavid du Colombier 
38467dd7cddfSDavid du Colombier             *dp++ = palette_lookup[p];
38477dd7cddfSDavid du Colombier          }
38487dd7cddfSDavid du Colombier          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
38497dd7cddfSDavid du Colombier          row_info->channels = 1;
38507dd7cddfSDavid du Colombier          row_info->pixel_depth = row_info->bit_depth;
3851*593dc095SDavid du Colombier          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
38527dd7cddfSDavid du Colombier       }
38537dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
38547dd7cddfSDavid du Colombier          palette_lookup != NULL && row_info->bit_depth == 8)
38557dd7cddfSDavid du Colombier       {
38567dd7cddfSDavid du Colombier          int r, g, b, p;
38577dd7cddfSDavid du Colombier          sp = row;
38587dd7cddfSDavid du Colombier          dp = row;
3859*593dc095SDavid du Colombier          for (i = 0; i < row_width; i++)
38607dd7cddfSDavid du Colombier          {
38617dd7cddfSDavid du Colombier             r = *sp++;
38627dd7cddfSDavid du Colombier             g = *sp++;
38637dd7cddfSDavid du Colombier             b = *sp++;
38647dd7cddfSDavid du Colombier             sp++;
38657dd7cddfSDavid du Colombier 
38667dd7cddfSDavid du Colombier             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
38677dd7cddfSDavid du Colombier                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
38687dd7cddfSDavid du Colombier                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
38697dd7cddfSDavid du Colombier                (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
38707dd7cddfSDavid du Colombier                ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
38717dd7cddfSDavid du Colombier                (PNG_DITHER_BLUE_BITS)) |
38727dd7cddfSDavid du Colombier                ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
38737dd7cddfSDavid du Colombier                ((1 << PNG_DITHER_BLUE_BITS) - 1));
38747dd7cddfSDavid du Colombier 
38757dd7cddfSDavid du Colombier             *dp++ = palette_lookup[p];
38767dd7cddfSDavid du Colombier          }
38777dd7cddfSDavid du Colombier          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
38787dd7cddfSDavid du Colombier          row_info->channels = 1;
38797dd7cddfSDavid du Colombier          row_info->pixel_depth = row_info->bit_depth;
3880*593dc095SDavid du Colombier          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
38817dd7cddfSDavid du Colombier       }
38827dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
38837dd7cddfSDavid du Colombier          dither_lookup && row_info->bit_depth == 8)
38847dd7cddfSDavid du Colombier       {
38857dd7cddfSDavid du Colombier          sp = row;
3886*593dc095SDavid du Colombier          for (i = 0; i < row_width; i++, sp++)
38877dd7cddfSDavid du Colombier          {
38887dd7cddfSDavid du Colombier             *sp = dither_lookup[*sp];
38897dd7cddfSDavid du Colombier          }
38907dd7cddfSDavid du Colombier       }
38917dd7cddfSDavid du Colombier    }
38927dd7cddfSDavid du Colombier }
38937dd7cddfSDavid du Colombier #endif
38947dd7cddfSDavid du Colombier 
3895*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
38967dd7cddfSDavid du Colombier #if defined(PNG_READ_GAMMA_SUPPORTED)
38977dd7cddfSDavid du Colombier static int png_gamma_shift[] =
38987dd7cddfSDavid du Colombier    {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
38997dd7cddfSDavid du Colombier 
39007dd7cddfSDavid du Colombier /* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
39017dd7cddfSDavid du Colombier  * tables, we don't make a full table if we are reducing to 8-bit in
39027dd7cddfSDavid du Colombier  * the future.  Note also how the gamma_16 tables are segmented so that
39037dd7cddfSDavid du Colombier  * we don't need to allocate > 64K chunks for a full 16-bit table.
39047dd7cddfSDavid du Colombier  */
3905*593dc095SDavid du Colombier void /* PRIVATE */
png_build_gamma_table(png_structp png_ptr)39067dd7cddfSDavid du Colombier png_build_gamma_table(png_structp png_ptr)
39077dd7cddfSDavid du Colombier {
39087dd7cddfSDavid du Colombier   png_debug(1, "in png_build_gamma_table\n");
3909*593dc095SDavid du Colombier   if(png_ptr->gamma != 0.0)
3910*593dc095SDavid du Colombier   {
39117dd7cddfSDavid du Colombier    if (png_ptr->bit_depth <= 8)
39127dd7cddfSDavid du Colombier    {
39137dd7cddfSDavid du Colombier       int i;
39147dd7cddfSDavid du Colombier       double g;
39157dd7cddfSDavid du Colombier 
3916*593dc095SDavid du Colombier       if (png_ptr->screen_gamma > .000001)
39177dd7cddfSDavid du Colombier          g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3918*593dc095SDavid du Colombier       else
3919*593dc095SDavid du Colombier          g = 1.0;
39207dd7cddfSDavid du Colombier 
39217dd7cddfSDavid du Colombier       png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
39227dd7cddfSDavid du Colombier          (png_uint_32)256);
39237dd7cddfSDavid du Colombier 
39247dd7cddfSDavid du Colombier       for (i = 0; i < 256; i++)
39257dd7cddfSDavid du Colombier       {
39267dd7cddfSDavid du Colombier          png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
39277dd7cddfSDavid du Colombier             g) * 255.0 + .5);
39287dd7cddfSDavid du Colombier       }
39297dd7cddfSDavid du Colombier 
3930*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3931*593dc095SDavid du Colombier     defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3932*593dc095SDavid du Colombier       if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
39337dd7cddfSDavid du Colombier       {
3934*593dc095SDavid du Colombier 
39357dd7cddfSDavid du Colombier          g = 1.0 / (png_ptr->gamma);
39367dd7cddfSDavid du Colombier 
39377dd7cddfSDavid du Colombier          png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
39387dd7cddfSDavid du Colombier             (png_uint_32)256);
39397dd7cddfSDavid du Colombier 
39407dd7cddfSDavid du Colombier          for (i = 0; i < 256; i++)
39417dd7cddfSDavid du Colombier          {
39427dd7cddfSDavid du Colombier             png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
39437dd7cddfSDavid du Colombier                g) * 255.0 + .5);
39447dd7cddfSDavid du Colombier          }
39457dd7cddfSDavid du Colombier 
39467dd7cddfSDavid du Colombier 
39477dd7cddfSDavid du Colombier          png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
39487dd7cddfSDavid du Colombier             (png_uint_32)256);
39497dd7cddfSDavid du Colombier 
3950*593dc095SDavid du Colombier          if(png_ptr->screen_gamma > 0.000001)
3951*593dc095SDavid du Colombier             g = 1.0 / png_ptr->screen_gamma;
3952*593dc095SDavid du Colombier          else
3953*593dc095SDavid du Colombier             g = png_ptr->gamma;   /* probably doing rgb_to_gray */
3954*593dc095SDavid du Colombier 
39557dd7cddfSDavid du Colombier          for (i = 0; i < 256; i++)
39567dd7cddfSDavid du Colombier          {
39577dd7cddfSDavid du Colombier             png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
39587dd7cddfSDavid du Colombier                g) * 255.0 + .5);
3959*593dc095SDavid du Colombier 
39607dd7cddfSDavid du Colombier          }
39617dd7cddfSDavid du Colombier       }
3962*593dc095SDavid du Colombier #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
39637dd7cddfSDavid du Colombier    }
39647dd7cddfSDavid du Colombier    else
39657dd7cddfSDavid du Colombier    {
39667dd7cddfSDavid du Colombier       double g;
39677dd7cddfSDavid du Colombier       int i, j, shift, num;
39687dd7cddfSDavid du Colombier       int sig_bit;
39697dd7cddfSDavid du Colombier       png_uint_32 ig;
39707dd7cddfSDavid du Colombier 
39717dd7cddfSDavid du Colombier       if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
39727dd7cddfSDavid du Colombier       {
39737dd7cddfSDavid du Colombier          sig_bit = (int)png_ptr->sig_bit.red;
39747dd7cddfSDavid du Colombier          if ((int)png_ptr->sig_bit.green > sig_bit)
39757dd7cddfSDavid du Colombier             sig_bit = png_ptr->sig_bit.green;
39767dd7cddfSDavid du Colombier          if ((int)png_ptr->sig_bit.blue > sig_bit)
39777dd7cddfSDavid du Colombier             sig_bit = png_ptr->sig_bit.blue;
39787dd7cddfSDavid du Colombier       }
39797dd7cddfSDavid du Colombier       else
39807dd7cddfSDavid du Colombier       {
39817dd7cddfSDavid du Colombier          sig_bit = (int)png_ptr->sig_bit.gray;
39827dd7cddfSDavid du Colombier       }
39837dd7cddfSDavid du Colombier 
39847dd7cddfSDavid du Colombier       if (sig_bit > 0)
39857dd7cddfSDavid du Colombier          shift = 16 - sig_bit;
39867dd7cddfSDavid du Colombier       else
39877dd7cddfSDavid du Colombier          shift = 0;
39887dd7cddfSDavid du Colombier 
39897dd7cddfSDavid du Colombier       if (png_ptr->transformations & PNG_16_TO_8)
39907dd7cddfSDavid du Colombier       {
39917dd7cddfSDavid du Colombier          if (shift < (16 - PNG_MAX_GAMMA_8))
39927dd7cddfSDavid du Colombier             shift = (16 - PNG_MAX_GAMMA_8);
39937dd7cddfSDavid du Colombier       }
39947dd7cddfSDavid du Colombier 
39957dd7cddfSDavid du Colombier       if (shift > 8)
39967dd7cddfSDavid du Colombier          shift = 8;
39977dd7cddfSDavid du Colombier       if (shift < 0)
39987dd7cddfSDavid du Colombier          shift = 0;
39997dd7cddfSDavid du Colombier 
40007dd7cddfSDavid du Colombier       png_ptr->gamma_shift = (png_byte)shift;
40017dd7cddfSDavid du Colombier 
40027dd7cddfSDavid du Colombier       num = (1 << (8 - shift));
40037dd7cddfSDavid du Colombier 
4004*593dc095SDavid du Colombier       if (png_ptr->screen_gamma > .000001)
40057dd7cddfSDavid du Colombier          g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4006*593dc095SDavid du Colombier       else
4007*593dc095SDavid du Colombier          g = 1.0;
40087dd7cddfSDavid du Colombier 
40097dd7cddfSDavid du Colombier       png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4010*593dc095SDavid du Colombier          (png_uint_32)(num * png_sizeof (png_uint_16p)));
40117dd7cddfSDavid du Colombier 
4012*593dc095SDavid du Colombier       if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
40137dd7cddfSDavid du Colombier       {
40147dd7cddfSDavid du Colombier          double fin, fout;
40157dd7cddfSDavid du Colombier          png_uint_32 last, max;
40167dd7cddfSDavid du Colombier 
40177dd7cddfSDavid du Colombier          for (i = 0; i < num; i++)
40187dd7cddfSDavid du Colombier          {
40197dd7cddfSDavid du Colombier             png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4020*593dc095SDavid du Colombier                (png_uint_32)(256 * png_sizeof (png_uint_16)));
40217dd7cddfSDavid du Colombier          }
40227dd7cddfSDavid du Colombier 
40237dd7cddfSDavid du Colombier          g = 1.0 / g;
40247dd7cddfSDavid du Colombier          last = 0;
40257dd7cddfSDavid du Colombier          for (i = 0; i < 256; i++)
40267dd7cddfSDavid du Colombier          {
40277dd7cddfSDavid du Colombier             fout = ((double)i + 0.5) / 256.0;
40287dd7cddfSDavid du Colombier             fin = pow(fout, g);
40297dd7cddfSDavid du Colombier             max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
40307dd7cddfSDavid du Colombier             while (last <= max)
40317dd7cddfSDavid du Colombier             {
40327dd7cddfSDavid du Colombier                png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
40337dd7cddfSDavid du Colombier                   [(int)(last >> (8 - shift))] = (png_uint_16)(
40347dd7cddfSDavid du Colombier                   (png_uint_16)i | ((png_uint_16)i << 8));
40357dd7cddfSDavid du Colombier                last++;
40367dd7cddfSDavid du Colombier             }
40377dd7cddfSDavid du Colombier          }
40387dd7cddfSDavid du Colombier          while (last < ((png_uint_32)num << 8))
40397dd7cddfSDavid du Colombier          {
40407dd7cddfSDavid du Colombier             png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
40417dd7cddfSDavid du Colombier                [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
40427dd7cddfSDavid du Colombier             last++;
40437dd7cddfSDavid du Colombier          }
40447dd7cddfSDavid du Colombier       }
40457dd7cddfSDavid du Colombier       else
40467dd7cddfSDavid du Colombier       {
40477dd7cddfSDavid du Colombier          for (i = 0; i < num; i++)
40487dd7cddfSDavid du Colombier          {
40497dd7cddfSDavid du Colombier             png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4050*593dc095SDavid du Colombier                (png_uint_32)(256 * png_sizeof (png_uint_16)));
40517dd7cddfSDavid du Colombier 
40527dd7cddfSDavid du Colombier             ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
40537dd7cddfSDavid du Colombier             for (j = 0; j < 256; j++)
40547dd7cddfSDavid du Colombier             {
40557dd7cddfSDavid du Colombier                png_ptr->gamma_16_table[i][j] =
40567dd7cddfSDavid du Colombier                   (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
40577dd7cddfSDavid du Colombier                      65535.0, g) * 65535.0 + .5);
40587dd7cddfSDavid du Colombier             }
40597dd7cddfSDavid du Colombier          }
40607dd7cddfSDavid du Colombier       }
40617dd7cddfSDavid du Colombier 
4062*593dc095SDavid du Colombier #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4063*593dc095SDavid du Colombier     defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4064*593dc095SDavid du Colombier       if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
40657dd7cddfSDavid du Colombier       {
4066*593dc095SDavid du Colombier 
40677dd7cddfSDavid du Colombier          g = 1.0 / (png_ptr->gamma);
40687dd7cddfSDavid du Colombier 
40697dd7cddfSDavid du Colombier          png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4070*593dc095SDavid du Colombier             (png_uint_32)(num * png_sizeof (png_uint_16p )));
40717dd7cddfSDavid du Colombier 
40727dd7cddfSDavid du Colombier          for (i = 0; i < num; i++)
40737dd7cddfSDavid du Colombier          {
40747dd7cddfSDavid du Colombier             png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4075*593dc095SDavid du Colombier                (png_uint_32)(256 * png_sizeof (png_uint_16)));
40767dd7cddfSDavid du Colombier 
40777dd7cddfSDavid du Colombier             ig = (((png_uint_32)i *
40787dd7cddfSDavid du Colombier                (png_uint_32)png_gamma_shift[shift]) >> 4);
40797dd7cddfSDavid du Colombier             for (j = 0; j < 256; j++)
40807dd7cddfSDavid du Colombier             {
40817dd7cddfSDavid du Colombier                png_ptr->gamma_16_to_1[i][j] =
40827dd7cddfSDavid du Colombier                   (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
40837dd7cddfSDavid du Colombier                      65535.0, g) * 65535.0 + .5);
40847dd7cddfSDavid du Colombier             }
40857dd7cddfSDavid du Colombier          }
4086*593dc095SDavid du Colombier 
4087*593dc095SDavid du Colombier          if(png_ptr->screen_gamma > 0.000001)
4088*593dc095SDavid du Colombier             g = 1.0 / png_ptr->screen_gamma;
4089*593dc095SDavid du Colombier          else
4090*593dc095SDavid du Colombier             g = png_ptr->gamma;   /* probably doing rgb_to_gray */
40917dd7cddfSDavid du Colombier 
40927dd7cddfSDavid du Colombier          png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4093*593dc095SDavid du Colombier             (png_uint_32)(num * png_sizeof (png_uint_16p)));
40947dd7cddfSDavid du Colombier 
40957dd7cddfSDavid du Colombier          for (i = 0; i < num; i++)
40967dd7cddfSDavid du Colombier          {
40977dd7cddfSDavid du Colombier             png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4098*593dc095SDavid du Colombier                (png_uint_32)(256 * png_sizeof (png_uint_16)));
40997dd7cddfSDavid du Colombier 
41007dd7cddfSDavid du Colombier             ig = (((png_uint_32)i *
41017dd7cddfSDavid du Colombier                (png_uint_32)png_gamma_shift[shift]) >> 4);
41027dd7cddfSDavid du Colombier             for (j = 0; j < 256; j++)
41037dd7cddfSDavid du Colombier             {
41047dd7cddfSDavid du Colombier                png_ptr->gamma_16_from_1[i][j] =
41057dd7cddfSDavid du Colombier                   (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
41067dd7cddfSDavid du Colombier                      65535.0, g) * 65535.0 + .5);
41077dd7cddfSDavid du Colombier             }
41087dd7cddfSDavid du Colombier          }
41097dd7cddfSDavid du Colombier       }
4110*593dc095SDavid du Colombier #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4111*593dc095SDavid du Colombier    }
41127dd7cddfSDavid du Colombier  }
41137dd7cddfSDavid du Colombier }
41147dd7cddfSDavid du Colombier #endif
4115*593dc095SDavid du Colombier /* To do: install integer version of png_build_gamma_table here */
4116*593dc095SDavid du Colombier #endif
41177dd7cddfSDavid du Colombier 
4118*593dc095SDavid du Colombier #if defined(PNG_MNG_FEATURES_SUPPORTED)
4119*593dc095SDavid du Colombier /* undoes intrapixel differencing  */
4120*593dc095SDavid du Colombier void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info,png_bytep row)4121*593dc095SDavid du Colombier png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4122*593dc095SDavid du Colombier {
4123*593dc095SDavid du Colombier    png_debug(1, "in png_do_read_intrapixel\n");
4124*593dc095SDavid du Colombier    if (
4125*593dc095SDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
4126*593dc095SDavid du Colombier        row != NULL && row_info != NULL &&
4127*593dc095SDavid du Colombier #endif
4128*593dc095SDavid du Colombier        (row_info->color_type & PNG_COLOR_MASK_COLOR))
4129*593dc095SDavid du Colombier    {
4130*593dc095SDavid du Colombier       int bytes_per_pixel;
4131*593dc095SDavid du Colombier       png_uint_32 row_width = row_info->width;
4132*593dc095SDavid du Colombier       if (row_info->bit_depth == 8)
4133*593dc095SDavid du Colombier       {
4134*593dc095SDavid du Colombier          png_bytep rp;
4135*593dc095SDavid du Colombier          png_uint_32 i;
4136*593dc095SDavid du Colombier 
4137*593dc095SDavid du Colombier          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4138*593dc095SDavid du Colombier             bytes_per_pixel = 3;
4139*593dc095SDavid du Colombier          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4140*593dc095SDavid du Colombier             bytes_per_pixel = 4;
4141*593dc095SDavid du Colombier          else
4142*593dc095SDavid du Colombier             return;
4143*593dc095SDavid du Colombier 
4144*593dc095SDavid du Colombier          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4145*593dc095SDavid du Colombier          {
4146*593dc095SDavid du Colombier             *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4147*593dc095SDavid du Colombier             *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4148*593dc095SDavid du Colombier          }
4149*593dc095SDavid du Colombier       }
4150*593dc095SDavid du Colombier       else if (row_info->bit_depth == 16)
4151*593dc095SDavid du Colombier       {
4152*593dc095SDavid du Colombier          png_bytep rp;
4153*593dc095SDavid du Colombier          png_uint_32 i;
4154*593dc095SDavid du Colombier 
4155*593dc095SDavid du Colombier          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4156*593dc095SDavid du Colombier             bytes_per_pixel = 6;
4157*593dc095SDavid du Colombier          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4158*593dc095SDavid du Colombier             bytes_per_pixel = 8;
4159*593dc095SDavid du Colombier          else
4160*593dc095SDavid du Colombier             return;
4161*593dc095SDavid du Colombier 
4162*593dc095SDavid du Colombier          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4163*593dc095SDavid du Colombier          {
4164*593dc095SDavid du Colombier             png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
4165*593dc095SDavid du Colombier             png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
4166*593dc095SDavid du Colombier             png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
4167*593dc095SDavid du Colombier             png_uint_32 red  = (png_uint_32)((s0+s1+65536L) & 0xffffL);
4168*593dc095SDavid du Colombier             png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
4169*593dc095SDavid du Colombier             *(rp  ) = (png_byte)((red >> 8) & 0xff);
4170*593dc095SDavid du Colombier             *(rp+1) = (png_byte)(red & 0xff);
4171*593dc095SDavid du Colombier             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4172*593dc095SDavid du Colombier             *(rp+5) = (png_byte)(blue & 0xff);
4173*593dc095SDavid du Colombier          }
4174*593dc095SDavid du Colombier       }
4175*593dc095SDavid du Colombier    }
4176*593dc095SDavid du Colombier }
4177*593dc095SDavid du Colombier #endif /* PNG_MNG_FEATURES_SUPPORTED */
4178