1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* pngrtran.c - transforms the data in a row for PNG readers
3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
4b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Last changed in libpng 1.6.10 [March 6, 2014]
5b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Copyright (c) 1998-2014 Glenn Randers-Pehrson
6893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
9a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * This code is released under the libpng license.
10a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * For conditions of distribution and use, see the disclaimer
11a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * and license in png.h
12a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott *
13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * This file contains functions optionally called by an application
14893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * in order to tell libpng how to handle data when reading a PNG.
15893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * Transformations that are used in both reading and writing are
16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * in pngtrans.c.
17893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
18893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
19b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include "pngpriv.h"
20b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
215f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_SUPPORTED
22893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
23893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Set the action on getting a CRC error for an ancillary or critical chunk. */
24893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
25b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
26893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
274215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_crc_action");
28b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
29a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL)
30a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   /* Tell libpng how we react to CRC errors in critical chunks */
33893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   switch (crit_action)
34893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
35a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
36893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
37a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
38a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_WARN_USE:                               /* Warn/use data */
39893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
40893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
41893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
42a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
43a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
44893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
45893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
46893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           PNG_FLAG_CRC_CRITICAL_IGNORE;
47893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
48a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
49a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
504215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_warning(png_ptr,
51b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            "Can't discard critical data on CRC error");
52a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
53a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
54893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      case PNG_CRC_DEFAULT:
55893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      default:
56893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
57893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
58893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
59893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   /* Tell libpng how we react to CRC errors in ancillary chunks */
61893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   switch (ancil_action)
62893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
63a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
64893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
65a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
66a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_WARN_USE:                              /* Warn/use data */
67893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
68893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
69893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
70a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
71a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
72893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
73893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
74893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
75893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
76a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
77a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
78893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
79893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
80893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
81a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
82a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
83a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
84893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      case PNG_CRC_DEFAULT:
85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      default:
86893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
87893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
88893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
89893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
90893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
91b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_TRANSFORMS_SUPPORTED
92b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Is it OK to set a transformation now?  Only if png_start_read_image or
93b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_read_update_info have not been called.  It is not necessary for the IHDR
94b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to have been read in all cases, the parameter allows for this check too.
95b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
96b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int
97b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_rtran_ok(png_structrp png_ptr, int need_IHDR)
98b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
99b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr != NULL)
100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->flags & PNG_FLAG_ROW_INIT)
102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_app_error(png_ptr,
103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            "invalid after png_start_read_image or png_read_update_info");
104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_app_error(png_ptr, "invalid before the PNG header has been read");
107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Turn on failure to initialize correctly for all transforms. */
111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         return 1; /* Ok */
114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return 0; /* no png_error possible! */
118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_BACKGROUND_SUPPORTED
122a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Handle alpha and tRNS via a background color */
123b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
124b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_background_fixed(png_structrp png_ptr,
125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_color_16p background_color, int background_gamma_code,
126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int need_expand, png_fixed_point background_gamma)
127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_background_fixed");
129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0) || background_color == NULL)
131a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_warning(png_ptr, "Application must supply a known background gamma");
136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      return;
137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->background = *background_color;
144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->background_gamma = background_gamma;
145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (need_expand)
147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else
149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
153b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
154b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_background(png_structrp png_ptr,
155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_color_16p background_color, int background_gamma_code,
156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int need_expand, double background_gamma)
157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif  /* FLOATING_POINT */
162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_BACKGROUND */
163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * one that pngrtran does first (scale) happens.  This is necessary to allow the
166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
169b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
170b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_scale_16(png_structrp png_ptr)
171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_scale_16");
173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_SCALE_16_TO_8;
178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Chop 16-bit depth files to 8-bit depth */
183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
184b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_strip_16(png_structrp png_ptr)
185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1864215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_strip_16");
1875f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
189a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_16_TO_8;
192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1955f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
197b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_strip_alpha(png_structrp png_ptr)
198893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1994215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_strip_alpha");
2005f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_STRIP_ALPHA;
205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
209b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_fixed_point
210b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktranslate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int is_screen)
212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Check for flag values.  The main reason for having the old Mac value as a
214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * flag is that it is pretty near impossible to work out what the correct
215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * value is from Apple documentation - a working Mac system is needed to
216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * discover the value!
217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma == PNG_DEFAULT_sRGB ||
219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* If there is no sRGB support this just sets the gamma to the standard
222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * sRGB value.  (This is a side effect of using this function!)
223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_sRGB_SUPPORTED
225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     else
227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_UNUSED(png_ptr)
228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (is_screen)
230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_sRGB;
231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_sRGB_INVERSE;
233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (output_gamma == PNG_GAMMA_MAC_18 ||
236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (is_screen)
239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_MAC_OLD;
240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_MAC_INVERSE;
242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return output_gamma;
245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
248b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_fixed_point
249b50c217251b086440efcdb273c22f86a06c80cbaChris Craikconvert_gamma_value(png_structrp png_ptr, double output_gamma)
250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following silently ignores cases where fixed point (times 100,000)
252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gamma values are passed to the floating point API.  This is safe and it
253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * means the fixed point constants work just fine with the floating point
254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * API.  The alternative would just lead to undetected errors and spurious
255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * bug reports.  Negative values fail inside the _fixed API unless they
256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * correspond to the flag values.
257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma > 0 && output_gamma < 128)
259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma *= PNG_FP_1;
260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* This preserves -1 and -2 exactly: */
262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   output_gamma = floor(output_gamma + .5);
263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_fixed_error(png_ptr, "gamma value");
266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return (png_fixed_point)output_gamma;
268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_ALPHA_MODE || READ_GAMMA */
271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
273b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
274b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_fixed_point output_gamma)
276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int compose = 0;
278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_fixed_point file_gamma;
279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_alpha_mode");
281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
283a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Validate the value to ensure it is in a reasonable range. The value
288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * is expected to be 1 or greater, but this range test allows for some
289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * viewing correction values.  The intent is to weed out users of this API
290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * who use the inverse of the gamma value accidentally!  Since some of these
291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * values are reasonable this may have to be changed.
292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma < 70000 || output_gamma > 300000)
294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "output gamma out of expected range");
295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The default file gamma is the inverse of the output gamma; the output
297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gamma may be changed below so get the file value first:
298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   file_gamma = png_reciprocal(output_gamma);
300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* There are really 8 possibilities here, composed of any combination
302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * of:
303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *    premultiply the color channels
305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *    do not encode non-opaque pixels
306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *    encode the alpha as well as the color channels
307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * The differences disappear if the input/output ('screen') gamma is 1.0,
309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * because then the encoding is a no-op and there is only the choice of
310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * premultiplying the color channels or not.
311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_alpha_mode and png_set_background interact because both use
313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_compose to do the work.  Calling both is only useful when
314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   switch (mode)
318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_PNG:        /* default: png standard */
320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* No compose, but it may be set by png_set_background! */
321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         compose = 1;
327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* The output is linear: */
330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_FP_1;
331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         compose = 1;
335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* output_gamma records the encoding of opaque pixels! */
338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         compose = 1;
342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_ENCODE_ALPHA;
343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      default:
347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "invalid alpha mode");
348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Only set the default gamma if the file gamma has not been set (this has
351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the side effect that the gamma in a second call to png_set_alpha_mode will
352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * be ignored.)
353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->colorspace.gamma == 0)
355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->colorspace.gamma = file_gamma;
357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* But always set the output gamma: */
361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->screen_gamma = output_gamma;
362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Finally, if pre-multiplying, set the background fields to achieve the
364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * desired result.
365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (compose)
367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* And obtain alpha pre-multiplication by composing on black: */
369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->transformations & PNG_COMPOSE)
375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr,
376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            "conflicting calls to set alpha mode and background");
377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations |= PNG_COMPOSE;
379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
383b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
384b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma));
388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_QUANTIZE_SUPPORTED
393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Dither file to 8-bit.  Supply a palette, the current number
394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * of elements in the palette, the maximum number of elements
395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * allowed, and a histogram if possible.  If the current number
396893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * of colors is greater then the maximum number, the palette will be
397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * modified to fit in the maximum number.  "full_quantize" indicates
398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * whether we need a quantizing cube set up for RGB images, or if we
399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * simply are reducing the number of colors in a paletted image.
400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projecttypedef struct png_dsort_struct
403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   struct png_dsort_struct * next;
405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_byte left;
406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_byte right;
407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} png_dsort;
408b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef png_dsort *   png_dsortp;
409b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef png_dsort * * png_dsortpp;
410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
412b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_quantize(png_structrp png_ptr, png_colorp palette,
413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int num_palette, int maximum_colors, png_const_uint_16p histogram,
414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int full_quantize)
415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_quantize");
4175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
419a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_QUANTIZE;
422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!full_quantize)
424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int i;
426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (png_uint_32)(num_palette * (sizeof (png_byte))));
429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      for (i = 0; i < num_palette; i++)
430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->quantize_index[i] = (png_byte)i;
431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (num_palette > maximum_colors)
434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (histogram != NULL)
436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This is easy enough, just throw out the least used colors.
438a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * Perhaps not the best solution, but good enough.
439a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int i;
442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
443a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initialize an array to sort colors */
444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             (png_uint_32)(num_palette * (sizeof (png_byte))));
446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Initialize the quantize_sort array */
448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0; i < num_palette; i++)
449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->quantize_sort[i] = (png_byte)i;
450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* Find the least used palette entries by starting a
452a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * bubble sort, and running it until we have sorted
453a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * out enough colors.  Note that we don't care about
454a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * sorting all the colors, just finding which are
455a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * least used.
456a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = num_palette - 1; i >= maximum_colors; i--)
459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
460a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            int done; /* To stop early if the list is pre-sorted */
461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int j;
462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
463893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            done = 1;
464893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (j = 0; j < i; j++)
465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (histogram[png_ptr->quantize_sort[j]]
467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   < histogram[png_ptr->quantize_sort[j + 1]])
468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_byte t;
470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  t = png_ptr->quantize_sort[j];
472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_sort[j + 1] = t;
474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  done = 0;
475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (done)
479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
482a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Swap the palette around, and set up a table, if necessary */
483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (full_quantize)
484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int j = num_palette;
486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
487a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            /* Put all the useful colors within the max, but don't
488a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             * move the others.
489a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             */
490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < maximum_colors; i++)
491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  do
495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     j--;
496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i] = palette[j];
499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int j = num_palette;
505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
506a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            /* Move all the used colors inside the max limit, and
507a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             * develop a translation table.
508a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             */
509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < maximum_colors; i++)
510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
511a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott               /* Only move the colors we need to */
512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
513893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_color tmp_color;
515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  do
517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     j--;
518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  tmp_color = palette[j];
521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[j] = palette[i];
522893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i] = tmp_color;
523a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                  /* Indicate where the color went */
524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_index[j] = (png_byte)i;
525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_index[i] = (png_byte)j;
526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
529a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            /* Find closest color for those colors we are not using */
530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < num_palette; i++)
531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int min_d, k, min_k, d_index;
535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
536a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                  /* Find the closest color to one we threw out */
537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  d_index = png_ptr->quantize_index[i];
538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (k = 1, min_k = 0; k < maximum_colors; k++)
540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     int d;
542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (d < min_d)
546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        min_d = d;
548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        min_k = k;
549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
551a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                  /* Point to closest color */
552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_index[i] = (png_byte)min_k;
553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_free(png_ptr, png_ptr->quantize_sort);
557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->quantize_sort = NULL;
558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
561893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This is much harder to do simply (and quickly).  Perhaps
562a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * we need to go through a median cut routine, but those
563a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * don't always behave themselves with only a few colors
564a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * as input.  So we will just find the closest two colors,
565a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * and throw out one of them (chosen somewhat randomly).
566a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * [We don't understand this at all, so if someone wants to
567a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          *  work on improving it, be our guest - AED, GRP]
568a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
569893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int i;
570893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int max_d;
571893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int num_new_palette;
572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_dsortp t;
573893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_dsortpp hash;
574893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
5754215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         t = NULL;
576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
577a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initialize palette index arrays */
578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             (png_uint_32)(num_palette * (sizeof (png_byte))));
580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             (png_uint_32)(num_palette * (sizeof (png_byte))));
582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
583a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initialize the sort array */
584893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0; i < num_palette; i++)
585893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
586893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_ptr->index_to_palette[i] = (png_byte)i;
587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_ptr->palette_to_index[i] = (png_byte)i;
588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
589893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
5905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             (sizeof (png_dsortp))));
592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         num_new_palette = num_palette;
594893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
595a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initial wild guess at how far apart the farthest pixel
596a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * pair we will be eliminating will be.  Larger
597a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * numbers mean more areas will be allocated, Smaller
598a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * numbers run the risk of not saving enough data, and
599a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * having to do this all over again.
600a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          *
601a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * I have not done extensive checking on this number.
602a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         max_d = 96;
604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         while (num_new_palette > maximum_colors)
606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < num_new_palette - 1; i++)
608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int j;
610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (j = i + 1; j < num_new_palette; j++)
612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d;
614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  d = PNG_COLOR_DIST(palette[i], palette[j]);
616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (d <= max_d)
618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t = (png_dsortp)png_malloc_warn(png_ptr,
621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         (png_uint_32)(sizeof (png_dsort)));
622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
623893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (t == NULL)
624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                         break;
625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
626893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t->next = hash[d];
627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t->left = (png_byte)i;
628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t->right = (png_byte)j;
629893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     hash[d] = t;
630893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
631893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
632893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (t == NULL)
633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (t != NULL)
637893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i <= max_d; i++)
638893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (hash[i] != NULL)
640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_dsortp p;
642893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
643893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (p = hash[i]; p; p = p->next)
644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
645893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if ((int)png_ptr->index_to_palette[p->left]
646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         < num_new_palette &&
647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         (int)png_ptr->index_to_palette[p->right]
648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         < num_new_palette)
649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        int j, next_j;
651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
652893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if (num_new_palette & 0x01)
653893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
654893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           j = p->left;
655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           next_j = p->right;
656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
657893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           j = p->right;
660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           next_j = p->left;
661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        num_new_palette--;
664893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        palette[png_ptr->index_to_palette[j]]
665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            = palette[num_new_palette];
666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!full_quantize)
667893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           int k;
669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           for (k = 0; k < num_palette; k++)
671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           {
672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                              if (png_ptr->quantize_index[k] ==
673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                  png_ptr->index_to_palette[j])
674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                 png_ptr->quantize_index[k] =
675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                     png_ptr->index_to_palette[next_j];
676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                              if ((int)png_ptr->quantize_index[k] ==
678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                  num_new_palette)
679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                 png_ptr->quantize_index[k] =
680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                     png_ptr->index_to_palette[j];
681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           }
682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_ptr->index_to_palette[png_ptr->palette_to_index
685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            [num_new_palette]] = png_ptr->index_to_palette[j];
686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            = png_ptr->palette_to_index[num_new_palette];
689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
6905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                        png_ptr->index_to_palette[j] =
6915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                            (png_byte)num_new_palette;
692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
6935f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                        png_ptr->palette_to_index[num_new_palette] =
6945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                            (png_byte)j;
695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
696893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (num_new_palette <= maximum_colors)
697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        break;
698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (num_new_palette <= maximum_colors)
700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 769; i++)
705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (hash[i] != NULL)
707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_dsortp p = hash[i];
709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  while (p)
710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t = p->next;
712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_free(png_ptr, p);
713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     p = t;
714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               hash[i] = 0;
717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            max_d += 96;
719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_free(png_ptr, hash);
721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_free(png_ptr, png_ptr->palette_to_index);
722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_free(png_ptr, png_ptr->index_to_palette);
7234215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->palette_to_index = NULL;
7244215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->index_to_palette = NULL;
725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      num_palette = maximum_colors;
727893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
728893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->palette == NULL)
729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->palette = palette;
731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->num_palette = (png_uint_16)num_palette;
733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (full_quantize)
735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int i;
737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_bytep distance;
738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          PNG_QUANTIZE_BLUE_BITS;
740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_size_t num_entries = ((png_size_t)1 << total_bits);
7445f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (png_uint_32)(num_entries * (sizeof (png_byte))));
747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
748893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (sizeof (png_byte))));
750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      for (i = 0; i < num_palette; i++)
754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int ir, ig, ib;
756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (ir = 0; ir < num_red; ir++)
761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            /* int dr = abs(ir - r); */
763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int dr = ((ir > r) ? ir - r : r - ir);
764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                PNG_QUANTIZE_GREEN_BITS));
766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (ig = 0; ig < num_green; ig++)
768893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
769893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               /* int dg = abs(ig - g); */
770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int dg = ((ig > g) ? ig - g : g - ig);
771893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int dt = dr + dg;
772893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int dm = ((dr > dg) ? dr : dg);
773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (ib = 0; ib < num_blue; ib++)
776893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d_index = index_g | ib;
778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  /* int db = abs(ib - b); */
779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int db = ((ib > b) ? ib - b : b - ib);
780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int dmax = ((dm > db) ? dm : db);
781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d = dmax + dt + db;
782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (d < (int)distance[d_index])
784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     distance[d_index] = (png_byte)d;
786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_ptr->palette_lookup[d_index] = (png_byte)i;
787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
791893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_free(png_ptr, distance);
794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_QUANTIZE_SUPPORTED */
797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
799b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
800b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_fixed_point file_gamma)
802893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_gamma_fixed");
8045f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
806a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
8075f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * premultiplied alpha support; this actually hides an undocumented feature
814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * of the previous implementation which allowed gamma processing to be
815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * disabled in background handling.  There is no evidence (so far) that this
816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * was being used; however, png_set_background itself accepted and must still
817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * accept '0' for the gamma value it takes, because it isn't always used.
818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * Since this is an API change (albeit a very minor one that removes an
820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * undocumented API feature) the following checks were only enabled in
821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * libpng-1.6.0.
822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (file_gamma <= 0)
824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "invalid file gamma in png_set_gamma");
825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (scrn_gamma <= 0)
827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Set the gamma values unconditionally - this overrides the value in the PNG
830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * different, easier, way to default the file gamma.
832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->colorspace.gamma = file_gamma;
834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->screen_gamma = scrn_gamma;
836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
839b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
840b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      convert_gamma_value(png_ptr, file_gamma));
844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif /* FLOATING_POINT_SUPPORTED */
846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_GAMMA */
847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
8485f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
849893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expand paletted images to RGB, expand grayscale images of
850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * to alpha channels.
852893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
854b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_expand(png_structrp png_ptr)
855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
8564215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_expand");
8575f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
859a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
8605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
861893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
864893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* GRR 19990627:  the following three functions currently are identical
865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  to png_set_expand().  However, it is entirely reasonable that someone
866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  might wish to expand an indexed image to RGB but *not* expand a single,
867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  fully transparent palette entry to a full alpha channel--perhaps instead
868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  the transparent color with a particular RGB value, or drop tRNS entirely.
870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  IOW, a future version of the library may make the transformations flag
871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  a bit more fine-grained, with separate bits for each of these three
872893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  functions.
873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
874893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  More to the point, these functions make it obvious what libpng will be
875893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  doing, whereas "expand" can (and does) mean any number of things.
876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
8775f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
8785f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott *  to expand only the sample depth but not to expand the tRNS to alpha
8795f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
880893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
881893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expand paletted images to RGB. */
883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
884b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_palette_to_rgb(png_structrp png_ptr)
885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
8864215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_palette_to_rgb");
8875f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
889a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
8905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
892893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
893893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expand grayscale images of less than 8-bit depth to 8 bits. */
895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
896b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
897893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
8984215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
8995f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
901a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
9025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
903893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_EXPAND;
904893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Expand tRNS chunks to alpha channels. */
907893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
908b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_tRNS_to_alpha(png_structrp png_ptr)
909893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_tRNS_to_alpha");
9115f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
913a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
9145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
915893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
916893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_EXPAND_16_SUPPORTED
920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it may not work correctly.)
922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
923893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
924b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_expand_16(png_structrp png_ptr)
925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_expand_16");
9275f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
932893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
934893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
9355f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
936893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
937b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_gray_to_rgb(png_structrp png_ptr)
938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
9394215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_gray_to_rgb");
9405f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 0))
942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Because rgb must be 8 bits or more: */
945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_expand_gray_1_2_4_to_8(png_ptr);
946893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_GRAY_TO_RGB;
947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
949893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
9505f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
951b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
952b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_fixed_point red, png_fixed_point green)
954893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
9554215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_rgb_to_gray");
9565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Need the IHDR here because of the check on color_type below. */
958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* TODO: fix this */
959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_rtran_ok(png_ptr, 1))
960a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
9615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   switch(error_action)
963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ERROR_ACTION_NONE:
965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_RGB_TO_GRAY;
966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
967a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ERROR_ACTION_WARN:
969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ERROR_ACTION_ERROR:
973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
975a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      default:
977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "invalid error action to rgb_to_gray");
978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
981893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
9825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
983893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->transformations |= PNG_EXPAND;
984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else
985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Make this an error in 1.6 because otherwise the application may assume
987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * that it just worked and get a memory overwrite.
988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr,
990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
997893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_16 red_int, green_int;
999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* NOTE: this calculation does not round, but this behavior is retained
1001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * for consistency, the inaccuracy is very small.  The code here always
1002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * overwrites the coefficients, regardless of whether they have been
1003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * defaulted or set already.
1004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
1006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
1007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->rgb_to_gray_red_coeff   = red_int;
1009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->rgb_to_gray_green_coeff = green_int;
1010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->rgb_to_gray_coefficients_set = 1;
1011893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1013893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
1014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (red >= 0 && green >= 0)
1016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_app_warning(png_ptr,
1017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               "ignoring out of range rgb_to_gray coefficients");
1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Use the defaults, from the cHRM chunk if set, else the historical
1020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
1021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * png_do_rgb_to_gray for more discussion of the values.  In this case
1022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * the coefficients are not marked as 'set' and are not overwritten if
1023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * something has already provided a default.
1024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
1026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->rgb_to_gray_green_coeff == 0)
1027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->rgb_to_gray_red_coeff   = 6968;
1029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->rgb_to_gray_green_coeff = 23434;
1030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
1032893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1033893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FLOATING_POINT_SUPPORTED
1037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Convert a RGB image to a grayscale of the same width.  This allows us,
1038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
1039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
1040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1041b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
1042b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
1043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   double green)
1044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_rgb_to_gray_fixed(png_ptr, error_action,
1046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_fixed(png_ptr, red, "rgb to gray red coefficient"),
1047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* FLOATING POINT */
1050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* RGB_TO_GRAY */
1052893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1053893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1054a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1055893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
1056b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    read_user_transform_fn)
1058893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
10594215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_read_user_transform_fn");
10605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
10615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_USER_TRANSFORM;
1063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->read_user_transform_fn = read_user_transform_fn;
1064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
1070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* In the case of gamma transformations only do transformations on images where
1071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
1072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * slows things down slightly, and also needlessly introduces small errors.
1073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
1074b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int /* PRIVATE */
1075b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
1076893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
1078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * correction as a difference of the overall transform from 1.0
1079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * We want to compare the threshold with s*f - 1, if we get
1081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * overflow here it is because of wacky gamma values so we
1082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * turn on processing anyway.
1083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_fixed_point gtest;
1085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
1086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       png_gamma_significant(gtest);
1087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Initialize everything needed for the read.  This includes modifying
1091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the palette.
1092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
1093893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*For the moment 'png_init_palette_transformations' and
1095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'png_init_rgb_transformations' only do some flag canceling optimizations.
1096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The intent is that these two routines should have palette or rgb operations
1097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * extracted from 'png_init_read_transformations'.
1098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
1099b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void /* PRIVATE */
1100b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_palette_transformations(png_structrp png_ptr)
1101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Called to handle the (input) palette case.  In png_do_read_transformations
1103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the first step is to expand the palette if requested, so this code must
1104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * take care to only make changes that are invariant with respect to the
1105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * palette expansion, or only do them if there is no expansion.
1106a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott    *
1107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * STRIP_ALPHA has already been handled in the caller (by setting num_trans
1108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * to 0.)
1109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    */
1110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_alpha = 0;
1111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_transparency = 0;
1112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->num_trans > 0)
1114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int i;
1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Ignore if all the entries are opaque (unlikely!) */
1118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      for (i=0; i<png_ptr->num_trans; ++i)
1119b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
1120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->trans_alpha[i] == 255)
1121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            continue;
1122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else if (png_ptr->trans_alpha[i] == 0)
1123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            input_has_transparency = 1;
1124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
1125b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1126b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            input_has_transparency = 1;
1127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            input_has_alpha = 1;
1128b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
1129b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1130b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
1131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* If no alpha we can optimize. */
1134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!input_has_alpha)
1135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Any alpha means background and associative alpha processing is
1137b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * and ENCODE_ALPHA are irrelevant.
1139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (!input_has_transparency)
1144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* png_set_background handling - deals with the complexity of whether the
1149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background color is in the file format or the screen format in the case
1150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * where an 'expand' will happen.
1151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following code cannot be entered in the alpha pre-multiplication case
1154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * because PNG_BACKGROUND_EXPAND is cancelled below.
1155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project       (png_ptr->transformations & PNG_EXPAND))
1158893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.red   =
1161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->palette[png_ptr->background.index].red;
1162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.green =
1163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->palette[png_ptr->background.index].green;
1164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.blue  =
1165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->palette[png_ptr->background.index].blue;
1166a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik        if (png_ptr->transformations & PNG_INVERT_ALPHA)
1169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik        {
1170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik           if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
1171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik           {
1172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik              /* Invert the alpha channel (in tRNS) unless the pixels are
1173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               * going to be expanded, in which case leave it for later
1174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               */
1175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik              int i, istop = png_ptr->num_trans;
1176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik              for (i=0; i<istop; i++)
1178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                 png_ptr->trans_alpha[i] = (png_byte)(255 -
1179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                    png_ptr->trans_alpha[i]);
1180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik           }
1181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik        }
1182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
1183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
1184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   } /* background expand and (therefore) no alpha association. */
1185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
1186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1188b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void /* PRIVATE */
1189b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_rgb_transformations(png_structrp png_ptr)
1190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Added to libpng-1.5.4: check the color type to determine whether there
1192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * is any alpha or transparency in the image and simply cancel the
1193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background and alpha mode stuff if there isn't.
1194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
1196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_transparency = png_ptr->num_trans > 0;
1197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* If no alpha we can optimize. */
1199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!input_has_alpha)
1200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Any alpha means background and associative alpha processing is
1202b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * and ENCODE_ALPHA are irrelevant.
1204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
1209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (!input_has_transparency)
1211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* png_set_background handling - deals with the complexity of whether the
1216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background color is in the file format or the screen format in the case
1217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * where an 'expand' will happen.
1218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following code cannot be entered in the alpha pre-multiplication case
1221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * because PNG_BACKGROUND_EXPAND is cancelled below.
1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (png_ptr->transformations & PNG_EXPAND) &&
1225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
1226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       /* i.e., GRAY or GRAY_ALPHA */
1227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
1229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Expand background and tRNS chunks */
1230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int gray = png_ptr->background.gray;
1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int trans_gray = png_ptr->trans_color.gray;
1232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         switch (png_ptr->bit_depth)
1234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            case 1:
1236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray *= 0xff;
1237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               trans_gray *= 0xff;
1238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               break;
1239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            case 2:
1241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray *= 0x55;
1242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               trans_gray *= 0x55;
1243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1244a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 4:
1246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray *= 0x11;
1247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               trans_gray *= 0x11;
1248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1249a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            default:
1251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 8:
1253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               /* FALL THROUGH (Already 8 bits) */
1254a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1255893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 16:
1256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               /* Already a full 16 bits */
1257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.red = png_ptr->background.green =
1261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->background.blue = (png_uint_16)gray;
1262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
1264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->trans_color.red = png_ptr->trans_color.green =
1266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
1267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
1268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   } /* background expand and (therefore) no alpha association. */
1270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
1271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1273b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */
1274b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_read_transformations(png_structrp png_ptr)
1275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_init_read_transformations");
1277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* This internal function is called from png_read_start_row in pngrutil.c
1279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * and it is called before the 'rowbytes' calculation is done, so the code
1280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * in here can change or update the transformations flags.
1281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * First do updates that do not depend on the details of the PNG image data
1283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * being processed.
1284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
1287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_alpha_mode and this is another source for a default file gamma so
1289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the test needs to be performed later - here.  In addition prior to 1.5.4
1290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the tests were repeated for the PALETTE color type here - this is no
1291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * longer necessary (and doesn't seem to have been necessary before.)
1292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* The following temporary indicates if overall gamma correction is
1295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * required.
1296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int gamma_correction = 0;
1298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->colorspace.gamma != 0) /* has been set */
1300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->screen_gamma != 0) /* screen set too */
1302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->screen_gamma);
1304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
1306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* Assume the output matches the input; a long time default behavior
1307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * of libpng, although the standard has nothing to say about this.
1308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             */
1309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
1310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
1311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (png_ptr->screen_gamma != 0)
1313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* The converse - assume the file matches the screen, note that this
1314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * perhaps undesireable default can (from 1.5.4) be changed by calling
1315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * png_set_alpha_mode (even if the alpha handling mode isn't required
1316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * or isn't changed from the default.)
1317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
1319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else /* neither are set */
1321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Just in case the following prevents any processing - file and screen
1322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * are both assumed to be linear and there is no way to introduce a
1323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * third gamma value other than png_set_background with 'UNIQUE', and,
1324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * prior to 1.5.4
1325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
1327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* We have a gamma value now. */
1329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
1330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Now turn the gamma transformation on or off as appropriate.  Notice
1332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
1333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * composition may independently cause gamma correction because it needs
1334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
1335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * hasn't been specified.)  In any case this flag may get turned off in
1336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the code immediately below if the transform can be handled outside the
1337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * row loop.
1338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (gamma_correction)
1340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_GAMMA;
1341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
1343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_GAMMA;
1344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Certain transformations have the effect of preventing other
1348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * transformations that happen afterward in png_do_read_transformations,
1349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * resolve the interdependencies here.  From the code of
1350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_do_read_transformations the order is:
1351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
1353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  2) PNG_STRIP_ALPHA (if no compose)
1354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  3) PNG_RGB_TO_GRAY
1355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
1356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  5) PNG_COMPOSE
1357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  6) PNG_GAMMA
1358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  7) PNG_STRIP_ALPHA (if compose)
1359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  8) PNG_ENCODE_ALPHA
1360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  9) PNG_SCALE_16_TO_8
1361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 10) PNG_16_TO_8
1362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 11) PNG_QUANTIZE (converts to palette)
1363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 12) PNG_EXPAND_16
1364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
1365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 14) PNG_INVERT_MONO
1366b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 15) PNG_INVERT_ALPHA
1367b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 16) PNG_SHIFT
1368b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 17) PNG_PACK
1369b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 18) PNG_BGR
1370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 19) PNG_PACKSWAP
1371b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 21) PNG_SWAP_ALPHA
1373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 22) PNG_SWAP_BYTES
1374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 23) PNG_USER_TRANSFORM [must be last]
1375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
1378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      !(png_ptr->transformations & PNG_COMPOSE))
1379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Stripping the alpha channel happens immediately after the 'expand'
1381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * transformations, before all other transformation, so it cancels out
1382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the alpha handling.  It has the side effect negating the effect of
1383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * PNG_EXPAND_tRNS too:
1384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
1386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_EXPAND_tRNS);
1387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * so transparency information would remain just so long as it wasn't
1391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * expanded.  This produces unexpected API changes if the set of things
1392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
1393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * documentation - which says ask for what you want, accept what you
1394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * get.)  This makes the behavior consistent from 1.5.4:
1395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->num_trans = 0;
1397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* STRIP_ALPHA supported, no COMPOSE */
1399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
1402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * settings will have no effect.
1403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!png_gamma_significant(png_ptr->screen_gamma))
1405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Make sure the coefficients for the rgb to gray conversion are set
1413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * appropriately.
1414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_colorspace_set_rgb_coefficients(png_ptr);
1417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Detect gray background and attempt to enable optimization for
1422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gray --> RGB case.
1423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
1425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
1426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background color might actually be gray yet not be flagged as such.
1427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * This is not a problem for the current code, which uses
1428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
1429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_do_gray_to_rgb() transformation.
1430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * TODO: this code needs to be revised to avoid the complexity and
1432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * interdependencies.  The color type of the background should be recorded in
1433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_background, along with the bit depth, then the code has a record
1434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * of exactly what color space the background is currently in.
1435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
1437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the file was grayscale the background value is gray.
1440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
1442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1443893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1444893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (png_ptr->transformations & PNG_COMPOSE)
1446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* PNG_COMPOSE: png_set_background was called with need_expand false,
1448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * so the color is in the color space of the output or png_set_alpha_mode
1449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * was called and the color is black.  Ignore RGB_TO_GRAY because that
1450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * happens before GRAY_TO_RGB.
1451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
1454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->background.red == png_ptr->background.green &&
1455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->background.red == png_ptr->background.blue)
1456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->background.gray = png_ptr->background.red;
1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
1460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
1461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
1466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * can be performed directly on the palette, and some (such as rgb to gray)
1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * can be optimized inside the palette.  This is particularly true of the
1468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * composite (background and alpha) stuff, which can be pretty much all done
1469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * in the palette even if the result is expanded to RGB or gray afterward.
1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * earlier and the palette stuff is actually handled on the first row.  This
1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * leads to the reported bug that the palette returned by png_get_PLTE is not
1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * updated.
1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_init_palette_transformations(png_ptr);
1478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else
1480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_init_rgb_transformations(png_ptr);
1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_EXPAND_16_SUPPORTED)
1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if ((png_ptr->transformations & PNG_EXPAND_16) &&
1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      (png_ptr->transformations & PNG_COMPOSE) &&
1486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->bit_depth != 16)
1488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* TODO: fix this.  Because the expand_16 operation is after the compose
1490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * handling the background color must be 8, not 16, bits deep, but the
1491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * application will supply a 16-bit value so reduce it here.
1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
1494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * present, so that case is ok (until do_expand_16 is moved.)
1495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * NOTE: this discards the low 16 bits of the user supplied background
1497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * color, but until expand_16 works properly there is no choice!
1498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.red);
1501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.green);
1502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.blue);
1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.gray);
1504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     undef CHOP
1505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
1507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
1510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      (png_ptr->transformations & PNG_COMPOSE) &&
1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->bit_depth == 16)
1515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
1517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * component this will also happen after PNG_COMPOSE and so the background
1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * color must be pre-expanded here.
1519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
1520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * TODO: fix this too.
1521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
1523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.green =
1524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         (png_uint_16)(png_ptr->background.green * 257);
1525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
1529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
1531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background support (see the comments in scripts/pnglibconf.dfa), this
1532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * allows pre-multiplication of the alpha channel to be implemented as
1533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * compositing on black.  This is probably sub-optimal and has been done in
1534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * implement the new API quickly, without lots of internal changes.)
1536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
1539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Includes ALPHA_MODE */
1541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background_1 = png_ptr->background;
1542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
1543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* This needs to change - in the palette image case a whole set of tables are
1545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * built when it would be quicker to just calculate the correct value for
1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * each palette entry directly.  Also, the test is too tricky - why check
1547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
1548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the gamma tables will not be built even if composition is required on a
1551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gamma encoded value.
1552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * In 1.5.4 this is addressed below by an additional check on the individual
1554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * tables.
1556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if ((png_ptr->transformations & PNG_GAMMA)
1558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
1559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         && (png_gamma_significant(png_ptr->colorspace.gamma) ||
1560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_gamma_significant(png_ptr->screen_gamma)))
1561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      || ((png_ptr->transformations & PNG_COMPOSE)
1562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         && (png_gamma_significant(png_ptr->colorspace.gamma)
1563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            || png_gamma_significant(png_ptr->screen_gamma)
1564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
1566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               && png_gamma_significant(png_ptr->background_gamma))
1567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
1568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
1569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         && png_gamma_significant(png_ptr->screen_gamma))
1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      )
1571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
15735f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
15745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_BACKGROUND_SUPPORTED
1575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->transformations & PNG_COMPOSE)
1576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Issue a warning about this combination: because RGB_TO_GRAY is
1578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * optimized to do the gamma transform if present yet do_background has
1579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * to do the same thing if both options are set a
1580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * double-gamma-correction happens.  This is true in all versions of
1581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * libpng to date.
1582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_warning(png_ptr,
1585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               "libpng does not support gamma+background+rgb_to_gray");
1586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* We don't get to here unless there is a tRNS chunk with non-opaque
1590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * entries - see the checking code at the start of this function.
1591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             */
1592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_color back, back_1;
1593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_colorp palette = png_ptr->palette;
1594893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int num_palette = png_ptr->num_palette;
1595893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
1597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1599893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back.red = png_ptr->gamma_table[png_ptr->background.red];
1600893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back.green = png_ptr->gamma_table[png_ptr->background.green];
1601893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
1602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
1604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
1605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
1606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else
1608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_fixed_point g, gs;
1610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               switch (png_ptr->background_gamma_type)
1612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  case PNG_BACKGROUND_GAMMA_SCREEN:
1614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     g = (png_ptr->screen_gamma);
1615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = PNG_FP_1;
1616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
1617a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  case PNG_BACKGROUND_GAMMA_FILE:
1619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g = png_reciprocal(png_ptr->colorspace.gamma);
1620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_ptr->screen_gamma);
1622893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
1623a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  case PNG_BACKGROUND_GAMMA_UNIQUE:
1625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g = png_reciprocal(png_ptr->background_gamma);
1626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = png_reciprocal2(png_ptr->background_gamma,
1627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_ptr->screen_gamma);
1628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
1629893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  default:
1630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g = PNG_FP_1;    /* back_1 */
1631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = PNG_FP_1;   /* back */
1632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     break;
1633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (png_gamma_significant(gs))
1636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      gs);
1639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      gs);
1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      gs);
1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
1646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  back.red   = (png_byte)png_ptr->background.red;
1648893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  back.green = (png_byte)png_ptr->background.green;
1649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  back.blue  = (png_byte)png_ptr->background.blue;
1650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (png_gamma_significant(g))
1653893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
1655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g);
1656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.green = png_gamma_8bit_correct(
1657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_ptr->background.green, g);
1658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g);
1660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
1663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.red   = (png_byte)png_ptr->background.red;
1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.green = (png_byte)png_ptr->background.green;
1666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.blue  = (png_byte)png_ptr->background.blue;
1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < num_palette; i++)
1671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (i < (int)png_ptr->num_trans &&
1673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   png_ptr->trans_alpha[i] != 0xff)
1674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  if (png_ptr->trans_alpha[i] == 0)
1676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
1677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i] = back;
1678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
1679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
1680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
1681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte v, w;
1682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     v = png_ptr->gamma_to_1[palette[i].red];
1684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
1685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i].red = png_ptr->gamma_from_1[w];
1686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     v = png_ptr->gamma_to_1[palette[i].green];
1688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
1689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i].green = png_ptr->gamma_from_1[w];
1690893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     v = png_ptr->gamma_to_1[palette[i].blue];
1692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
1693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i].blue = png_ptr->gamma_from_1[w];
1694893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
1695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1696893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
1697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i].red = png_ptr->gamma_table[palette[i].red];
1699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i].green = png_ptr->gamma_table[palette[i].green];
1700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* Prevent the transformations being done again.
1705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             *
1706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * NOTE: this is highly dubious; it removes the transformations in
1707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * place.  This seems inconsistent with the general treatment of the
1708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * transformations elsewhere.
17095f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott             */
1710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
1711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else /* color_type != PNG_COLOR_TYPE_PALETTE */
1715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int gs_sig, g_sig;
1717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
1719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            switch (png_ptr->background_gamma_type)
1721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case PNG_BACKGROUND_GAMMA_SCREEN:
1723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  g = png_ptr->screen_gamma;
1724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  /* gs = PNG_FP_1; */
1725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
1726a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1727893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case PNG_BACKGROUND_GAMMA_FILE:
1728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  g = png_reciprocal(png_ptr->colorspace.gamma);
1729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
1730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_ptr->screen_gamma);
1731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
1732a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case PNG_BACKGROUND_GAMMA_UNIQUE:
1734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  g = png_reciprocal(png_ptr->background_gamma);
1735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gs = png_reciprocal2(png_ptr->background_gamma,
1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->screen_gamma);
1737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
1738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               default:
1740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_error(png_ptr, "invalid background gamma type");
1741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1742893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            g_sig = png_gamma_significant(g);
1744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            gs_sig = png_gamma_significant(gs);
1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            if (g_sig)
1747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
1748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   png_ptr->background.gray, g);
1749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            if (gs_sig)
1751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->background.gray = png_gamma_correct(png_ptr,
1752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   png_ptr->background.gray, gs);
1753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if ((png_ptr->background.red != png_ptr->background.green) ||
1755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                (png_ptr->background.red != png_ptr->background.blue) ||
1756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                (png_ptr->background.red != png_ptr->background.gray))
1757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               /* RGB or RGBA with color background */
1759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (g_sig)
1760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
1762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.red, g);
1763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
1765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.green, g);
1766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
1768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.blue, g);
1769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (gs_sig)
1772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background.red = png_gamma_correct(png_ptr,
1774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.red, gs);
1775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background.green = png_gamma_correct(png_ptr,
1777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.green, gs);
1778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background.blue = png_gamma_correct(png_ptr,
1780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.blue, gs);
1781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else
1785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_ptr->background_1.red = png_ptr->background_1.green
1788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_ptr->background.red = png_ptr->background.green
1791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   = png_ptr->background.blue = png_ptr->background.gray;
1792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* The background is now in screen gamma: */
1795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
1796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         } /* color_type != PNG_COLOR_TYPE_PALETTE */
1797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }/* png_ptr->transformations & PNG_BACKGROUND */
1798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
1800a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      /* Transformation does not include PNG_BACKGROUND */
1801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
1803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
1806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
1807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
1808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         )
1809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1810893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_colorp palette = png_ptr->palette;
1811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int num_palette = png_ptr->num_palette;
1812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int i;
1813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* NOTE: there are other transformations that should probably be in
1815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * here too.
1816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1817893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0; i < num_palette; i++)
1818893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1819893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i].red = png_ptr->gamma_table[palette[i].red];
1820893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i].green = png_ptr->gamma_table[palette[i].green];
1821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
18245f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         /* Done the gamma correction. */
18255f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         png_ptr->transformations &= ~PNG_GAMMA;
1826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
1827893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
18285f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_BACKGROUND_SUPPORTED
1829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
1830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_GAMMA_SUPPORTED */
1832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
18335f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_BACKGROUND_SUPPORTED
1834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* No GAMMA transformation (see the hanging else 4 lines above) */
1835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if ((png_ptr->transformations & PNG_COMPOSE) &&
1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1838893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int i;
1839893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int istop = (int)png_ptr->num_trans;
1840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_color back;
1841893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_colorp palette = png_ptr->palette;
1842893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      back.red   = (png_byte)png_ptr->background.red;
1844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      back.green = (png_byte)png_ptr->background.green;
1845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      back.blue  = (png_byte)png_ptr->background.blue;
1846893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      for (i = 0; i < istop; i++)
1848893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->trans_alpha[i] == 0)
1850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i] = back;
1852893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else if (png_ptr->trans_alpha[i] != 0xff)
1855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            /* The png_composite() macro is defined in png.h */
1857893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_composite(palette[i].red, palette[i].red,
1858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_ptr->trans_alpha[i], back.red);
1859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_composite(palette[i].green, palette[i].green,
1861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_ptr->trans_alpha[i], back.green);
1862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_composite(palette[i].blue, palette[i].blue,
1864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_ptr->trans_alpha[i], back.blue);
1865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_COMPOSE;
1869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
18725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_SHIFT_SUPPORTED
1873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if ((png_ptr->transformations & PNG_SHIFT) &&
1874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      !(png_ptr->transformations & PNG_EXPAND) &&
1875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int i;
1878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int istop = png_ptr->num_palette;
1879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int shift = 8 - png_ptr->sig_bit.red;
1880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_SHIFT;
1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* significant bits can be in the range 1 to 7 for a meaninful result, if
1884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the number of significant bits is 0 then no shift is done (this is an
1885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * error condition which is silently ignored.)
1886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1887b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (shift > 0 && shift < 8)
1888b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i=0; i<istop; ++i)
1889b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1890b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            int component = png_ptr->palette[i].red;
1891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1892b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            component >>= shift;
1893b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_ptr->palette[i].red = (png_byte)component;
1894b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      shift = 8 - png_ptr->sig_bit.green;
1897b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (shift > 0 && shift < 8)
1898b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i=0; i<istop; ++i)
1899b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1900b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            int component = png_ptr->palette[i].green;
1901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1902b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            component >>= shift;
1903b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_ptr->palette[i].green = (png_byte)component;
1904b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      shift = 8 - png_ptr->sig_bit.blue;
1907b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (shift > 0 && shift < 8)
1908b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i=0; i<istop; ++i)
1909b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1910b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            int component = png_ptr->palette[i].blue;
1911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            component >>= shift;
1913b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_ptr->palette[i].blue = (png_byte)component;
1914b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1915893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1916893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif  /* PNG_READ_SHIFT_SUPPORTED */
1917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Modify the info structure to reflect the transformations.  The
1920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * info should be updated so a PNG file could be written with it,
1921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * assuming the transformations result in valid PNG data.
1922893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
1923893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
1924b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
1925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
19264215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_read_transform_info");
19275f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
19285f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
1929893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->transformations & PNG_EXPAND)
1930893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1931893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1932893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* This check must match what actually happens in
1934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * it is all opaque we must do the same (at present it does not.)
1936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->num_trans > 0)
1938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
1941893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1943893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->bit_depth = 8;
1944893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->num_trans = 0;
1945b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
1946b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if (png_ptr->palette == NULL)
1947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_error (png_ptr, "Palette is NULL in indexed image");
1948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1949893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
1950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1951893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (png_ptr->num_trans)
1952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (png_ptr->transformations & PNG_EXPAND_tRNS)
1954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1955893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1956893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (info_ptr->bit_depth < 8)
1957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            info_ptr->bit_depth = 8;
1958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1959893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->num_trans = 0;
1960893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1961893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
1965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
1966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following is almost certainly wrong unless the background value is in
1967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the screen space!
1968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations & PNG_COMPOSE)
1970893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->background = png_ptr->background;
1971893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1972893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
19735f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
1974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * however it seems that the code in png_init_read_transformations, which has
1976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * been called before this from png_read_update_info->png_read_start_row
1977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * sometimes does the gamma transform and cancels the flag.
1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
1980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the screen_gamma value.  The following probably results in weirdness if
1981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the info_ptr is used by the app after the rows have been read.
1982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
1984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (info_ptr->bit_depth == 16)
1987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_READ_16BIT_SUPPORTED
1989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
1990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->transformations & PNG_SCALE_16_TO_8)
1991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            info_ptr->bit_depth = 8;
1992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
1993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
1995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->transformations & PNG_16_TO_8)
1996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            info_ptr->bit_depth = 8;
1997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
1998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  else
2000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* No 16 bit support: force chopping 16-bit input down to 8, in this case
2001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the app program can chose if both APIs are available by setting the
2002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * correct scaling to use.
2003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
2004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* For compatibility with previous versions use the strip method by
2006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * default.  This code works because if PNG_SCALE_16_TO_8 is already
2007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * set the code below will do that in preference to the chop.
2008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
2009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_16_TO_8;
2010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         info_ptr->bit_depth = 8;
2011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     else
2012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->transformations |= PNG_SCALE_16_TO_8;
2015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            info_ptr->bit_depth = 8;
2016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#        else
2017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            CONFIGURATION ERROR: you must enable at least one 16 to 8 method
2019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#        endif
2020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#    endif
2021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* !READ_16BIT_SUPPORTED */
2022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2023893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20245f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type = (png_byte)(info_ptr->color_type |
2027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_COLOR_MASK_COLOR);
2028893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2029893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2031893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
2032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type = (png_byte)(info_ptr->color_type &
2033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         ~PNG_COLOR_MASK_COLOR);
2034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2035893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_QUANTIZE_SUPPORTED
2037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations & PNG_QUANTIZE)
2038893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2040a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2041a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
2042893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
2044893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2046893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2047893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_EXPAND_16_SUPPORTED
2049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
2050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->bit_depth = 16;
2053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
20565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_PACK_SUPPORTED
2057893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
2058893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->bit_depth = 8;
2059893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2060893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels = 1;
2063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
2065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels = 3;
2066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
2068893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels = 1;
2069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations & PNG_STRIP_ALPHA)
2072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type = (png_byte)(info_ptr->color_type &
2074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         ~PNG_COLOR_MASK_ALPHA);
2075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->num_trans = 0;
2076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2078893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2079893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
2080893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels++;
2081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_FILLER_SUPPORTED
2083893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
2084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if ((png_ptr->transformations & PNG_FILLER) &&
2085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2086893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
2087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels++;
2089a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      /* If adding a true alpha channel not just filler */
2090893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->transformations & PNG_ADD_ALPHA)
2091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2093893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
2096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectdefined(PNG_READ_USER_TRANSFORM_SUPPORTED)
20974215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
2100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->bit_depth = png_ptr->user_transform_depth;
2101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (info_ptr->channels < png_ptr->user_transform_channels)
2103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->channels = png_ptr->user_transform_channels;
2104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       info_ptr->bit_depth);
2109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
21104215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * check in png_rowbytes that the user buffer won't get overwritten.  Note
2114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * that the field is not always set - if png_read_update_info isn't called
2115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the application has to either not do any transforms or get the calculation
2116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * right itself.
2117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
2118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->info_rowbytes = info_ptr->rowbytes;
2119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
21205f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifndef PNG_READ_EXPAND_SUPPORTED
21214215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   if (png_ptr)
2122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      return;
2123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2124893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2126b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACK_SUPPORTED
2127b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
2128b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * without changing the actual values.  Thus, if you had a row with
2129b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * a bit depth of 1, you would end up with bytes that only contained
2130b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
2131b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * png_do_shift() after this.
2132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
2133b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2134b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_unpack(png_row_infop row_info, png_bytep row)
2135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2136b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_unpack");
2137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2138b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (row_info->bit_depth < 8)
2139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2140b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_uint_32 i;
2141b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_uint_32 row_width=row_info->width;
2142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2143b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      switch (row_info->bit_depth)
2144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2145b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         case 1:
2146b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2147b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
2148b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep dp = row + (png_size_t)row_width - 1;
2149b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2150b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            for (i = 0; i < row_width; i++)
2151b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            {
2152b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               *dp = (png_byte)((*sp >> shift) & 0x01);
2153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2154b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               if (shift == 7)
2155b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               {
2156b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 0;
2157b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  sp--;
2158b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               }
2159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2160b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               else
2161b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift++;
2162b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2163b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               dp--;
2164b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            }
2165b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2166b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
2167b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2168b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         case 2:
2169b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2170b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2171b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
2172b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep dp = row + (png_size_t)row_width - 1;
2173b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2174b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            for (i = 0; i < row_width; i++)
2175b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            {
2176b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               *dp = (png_byte)((*sp >> shift) & 0x03);
2177b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2178b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               if (shift == 6)
2179b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               {
2180b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 0;
2181b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  sp--;
2182b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               }
2183b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2184b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               else
2185b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift += 2;
2186b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2187b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               dp--;
2188b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            }
2189b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2190b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
2191b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2192b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         case 4:
2193b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2194b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
2195b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep dp = row + (png_size_t)row_width - 1;
2196b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2197b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            for (i = 0; i < row_width; i++)
2198b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            {
2199b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               *dp = (png_byte)((*sp >> shift) & 0x0f);
2200b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2201b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               if (shift == 4)
2202b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               {
2203b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 0;
2204b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  sp--;
2205b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               }
2206b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2207b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               else
2208b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 4;
2209b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2210b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               dp--;
2211b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            }
2212b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2213b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
2214b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2215b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         default:
2216b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2218b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->bit_depth = 8;
2219b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2220b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->rowbytes = row_width * row_info->channels;
2221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2222b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}
2223893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2225b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SHIFT_SUPPORTED
2226b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Reverse the effects of png_do_shift.  This routine merely shifts the
2227b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * pixels back to their significant bits values.  Thus, if you have
2228b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * a row of bit depth 8, but only 5 are significant, this will shift
2229b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the values back to 0 through 31.
2230b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */
2231b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2232b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_unshift(png_row_infop row_info, png_bytep row,
2233b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    png_const_color_8p sig_bits)
2234b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{
2235b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   int color_type;
2236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2237b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_unshift");
2238b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2239b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* The palette case has already been handled in the _init routine. */
2240b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   color_type = row_info->color_type;
2241b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2242b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (color_type != PNG_COLOR_TYPE_PALETTE)
2243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2244b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int shift[4];
2245b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int channels = 0;
2246b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int bit_depth = row_info->bit_depth;
2247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2248b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (color_type & PNG_COLOR_MASK_COLOR)
2249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2250b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->red;
2251b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->green;
2252b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->blue;
2253b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
2254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2255b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else
2256b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
2257b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->gray;
2258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2260b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (color_type & PNG_COLOR_MASK_ALPHA)
2261b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
2262b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->alpha;
2263b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
2264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2265b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
2266b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         int c, have_shift;
2267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2268b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (c = have_shift = 0; c < channels; ++c)
2269b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2270b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            /* A shift of more than the bit depth is an error condition but it
2271b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * gets ignored here.
2272b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             */
2273b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            if (shift[c] <= 0 || shift[c] >= bit_depth)
2274b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               shift[c] = 0;
2275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            else
2277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               have_shift = 1;
2278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
2279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (!have_shift)
2281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
2282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      switch (bit_depth)
2285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
2287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Must be 1bpp gray: should not be here! */
2288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* NOTREACHED */
2289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            break;
2290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 2:
2292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Must be 2bpp gray */
2293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* assert(channels == 1 && shift[0] == 1) */
2294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp = row;
2296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int b = (*bp >> 1) & 0x55;
2301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *bp++ = (png_byte)b;
2302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2305a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
2306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 4:
2307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Must be 4bpp gray */
2308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* assert(channels == 1) */
2309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep bp = row;
2311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int gray_shift = shift[0];
2313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int mask =  0xf >> gray_shift;
2314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            mask |= mask << 4;
2316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int b = (*bp >> gray_shift) & mask;
2320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *bp++ = (png_byte)b;
2321893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2324a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
2325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 8:
2326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Single byte components, G, GA, RGB, RGBA */
2327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep bp = row;
2329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int channel = 0;
2331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int b = *bp >> shift[channel];
2335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (++channel >= channels)
2336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  channel = 0;
2337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *bp++ = (png_byte)b;
2338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2340893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2341a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
2342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 16:
2344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Double byte components, G, GA, RGB, RGBA */
2345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep bp = row;
2347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int channel = 0;
2349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int value = (bp[0] << 8) + bp[1];
2353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               value >>= shift[channel];
2355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (++channel >= channels)
2356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  channel = 0;
2357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *bp++ = (png_byte)(value >> 8);
2358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *bp++ = (png_byte)(value & 0xff);
2359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2360893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Scale rows of bit depth 16 down to 8 accurately */
2370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2371b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
2372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_scale_16_to_8");
23745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (row_info->bit_depth == 16)
2376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep sp = row; /* source */
2378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep dp = row; /* destination */
2379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      while (sp < ep)
2382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* The input is an array of 16 bit components, these must be scaled to
2384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * 8 bits each.  For a 16 bit value V the required value (from the PNG
2385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * specification) is:
2386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    (V * 255) / 65535
2388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * This reduces to round(V / 257), or floor((V + 128.5)/257)
2390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * Represent V as the two byte value vhi.vlo.  Make a guess that the
2392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * result is the top byte of V, vhi, then the correction to this value
2393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * is:
2394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
2396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *          = floor(((vlo-vhi) + 128.5) / 257)
2397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * This can be approximated using integer arithmetic (and a signed
2399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * shift):
2400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    error = (vlo-vhi+128) >> 8;
2402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * The approximate differs from the exact answer only when (vlo-vhi) is
2404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * 128; it then gives a correction of +1 when the exact correction is
2405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit
2406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * input values) is:
2407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    error = (vlo-vhi+128)*65535 >> 24;
2409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * An alternative arithmetic calculation which also gives no errors is:
2411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    (V * 255 + 32895) >> 16
2413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
2414893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_int_32 tmp = *sp++; /* must be signed! */
2416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         *dp++ = (png_byte)tmp;
2418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->bit_depth = 8;
2421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->rowbytes = row_info->width * row_info->channels;
2423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
2425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2428b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Simply discard the low byte.  This was the default behavior prior
2430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to libpng-1.5.4.
2431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
2432b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_chop(png_row_infop row_info, png_bytep row)
2433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
2434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_chop");
2435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->bit_depth == 16)
2437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep sp = row; /* source */
2439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep dp = row; /* destination */
2440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      while (sp < ep)
2443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
2444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         *dp++ = *sp;
2445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         sp += 2; /* skip low byte */
2446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->bit_depth = 8;
2449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->rowbytes = row_info->width * row_info->channels;
2451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2453893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
24555f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2456b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
2458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
24594215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_read_swap_alpha");
24605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_uint_32 row_width = row_info->width;
2463893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2464893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from RGBA to ARGB */
2466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2467893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save;
2471893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save = *(--sp);
2476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save;
2480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from RRGGBBAA to AARRGGBB */
2485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2487893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save[2];
2490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2492893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[0] = *(--sp);
2495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[1] = *(--sp);
2496893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[0];
2503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[1];
2504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from GA to AG */
2512893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2513893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save;
2517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2518893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save = *(--sp);
2522893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save;
2524893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2525893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from GGAA to AAGG */
2529893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save[2];
2534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2536893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[0] = *(--sp);
2539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[1] = *(--sp);
2540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[0];
2543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[1];
2544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
25525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2553b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
2555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 row_width;
25574215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_read_invert_alpha");
25585f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_width = row_info->width;
2560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2561893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
2563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2564893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This inverts the alpha channel in RGBA */
2565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp = row + row_info->rowbytes;
2566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2568893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*          This does nothing:
2574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            We can replace it with:
2578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project*/
2579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            sp-=3;
2580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            dp=sp;
2581893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2583893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* This inverts the alpha channel in RRGGBBAA */
2586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
2587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
2588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp = row + row_info->rowbytes;
2589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*          This does nothing:
2598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            We can replace it with:
2605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project*/
2606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            sp-=6;
2607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            dp=sp;
2608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
2615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This inverts the alpha channel in GA */
2617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp = row + row_info->rowbytes;
2618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2625893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
2630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
2631893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This inverts the alpha channel in GGAA */
2632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp  = row + row_info->rowbytes;
2633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/*
2641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2643893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project*/
2644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            sp-=2;
2645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            dp=sp;
2646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2652893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
26535f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_FILLER_SUPPORTED
2654893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Add filler channel if we have RGB color */
2655b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_read_filler(png_row_infop row_info, png_bytep row,
2657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_uint_32 filler, png_uint_32 flags)
2658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
2660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width = row_info->width;
2661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2665893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_byte lo_filler = (png_byte)(filler & 0xff);
2666893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
26674215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_read_filler");
26685f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (
2670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project       row_info->color_type == PNG_COLOR_TYPE_GRAY)
2671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
26724215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      if (row_info->bit_depth == 8)
2673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (flags & PNG_FLAG_FILLER_AFTER)
2675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from G to GX */
2677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width;
2678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp =  sp + (png_size_t)row_width;
2679893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
2685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 16;
2687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 2;
2688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2690893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from G to XG */
2693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width;
2694893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width;
2695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2696893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 16;
2702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 2;
2703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
27074215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      else if (row_info->bit_depth == 16)
2708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (flags & PNG_FLAG_FILLER_AFTER)
2710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from GG to GGXX */
2712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2;
2713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = hi_filler;
2717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = hi_filler;
2722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
2723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2728893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from GG to XXGG */
2731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2;
2732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2734893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = hi_filler;
2738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2740893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2742893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2746893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   } /* COLOR_TYPE == GRAY */
2747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2748893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
27494215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      if (row_info->bit_depth == 8)
2750893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (flags & PNG_FLAG_FILLER_AFTER)
2752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RGB to RGBX */
2754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 3;
2755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width;
2756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
2764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2765893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2769893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RGB to XRGB */
2772893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 3;
2773893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp + (png_size_t)row_width;
2774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2776893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
27884215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      else if (row_info->bit_depth == 16)
2789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (flags & PNG_FLAG_FILLER_AFTER)
2791893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RRGGBB to RRGGBBXX */
2793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 6;
2794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2796893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = hi_filler;
2798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2800893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2802893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2803893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2805893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = hi_filler;
2807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
2808893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 64;
2810893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 8;
2811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2814893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RRGGBB to XXRRGGBB */
2816893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 6;
2817893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2818893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2819893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2820893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2824893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2826893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = hi_filler;
2827893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2831893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 64;
2832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 8;
2833893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   } /* COLOR_TYPE == RGB */
2837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2838893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2839893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
28405f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2841a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Expand grayscale files to RGB, with or without alpha */
2842b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
2846893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width = row_info->width;
2847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
28484215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_gray_to_rgb");
28495f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (row_info->bit_depth >= 8 &&
2851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2852893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2854893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes G to RGB */
2858893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width - 1;
2859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2861893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2864893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes GG to RRGGBB */
2871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2872893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 4;
2873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2874893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2875893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2877893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2879893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2880893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2881893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2886893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2888893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes GA to RGBA */
2890893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2892893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2893893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2897893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2899893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2902893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes GGAA to RRGGBBAA */
2904893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 4;
2906893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2907893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2908893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2909893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2910893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2911893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2912893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2913893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2914893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2915893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2916893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->channels = (png_byte)(row_info->channels + 2);
2920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->color_type |= PNG_COLOR_MASK_COLOR;
2921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->pixel_depth = (png_byte)(row_info->channels *
2922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          row_info->bit_depth);
29234215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2924893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2926893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2927893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
29285f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2929a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Reduce RGB files to grayscale, with or without alpha
2930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
2931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
2932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * versions dated 1998 through November 2002 have been archived at
2933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
2934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
29354215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * Charles Poynton poynton at poynton.com
2936893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2937893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  which can be expressed with integers as
2940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Poynton's current link (as of January 2003 through July 2011):
2944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * <http://www.poynton.com/notes/colour_and_gamma/>
2945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * has changed the numbers slightly:
2946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = 0.2126*R + 0.7152*G + 0.0722*B
2948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2949893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  which can be expressed with integers as
2950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
2952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
2954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  end point chromaticities and the D65 white point.  Depending on the
2955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  precision used for the D65 white point this produces a variety of different
2956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
2957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  used (0.3127,0.3290) the Y calculation would be:
2958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  While this is correct the rounding results in an overflow for white, because
2962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
2963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  libpng uses, instead, the closest non-overflowing approximation:
2964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
2966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
2968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  (including an sRGB chunk) then the chromaticities are used to calculate the
2969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  coefficients.  See the chunk handling in pngrutil.c for more information.
2970893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  In all cases the calculation is to be done in a linear colorspace.  If no
2972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  gamma information is available to correct the encoding of the original RGB
2973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  values this results in an implicit assumption that the original PNG RGB
2974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  values were linear.
2975893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  Other integer coefficents can be used via png_set_rgb_to_gray().  Because
2977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  the API takes just red and green coefficients the blue coefficient is
2978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  calculated to make the sum 32768.  This will result in different rounding
2979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  to that used above.
2980893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
2981b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int
2982b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2983893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int rgb_error = 0;
2986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
29874215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_rgb_to_gray");
29885f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
2990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (row_info->color_type & PNG_COLOR_MASK_COLOR))
2991893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 bc = 32768 - rc - gc;
2995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 row_width = row_info->width;
2996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST int have_alpha =
2997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
2998893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
3000893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
3002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Notice that gamma to/from 1 are not necessarily inverses (if
3003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * there is an overall gamma correction).  Prior to 1.5.5 this code
3004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * checked the linearized values for equality; this doesn't match
3005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * the documentation, the original values must be checked.
3006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
3007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
3008893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte red   = *(sp++);
3016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte green = *(sp++);
3017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte blue  = *(sp++);
3018893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red != green || red != blue)
3020893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  red = png_ptr->gamma_to_1[red];
3022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  green = png_ptr->gamma_to_1[green];
3023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  blue = png_ptr->gamma_to_1[blue];
3024893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = png_ptr->gamma_from_1[
3027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      (rc*red + gc*green + bc*blue + 16384)>>15];
3028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
3029893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
3031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
3032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  /* If there is no overall correction the table will not be
3033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   * set.
3034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   */
3035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  if (png_ptr->gamma_table != NULL)
3036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     red = png_ptr->gamma_table[red];
3037893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = red;
3039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (have_alpha)
3042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
3045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
3046893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
3048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3053893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte red   = *(sp++);
3055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte green = *(sp++);
3056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte blue  = *(sp++);
3057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red != green || red != blue)
3059893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  /* NOTE: this is the historical approach which simply
3062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   * truncates the results.
3063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   */
3064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
3066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
3068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = red;
3069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (have_alpha)
3071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3072893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3074893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
3075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else /* RGB bit_depth == 16 */
3077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
3079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
3080893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3086893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_uint_16 red, green, blue, w;
3088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red == green && red == blue)
3094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  if (png_ptr->gamma_16_table != NULL)
3096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     w = png_ptr->gamma_16_table[(red&0xff)
3097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         >> png_ptr->gamma_shift][red>>8];
3098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  else
3100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     w = red;
3101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
3104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
3106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      >> png_ptr->gamma_shift][red>>8];
3107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_uint_16 green_1 =
3108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->gamma_16_to_1[(green&0xff) >>
3109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->gamma_shift][green>>8];
3110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
3111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      >> png_ptr->gamma_shift][blue>>8];
3112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
3113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      + bc*blue_1 + 16384)>>15);
3114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
3115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->gamma_shift][gray16 >> 8];
3116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3118893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)((w>>8) & 0xff);
3120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)(w & 0xff);
3121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (have_alpha)
3123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
3124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(dp++) = *(sp++);
3126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
3129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
3130893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
3132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_uint_16 red, green, blue, gray16;
3139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red != green || red != blue)
3145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               /* From 1.5.5 in the 16 bit case do the accurate conversion even
3148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                * in the 'fast' case - this is because this is where the code
3149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                * ends up when handling linear 16 bit data.
3150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                */
3151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
3152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  15);
3153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)((gray16>>8) & 0xff);
3154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)(gray16 & 0xff);
3155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (have_alpha)
3157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(dp++) = *(sp++);
3160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
3164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->channels = (png_byte)(row_info->channels - 2);
3166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->color_type = (png_byte)(row_info->color_type &
3167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          ~PNG_COLOR_MASK_COLOR);
3168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->pixel_depth = (png_byte)(row_info->channels *
3169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          row_info->bit_depth);
31704215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3171893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
3172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   return rgb_error;
3173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
3174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
3177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
3178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Replace any alpha or transparency with the supplied background color.
3179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * "background" is already in the screen gamma, while "background_1" is
3180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * at a gamma of 1.0.  Paletted files have already been taken care of.
3181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
3182b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
3183b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
31855f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_table = png_ptr->gamma_table;
3187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
3188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
3189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
3190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
3191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
3192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int gamma_shift = png_ptr->gamma_shift;
3193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_bytep sp;
3197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
3198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 row_width = row_info->width;
3199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int shift;
3200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_compose");
32025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
3203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
3204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      switch (row_info->color_type)
3205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY:
3207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3208893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            switch (row_info->bit_depth)
3209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 1:
3211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = 7;
3214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
3215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if ((png_uint_16)((*sp >> shift) & 0x01)
3217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        == png_ptr->trans_color.gray)
3218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
3220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        tmp |= png_ptr->background.gray << shift;
3221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)(tmp & 0xff);
3222893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (!shift)
3225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 7;
3227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp++;
3228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift--;
3232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3235a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 2:
3237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
32385f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_table != NULL)
3240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 6;
3243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x03)
3246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           tmp |= png_ptr->background.gray << shift;
3250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int p = (*sp >> shift) & 0x03;
3256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int g = (gamma_table [p | (p << 2) |
3257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                               (p << 4) | (p << 6)] >> 6) & 0x03;
3258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           tmp |= g << shift;
3260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if (!shift)
3264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 6;
3266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 2;
3271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 6;
3279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x03)
3282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           tmp |= png_ptr->background.gray << shift;
3286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if (!shift)
3290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 6;
3292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 2;
3297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3301a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 4:
3303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
33045f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_table != NULL)
3306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 4;
3309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
3315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           tmp |= png_ptr->background.gray << shift;
3316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int p = (*sp >> shift) & 0x0f;
3322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
3323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                              0x0f;
3324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
3325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           tmp |= g << shift;
3326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if (!shift)
3330893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 4;
3332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 4;
3337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3340893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 4;
3345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
3351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           tmp |= png_ptr->background.gray << shift;
3352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if (!shift)
3356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 4;
3358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 4;
3363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3367a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 8:
3369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
33705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_table != NULL)
3372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp++)
3375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (*sp == png_ptr->trans_color.gray)
3377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)png_ptr->background.gray;
3378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           *sp = gamma_table[*sp];
3381893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp++)
3388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (*sp == png_ptr->trans_color.gray)
3390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)png_ptr->background.gray;
3391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3392893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3393893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3395a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3396893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 16:
3397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
33985f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_16 != NULL)
3400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp += 2)
3403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3404893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (v == png_ptr->trans_color.gray)
3409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3410a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                           /* Background is already in screen gamma */
3411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)((png_ptr->background.gray >> 8)
3412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *(sp + 1) = (png_byte)(png_ptr->background.gray
3414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           *sp = (png_byte)((v >> 8) & 0xff);
3421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           *(sp + 1) = (png_byte)(v & 0xff);
3422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp += 2)
3430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (v == png_ptr->trans_color.gray)
3436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)((png_ptr->background.gray >> 8)
3438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *(sp + 1) = (png_byte)(png_ptr->background.gray
3440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3443893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3444893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3445893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               default:
3448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  break;
3449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3452a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3453893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB:
3454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3455893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
34575f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_table != NULL)
3459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3460893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 3)
3462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (*sp == png_ptr->trans_color.red &&
3464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 1) == png_ptr->trans_color.green &&
3465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 2) == png_ptr->trans_color.blue)
3466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *sp = gamma_table[*sp];
3475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 1) = gamma_table[*(sp + 1)];
3476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 2) = gamma_table[*(sp + 2)];
3477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 3)
3485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (*sp == png_ptr->trans_color.red &&
3487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 1) == png_ptr->trans_color.green &&
3488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 2) == png_ptr->trans_color.blue)
3489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3496893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
3498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
34995f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_16 != NULL)
3501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 6)
3504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 5));
3512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (r == png_ptr->trans_color.red &&
3514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         g == png_ptr->trans_color.green &&
3515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         b == png_ptr->trans_color.blue)
3516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3517a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3529893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *sp = (png_byte)((v >> 8) & 0xff);
3533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 1) = (png_byte)(v & 0xff);
3534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3536893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 3) = (png_byte)(v & 0xff);
3538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 5) = (png_byte)(v & 0xff);
3542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 6)
3551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 5));
3559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (r == png_ptr->trans_color.red &&
3561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         g == png_ptr->trans_color.green &&
3562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         b == png_ptr->trans_color.blue)
3563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3573893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3574893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3575893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3577893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3579a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY_ALPHA:
3581893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3583893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
35845f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3585893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3586893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_table != NULL)
3587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 2)
3590893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 a = *(sp + 1);
3592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == 0xff)
3594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = gamma_table[*sp];
3595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3598a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.gray;
3600893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_byte v, w;
3605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*sp];
3607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.gray);
3608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize)
3609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = gamma_from_1[w];
3610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = w;
3611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 2)
3619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte a = *(sp + 1);
3621893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.gray;
3624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xff)
3626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*sp, *sp, a, png_ptr->background.gray);
3627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3629893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3630893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (png_ptr->bit_depth == 16) */
3631893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
36325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_16_to_1 != NULL)
3635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3638893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3642893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == (png_uint_16)0xffff)
3643893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3645893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3652893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3653a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.gray >> 8)
3655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3657893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 g, v, w;
3662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (optimize)
3666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = v;
3667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        else
3668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((w >> 8) & 0xff);
3670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(w & 0xff);
3671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3679893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.gray >> 8)
3686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xffff)
3691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 g, v;
3693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3694893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, g, a, png_ptr->background.gray);
3696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3704a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB_ALPHA:
3706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
37095f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_table != NULL)
3712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte a = *(sp + 3);
3717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == 0xff)
3719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = gamma_table[*sp];
3721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = gamma_table[*(sp + 1)];
3722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = gamma_table[*(sp + 2)];
3723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3727a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3734893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_byte v, w;
3736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*sp];
3738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.red);
3739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize) w = gamma_from_1[w];
3740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = w;
3741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3742893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*(sp + 1)];
3743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.green);
3744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize) w = gamma_from_1[w];
3745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = w;
3746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*(sp + 2)];
3748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.blue);
3749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize) w = gamma_from_1[w];
3750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = w;
3751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte a = *(sp + 3);
3761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xff)
3770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*sp, *sp, a, png_ptr->background.red);
3772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*(sp + 1), *(sp + 1), a,
3774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            png_ptr->background.green);
3775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*(sp + 2), *(sp + 2), a,
3777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            png_ptr->background.blue);
3778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
3783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
37845f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_16_to_1 != NULL)
3787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 8)
3790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3791893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                         << 8) + (png_uint_16)(*(sp + 7)));
3793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == (png_uint_16)0xffff)
3795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3796893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3802893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(v & 0xff);
3805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(v & 0xff);
3809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3813a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3826893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_uint_16 v, w;
3828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(w, v, a, png_ptr->background_1.red);
3831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize)
3832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
3833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                8];
3834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((w >> 8) & 0xff);
3835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(w & 0xff);
3836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(w, v, a, png_ptr->background_1.green);
3839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize)
3840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
3841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                8];
3842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
3844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(w & 0xff);
3845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3846893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(w, v, a, png_ptr->background_1.blue);
3848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (!optimize)
3849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
3850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                8];
3851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
3853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(w & 0xff);
3854893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3858893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3861893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 8)
3863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3864893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         << 8) + (png_uint_16)(*(sp + 7)));
3866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xffff)
3881893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3884893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3886893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                            + *(sp + 3));
3887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3888893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                            + *(sp + 5));
3889893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, r, a, png_ptr->background.red);
3891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, g, a, png_ptr->background.green);
3895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(v & 0xff);
3897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, b, a, png_ptr->background.blue);
3899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(v & 0xff);
3901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3902893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3903893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3904893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3906893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3907893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
3909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            break;
3910893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
3911893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
3912893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
3913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
3914893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
39155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3916893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Gamma correct the image, avoiding the alpha channel.  Make sure
3917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * you do this after you deal with the transparency issue on grayscale
3918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * or RGB images. If your bit depth is 8, use gamma_table, if it
3919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * is 16, use gamma_16_table and gamma_shift.  Build these with
3920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * build_gamma_table().
3921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
3922b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
3923b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3924893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
3925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_table = png_ptr->gamma_table;
3926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
3927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int gamma_shift = png_ptr->gamma_shift;
3928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3929893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep sp;
3930893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
3931893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width=row_info->width;
3932893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
39334215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_gamma");
39345f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
3935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3937893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
3938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      switch (row_info->color_type)
3939893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB:
3941893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3942893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3943893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3944893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
3945893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
3946893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3949893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3951893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3954893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3956893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
3957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3958893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
3959893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
3960893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3961893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v;
3962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3964893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
3965893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
3966893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
3967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3968893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3969893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
3970893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
3971893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
3972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3973893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3974893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
3975893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
3976893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
3977893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3978893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3980893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3981a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3982893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB_ALPHA:
3983893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
3987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
3988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3989893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3992893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3996893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3998893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3999893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4000893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4002893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
4003893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4004893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4006893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4007893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4008893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4009893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4010893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4013893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4015893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4017893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4018893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4020893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 4;
4021893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4022893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4023893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
4024893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4025a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4026893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY_ALPHA:
4027893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4028893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
4029893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4031893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4032893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4033893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
4034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4035893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4036893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4038893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
4039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4040893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4042893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4044893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4046893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 4;
4047893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4048893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4049893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
4050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4051a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4052893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY:
4053893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4054893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 2)
4055893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4056893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4057893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i += 4)
4058893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4059893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int a = *sp & 0xc0;
4060893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int b = *sp & 0x30;
4061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int c = *sp & 0x0c;
4062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d = *sp & 0x03;
4063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)(
40655f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
40665f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
40675f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
40685f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4070893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4071893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4072a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 4)
4074893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4075893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4076893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i += 2)
4077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4078893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int msb = *sp & 0xf0;
4079893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int lsb = *sp & 0x0f;
4080893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
40825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
4083893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4086a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else if (row_info->bit_depth == 8)
4088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4090893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4091893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
4093893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4096a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4097893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else if (row_info->bit_depth == 16)
4098893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4108893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
4109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
4112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            break;
4113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
4114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
4115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
4116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
4117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Encode the alpha channel to the output gamma (the input channel is always
4120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear.)  Called only with color types that have an alpha channel.  Needs the
4121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * from_1 tables.
4122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
4123b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4124b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
4126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 row_width = row_info->width;
4127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_encode_alpha");
4129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
4131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
4132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
4133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
4134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_CONST png_bytep table = png_ptr->gamma_from_1;
4135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (table != NULL)
4137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
4138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            PNG_CONST int step =
4139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* The alpha channel is the last component: */
4142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            row += step - 1;
4143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (; row_width > 0; --row_width, row += step)
4145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *row = table[*row];
4146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
4148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
4149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
4150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (row_info->bit_depth == 16)
4152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
4153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
4154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_CONST int gamma_shift = png_ptr->gamma_shift;
4155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (table != NULL)
4157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
4158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            PNG_CONST int step =
4159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* The alpha channel is the last component: */
4162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            row += step - 2;
4163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (; row_width > 0; --row_width, row += step)
4165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            {
4166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_uint_16 v;
4167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               v = table[*(row + 1) >> gamma_shift][*row];
4169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *row = (png_byte)((v >> 8) & 0xff);
4170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(row + 1) = (png_byte)(v & 0xff);
4171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            }
4172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
4174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
4175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4176893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Only get to here if called with a weird row_info; no harm has been done,
4179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * so just issue a warning.
4180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
4181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
41855f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
4186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expands a palette row to an RGB or RGBA row depending
4187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * upon whether you supply trans and num_trans.
4188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
4189b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_expand_palette(png_row_infop row_info, png_bytep row,
4191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
4192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
4193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int shift, value;
4194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep sp, dp;
4195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
4196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width=row_info->width;
4197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
41984215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_expand_palette");
41995f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
4202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->bit_depth < 8)
4203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         switch (row_info->bit_depth)
4205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 1:
4207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4208893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)((row_width - 1) >> 3);
4209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)row_width - 1;
4210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               shift = 7 - (int)((row_width + 7) & 0x07);
4211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if ((*sp >> shift) & 0x01)
4214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = 1;
4215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = 0;
4218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4219893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (shift == 7)
4220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 0;
4222893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp--;
4223893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift++;
4227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp--;
4229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
4231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4232a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 2:
4234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4235893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)((row_width - 1) >> 2);
4236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)row_width - 1;
4237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  value = (*sp >> shift) & 0x03;
4241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp = (png_byte)value;
4242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (shift == 6)
4243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 0;
4245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp--;
4246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift += 2;
4250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp--;
4252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
4254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4255a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 4:
4257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)((row_width - 1) >> 1);
4259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)row_width - 1;
4260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               shift = (int)((row_width & 0x01) << 2);
4261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  value = (*sp >> shift) & 0x0f;
4264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp = (png_byte)value;
4265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (shift == 4)
4266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 0;
4268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp--;
4269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift += 4;
4273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp--;
4275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
4277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            default:
4280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               break;
4281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->bit_depth = 8;
4283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->pixel_depth = 8;
4284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->rowbytes = row_width;
4285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
4288893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            if (num_trans > 0)
4291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)row_width - 1;
4293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)(row_width << 2) - 1;
4294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if ((int)(*sp) >= num_trans)
4298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     *dp-- = trans_alpha[*sp];
4302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].blue;
4304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].green;
4305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].red;
4306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp--;
4307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->bit_depth = 8;
4309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->pixel_depth = 32;
4310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->rowbytes = row_width * 4;
4311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->color_type = 6;
4312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->channels = 4;
4313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else
4316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)row_width - 1;
4318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)(row_width * 3) - 1;
4319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4321893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].blue;
4323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].green;
4324893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].red;
4325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp--;
4326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4327a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->bit_depth = 8;
4329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->pixel_depth = 24;
4330893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->rowbytes = row_width * 3;
4331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->color_type = 2;
4332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->channels = 3;
4333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4334893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* If the bit depth < 8, it is expanded to 8.  Also, if the already
4340893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * expanded transparency value is supplied, an alpha channel is built.
4341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
4342b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_expand(png_row_infop row_info, png_bytep row,
4344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_color_16p trans_color)
4345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
4346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int shift, value;
4347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep sp, dp;
4348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
4349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width=row_info->width;
4350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
43514215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_expand");
43525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
4354893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
4355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         unsigned int gray = trans_color ? trans_color->gray : 0;
4357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth < 8)
4359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4360893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            switch (row_info->bit_depth)
4361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 1:
4363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gray = (gray & 0x01) * 0xff;
4365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row + (png_size_t)((row_width - 1) >> 3);
4366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp = row + (png_size_t)row_width - 1;
4367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = 7 - (int)((row_width + 7) & 0x07);
4368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
4369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if ((*sp >> shift) & 0x01)
4371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *dp = 0xff;
4372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *dp = 0;
4375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (shift == 7)
4377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
4378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 0;
4379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp--;
4380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
4381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift++;
4384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     dp--;
4386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
4388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4389a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 2:
4391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gray = (gray & 0x03) * 0x55;
4393893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row + (png_size_t)((row_width - 1) >> 2);
4394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp = row + (png_size_t)row_width - 1;
4395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4396893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
4397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     value = (*sp >> shift) & 0x03;
4399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
4400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        (value << 6));
4401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (shift == 6)
4402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
4403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 0;
4404893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp--;
4405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
4406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift += 2;
4409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     dp--;
4411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
4413893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4414a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 4:
4416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gray = (gray & 0x0f) * 0x11;
4418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row + (png_size_t)((row_width - 1) >> 1);
4419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp = row + (png_size_t)row_width - 1;
4420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
4422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     value = (*sp >> shift) & 0x0f;
4424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = (png_byte)(value | (value << 4));
4425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (shift == 4)
4426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
4427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 0;
4428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp--;
4429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
4430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 4;
4433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     dp--;
4435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
4437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               default:
4440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  break;
4441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4442a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4443893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->bit_depth = 8;
4444893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 8;
4445893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width;
4446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4447893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (trans_color != NULL)
4449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
4451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               gray = gray & 0xff;
4453893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)row_width - 1;
4454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)(row_width << 1) - 1;
4455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (*sp == gray)
4459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0;
4460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4464893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = *sp--;
4465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4467a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else if (row_info->bit_depth == 16)
4469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               unsigned int gray_high = (gray >> 8) & 0xff;
4471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               unsigned int gray_low = gray & 0xff;
4472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + row_info->rowbytes - 1;
4473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (row_info->rowbytes << 1) - 1;
4474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
44764215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
4477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0;
4479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0;
4480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = *sp--;
4489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = *sp--;
4490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4492a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
4494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
4495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4496893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
4497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_width);
4498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
4501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
4503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte red = (png_byte)(trans_color->red & 0xff);
4505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte green = (png_byte)(trans_color->green & 0xff);
4506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte blue = (png_byte)(trans_color->blue & 0xff);
4507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            sp = row + (png_size_t)row_info->rowbytes - 1;
4508893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            dp = row + (png_size_t)(row_width << 2) - 1;
4509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
4510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
4512893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0;
4513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
4515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0xff;
4516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4518893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4522893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else if (row_info->bit_depth == 16)
4523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
4525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
4526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
4527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte red_low = (png_byte)(trans_color->red & 0xff);
4528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte green_low = (png_byte)(trans_color->green & 0xff);
4529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
4530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            sp = row + row_info->rowbytes - 1;
4531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            dp = row + (png_size_t)(row_width << 3) - 1;
4532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
4533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (*(sp - 5) == red_high &&
4535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 4) == red_low &&
4536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 3) == green_high &&
4537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 2) == green_low &&
4538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 1) == blue_high &&
4539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp    ) == blue_low)
4540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0;
4542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0;
4543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
4546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0xff;
4548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0xff;
4549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4556893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
4560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->channels = 4;
4561893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
45624215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4564893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4566893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4567893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_EXPAND_16_SUPPORTED
4569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* If the bit depth is 8 and the color type is not a palette type expand the
4570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * whole row to 16 bits.  Has no effect otherwise.
4571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
4572b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4573b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_expand_16(png_row_infop row_info, png_bytep row)
4574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
4575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->bit_depth == 8 &&
4576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
4577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
4578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* The row have a sequence of bytes containing [0..255] and we need
4579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * to turn it into another row containing [0..65535], to do this we
4580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * calculate:
4581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
4582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *  (input / 255) * 65535
4583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
4584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *  Which happens to be exactly input * 257 and this can be achieved
4585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *  simply by byte replication in place (copying backwards).
4586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
4587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
4588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
4589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      while (dp > sp)
4590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         dp[-2] = dp[-1] = *--sp, dp -= 2;
4591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->rowbytes *= 2;
4593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->bit_depth = 16;
4594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
4596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
4597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
4598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4599b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_QUANTIZE_SUPPORTED
4600b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4601b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_quantize(png_row_infop row_info, png_bytep row,
4602b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
4603b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{
4604b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_bytep sp, dp;
4605b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_uint_32 i;
4606b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_uint_32 row_width=row_info->width;
4607b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4608b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_quantize");
4609b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4610b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (row_info->bit_depth == 8)
4611b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4612b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
4613b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4614b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         int r, g, b, p;
4615b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         sp = row;
4616b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         dp = row;
4617b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i = 0; i < row_width; i++)
4618b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
4619b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            r = *sp++;
4620b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            g = *sp++;
4621b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            b = *sp++;
4622b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4623b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            /* This looks real messy, but the compiler will reduce
4624b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * it down to a reasonable formula.  For example, with
4625b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * 5 bits per color, we get:
4626b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * p = (((r >> 3) & 0x1f) << 10) |
4627b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             *    (((g >> 3) & 0x1f) << 5) |
4628b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             *    ((b >> 3) & 0x1f);
4629b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             */
4630b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4631b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4632b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4633b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4634b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4635b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_BLUE_BITS)) |
4636b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4637b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4638b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4639b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            *dp++ = palette_lookup[p];
4640b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
4641b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4642b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4643b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->channels = 1;
4644b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->pixel_depth = row_info->bit_depth;
4645b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4646b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4647b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4648b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4649b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         palette_lookup != NULL)
4650b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4651b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         int r, g, b, p;
4652b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         sp = row;
4653b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         dp = row;
4654b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i = 0; i < row_width; i++)
4655b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
4656b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            r = *sp++;
4657b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            g = *sp++;
4658b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            b = *sp++;
4659b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            sp++;
4660b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4661b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4662b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4663b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4664b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4665b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4666b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_BLUE_BITS)) |
4667b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4668b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4669b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4670b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            *dp++ = palette_lookup[p];
4671b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
4672b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4673b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4674b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->channels = 1;
4675b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->pixel_depth = row_info->bit_depth;
4676b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4677b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4678b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4679b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4680b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         quantize_lookup)
4681b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4682b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         sp = row;
4683b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4684b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i = 0; i < row_width; i++, sp++)
4685b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
4686b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            *sp = quantize_lookup[*sp];
4687b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
4688b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4689b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4690b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}
4691b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* PNG_READ_QUANTIZE_SUPPORTED */
4692b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4693b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Transform the row.  The order of transformations is significant,
4694b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * and is very touchy.  If you add a transformation, take care to
4695b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * decide how it fits in with the other transformations here.
4696b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */
4697b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarivoid /* PRIVATE */
4698b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
4699b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{
4700b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_read_transformations");
4701b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4702b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->row_buf == NULL)
4703b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4704b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
4705b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * error is incredibly rare and incredibly easy to debug without this
4706b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * information.
4707b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4708b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_error(png_ptr, "NULL row buffer");
4709b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4710b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4711b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
4712b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
4713b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
4714b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * all transformations, however in practice the ROW_INIT always gets done on
4715b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * demand, if necessary.
4716b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
4717b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
4718b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      !(png_ptr->flags & PNG_FLAG_ROW_INIT))
4719b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4720b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Application has failed to call either png_read_start_image() or
4721b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * png_read_update_info() after setting transforms that expand pixels.
4722b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
4723b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4724b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_error(png_ptr, "Uninitialized row");
4725b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4726b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4727b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_SUPPORTED
4728b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_EXPAND)
4729b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4730b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4731b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4732b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
4733b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4734b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4735b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4736b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else
4737b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4738b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if (png_ptr->num_trans &&
4739b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             (png_ptr->transformations & PNG_EXPAND_tRNS))
4740b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_do_expand(row_info, png_ptr->row_buf + 1,
4741b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                &(png_ptr->trans_color));
4742b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4743b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         else
4744b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_do_expand(row_info, png_ptr->row_buf + 1,
4745b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                NULL);
4746b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4747b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4748b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4749b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4750b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4751b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
4752b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      !(png_ptr->transformations & PNG_COMPOSE) &&
4753b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
4754b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4755b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4756b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         0 /* at_start == false, because SWAP_ALPHA happens later */);
4757b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4758b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4759b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4760b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
4761b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4762b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int rgb_error =
4763b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          png_do_rgb_to_gray(png_ptr, row_info,
4764b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari              png_ptr->row_buf + 1);
4765b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4766b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (rgb_error)
4767b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4768b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         png_ptr->rgb_to_gray_status=1;
4769b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4770b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             PNG_RGB_TO_GRAY_WARN)
4771b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4772b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4773b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4774b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             PNG_RGB_TO_GRAY_ERR)
4775b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4776b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4777b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4778b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4779b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4780b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
4781b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4782b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   In most cases, the "simple transparency" should be done prior to doing
4783b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
4784b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   pixel is transparent.  You would also need to make sure that the
4785b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   transparency information is upgraded to RGB.
4786b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4787b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   To summarize, the current flow is:
4788b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
4789b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   with background "in place" if transparent,
4790b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   convert to RGB if necessary
4791b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + alpha -> composite with gray background and remove alpha bytes,
4792b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   convert to RGB if necessary
4793b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4794b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   To support RGB backgrounds for gray images we need:
4795b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + simple transparency -> convert to RGB + simple transparency,
4796b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   compare 3 or 6 bytes and composite with
4797b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   background "in place" if transparent
4798b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   (3x compare/pixel compared to doing
4799b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   composite with gray bkgrnd)
4800b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + alpha -> convert to RGB + alpha, composite with background and
4801b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   remove alpha bytes (3x float
4802b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   operations/pixel compared with composite
4803b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   on gray background)
4804b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4805b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  Greg's change will do this.  The reason it wasn't done before is for
4806b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  performance, as this increases the per-pixel operations.  If we would check
4807b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  in advance if the background was gray or RGB, and position the gray-to-RGB
4808b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  transform appropriately, then it would save a lot of work/time.
4809b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */
4810b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4811b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4812b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* If gray -> RGB, do so now only if background is non-gray; else do later
4813b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * for performance reasons
4814b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
4815b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
4816b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
4817b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4818b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4819b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4820b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4821b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4822b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_COMPOSE)
4823b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
4824b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4826b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GAMMA_SUPPORTED
4827b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->transformations & PNG_GAMMA) &&
4828b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4829b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Because RGB_TO_GRAY does the gamma transform. */
4830b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
4831b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4832b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4833b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4834b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Because PNG_COMPOSE does the gamma transform if there is something to
4835b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * do (if there is an alpha channel or transparency.)
4836b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4837b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       !((png_ptr->transformations & PNG_COMPOSE) &&
4838b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       ((png_ptr->num_trans != 0) ||
4839b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
4840b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4841b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Because png_init_read_transformations transforms the palette, unless
4842b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * RGB_TO_GRAY will do the transform.
4843b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4844b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
4845b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
4846b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
48475f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4848b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4849b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
4850b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      (png_ptr->transformations & PNG_COMPOSE) &&
4851b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
4852b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4853b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4854b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         0 /* at_start == false, because SWAP_ALPHA happens later */);
4855b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4857b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4858b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
4859b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      (row_info->color_type & PNG_COLOR_MASK_ALPHA))
4860b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
4861b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4863b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
4864b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_SCALE_16_TO_8)
4865b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
4866b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4868b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
4869b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* There is no harm in doing both of these because only one has any effect,
4870b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * by putting the 'scale' option first if the app asks for scale (either by
4871b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * calling the API or in a TRANSFORM flag) this is what happens.
4872b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
4873b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_16_TO_8)
4874b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_chop(row_info, png_ptr->row_buf + 1);
4875b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4877b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_QUANTIZE_SUPPORTED
4878b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_QUANTIZE)
4879b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4880b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_quantize(row_info, png_ptr->row_buf + 1,
4881b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          png_ptr->palette_lookup, png_ptr->quantize_index);
4882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4883b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (row_info->rowbytes == 0)
4884b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
4885b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4886b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* PNG_READ_QUANTIZE_SUPPORTED */
4887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4888b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_16_SUPPORTED
4889b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* Do the expansion now, after all the arithmetic has been done.  Notice
4890b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * that previous transformations can handle the PNG_EXPAND_16 flag if this
4891b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * is efficient (particularly true in the case of gamma correction, where
4892b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * better accuracy results faster!)
4893b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
4894b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_EXPAND_16)
4895b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_expand_16(row_info, png_ptr->row_buf + 1);
4896b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4898b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4899b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
4900b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
4901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
4902b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4903b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4905b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_SUPPORTED
4906b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_INVERT_MONO)
4907b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_invert(row_info, png_ptr->row_buf + 1);
4908b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4910b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
4911b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_INVERT_ALPHA)
4912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
4913b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4914893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4915b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SHIFT_SUPPORTED
4916b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_SHIFT)
4917b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_unshift(row_info, png_ptr->row_buf + 1,
4918b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          &(png_ptr->shift));
4919b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
49205f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4921b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACK_SUPPORTED
4922b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_PACK)
4923b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_unpack(row_info, png_ptr->row_buf + 1);
4924b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4926b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
4927b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* Added at libpng-1.5.10 */
4928b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4929b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       png_ptr->num_palette_max >= 0)
4930b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_check_palette_indexes(png_ptr, row_info);
4931b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4932893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4933b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_BGR_SUPPORTED
4934b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_BGR)
4935b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_bgr(row_info, png_ptr->row_buf + 1);
4936b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4937a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4938b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACKSWAP_SUPPORTED
4939b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_PACKSWAP)
4940b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_packswap(row_info, png_ptr->row_buf + 1);
4941b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4942a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4943b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_FILLER_SUPPORTED
4944b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_FILLER)
4945b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_read_filler(row_info, png_ptr->row_buf + 1,
4946b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          (png_uint_32)png_ptr->filler, png_ptr->flags);
4947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4949b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
4950b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_SWAP_ALPHA)
4951b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
4952b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4954b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_16BIT_SUPPORTED
4955b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_SUPPORTED
4956b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_SWAP_BYTES)
4957b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_swap(row_info, png_ptr->row_buf + 1);
4958b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4959b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4960a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4961b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
4962b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->transformations & PNG_USER_TRANSFORM)
4963b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    {
4964b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (png_ptr->read_user_transform_fn != NULL)
4965b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
4966b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             (png_ptr,     /* png_ptr */
4967b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             row_info,     /* row_info: */
4968b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_uint_32 width;       width of row */
4969b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_size_t rowbytes;     number of bytes in row */
4970b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte color_type;     color type of pixels */
4971b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte bit_depth;      bit depth of samples */
4972b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte channels;       number of channels (1-4) */
4973b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
4974b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             png_ptr->row_buf + 1);    /* start of pixel data for row */
4975b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
4976b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (png_ptr->user_transform_depth)
4977b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->bit_depth = png_ptr->user_transform_depth;
4978a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4979b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (png_ptr->user_transform_channels)
4980b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->channels = png_ptr->user_transform_channels;
4981b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4982b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
4983b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          row_info->channels);
4984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4985b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
4986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4987b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4989b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4990b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
4991893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_READ_SUPPORTED */
4992