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 *
47a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * Last changed in libpng 1.6.24 [August 4, 2016]
5114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * Copyright (c) 1998-2002,2004,2006-2016 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,
517a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis             "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
949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * to have been read in all cases; the need_IHDR parameter allows for this
959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * check too.
96b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
97b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int
98b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_rtran_ok(png_structrp png_ptr, int need_IHDR)
99b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr != NULL)
101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_app_error(png_ptr,
1047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis             "invalid after png_start_read_image or png_read_update_info");
105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_app_error(png_ptr, "invalid before the PNG header has been read");
108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Turn on failure to initialize correctly for all transforms. */
112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         return 1; /* Ok */
115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return 0; /* no png_error possible! */
119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_BACKGROUND_SUPPORTED
123a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Handle alpha and tRNS via a background color */
124b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
125b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_background_fixed(png_structrp png_ptr,
126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_color_16p background_color, int background_gamma_code,
127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int need_expand, png_fixed_point background_gamma)
128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_background_fixed");
130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
132a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_warning(png_ptr, "Application must supply a known background gamma");
137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      return;
138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->background = *background_color;
145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->background_gamma = background_gamma;
146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
1479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (need_expand != 0)
148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else
150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
154b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
155b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_background(png_structrp png_ptr,
156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_color_16p background_color, int background_gamma_code,
157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int need_expand, double background_gamma)
158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1627a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#  endif /* FLOATING_POINT */
163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_BACKGROUND */
164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * one that pngrtran does first (scale) happens.  This is necessary to allow the
167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
170b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
171b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_scale_16(png_structrp png_ptr)
172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_scale_16");
174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_SCALE_16_TO_8;
179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Chop 16-bit depth files to 8-bit depth */
184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
185b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_strip_16(png_structrp png_ptr)
186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1874215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_strip_16");
1885f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
1899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
190a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_16_TO_8;
193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1965f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
198b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_strip_alpha(png_structrp png_ptr)
199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2004215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_strip_alpha");
2015f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_STRIP_ALPHA;
206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
210b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_fixed_point
211b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktranslate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
2127a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis    int is_screen)
213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Check for flag values.  The main reason for having the old Mac value as a
215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * flag is that it is pretty near impossible to work out what the correct
216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * value is from Apple documentation - a working Mac system is needed to
217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * discover the value!
218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma == PNG_DEFAULT_sRGB ||
220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* If there is no sRGB support this just sets the gamma to the standard
223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * sRGB value.  (This is a side effect of using this function!)
224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_sRGB_SUPPORTED
226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     else
228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_UNUSED(png_ptr)
229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
2309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (is_screen != 0)
231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_sRGB;
232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_sRGB_INVERSE;
234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (output_gamma == PNG_GAMMA_MAC_18 ||
237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (is_screen != 0)
240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_MAC_OLD;
241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_GAMMA_MAC_INVERSE;
243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return output_gamma;
246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
249b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_fixed_point
250b50c217251b086440efcdb273c22f86a06c80cbaChris Craikconvert_gamma_value(png_structrp png_ptr, double output_gamma)
251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following silently ignores cases where fixed point (times 100,000)
253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gamma values are passed to the floating point API.  This is safe and it
254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * means the fixed point constants work just fine with the floating point
255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * API.  The alternative would just lead to undetected errors and spurious
256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * bug reports.  Negative values fail inside the _fixed API unless they
257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * correspond to the flag values.
258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma > 0 && output_gamma < 128)
260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      output_gamma *= PNG_FP_1;
261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* This preserves -1 and -2 exactly: */
263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   output_gamma = floor(output_gamma + .5);
264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_fixed_error(png_ptr, "gamma value");
267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return (png_fixed_point)output_gamma;
269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_ALPHA_MODE || READ_GAMMA */
272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
274b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
275b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
2767a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis    png_fixed_point output_gamma)
277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int compose = 0;
279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_fixed_point file_gamma;
280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_alpha_mode");
282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
284a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Validate the value to ensure it is in a reasonable range. The value
289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * is expected to be 1 or greater, but this range test allows for some
290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * viewing correction values.  The intent is to weed out users of this API
291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * who use the inverse of the gamma value accidentally!  Since some of these
292114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett    * values are reasonable this may have to be changed:
293114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett    *
294114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit
295114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett    * gamma of 36, and its reciprocal.)
296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
297114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett   if (output_gamma < 1000 || output_gamma > 10000000)
298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "output gamma out of expected range");
299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The default file gamma is the inverse of the output gamma; the output
301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gamma may be changed below so get the file value first:
302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   file_gamma = png_reciprocal(output_gamma);
304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* There are really 8 possibilities here, composed of any combination
306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * of:
307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *    premultiply the color channels
309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *    do not encode non-opaque pixels
310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *    encode the alpha as well as the color channels
311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * The differences disappear if the input/output ('screen') gamma is 1.0,
313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * because then the encoding is a no-op and there is only the choice of
314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * premultiplying the color channels or not.
315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_alpha_mode and png_set_background interact because both use
317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_compose to do the work.  Calling both is only useful when
318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   switch (mode)
322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_PNG:        /* default: png standard */
324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* No compose, but it may be set by png_set_background! */
325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         compose = 1;
331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* The output is linear: */
334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         output_gamma = PNG_FP_1;
335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         compose = 1;
339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* output_gamma records the encoding of opaque pixels! */
342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         compose = 1;
346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_ENCODE_ALPHA;
347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      default:
351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "invalid alpha mode");
352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Only set the default gamma if the file gamma has not been set (this has
355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the side effect that the gamma in a second call to png_set_alpha_mode will
356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * be ignored.)
357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->colorspace.gamma == 0)
359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->colorspace.gamma = file_gamma;
361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* But always set the output gamma: */
365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->screen_gamma = output_gamma;
366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Finally, if pre-multiplying, set the background fields to achieve the
368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * desired result.
369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
3709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (compose != 0)
371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* And obtain alpha pre-multiplication by composing on black: */
373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr,
3807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis             "conflicting calls to set alpha mode and background");
381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations |= PNG_COMPOSE;
383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
387b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
388b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
3917a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis       output_gamma));
392893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_QUANTIZE_SUPPORTED
397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Dither file to 8-bit.  Supply a palette, the current number
398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * of elements in the palette, the maximum number of elements
399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * allowed, and a histogram if possible.  If the current number
4009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * of colors is greater than the maximum number, the palette will be
401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * modified to fit in the maximum number.  "full_quantize" indicates
402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * whether we need a quantizing cube set up for RGB images, or if we
403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * simply are reducing the number of colors in a paletted image.
404893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projecttypedef struct png_dsort_struct
407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   struct png_dsort_struct * next;
409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_byte left;
410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_byte right;
411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} png_dsort;
412b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef png_dsort *   png_dsortp;
413b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef png_dsort * * png_dsortpp;
414893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
416b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_quantize(png_structrp png_ptr, png_colorp palette,
417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int num_palette, int maximum_colors, png_const_uint_16p histogram,
418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    int full_quantize)
419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_quantize");
4215f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
423a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= PNG_QUANTIZE;
426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (full_quantize == 0)
428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int i;
430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
432851c67770f9cebece9c79e914a54c348f539a512Matt Sarett          (png_uint_32)(num_palette * (sizeof (png_byte))));
433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      for (i = 0; i < num_palette; i++)
434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->quantize_index[i] = (png_byte)i;
435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (num_palette > maximum_colors)
438893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (histogram != NULL)
440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This is easy enough, just throw out the least used colors.
442a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * Perhaps not the best solution, but good enough.
443a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
444893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
445893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int i;
446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
447a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initialize an array to sort colors */
448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
449851c67770f9cebece9c79e914a54c348f539a512Matt Sarett             (png_uint_32)(num_palette * (sizeof (png_byte))));
450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Initialize the quantize_sort array */
452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0; i < num_palette; i++)
453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->quantize_sort[i] = (png_byte)i;
454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
455893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* Find the least used palette entries by starting a
456a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * bubble sort, and running it until we have sorted
457a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * out enough colors.  Note that we don't care about
458a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * sorting all the colors, just finding which are
459a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * least used.
460a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = num_palette - 1; i >= maximum_colors; i--)
463893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
464a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            int done; /* To stop early if the list is pre-sorted */
465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int j;
466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
467893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            done = 1;
468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (j = 0; j < i; j++)
469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (histogram[png_ptr->quantize_sort[j]]
471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   < histogram[png_ptr->quantize_sort[j + 1]])
472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_byte t;
474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  t = png_ptr->quantize_sort[j];
476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_sort[j + 1] = t;
478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  done = 0;
479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett            if (done != 0)
483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
486a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Swap the palette around, and set up a table, if necessary */
4879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if (full_quantize != 0)
488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int j = num_palette;
490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
491a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            /* Put all the useful colors within the max, but don't
492a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             * move the others.
493a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             */
494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < maximum_colors; i++)
495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  do
499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     j--;
500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i] = palette[j];
503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
506893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
508893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int j = num_palette;
509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
510a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            /* Move all the used colors inside the max limit, and
511a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             * develop a translation table.
512a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott             */
513893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < maximum_colors; i++)
514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
515a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott               /* Only move the colors we need to */
516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
518893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_color tmp_color;
519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  do
521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     j--;
522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
524893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  tmp_color = palette[j];
525893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[j] = palette[i];
526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i] = tmp_color;
527a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                  /* Indicate where the color went */
528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_index[j] = (png_byte)i;
529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_index[i] = (png_byte)j;
530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
533a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            /* Find closest color for those colors we are not using */
534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < num_palette; i++)
535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int min_d, k, min_k, d_index;
539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
540a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                  /* Find the closest color to one we threw out */
541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  d_index = png_ptr->quantize_index[i];
542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (k = 1, min_k = 0; k < maximum_colors; k++)
544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     int d;
546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (d < min_d)
550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        min_d = d;
552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        min_k = k;
553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
555a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                  /* Point to closest color */
556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->quantize_index[i] = (png_byte)min_k;
557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_free(png_ptr, png_ptr->quantize_sort);
561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->quantize_sort = NULL;
562893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
564893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This is much harder to do simply (and quickly).  Perhaps
566a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * we need to go through a median cut routine, but those
567a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * don't always behave themselves with only a few colors
568a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * as input.  So we will just find the closest two colors,
569a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * and throw out one of them (chosen somewhat randomly).
570a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * [We don't understand this at all, so if someone wants to
571a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          *  work on improving it, be our guest - AED, GRP]
572a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
573893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int i;
574893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int max_d;
575893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int num_new_palette;
576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_dsortp t;
577893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_dsortpp hash;
578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
5794215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         t = NULL;
580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
581a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initialize palette index arrays */
582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
583851c67770f9cebece9c79e914a54c348f539a512Matt Sarett             (png_uint_32)(num_palette * (sizeof (png_byte))));
584893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
585851c67770f9cebece9c79e914a54c348f539a512Matt Sarett             (png_uint_32)(num_palette * (sizeof (png_byte))));
586893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
587a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initialize the sort array */
588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0; i < num_palette; i++)
589893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
590893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_ptr->index_to_palette[i] = (png_byte)i;
591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_ptr->palette_to_index[i] = (png_byte)i;
592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
5945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             (sizeof (png_dsortp))));
596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         num_new_palette = num_palette;
598893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
599a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott         /* Initial wild guess at how far apart the farthest pixel
600a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * pair we will be eliminating will be.  Larger
601a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * numbers mean more areas will be allocated, Smaller
602a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * numbers run the risk of not saving enough data, and
603a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * having to do this all over again.
604a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          *
605a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          * I have not done extensive checking on this number.
606a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          */
607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         max_d = 96;
608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         while (num_new_palette > maximum_colors)
610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < num_new_palette - 1; i++)
612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int j;
614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (j = i + 1; j < num_new_palette; j++)
616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d;
618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  d = PNG_COLOR_DIST(palette[i], palette[j]);
620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
621893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (d <= max_d)
622893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
623893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t = (png_dsortp)png_malloc_warn(png_ptr,
625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         (png_uint_32)(sizeof (png_dsort)));
626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (t == NULL)
628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                         break;
629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
630893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t->next = hash[d];
631893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t->left = (png_byte)i;
632893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t->right = (png_byte)j;
633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     hash[d] = t;
634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (t == NULL)
637893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
638893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (t != NULL)
641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i <= max_d; i++)
642893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
643893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (hash[i] != NULL)
644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
645893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_dsortp p;
646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (p = hash[i]; p; p = p->next)
648893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if ((int)png_ptr->index_to_palette[p->left]
650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         < num_new_palette &&
651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         (int)png_ptr->index_to_palette[p->right]
652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         < num_new_palette)
653893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
654893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        int j, next_j;
655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if (num_new_palette & 0x01)
657893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           j = p->left;
659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           next_j = p->right;
660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           j = p->right;
664893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           next_j = p->left;
665893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
666893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
667893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        num_new_palette--;
668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        palette[png_ptr->index_to_palette[j]]
669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            = palette[num_new_palette];
6709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (full_quantize == 0)
671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           int k;
673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           for (k = 0; k < num_palette; k++)
675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           {
676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                              if (png_ptr->quantize_index[k] ==
677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                  png_ptr->index_to_palette[j])
678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                 png_ptr->quantize_index[k] =
679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                     png_ptr->index_to_palette[next_j];
680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                              if ((int)png_ptr->quantize_index[k] ==
682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                  num_new_palette)
683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                 png_ptr->quantize_index[k] =
684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                     png_ptr->index_to_palette[j];
685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           }
686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_ptr->index_to_palette[png_ptr->palette_to_index
689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            [num_new_palette]] = png_ptr->index_to_palette[j];
690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            = png_ptr->palette_to_index[num_new_palette];
693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
6945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                        png_ptr->index_to_palette[j] =
6955f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                            (png_byte)num_new_palette;
696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
6975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                        png_ptr->palette_to_index[num_new_palette] =
6985f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                            (png_byte)j;
699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (num_new_palette <= maximum_colors)
701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        break;
702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (num_new_palette <= maximum_colors)
704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 769; i++)
709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (hash[i] != NULL)
711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_dsortp p = hash[i];
713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  while (p)
714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     t = p->next;
716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_free(png_ptr, p);
717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     p = t;
718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               hash[i] = 0;
721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            max_d += 96;
723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_free(png_ptr, hash);
725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_free(png_ptr, png_ptr->palette_to_index);
726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_free(png_ptr, png_ptr->index_to_palette);
7274215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->palette_to_index = NULL;
7284215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->index_to_palette = NULL;
729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      num_palette = maximum_colors;
731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->palette == NULL)
733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
734893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->palette = palette;
735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->num_palette = (png_uint_16)num_palette;
737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
7389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (full_quantize != 0)
739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
740893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int i;
741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_bytep distance;
742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          PNG_QUANTIZE_BLUE_BITS;
744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_size_t num_entries = ((png_size_t)1 << total_bits);
7485f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (png_uint_32)(num_entries * (sizeof (png_byte))));
751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (sizeof (png_byte))));
754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      for (i = 0; i < num_palette; i++)
758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int ir, ig, ib;
760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (ir = 0; ir < num_red; ir++)
765893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            /* int dr = abs(ir - r); */
767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int dr = ((ir > r) ? ir - r : r - ir);
768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                PNG_QUANTIZE_GREEN_BITS));
770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
771893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (ig = 0; ig < num_green; ig++)
772893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
773893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               /* int dg = abs(ig - g); */
774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int dg = ((ig > g) ? ig - g : g - ig);
775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int dt = dr + dg;
776893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               int dm = ((dr > dg) ? dr : dg);
777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (ib = 0; ib < num_blue; ib++)
780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d_index = index_g | ib;
782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  /* int db = abs(ib - b); */
783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int db = ((ib > b) ? ib - b : b - ib);
784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int dmax = ((dm > db) ? dm : db);
785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d = dmax + dt + db;
786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (d < (int)distance[d_index])
788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     distance[d_index] = (png_byte)d;
790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_ptr->palette_lookup[d_index] = (png_byte)i;
791893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
796893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_free(png_ptr, distance);
798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
8009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_QUANTIZE */
801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
803b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
804b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
8057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis    png_fixed_point file_gamma)
806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_gamma_fixed");
8085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
810a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
8115f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * premultiplied alpha support; this actually hides an undocumented feature
818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * of the previous implementation which allowed gamma processing to be
819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * disabled in background handling.  There is no evidence (so far) that this
820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * was being used; however, png_set_background itself accepted and must still
821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * accept '0' for the gamma value it takes, because it isn't always used.
822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * Since this is an API change (albeit a very minor one that removes an
824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * undocumented API feature) the following checks were only enabled in
825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * libpng-1.6.0.
826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (file_gamma <= 0)
828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "invalid file gamma in png_set_gamma");
829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (scrn_gamma <= 0)
831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Set the gamma values unconditionally - this overrides the value in the PNG
834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * different, easier, way to default the file gamma.
836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->colorspace.gamma = file_gamma;
838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->screen_gamma = scrn_gamma;
840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_FLOATING_POINT_SUPPORTED
843b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
844b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
8477a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis       convert_gamma_value(png_ptr, file_gamma));
848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
8499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#  endif /* FLOATING_POINT */
850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_GAMMA */
851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
8525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expand paletted images to RGB, expand grayscale images of
854893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * to alpha channels.
856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
857893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
858b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_expand(png_structrp png_ptr)
859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
8604215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_expand");
8615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
863a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
8645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* GRR 19990627:  the following three functions currently are identical
869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  to png_set_expand().  However, it is entirely reasonable that someone
870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  might wish to expand an indexed image to RGB but *not* expand a single,
871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  fully transparent palette entry to a full alpha channel--perhaps instead
872893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  the transparent color with a particular RGB value, or drop tRNS entirely.
874893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  IOW, a future version of the library may make the transformations flag
875893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  a bit more fine-grained, with separate bits for each of these three
876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  functions.
877893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  More to the point, these functions make it obvious what libpng will be
879893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  doing, whereas "expand" can (and does) mean any number of things.
880893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
8815f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
8825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott *  to expand only the sample depth but not to expand the tRNS to alpha
8835f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
884893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
886893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expand paletted images to RGB. */
887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
888b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_palette_to_rgb(png_structrp png_ptr)
889893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
8904215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_palette_to_rgb");
8915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
893a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
8945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
897893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expand grayscale images of less than 8-bit depth to 8 bits. */
899893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
900b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
9024215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
9035f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
9049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
905a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
9065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
907893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_EXPAND;
908893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
909893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Expand tRNS chunks to alpha channels. */
911893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
912b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_tRNS_to_alpha(png_structrp png_ptr)
913893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_tRNS_to_alpha");
9155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
9169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
917a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
9185f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
9219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_EXPAND */
922893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_EXPAND_16_SUPPORTED
924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it may not work correctly.)
926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
927893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
928b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_expand_16(png_structrp png_ptr)
929893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_set_expand_16");
9315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
9329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
936893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
9395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
941b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_gray_to_rgb(png_structrp png_ptr)
942893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
9434215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_gray_to_rgb");
9445f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
9459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 0) == 0)
946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      return;
947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Because rgb must be 8 bits or more: */
949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_expand_gray_1_2_4_to_8(png_ptr);
950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_GRAY_TO_RGB;
951893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
9545f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
955b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGFAPI
956b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_fixed_point red, png_fixed_point green)
958893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
9594215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_rgb_to_gray");
9605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Need the IHDR here because of the check on color_type below. */
962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* TODO: fix this */
9639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_rtran_ok(png_ptr, 1) == 0)
964a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
9655f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
9669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   switch (error_action)
967893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ERROR_ACTION_NONE:
969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_RGB_TO_GRAY;
970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
971a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ERROR_ACTION_WARN:
973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      case PNG_ERROR_ACTION_ERROR:
977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         break;
979a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      default:
981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "invalid error action to rgb_to_gray");
982893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
9855f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->transformations |= PNG_EXPAND;
987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else
988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Make this an error in 1.6 because otherwise the application may assume
990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * that it just worked and get a memory overwrite.
991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr,
9937a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis          "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
996893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
997893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
998893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
1000893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_16 red_int, green_int;
1002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* NOTE: this calculation does not round, but this behavior is retained
10049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          * for consistency; the inaccuracy is very small.  The code here always
1005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * overwrites the coefficients, regardless of whether they have been
1006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * defaulted or set already.
1007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
1009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
1010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->rgb_to_gray_red_coeff   = red_int;
1012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->rgb_to_gray_green_coeff = green_int;
1013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->rgb_to_gray_coefficients_set = 1;
1014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1016893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
1017893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (red >= 0 && green >= 0)
1019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_app_warning(png_ptr,
10207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                "ignoring out of range rgb_to_gray coefficients");
1021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Use the defaults, from the cHRM chunk if set, else the historical
1023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
1024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * png_do_rgb_to_gray for more discussion of the values.  In this case
1025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * the coefficients are not marked as 'set' and are not overwritten if
1026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * something has already provided a default.
1027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
10297a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis             png_ptr->rgb_to_gray_green_coeff == 0)
1030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->rgb_to_gray_red_coeff   = 6968;
1032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->rgb_to_gray_green_coeff = 23434;
1033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
1035893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1036893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1037893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FLOATING_POINT_SUPPORTED
1040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Convert a RGB image to a grayscale of the same width.  This allows us,
1041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
1042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
1043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1044b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI
1045b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
10467a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis    double green)
1047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_set_rgb_to_gray_fixed(png_ptr, error_action,
10497a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
1050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* FLOATING POINT */
1053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* RGB_TO_GRAY */
1055893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1056893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1057a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1058893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
1059b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    read_user_transform_fn)
1061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
10624215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_set_read_user_transform_fn");
10635f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
10645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->transformations |= PNG_USER_TRANSFORM;
1066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->read_user_transform_fn = read_user_transform_fn;
1067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1068893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1070893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
1073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* In the case of gamma transformations only do transformations on images where
1074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
1075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * slows things down slightly, and also needlessly introduces small errors.
1076893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
1077b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int /* PRIVATE */
1078b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
1079893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
1081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * correction as a difference of the overall transform from 1.0
1082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * We want to compare the threshold with s*f - 1, if we get
1084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * overflow here it is because of wacky gamma values so we
1085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * turn on processing anyway.
1086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_fixed_point gtest;
1088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
1089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       png_gamma_significant(gtest);
1090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1091893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Initialize everything needed for the read.  This includes modifying
1094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the palette.
1095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
1096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
10979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett/* For the moment 'png_init_palette_transformations' and
1098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'png_init_rgb_transformations' only do some flag canceling optimizations.
1099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The intent is that these two routines should have palette or rgb operations
1100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * extracted from 'png_init_read_transformations'.
1101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
1102b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void /* PRIVATE */
1103b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_palette_transformations(png_structrp png_ptr)
1104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Called to handle the (input) palette case.  In png_do_read_transformations
1106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the first step is to expand the palette if requested, so this code must
1107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * take care to only make changes that are invariant with respect to the
1108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * palette expansion, or only do them if there is no expansion.
1109a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott    *
1110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * STRIP_ALPHA has already been handled in the caller (by setting num_trans
1111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * to 0.)
1112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    */
1113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_alpha = 0;
1114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_transparency = 0;
1115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->num_trans > 0)
1117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int i;
1119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Ignore if all the entries are opaque (unlikely!) */
1121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      for (i=0; i<png_ptr->num_trans; ++i)
1122b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
1123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->trans_alpha[i] == 255)
1124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            continue;
1125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else if (png_ptr->trans_alpha[i] == 0)
1126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            input_has_transparency = 1;
1127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
1128b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1129b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            input_has_transparency = 1;
1130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            input_has_alpha = 1;
1131b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
1132b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1133b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
1134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* If no alpha we can optimize. */
11379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (input_has_alpha == 0)
1138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Any alpha means background and associative alpha processing is
1140b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * and ENCODE_ALPHA are irrelevant.
1142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
11469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (input_has_transparency == 0)
1147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* png_set_background handling - deals with the complexity of whether the
1152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background color is in the file format or the screen format in the case
1153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * where an 'expand' will happen.
1154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following code cannot be entered in the alpha pre-multiplication case
1157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * because PNG_BACKGROUND_EXPAND is cancelled below.
1158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
11599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
11609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_EXPAND) != 0)
1161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.red   =
1164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->palette[png_ptr->background.index].red;
1165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.green =
1166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->palette[png_ptr->background.index].green;
1167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.blue  =
1168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->palette[png_ptr->background.index].blue;
1169a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
11719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett        if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik        {
11739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett           if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik           {
1175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik              /* Invert the alpha channel (in tRNS) unless the pixels are
1176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               * going to be expanded, in which case leave it for later
1177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               */
1178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik              int i, istop = png_ptr->num_trans;
1179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik              for (i=0; i<istop; i++)
1181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                 png_ptr->trans_alpha[i] = (png_byte)(255 -
1182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                    png_ptr->trans_alpha[i]);
1183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik           }
1184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik        }
11859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_INVERT_ALPHA */
1186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
1187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   } /* background expand and (therefore) no alpha association. */
11889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_EXPAND && READ_BACKGROUND */
1189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1191b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void /* PRIVATE */
1192b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_rgb_transformations(png_structrp png_ptr)
1193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Added to libpng-1.5.4: check the color type to determine whether there
1195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * is any alpha or transparency in the image and simply cancel the
1196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background and alpha mode stuff if there isn't.
1197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
1199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int input_has_transparency = png_ptr->num_trans > 0;
1200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* If no alpha we can optimize. */
12029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (input_has_alpha == 0)
1203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Any alpha means background and associative alpha processing is
1205b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * and ENCODE_ALPHA are irrelevant.
1207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
1212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
12139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (input_has_transparency == 0)
1214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* png_set_background handling - deals with the complexity of whether the
1219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background color is in the file format or the screen format in the case
1220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * where an 'expand' will happen.
1221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following code cannot be entered in the alpha pre-multiplication case
1224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * because PNG_BACKGROUND_EXPAND is cancelled below.
1225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
12269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
12279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_EXPAND) != 0 &&
12289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       /* i.e., GRAY or GRAY_ALPHA */
1230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
1232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Expand background and tRNS chunks */
1233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int gray = png_ptr->background.gray;
1234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         int trans_gray = png_ptr->trans_color.gray;
1235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         switch (png_ptr->bit_depth)
1237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            case 1:
1239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray *= 0xff;
1240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               trans_gray *= 0xff;
1241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               break;
1242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            case 2:
1244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray *= 0x55;
1245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               trans_gray *= 0x55;
1246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1247a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 4:
1249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray *= 0x11;
1250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               trans_gray *= 0x11;
1251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1252a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            default:
1254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1255893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 8:
1256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               /* FALL THROUGH (Already 8 bits) */
1257a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 16:
1259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               /* Already a full 16 bits */
1260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->background.red = png_ptr->background.green =
1264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->background.blue = (png_uint_16)gray;
1265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
12669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->trans_color.red = png_ptr->trans_color.green =
1269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
1270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
1271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   } /* background expand and (therefore) no alpha association. */
12739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_EXPAND && READ_BACKGROUND */
1274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
1275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1276b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */
1277b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_read_transformations(png_structrp png_ptr)
1278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
1279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_init_read_transformations");
1280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* This internal function is called from png_read_start_row in pngrutil.c
1282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * and it is called before the 'rowbytes' calculation is done, so the code
1283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * in here can change or update the transformations flags.
1284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * First do updates that do not depend on the details of the PNG image data
1286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * being processed.
1287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
1290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_alpha_mode and this is another source for a default file gamma so
1292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the test needs to be performed later - here.  In addition prior to 1.5.4
1293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the tests were repeated for the PALETTE color type here - this is no
1294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * longer necessary (and doesn't seem to have been necessary before.)
1295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* The following temporary indicates if overall gamma correction is
1298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * required.
1299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int gamma_correction = 0;
1301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->colorspace.gamma != 0) /* has been set */
1303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->screen_gamma != 0) /* screen set too */
1305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
13067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                png_ptr->screen_gamma);
1307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
1309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* Assume the output matches the input; a long time default behavior
1310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * of libpng, although the standard has nothing to say about this.
1311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             */
1312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
1313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
1314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (png_ptr->screen_gamma != 0)
1316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* The converse - assume the file matches the screen, note that this
1317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * perhaps undesireable default can (from 1.5.4) be changed by calling
1318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * png_set_alpha_mode (even if the alpha handling mode isn't required
1319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * or isn't changed from the default.)
1320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
1322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else /* neither are set */
1324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Just in case the following prevents any processing - file and screen
1325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * are both assumed to be linear and there is no way to introduce a
1326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * third gamma value other than png_set_background with 'UNIQUE', and,
1327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * prior to 1.5.4
1328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
1330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* We have a gamma value now. */
1332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
1333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Now turn the gamma transformation on or off as appropriate.  Notice
1335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
1336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * composition may independently cause gamma correction because it needs
1337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
1338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * hasn't been specified.)  In any case this flag may get turned off in
1339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the code immediately below if the transform can be handled outside the
1340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * row loop.
1341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
13429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (gamma_correction != 0)
1343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_GAMMA;
1344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
1346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations &= ~PNG_GAMMA;
1347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Certain transformations have the effect of preventing other
13519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett    * transformations that happen afterward in png_do_read_transformations;
1352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * resolve the interdependencies here.  From the code of
1353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_do_read_transformations the order is:
1354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
1356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  2) PNG_STRIP_ALPHA (if no compose)
1357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  3) PNG_RGB_TO_GRAY
1358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
1359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  5) PNG_COMPOSE
1360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  6) PNG_GAMMA
1361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  7) PNG_STRIP_ALPHA (if compose)
1362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  8) PNG_ENCODE_ALPHA
1363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *  9) PNG_SCALE_16_TO_8
1364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 10) PNG_16_TO_8
1365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 11) PNG_QUANTIZE (converts to palette)
1366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 12) PNG_EXPAND_16
1367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
1368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 14) PNG_INVERT_MONO
1369b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 15) PNG_INVERT_ALPHA
1370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 16) PNG_SHIFT
1371b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 17) PNG_PACK
1372b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 18) PNG_BGR
1373b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 19) PNG_PACKSWAP
1374b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 21) PNG_SWAP_ALPHA
1376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 22) PNG_SWAP_BYTES
1377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 23) PNG_USER_TRANSFORM [must be last]
1378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
13809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
13819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_COMPOSE) == 0)
1382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Stripping the alpha channel happens immediately after the 'expand'
1384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * transformations, before all other transformation, so it cancels out
1385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the alpha handling.  It has the side effect negating the effect of
1386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * PNG_EXPAND_tRNS too:
1387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
1389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_EXPAND_tRNS);
1390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * so transparency information would remain just so long as it wasn't
1394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * expanded.  This produces unexpected API changes if the set of things
1395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
1396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * documentation - which says ask for what you want, accept what you
1397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * get.)  This makes the behavior consistent from 1.5.4:
1398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->num_trans = 0;
1400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* STRIP_ALPHA supported, no COMPOSE */
1402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
1405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * settings will have no effect.
1406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
14079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_gamma_significant(png_ptr->screen_gamma) == 0)
1408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1413893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Make sure the coefficients for the rgb to gray conversion are set
1416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * appropriately.
1417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
14189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_colorspace_set_rgb_coefficients(png_ptr);
1420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Detect gray background and attempt to enable optimization for
1425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gray --> RGB case.
1426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
1428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
1429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background color might actually be gray yet not be flagged as such.
1430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * This is not a problem for the current code, which uses
1431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
1432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_do_gray_to_rgb() transformation.
1433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * TODO: this code needs to be revised to avoid the complexity and
1435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * interdependencies.  The color type of the background should be recorded in
1436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * png_set_background, along with the bit depth, then the code has a record
1437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * of exactly what color space the background is currently in.
1438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
14399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the file was grayscale the background value is gray.
1443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
14449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1447893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
14489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* PNG_COMPOSE: png_set_background was called with need_expand false,
1451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * so the color is in the color space of the output or png_set_alpha_mode
1452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * was called and the color is black.  Ignore RGB_TO_GRAY because that
1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * happens before GRAY_TO_RGB.
1454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
14559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
1456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->background.red == png_ptr->background.green &&
1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->background.red == png_ptr->background.blue)
1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
1460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->background.gray = png_ptr->background.red;
1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
14659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_EXPAND && READ_BACKGROUND */
14669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_GRAY_TO_RGB */
1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
1469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * can be performed directly on the palette, and some (such as rgb to gray)
1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * can be optimized inside the palette.  This is particularly true of the
1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * composite (background and alpha) stuff, which can be pretty much all done
1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * in the palette even if the result is expanded to RGB or gray afterward.
1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * earlier and the palette stuff is actually handled on the first row.  This
1476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * leads to the reported bug that the palette returned by png_get_PLTE is not
1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * updated.
1478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_init_palette_transformations(png_ptr);
1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else
1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_init_rgb_transformations(png_ptr);
1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_EXPAND_16_SUPPORTED)
14879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
14889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
14899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
14909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       png_ptr->bit_depth != 16)
1491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* TODO: fix this.  Because the expand_16 operation is after the compose
1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * handling the background color must be 8, not 16, bits deep, but the
1494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * application will supply a 16-bit value so reduce it here.
1495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
1497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * present, so that case is ok (until do_expand_16 is moved.)
1498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
1499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * NOTE: this discards the low 16 bits of the user supplied background
1500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * color, but until expand_16 works properly there is no choice!
1501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.red);
1504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.green);
1505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.blue);
1506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      CHOP(png_ptr->background.gray);
1507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     undef CHOP
1508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
15099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_BACKGROUND && READ_EXPAND_16 */
1510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
15149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
15159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
15169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
15179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       png_ptr->bit_depth == 16)
1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
1520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * component this will also happen after PNG_COMPOSE and so the background
1521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * color must be pre-expanded here.
1522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
1523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * TODO: fix this too.
1524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.green =
1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         (png_uint_16)(png_ptr->background.green * 257);
1528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
1529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
1530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
1531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
1532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
1534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * background support (see the comments in scripts/pnglibconf.dfa), this
1535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * allows pre-multiplication of the alpha channel to be implemented as
1536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * compositing on black.  This is probably sub-optimal and has been done in
1537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * implement the new API quickly, without lots of internal changes.)
1539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
1542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* Includes ALPHA_MODE */
1544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->background_1 = png_ptr->background;
1545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* This needs to change - in the palette image case a whole set of tables are
1548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * built when it would be quicker to just calculate the correct value for
1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * each palette entry directly.  Also, the test is too tricky - why check
1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
1551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
1552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
1553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the gamma tables will not be built even if composition is required on a
1554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * gamma encoded value.
1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * In 1.5.4 this is addressed below by an additional check on the individual
1557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
1558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * tables.
1559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
15609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
15619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
15629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
15639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
15649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett        ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
15659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
15669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          png_gamma_significant(png_ptr->screen_gamma) != 0
1567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_READ_BACKGROUND_SUPPORTED
15689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
15699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett           png_gamma_significant(png_ptr->background_gamma) != 0)
1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  endif
15719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett        )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
15729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       png_gamma_significant(png_ptr->screen_gamma) != 0))
1573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
15755f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
15765f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_BACKGROUND_SUPPORTED
15779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Issue a warning about this combination: because RGB_TO_GRAY is
1580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * optimized to do the gamma transform if present yet do_background has
1581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * to do the same thing if both options are set a
1582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * double-gamma-correction happens.  This is true in all versions of
1583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * libpng to date.
1584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
15859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_warning(png_ptr,
15877a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                "libpng does not support gamma+background+rgb_to_gray");
1588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
15899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
1590893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* We don't get to here unless there is a tRNS chunk with non-opaque
1592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * entries - see the checking code at the start of this function.
1593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             */
1594893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_color back, back_1;
1595893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_colorp palette = png_ptr->palette;
1596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int num_palette = png_ptr->num_palette;
1597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1598893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
1599893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1601893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back.red = png_ptr->gamma_table[png_ptr->background.red];
1602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back.green = png_ptr->gamma_table[png_ptr->background.green];
1603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
1604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
1606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
1607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
1608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else
1610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_fixed_point g, gs;
1612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               switch (png_ptr->background_gamma_type)
1614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  case PNG_BACKGROUND_GAMMA_SCREEN:
1616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     g = (png_ptr->screen_gamma);
1617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = PNG_FP_1;
1618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
1619a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  case PNG_BACKGROUND_GAMMA_FILE:
1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g = png_reciprocal(png_ptr->colorspace.gamma);
1622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
16237a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                         png_ptr->screen_gamma);
1624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
1625a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1626893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  case PNG_BACKGROUND_GAMMA_UNIQUE:
1627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g = png_reciprocal(png_ptr->background_gamma);
1628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = png_reciprocal2(png_ptr->background_gamma,
16297a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                         png_ptr->screen_gamma);
1630893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     break;
1631893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  default:
1632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     g = PNG_FP_1;    /* back_1 */
1633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     gs = PNG_FP_1;   /* back */
1634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     break;
1635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
16379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (png_gamma_significant(gs) != 0)
1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      gs);
1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      gs);
1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      gs);
1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
1648893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  back.red   = (png_byte)png_ptr->background.red;
1650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  back.green = (png_byte)png_ptr->background.green;
1651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  back.blue  = (png_byte)png_ptr->background.blue;
1652893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
16549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (png_gamma_significant(g) != 0)
1655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
16577a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                      g);
1658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.green = png_gamma_8bit_correct(
16597a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                      png_ptr->background.green, g);
1660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
16617a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                      g);
1662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.red   = (png_byte)png_ptr->background.red;
1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.green = (png_byte)png_ptr->background.green;
1668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  back_1.blue  = (png_byte)png_ptr->background.blue;
1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < num_palette; i++)
1673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (i < (int)png_ptr->num_trans &&
1675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   png_ptr->trans_alpha[i] != 0xff)
1676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  if (png_ptr->trans_alpha[i] == 0)
1678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
1679893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i] = back;
1680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
1681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
1682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
1683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte v, w;
1684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     v = png_ptr->gamma_to_1[palette[i].red];
1686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
1687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i].red = png_ptr->gamma_from_1[w];
1688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     v = png_ptr->gamma_to_1[palette[i].green];
1690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
1691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i].green = png_ptr->gamma_from_1[w];
1692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     v = png_ptr->gamma_to_1[palette[i].blue];
1694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
1695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     palette[i].blue = png_ptr->gamma_from_1[w];
1696893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
1697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
1699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i].red = png_ptr->gamma_table[palette[i].red];
1701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i].green = png_ptr->gamma_table[palette[i].green];
1702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* Prevent the transformations being done again.
1707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             *
1708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * NOTE: this is highly dubious; it removes the transformations in
1709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * place.  This seems inconsistent with the general treatment of the
1710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * transformations elsewhere.
17115f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott             */
1712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
1713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else /* color_type != PNG_COLOR_TYPE_PALETTE */
1717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int gs_sig, g_sig;
1719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
1720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
1721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            switch (png_ptr->background_gamma_type)
1723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case PNG_BACKGROUND_GAMMA_SCREEN:
1725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  g = png_ptr->screen_gamma;
1726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  /* gs = PNG_FP_1; */
1727893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
1728a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case PNG_BACKGROUND_GAMMA_FILE:
1730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  g = png_reciprocal(png_ptr->colorspace.gamma);
1731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
17327a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                      png_ptr->screen_gamma);
1733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
1734a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case PNG_BACKGROUND_GAMMA_UNIQUE:
1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  g = png_reciprocal(png_ptr->background_gamma);
1737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gs = png_reciprocal2(png_ptr->background_gamma,
1738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->screen_gamma);
1739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
1740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               default:
1742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_error(png_ptr, "invalid background gamma type");
1743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            g_sig = png_gamma_significant(g);
1746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            gs_sig = png_gamma_significant(gs);
1747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
17489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett            if (g_sig != 0)
1749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
1750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   png_ptr->background.gray, g);
1751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
17529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett            if (gs_sig != 0)
1753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_ptr->background.gray = png_gamma_correct(png_ptr,
1754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   png_ptr->background.gray, gs);
1755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if ((png_ptr->background.red != png_ptr->background.green) ||
1757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                (png_ptr->background.red != png_ptr->background.blue) ||
1758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                (png_ptr->background.red != png_ptr->background.gray))
1759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               /* RGB or RGBA with color background */
17619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (g_sig != 0)
1762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
1764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.red, g);
1765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.green, g);
1768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
1770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.blue, g);
1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
17739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (gs_sig != 0)
1774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
1775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background.red = png_gamma_correct(png_ptr,
1776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.red, gs);
1777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background.green = png_gamma_correct(png_ptr,
1779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.green, gs);
1780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_ptr->background.blue = png_gamma_correct(png_ptr,
1782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->background.blue, gs);
1783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
1784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else
1787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_ptr->background_1.red = png_ptr->background_1.green
1790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_ptr->background.red = png_ptr->background.green
1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   = png_ptr->background.blue = png_ptr->background.gray;
1794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* The background is now in screen gamma: */
1797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
1798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         } /* color_type != PNG_COLOR_TYPE_PALETTE */
1799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }/* png_ptr->transformations & PNG_BACKGROUND */
1800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
1802a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      /* Transformation does not include PNG_BACKGROUND */
18039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_BACKGROUND */
1804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
1807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
1808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
1809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
1810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         )
1811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_colorp palette = png_ptr->palette;
1813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int num_palette = png_ptr->num_palette;
1814893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         int i;
1815893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* NOTE: there are other transformations that should probably be in
1817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * here too.
1818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1819893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0; i < num_palette; i++)
1820893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i].red = png_ptr->gamma_table[palette[i].red];
1822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i].green = png_ptr->gamma_table[palette[i].green];
1823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1824893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
18265f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         /* Done the gamma correction. */
18275f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         png_ptr->transformations &= ~PNG_GAMMA;
1828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
1829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
18305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_BACKGROUND_SUPPORTED
1831893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
1832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
18339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_GAMMA */
1834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
18355f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_BACKGROUND_SUPPORTED
1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* No GAMMA transformation (see the hanging else 4 lines above) */
18379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1839893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int i;
1841893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      int istop = (int)png_ptr->num_trans;
1842893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_color back;
1843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_colorp palette = png_ptr->palette;
1844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      back.red   = (png_byte)png_ptr->background.red;
1846893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      back.green = (png_byte)png_ptr->background.green;
1847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      back.blue  = (png_byte)png_ptr->background.blue;
1848893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1849893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      for (i = 0; i < istop; i++)
1850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->trans_alpha[i] == 0)
1852893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            palette[i] = back;
1854893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else if (png_ptr->trans_alpha[i] != 0xff)
1857893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1858893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            /* The png_composite() macro is defined in png.h */
1859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_composite(palette[i].red, palette[i].red,
1860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_ptr->trans_alpha[i], back.red);
1861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_composite(palette[i].green, palette[i].green,
1863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_ptr->trans_alpha[i], back.green);
1864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_composite(palette[i].blue, palette[i].blue,
1866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_ptr->trans_alpha[i], back.blue);
1867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_COMPOSE;
1871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
18729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_BACKGROUND */
1873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
18745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_SHIFT_SUPPORTED
18759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
18769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_EXPAND) == 0 &&
1877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int i;
1880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int istop = png_ptr->num_palette;
1881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      int shift = 8 - png_ptr->sig_bit.red;
1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformations &= ~PNG_SHIFT;
1884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* significant bits can be in the range 1 to 7 for a meaninful result, if
1886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the number of significant bits is 0 then no shift is done (this is an
1887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * error condition which is silently ignored.)
1888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
1889b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (shift > 0 && shift < 8)
1890b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i=0; i<istop; ++i)
1891b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1892b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            int component = png_ptr->palette[i].red;
1893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1894b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            component >>= shift;
1895b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_ptr->palette[i].red = (png_byte)component;
1896b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      shift = 8 - png_ptr->sig_bit.green;
1899b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (shift > 0 && shift < 8)
1900b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i=0; i<istop; ++i)
1901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1902b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            int component = png_ptr->palette[i].green;
1903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1904b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            component >>= shift;
1905b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_ptr->palette[i].green = (png_byte)component;
1906b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      shift = 8 - png_ptr->sig_bit.blue;
1909b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (shift > 0 && shift < 8)
1910b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i=0; i<istop; ++i)
1911b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
1912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            int component = png_ptr->palette[i].blue;
1913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1914b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            component >>= shift;
1915b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_ptr->palette[i].blue = (png_byte)component;
1916b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
1917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
19187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif /* READ_SHIFT */
1919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Modify the info structure to reflect the transformations.  The
1922893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * info should be updated so a PNG file could be written with it,
1923893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * assuming the transformations result in valid PNG data.
1924893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
1925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
1926b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
1927893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
19284215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_read_transform_info");
19295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
19305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
19319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_EXPAND) != 0)
1932893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1933893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1934893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
1935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* This check must match what actually happens in
1936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * it is all opaque we must do the same (at present it does not.)
1938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
1939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->num_trans > 0)
1940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1942893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
1943893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1945893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->bit_depth = 8;
1946893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->num_trans = 0;
1947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
1948b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if (png_ptr->palette == NULL)
1949b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_error (png_ptr, "Palette is NULL in indexed image");
1950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1951893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
1952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
19539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if (png_ptr->num_trans != 0)
1954893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
19559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett            if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
1956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1958893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (info_ptr->bit_depth < 8)
1959893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            info_ptr->bit_depth = 8;
1960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1961893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->num_trans = 0;
1962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1964893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1965893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
1967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
1968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following is almost certainly wrong unless the background value is in
1969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the screen space!
1970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
19719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1972893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->background = png_ptr->background;
1973893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1974893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
19755f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
1976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * however it seems that the code in png_init_read_transformations, which has
1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * been called before this from png_read_update_info->png_read_start_row
1979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * sometimes does the gamma transform and cancels the flag.
1980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    *
1981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
1982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the screen_gamma value.  The following probably results in weirdness if
1983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the info_ptr is used by the app after the rows have been read.
1984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
1986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (info_ptr->bit_depth == 16)
1989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
1990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  ifdef PNG_READ_16BIT_SUPPORTED
1991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
19929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
1993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            info_ptr->bit_depth = 8;
1994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
1995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
19979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((png_ptr->transformations & PNG_16_TO_8) != 0)
1998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            info_ptr->bit_depth = 8;
1999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     endif
2000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#  else
20029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      /* No 16-bit support: force chopping 16-bit input down to 8, in this case
2003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the app program can chose if both APIs are available by setting the
2004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * correct scaling to use.
2005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
2006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* For compatibility with previous versions use the strip method by
2008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * default.  This code works because if PNG_SCALE_16_TO_8 is already
2009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * set the code below will do that in preference to the chop.
2010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
2011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->transformations |= PNG_16_TO_8;
2012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         info_ptr->bit_depth = 8;
2013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#     else
2014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->transformations |= PNG_SCALE_16_TO_8;
2017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            info_ptr->bit_depth = 8;
2018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#        else
2019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            CONFIGURATION ERROR: you must enable at least one 16 to 8 method
2021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#        endif
2022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#    endif
20239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* !READ_16BIT */
2024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20265f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
20279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
2028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type = (png_byte)(info_ptr->color_type |
2029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_COLOR_MASK_COLOR);
2030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2031893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
20339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
2034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type = (png_byte)(info_ptr->color_type &
2035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         ~PNG_COLOR_MASK_COLOR);
2036893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2037893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_QUANTIZE_SUPPORTED
20399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
2040893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2042a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
20439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
2044893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
2046893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2047893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2048893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2049893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_EXPAND_16_SUPPORTED
20519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
20529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       info_ptr->bit_depth == 8 &&
20539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->bit_depth = 16;
2056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
20595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_PACK_SUPPORTED
20609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_PACK) != 0 &&
20619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (info_ptr->bit_depth < 8))
2062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->bit_depth = 8;
2063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels = 1;
2067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
20689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
2069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels = 3;
2070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2071893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
2072893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels = 1;
2073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
20759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
2076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->color_type = (png_byte)(info_ptr->color_type &
2078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         ~PNG_COLOR_MASK_ALPHA);
2079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      info_ptr->num_trans = 0;
2080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2082893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
2084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels++;
2085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20865f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_FILLER_SUPPORTED
2087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
20889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_FILLER) != 0 &&
20899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
20909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
2091893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      info_ptr->channels++;
2093a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      /* If adding a true alpha channel not just filler */
20949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
2095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2097893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2098893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
2100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectdefined(PNG_READ_USER_TRANSFORM_SUPPORTED)
21019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
21039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (png_ptr->user_transform_depth != 0)
2104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->bit_depth = png_ptr->user_transform_depth;
2105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
21069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (png_ptr->user_transform_channels != 0)
2107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         info_ptr->channels = png_ptr->user_transform_channels;
2108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       info_ptr->bit_depth);
2113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
21144215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * check in png_rowbytes that the user buffer won't get overwritten.  Note
2118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * that the field is not always set - if png_read_update_info isn't called
2119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * the application has to either not do any transforms or get the calculation
2120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * right itself.
2121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
2122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_ptr->info_rowbytes = info_ptr->rowbytes;
2123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
21245f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifndef PNG_READ_EXPAND_SUPPORTED
21259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if (png_ptr != NULL)
2126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      return;
2127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2130b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACK_SUPPORTED
2131b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
2132b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * without changing the actual values.  Thus, if you had a row with
2133b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * a bit depth of 1, you would end up with bytes that only contained
2134b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
2135b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * png_do_shift() after this.
2136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
2137b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2138b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_unpack(png_row_infop row_info, png_bytep row)
2139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2140b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_unpack");
2141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2142b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (row_info->bit_depth < 8)
2143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2144b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_uint_32 i;
2145b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_uint_32 row_width=row_info->width;
2146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2147b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      switch (row_info->bit_depth)
2148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2149b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         case 1:
2150b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2151b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
2152b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep dp = row + (png_size_t)row_width - 1;
2153851c67770f9cebece9c79e914a54c348f539a512Matt Sarett            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2154b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            for (i = 0; i < row_width; i++)
2155b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            {
2156b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               *dp = (png_byte)((*sp >> shift) & 0x01);
2157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2158b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               if (shift == 7)
2159b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               {
2160b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 0;
2161b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  sp--;
2162b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               }
2163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2164b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               else
2165b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift++;
2166b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2167b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               dp--;
2168b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            }
2169b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2170b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
2171b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2172b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         case 2:
2173b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2174b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2175b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
2176b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep dp = row + (png_size_t)row_width - 1;
2177851c67770f9cebece9c79e914a54c348f539a512Matt Sarett            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2178b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            for (i = 0; i < row_width; i++)
2179b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            {
2180b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               *dp = (png_byte)((*sp >> shift) & 0x03);
2181b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2182b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               if (shift == 6)
2183b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               {
2184b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 0;
2185b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  sp--;
2186b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               }
2187b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2188b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               else
2189b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift += 2;
2190b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2191b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               dp--;
2192b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            }
2193b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2194b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
2195b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2196b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         case 4:
2197b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2198b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
2199b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_bytep dp = row + (png_size_t)row_width - 1;
2200851c67770f9cebece9c79e914a54c348f539a512Matt Sarett            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2201b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            for (i = 0; i < row_width; i++)
2202b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            {
2203b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               *dp = (png_byte)((*sp >> shift) & 0x0f);
2204b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2205b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               if (shift == 4)
2206b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               {
2207b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 0;
2208b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  sp--;
2209b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               }
2210b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2211b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               else
2212b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                  shift = 4;
2213b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2214b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               dp--;
2215b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            }
2216b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2217b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
2218b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2219b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         default:
2220b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            break;
2221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2222b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->bit_depth = 8;
2223b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2224b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->rowbytes = row_width * row_info->channels;
2225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2226b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}
2227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2229b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SHIFT_SUPPORTED
2230b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Reverse the effects of png_do_shift.  This routine merely shifts the
2231b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * pixels back to their significant bits values.  Thus, if you have
2232b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * a row of bit depth 8, but only 5 are significant, this will shift
2233b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the values back to 0 through 31.
2234b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */
2235b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2236b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_unshift(png_row_infop row_info, png_bytep row,
2237b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    png_const_color_8p sig_bits)
2238b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{
2239b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   int color_type;
2240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2241b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_unshift");
2242b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2243b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* The palette case has already been handled in the _init routine. */
2244b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   color_type = row_info->color_type;
2245b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
2246b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (color_type != PNG_COLOR_TYPE_PALETTE)
2247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2248b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int shift[4];
2249b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int channels = 0;
2250b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int bit_depth = row_info->bit_depth;
2251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
22529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
2253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2254b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->red;
2255b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->green;
2256b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->blue;
2257b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
2258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2259b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else
2260b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
2261b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->gray;
2262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
22649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
2265b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
2266b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         shift[channels++] = bit_depth - sig_bits->alpha;
2267b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
2268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2269b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
2270b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         int c, have_shift;
2271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2272b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (c = have_shift = 0; c < channels; ++c)
2273b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
2274b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            /* A shift of more than the bit depth is an error condition but it
2275b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * gets ignored here.
2276b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             */
2277b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            if (shift[c] <= 0 || shift[c] >= bit_depth)
2278b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari               shift[c] = 0;
2279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            else
2281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               have_shift = 1;
2282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
2283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
22849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if (have_shift == 0)
2285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
2286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      switch (bit_depth)
2289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
2291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Must be 1bpp gray: should not be here! */
2292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* NOTREACHED */
2293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            break;
2294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 2:
2296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Must be 2bpp gray */
2297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* assert(channels == 1 && shift[0] == 1) */
2298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp = row;
2300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int b = (*bp >> 1) & 0x55;
2305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *bp++ = (png_byte)b;
2306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2309a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
2310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 4:
2311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Must be 4bpp gray */
2312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* assert(channels == 1) */
2313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2314893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep bp = row;
2315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int gray_shift = shift[0];
2317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int mask =  0xf >> gray_shift;
2318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            mask |= mask << 4;
2320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int b = (*bp >> gray_shift) & mask;
2324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *bp++ = (png_byte)b;
2325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2328a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
2329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 8:
2330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Single byte components, G, GA, RGB, RGBA */
2331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep bp = row;
2333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int channel = 0;
2335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int b = *bp >> shift[channel];
2339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (++channel >= channels)
2340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  channel = 0;
2341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *bp++ = (png_byte)b;
2342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2345a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
2346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 16:
2348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Double byte components, G, GA, RGB, RGBA */
2349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep bp = row;
2351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep bp_end = bp + row_info->rowbytes;
2352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            int channel = 0;
2353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            while (bp < bp_end)
2355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               int value = (bp[0] << 8) + bp[1];
2357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               value >>= shift[channel];
2359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (++channel >= channels)
2360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  channel = 0;
2361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *bp++ = (png_byte)(value >> 8);
23629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               *bp++ = (png_byte)value;
2363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
2365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Scale rows of bit depth 16 down to 8 accurately */
2374b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2375b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
2376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_scale_16_to_8");
23785f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (row_info->bit_depth == 16)
2380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep sp = row; /* source */
2382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep dp = row; /* destination */
2383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      while (sp < ep)
2386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
23879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         /* The input is an array of 16-bit components, these must be scaled to
23889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          * 8 bits each.  For a 16-bit value V the required value (from the PNG
2389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * specification) is:
2390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    (V * 255) / 65535
2392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * This reduces to round(V / 257), or floor((V + 128.5)/257)
2394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * Represent V as the two byte value vhi.vlo.  Make a guess that the
2396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * result is the top byte of V, vhi, then the correction to this value
2397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * is:
2398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
2400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *          = floor(((vlo-vhi) + 128.5) / 257)
2401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * This can be approximated using integer arithmetic (and a signed
2403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * shift):
2404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    error = (vlo-vhi+128) >> 8;
2406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * The approximate differs from the exact answer only when (vlo-vhi) is
2408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * 128; it then gives a correction of +1 when the exact correction is
24099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          * 0.  This gives 128 errors.  The exact answer (correct for all 16-bit
2410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * input values) is:
2411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    error = (vlo-vhi+128)*65535 >> 24;
2413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * An alternative arithmetic calculation which also gives no errors is:
2415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *
2416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          *    (V * 255 + 32895) >> 16
2417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
2418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_int_32 tmp = *sp++; /* must be signed! */
2420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         *dp++ = (png_byte)tmp;
2422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->bit_depth = 8;
2425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->rowbytes = row_info->width * row_info->channels;
2427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
2429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2432b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Simply discard the low byte.  This was the default behavior prior
2434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to libpng-1.5.4.
2435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
2436b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_chop(png_row_infop row_info, png_bytep row)
2437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
2438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_chop");
2439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->bit_depth == 16)
2441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep sp = row; /* source */
2443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep dp = row; /* destination */
2444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      while (sp < ep)
2447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
2448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         *dp++ = *sp;
2449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         sp += 2; /* skip low byte */
2450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->bit_depth = 8;
2453893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->rowbytes = row_info->width * row_info->channels;
2455893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
24595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2460b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
2462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
24634215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_read_swap_alpha");
24645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_uint_32 row_width = row_info->width;
2467893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from RGBA to ARGB */
2470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2471893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save;
2475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save = *(--sp);
2480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save;
2484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from RRGGBBAA to AARRGGBB */
2489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2492893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save[2];
2494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2496893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[0] = *(--sp);
2499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[1] = *(--sp);
2500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2506893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[0];
2507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[1];
2508893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2513893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from GA to AG */
2516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2518893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save;
2521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2522893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2524893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2525893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save = *(--sp);
2526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save;
2528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2529893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This converts from GGAA to AAGG */
2533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + row_info->rowbytes;
2536893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp;
2537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_byte save[2];
2538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_uint_32 i;
2539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[0] = *(--sp);
2543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               save[1] = *(--sp);
2544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[0];
2547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = save[1];
2548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
25565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2557b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
2559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 row_width;
25614215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_read_invert_alpha");
25625f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_width = row_info->width;
2564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
2567893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2568893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This inverts the alpha channel in RGBA */
2569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp = row + row_info->rowbytes;
2570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*          This does nothing:
2578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            We can replace it with:
2582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project*/
2583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            sp-=3;
2584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            dp=sp;
2585893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* This inverts the alpha channel in RRGGBBAA */
2590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
2591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
2592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp = row + row_info->rowbytes;
2593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2595893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*          This does nothing:
2602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            We can replace it with:
2609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project*/
2610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            sp-=6;
2611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            dp=sp;
2612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
2616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
2618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
2619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This inverts the alpha channel in GA */
2621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp = row + row_info->rowbytes;
2622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2629893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
2631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
2633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
2634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
2635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         /* This inverts the alpha channel in GGAA */
2636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep sp  = row + row_info->rowbytes;
2637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_bytep dp = sp;
2638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_uint_32 i;
2639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         for (i = 0; i < row_width; i++)
2641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
2642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = (png_byte)(255 - *(--sp));
2644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/*
2645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            *(--dp) = *(--sp);
2647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project*/
2648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            sp-=2;
2649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            dp=sp;
2650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2653893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2654893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
26575f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_FILLER_SUPPORTED
2658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Add filler channel if we have RGB color */
2659b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_read_filler(png_row_infop row_info, png_bytep row,
2661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_uint_32 filler, png_uint_32 flags)
2662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
2664893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width = row_info->width;
2665893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
26679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   png_byte hi_filler = (png_byte)(filler>>8);
2668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
26699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   png_byte lo_filler = (png_byte)filler;
2670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
26714215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_read_filler");
26725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (
2674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project       row_info->color_type == PNG_COLOR_TYPE_GRAY)
2675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
26764215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      if (row_info->bit_depth == 8)
2677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
26789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2679893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from G to GX */
2681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width;
2682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp =  sp + (png_size_t)row_width;
2683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
2689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2690893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 16;
2691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 2;
2692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2694893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from G to XG */
2697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width;
2698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width;
2699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 16;
2706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 2;
2707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
27114215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      else if (row_info->bit_depth == 16)
2712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
27139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from GG to GGXX */
2716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2;
2717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
27219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               *(--dp) = hi_filler;
2722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
27269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett            *(--dp) = hi_filler;
2727893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2728893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from GG to XXGG */
2735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2;
2736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2740893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
27429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               *(--dp) = hi_filler;
2743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
2745893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2746893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2748893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2750893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   } /* COLOR_TYPE == GRAY */
2751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
27534215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      if (row_info->bit_depth == 8)
2754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
27559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RGB to RGBX */
2758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 3;
2759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width;
2760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2765893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
2768893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2769893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2771893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2773893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RGB to XRGB */
2776893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 3;
2777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp + (png_size_t)row_width;
2778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
2784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 32;
2787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 4;
2788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_16BIT_SUPPORTED
27924215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      else if (row_info->bit_depth == 16)
2793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
27949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RRGGBB to RRGGBBXX */
2797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 6;
2798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 1; i < row_width; i++)
2800893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
28029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               *(--dp) = hi_filler;
2803893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2805893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2808893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2810893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *(--dp) = lo_filler;
28119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett            *(--dp) = hi_filler;
2812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 64;
2814893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 8;
2815893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2817893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2818893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes the data from RRGGBB to XXRRGGBB */
2820893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 6;
2821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2824893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2826893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2827893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = *(--sp);
2830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(--dp) = lo_filler;
28319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               *(--dp) = hi_filler;
2832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 4;
2835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 64;
2836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width * 8;
2837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2838893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
2840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   } /* COLOR_TYPE == RGB */
2841893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2842893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
28445f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2845a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Expand grayscale files to RGB, with or without alpha */
2846b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
2847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2848893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2849893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
2850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width = row_info->width;
2851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
28524215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_gray_to_rgb");
28535f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
2854893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (row_info->bit_depth >= 8 &&
28559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
2856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2857893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2858893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes G to RGB */
2862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width - 1;
2863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2864893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2872893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes GG to RRGGBB */
2875893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 4;
2877893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2879893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2880893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2881893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2884893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2886893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2889893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2890893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
2891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
2892893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes GA to RGBA */
2894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 2;
2896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2897893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2899893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2900893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2902893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2903893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
2905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else
2906893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
2907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* This changes GGAA to RRGGBBAA */
2908893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2909893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_bytep dp = sp  + (png_size_t)row_width * 4;
2910893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
2911893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
2912893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2913893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2914893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2915893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2916893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *sp;
2917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp - 1);
2918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *(dp--) = *(sp--);
2920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
2921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
2922893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
2923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->channels = (png_byte)(row_info->channels + 2);
2924893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->color_type |= PNG_COLOR_MASK_COLOR;
2925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->pixel_depth = (png_byte)(row_info->channels *
2926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          row_info->bit_depth);
29274215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2928893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
2929893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
2930893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
2931893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
29325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2933a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Reduce RGB files to grayscale, with or without alpha
2934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
2935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
2936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * versions dated 1998 through November 2002 have been archived at
2937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
2938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
29394215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * Charles Poynton poynton at poynton.com
2940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2941893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2942893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  which can be expressed with integers as
2944893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Poynton's current link (as of January 2003 through July 2011):
2948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * <http://www.poynton.com/notes/colour_and_gamma/>
2949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * has changed the numbers slightly:
2950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = 0.2126*R + 0.7152*G + 0.0722*B
2952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  which can be expressed with integers as
2954893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
2956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
2958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  end point chromaticities and the D65 white point.  Depending on the
2959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  precision used for the D65 white point this produces a variety of different
2960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
2961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  used (0.3127,0.3290) the Y calculation would be:
2962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  While this is correct the rounding results in an overflow for white, because
2966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
2967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  libpng uses, instead, the closest non-overflowing approximation:
2968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
2970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *
2971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
2972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  (including an sRGB chunk) then the chromaticities are used to calculate the
2973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  coefficients.  See the chunk handling in pngrutil.c for more information.
2974893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  In all cases the calculation is to be done in a linear colorspace.  If no
2976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  gamma information is available to correct the encoding of the original RGB
2977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  values this results in an implicit assumption that the original PNG RGB
2978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  values were linear.
2979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
2980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  Other integer coefficents can be used via png_set_rgb_to_gray().  Because
2981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  the API takes just red and green coefficients the blue coefficient is
2982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  calculated to make the sum 32768.  This will result in different rounding
2983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *  to that used above.
2984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
2985b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int
2986b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
2989893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int rgb_error = 0;
2990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
29914215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_rgb_to_gray");
29925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
29939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
29949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
2995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 bc = 32768 - rc - gc;
2999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST png_uint_32 row_width = row_info->width;
3000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      PNG_CONST int have_alpha =
3001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3002893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
3004893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
3006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Notice that gamma to/from 1 are not necessarily inverses (if
3007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * there is an overall gamma correction).  Prior to 1.5.5 this code
3008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * checked the linearized values for equality; this doesn't match
3009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * the documentation, the original values must be checked.
3010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
3011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
3012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3016893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3018893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte red   = *(sp++);
3020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte green = *(sp++);
3021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte blue  = *(sp++);
3022893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red != green || red != blue)
3024893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  red = png_ptr->gamma_to_1[red];
3026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  green = png_ptr->gamma_to_1[green];
3027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  blue = png_ptr->gamma_to_1[blue];
3028893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = png_ptr->gamma_from_1[
3031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      (rc*red + gc*green + bc*blue + 16384)>>15];
3032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
3033893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
3035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
3036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  /* If there is no overall correction the table will not be
3037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   * set.
3038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   */
3039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  if (png_ptr->gamma_table != NULL)
3040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     red = png_ptr->gamma_table[red];
3041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = red;
3043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
30459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (have_alpha != 0)
3046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3047893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
3049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
3050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
3052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3057893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte red   = *(sp++);
3059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte green = *(sp++);
3060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_byte blue  = *(sp++);
3061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red != green || red != blue)
3063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  /* NOTE: this is the historical approach which simply
3066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   * truncates the results.
3067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   */
3068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               }
3070893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
3072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = red;
3073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
30749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (have_alpha != 0)
3075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3076893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3078893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
3079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else /* RGB bit_depth == 16 */
3081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED
3083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
3084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3090893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_uint_16 red, green, blue, w;
30929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               png_byte hi,lo;
3093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
30949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
30959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
30969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red == green && red == blue)
3099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  if (png_ptr->gamma_16_table != NULL)
31019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                     w = png_ptr->gamma_16_table[(red & 0xff)
31029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                         >> png_ptr->gamma_shift][red >> 8];
3103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  else
3105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     w = red;
3106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               else
3109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
31109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red & 0xff)
3111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      >> png_ptr->gamma_shift][red>>8];
3112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_uint_16 green_1 =
31139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                      png_ptr->gamma_16_to_1[(green & 0xff) >>
3114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->gamma_shift][green>>8];
31159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue & 0xff)
3116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      >> png_ptr->gamma_shift][blue>>8];
3117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
3118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      + bc*blue_1 + 16384)>>15);
31199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                  w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
3120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                      png_ptr->gamma_shift][gray16 >> 8];
3121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)((w>>8) & 0xff);
3125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)(w & 0xff);
3126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
31279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (have_alpha != 0)
3128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               {
3129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3130893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(dp++) = *(sp++);
3131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
3134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
3135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
3137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep sp = row;
3138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_bytep dp = row;
3139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_uint_32 i;
3140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (i = 0; i < row_width; i++)
3142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_uint_16 red, green, blue, gray16;
31449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               png_byte hi,lo;
3145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
31469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
31479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
31489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               if (red != green || red != blue)
3151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  rgb_error |= 1;
3152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
31539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               /* From 1.5.5 in the 16-bit case do the accurate conversion even
3154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                * in the 'fast' case - this is because this is where the code
31559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                * ends up when handling linear 16-bit data.
3156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                */
3157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
3158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  15);
31599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
3160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(dp++) = (png_byte)(gray16 & 0xff);
3161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
31629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett               if (have_alpha != 0)
3163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  *(dp++) = *(sp++);
3165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(dp++) = *(sp++);
3166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
3170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->channels = (png_byte)(row_info->channels - 2);
3172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->color_type = (png_byte)(row_info->color_type &
3173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          ~PNG_COLOR_MASK_COLOR);
3174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      row_info->pixel_depth = (png_byte)(row_info->channels *
3175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          row_info->bit_depth);
31764215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
3178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   return rgb_error;
3179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
3180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
3183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
3184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Replace any alpha or transparency with the supplied background color.
3185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * "background" is already in the screen gamma, while "background_1" is
3186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * at a gamma of 1.0.  Paletted files have already been taken care of.
3187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
3188b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
3189b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
31915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_table = png_ptr->gamma_table;
3193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
3194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
3195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
3196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
3197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
3198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int gamma_shift = png_ptr->gamma_shift;
3199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_bytep sp;
3203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
3204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 row_width = row_info->width;
3205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int shift;
3206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_compose");
32085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
3209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
3210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      switch (row_info->color_type)
3211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY:
3213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            switch (row_info->bit_depth)
3215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 1:
3217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3219893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = 7;
3220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
3221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3222893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if ((png_uint_16)((*sp >> shift) & 0x01)
3223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        == png_ptr->trans_color.gray)
3224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
3226851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                        tmp |= png_ptr->background.gray << shift;
3227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)(tmp & 0xff);
3228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
32309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                     if (shift == 0)
3231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 7;
3233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp++;
3234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift--;
3238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3241a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 2:
3243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
32445f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_table != NULL)
3246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 6;
3249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x03)
3252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3255851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                           tmp |= png_ptr->background.gray << shift;
3256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int p = (*sp >> shift) & 0x03;
3262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int g = (gamma_table [p | (p << 2) |
3263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                               (p << 4) | (p << 6)] >> 6) & 0x03;
3264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3265851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                           tmp |= g << shift;
3266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
32699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (shift == 0)
3270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 6;
3272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 2;
3277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 6;
3285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3286893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x03)
3288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3291851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                           tmp |= png_ptr->background.gray << shift;
3292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
32959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (shift == 0)
3296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 6;
3298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 2;
3303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3307a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 4:
3309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
33105f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_table != NULL)
3312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3314893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 4;
3315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
33209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3321851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                           tmp |= png_ptr->background.gray << shift;
3322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int p = (*sp >> shift) & 0x0f;
3328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
3329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                              0x0f;
33309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3331851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                           tmp |= g << shift;
3332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
33359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (shift == 0)
3336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 4;
3338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 4;
3343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 4;
3351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++)
3352893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            == png_ptr->trans_color.gray)
3355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
33569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3357851c67770f9cebece9c79e914a54c348f539a512Matt Sarett                           tmp |= png_ptr->background.gray << shift;
3358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)(tmp & 0xff);
3359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
33619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (shift == 0)
3362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift = 4;
3364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           sp++;
3365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           shift -= 4;
3369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3373a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 8:
3375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
33765f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_table != NULL)
3378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp++)
3381893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (*sp == png_ptr->trans_color.gray)
3383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)png_ptr->background.gray;
3384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           *sp = gamma_table[*sp];
3387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3389893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3392893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3393893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp++)
3394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (*sp == png_ptr->trans_color.gray)
3396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)png_ptr->background.gray;
3397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3401a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 16:
3403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
34045f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (gamma_16 != NULL)
3406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp += 2)
3409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (v == png_ptr->trans_color.gray)
3415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3416a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                           /* Background is already in screen gamma */
3417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)((png_ptr->background.gray >> 8)
3418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *(sp + 1) = (png_byte)(png_ptr->background.gray
3420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        else
3424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           *sp = (png_byte)((v >> 8) & 0xff);
3427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                           *(sp + 1) = (png_byte)(v & 0xff);
3428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
3432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp = row;
3435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     for (i = 0; i < row_width; i++, sp += 2)
3436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3438893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        if (v == png_ptr->trans_color.gray)
3442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        {
3443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *sp = (png_byte)((png_ptr->background.gray >> 8)
3444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           *(sp + 1) = (png_byte)(png_ptr->background.gray
3446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3447893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        }
3448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
3451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               default:
3454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  break;
3455893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3458a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB:
3460893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
34635f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3464893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_table != NULL)
3465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3467893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 3)
3468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (*sp == png_ptr->trans_color.red &&
3470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 1) == png_ptr->trans_color.green &&
3471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 2) == png_ptr->trans_color.blue)
3472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *sp = gamma_table[*sp];
3481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 1) = gamma_table[*(sp + 1)];
3482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 2) = gamma_table[*(sp + 2)];
3483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3487893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 3)
3491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (*sp == png_ptr->trans_color.red &&
3493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 1) == png_ptr->trans_color.green &&
3494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         *(sp + 2) == png_ptr->trans_color.blue)
3495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
3504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
35055f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3506893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_16 != NULL)
3507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3508893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 6)
3510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 5));
3518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (r == png_ptr->trans_color.red &&
3520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         g == png_ptr->trans_color.green &&
3521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         b == png_ptr->trans_color.blue)
3522893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3523a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3536893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *sp = (png_byte)((v >> 8) & 0xff);
3539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 1) = (png_byte)(v & 0xff);
3540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 3) = (png_byte)(v & 0xff);
3544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *(sp + 5) = (png_byte)(v & 0xff);
3548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3556893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++, sp += 6)
3557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 5));
3565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (r == png_ptr->trans_color.red &&
3567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         g == png_ptr->trans_color.green &&
3568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         b == png_ptr->trans_color.blue)
3569893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3579893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3581893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3583893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3584893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3585a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3586893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY_ALPHA:
3587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3589893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
35905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_table != NULL)
3593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3594893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 2)
3596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 a = *(sp + 1);
3598893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3599893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == 0xff)
3600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = gamma_table[*sp];
3601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3604a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.gray;
3606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_byte v, w;
3611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*sp];
3613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.gray);
36149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0)
3615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = gamma_from_1[w];
3616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = w;
3617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3621893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3622893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3623893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 2)
3625893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3626893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte a = *(sp + 1);
3627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.gray;
3630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xff)
3632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*sp, *sp, a, png_ptr->background.gray);
3633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (png_ptr->bit_depth == 16) */
3637893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
36385f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_16_to_1 != NULL)
3641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3642893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3648893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == (png_uint_16)0xffff)
3649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3652893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3657893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3659a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.gray >> 8)
3661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3665893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3666893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3667893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 g, v, w;
3668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, g, a, png_ptr->background_1.gray);
36719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize != 0)
3672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                           w = v;
3673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        else
36749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           w = gamma_16_from_1[(v & 0xff) >>
36759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                               gamma_shift][v >> 8];
3676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((w >> 8) & 0xff);
3677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(w & 0xff);
3678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3679893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         + *(sp + 3));
3689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.gray >> 8)
3693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xffff)
3698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 g, v;
3700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, g, a, png_ptr->background.gray);
3703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3711a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB_ALPHA:
3713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
37165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_table != NULL)
3719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte a = *(sp + 3);
3724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == 0xff)
3726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = gamma_table[*sp];
3728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = gamma_table[*(sp + 1)];
3729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = gamma_table[*(sp + 2)];
3730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3734a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3740893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3742893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_byte v, w;
3743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*sp];
3745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.red);
37469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0) w = gamma_from_1[w];
3747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = w;
3748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3749893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*(sp + 1)];
3750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.green);
37519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0) w = gamma_from_1[w];
3752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = w;
3753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_to_1[*(sp + 2)];
3755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(w, v, a, png_ptr->background_1.blue);
37569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0) w = gamma_from_1[w];
3757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = w;
3758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 4)
3766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_byte a = *(sp + 3);
3768893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)png_ptr->background.red;
3772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)png_ptr->background.green;
3773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)png_ptr->background.blue;
3774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xff)
3777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*sp, *sp, a, png_ptr->background.red);
3779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*(sp + 1), *(sp + 1), a,
3781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            png_ptr->background.green);
3782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite(*(sp + 2), *(sp + 2), a,
3784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                            png_ptr->background.blue);
3785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
3790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
37915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   gamma_16_to_1 != NULL)
3794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 8)
3797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                         << 8) + (png_uint_16)(*(sp + 7)));
3800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (a == (png_uint_16)0xffff)
3802893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3803893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3805893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(v & 0xff);
3812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(v & 0xff);
3816893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3818893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else if (a == 0)
3819893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3820a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott                        /* Background is already in screen gamma */
3821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
3833893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_uint_16 v, w;
3835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(w, v, a, png_ptr->background_1.red);
38389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0)
38399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                8];
3841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((w >> 8) & 0xff);
3842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(w & 0xff);
3843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(w, v, a, png_ptr->background_1.green);
38469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0)
38479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                8];
3849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
3851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(w & 0xff);
3852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(w, v, a, png_ptr->background_1.blue);
38559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                        if (optimize == 0)
38569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                8];
3858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
3860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(w & 0xff);
3861893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
3866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row;
3869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  for (i = 0; i < row_width; i++, sp += 8)
3870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
3871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                         << 8) + (png_uint_16)(*(sp + 7)));
3873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     if (a == 0)
3875893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(png_ptr->background.green
3881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                                & 0xff);
3884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     else if (a < 0xffff)
3888893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
3889893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 v;
3890893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3892893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3893893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                            + *(sp + 3));
3894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                            + *(sp + 5));
3896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, r, a, png_ptr->background.red);
3898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *sp = (png_byte)((v >> 8) & 0xff);
3899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 1) = (png_byte)(v & 0xff);
3900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, g, a, png_ptr->background.green);
3902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 3) = (png_byte)(v & 0xff);
3904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        png_composite_16(v, b, a, png_ptr->background.blue);
3906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                        *(sp + 5) = (png_byte)(v & 0xff);
3908893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
3909893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
3910893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3911893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3912893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3913893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3914893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
3916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            break;
3917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
3918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
3919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
39209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
3921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
39225f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_GAMMA_SUPPORTED
3923893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Gamma correct the image, avoiding the alpha channel.  Make sure
3924893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * you do this after you deal with the transparency issue on grayscale
3925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * or RGB images. If your bit depth is 8, use gamma_table, if it
3926893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * is 16, use gamma_16_table and gamma_shift.  Build these with
3927893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * build_gamma_table().
3928893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
3929b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
3930b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3931893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
3932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_bytep gamma_table = png_ptr->gamma_table;
3933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
3934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int gamma_shift = png_ptr->gamma_shift;
3935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3936893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep sp;
3937893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
3938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width=row_info->width;
3939893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
39404215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_gamma");
39415f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
3942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3944893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
3945893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      switch (row_info->color_type)
3946893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
3947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB:
3948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3949893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3951893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
3952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
3953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3954893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3955893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3956893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3958893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3959893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3960893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3961893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
3964893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3965893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
3966893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
3967893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3968893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v;
3969893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3970893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3971893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
3972893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
3973893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
3974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3975893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3976893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
3977893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
3978893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
3979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3980893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3981893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
3982893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
3983893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
3984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
3985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
3986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
3987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
3988a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3989893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_RGB_ALPHA:
3990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
3991893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
3992893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
3993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
3994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
3995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
3996893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
3997893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
3998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
3999893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
4000893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4002893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
4003893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4006893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4007893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4009893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
4010893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4011893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4013893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4015893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4016893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4017893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4020893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4021893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4022893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4024893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4026893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4027893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 4;
4028893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4029893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
4031893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4032a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4033893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY_ALPHA:
4034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4035893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
4036893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4037893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4038893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4040893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
4041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4042893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else /* if (row_info->bit_depth == 16) */
4046893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4047893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4048893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4049893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4051893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4052893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4053893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 4;
4054893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4055893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4056893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
4057893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4058a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4059893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case PNG_COLOR_TYPE_GRAY:
4060893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 2)
4062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i += 4)
4065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int a = *sp & 0xc0;
4067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int b = *sp & 0x30;
4068893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int c = *sp & 0x0c;
4069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int d = *sp & 0x03;
4070893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4071893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)(
40725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
40735f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
40745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
40755f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4076893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4078893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4079a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4080893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 4)
4081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4082893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4083893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i += 2)
4084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int msb = *sp & 0xf0;
4086893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  int lsb = *sp & 0x0f;
4087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
40895f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
4090893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4091893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4093a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else if (row_info->bit_depth == 8)
4095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4097893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4098893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = gamma_table[*sp];
4100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp++;
4101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4103a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else if (row_info->bit_depth == 16)
4105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row;
4107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4108893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *sp = (png_byte)((v >> 8) & 0xff);
4111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *(sp + 1) = (png_byte)(v & 0xff);
4112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp += 2;
4113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
4116893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
4119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            break;
4120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
4121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
4122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
4123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
4124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Encode the alpha channel to the output gamma (the input channel is always
4127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear.)  Called only with color types that have an alpha channel.  Needs the
4128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * from_1 tables.
4129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
4130b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4131b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
4133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 row_width = row_info->width;
4134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_debug(1, "in png_do_encode_alpha");
4136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
41379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
4139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
4140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
4141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_CONST png_bytep table = png_ptr->gamma_from_1;
4142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (table != NULL)
4144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
4145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            PNG_CONST int step =
4146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* The alpha channel is the last component: */
4149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            row += step - 1;
4150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (; row_width > 0; --row_width, row += step)
4152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *row = table[*row];
4153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
4155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
4156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
4157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (row_info->bit_depth == 16)
4159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
4160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
4161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_CONST int gamma_shift = png_ptr->gamma_shift;
4162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (table != NULL)
4164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         {
4165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            PNG_CONST int step =
4166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* The alpha channel is the last component: */
4169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            row += step - 2;
4170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            for (; row_width > 0; --row_width, row += step)
4172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            {
4173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_uint_16 v;
4174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               v = table[*(row + 1) >> gamma_shift][*row];
4176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *row = (png_byte)((v >> 8) & 0xff);
4177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               *(row + 1) = (png_byte)(v & 0xff);
4178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            }
4179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
4181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
4182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* Only get to here if called with a weird row_info; no harm has been done,
4186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * so just issue a warning.
4187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
4188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
41925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_EXPAND_SUPPORTED
4193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Expands a palette row to an RGB or RGBA row depending
4194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * upon whether you supply trans and num_trans.
4195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
4196b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_expand_palette(png_row_infop row_info, png_bytep row,
41987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis    png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
4199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
4200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int shift, value;
4201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep sp, dp;
4202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
4203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width=row_info->width;
4204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
42054215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_expand_palette");
42065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4208893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
4209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->bit_depth < 8)
4210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         switch (row_info->bit_depth)
4212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 1:
4214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)((row_width - 1) >> 3);
4216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)row_width - 1;
4217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               shift = 7 - (int)((row_width + 7) & 0x07);
4218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4219893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if ((*sp >> shift) & 0x01)
4221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = 1;
4222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4223893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = 0;
4225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (shift == 7)
4227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 0;
4229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp--;
4230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift++;
4234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4235893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp--;
4236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
4238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4239a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 2:
4241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)((row_width - 1) >> 2);
4243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)row_width - 1;
4244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  value = (*sp >> shift) & 0x03;
4248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp = (png_byte)value;
4249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (shift == 6)
4250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 0;
4252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp--;
4253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4255893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift += 2;
4257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp--;
4259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
4261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4262a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            case 4:
4264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)((row_width - 1) >> 1);
4266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)row_width - 1;
4267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               shift = (int)((row_width & 0x01) << 2);
4268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  value = (*sp >> shift) & 0x0f;
4271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp = (png_byte)value;
4272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if (shift == 4)
4273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift = 0;
4275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     sp--;
4276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     shift += 4;
4280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp--;
4282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
4284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            default:
4287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               break;
4288893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->bit_depth = 8;
4290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->pixel_depth = 8;
4291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->rowbytes = row_width;
4292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info->bit_depth == 8)
4295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            if (num_trans > 0)
4298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)row_width - 1;
4300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)(row_width << 2) - 1;
4301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  if ((int)(*sp) >= num_trans)
4305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                     *dp-- = trans_alpha[*sp];
4309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].blue;
4311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].green;
4312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].red;
4313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp--;
4314893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->bit_depth = 8;
4316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->pixel_depth = 32;
4317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->rowbytes = row_width * 4;
4318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->color_type = 6;
4319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->channels = 4;
4320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else
4323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4324893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)row_width - 1;
4325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)(row_width * 3) - 1;
4326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].blue;
4330893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].green;
4331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = palette[*sp].red;
4332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp--;
4333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4334a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->bit_depth = 8;
4336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->pixel_depth = 24;
4337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->rowbytes = row_width * 3;
4338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->color_type = 2;
4339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               row_info->channels = 3;
4340893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* If the bit depth < 8, it is expanded to 8.  Also, if the already
4347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * expanded transparency value is supplied, an alpha channel is built.
4348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
4349b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_expand(png_row_infop row_info, png_bytep row,
4351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_color_16p trans_color)
4352893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
4353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   int shift, value;
4354893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep sp, dp;
4355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 i;
4356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 row_width=row_info->width;
4357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
43584215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_debug(1, "in png_do_expand");
43595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4360893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
4361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
4362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
43639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
4364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth < 8)
4366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            switch (row_info->bit_depth)
4368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 1:
4370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gray = (gray & 0x01) * 0xff;
4372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row + (png_size_t)((row_width - 1) >> 3);
4373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp = row + (png_size_t)row_width - 1;
4374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = 7 - (int)((row_width + 7) & 0x07);
4375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
4376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if ((*sp >> shift) & 0x01)
4378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *dp = 0xff;
4379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4381893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        *dp = 0;
4382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (shift == 7)
4384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
4385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 0;
4386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp--;
4387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
4388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4389893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift++;
4391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4392893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     dp--;
4393893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
4395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4396a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 2:
4398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gray = (gray & 0x03) * 0x55;
4400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row + (png_size_t)((row_width - 1) >> 2);
4401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp = row + (png_size_t)row_width - 1;
4402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
4404893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     value = (*sp >> shift) & 0x03;
4406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
4407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        (value << 6));
4408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (shift == 6)
4409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
4410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 0;
4411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp--;
4412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
4413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4414893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift += 2;
4416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     dp--;
4418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
4420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4421a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               case 4:
4423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  gray = (gray & 0x0f) * 0x11;
4425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  sp = row + (png_size_t)((row_width - 1) >> 1);
4426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  dp = row + (png_size_t)row_width - 1;
4427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  for (i = 0; i < row_width; i++)
4429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     value = (*sp >> shift) & 0x0f;
4431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp = (png_byte)(value | (value << 4));
4432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     if (shift == 4)
4433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     {
4434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 0;
4435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        sp--;
4436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     }
4437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4438893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     else
4439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                        shift = 4;
4440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     dp--;
4442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4443893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  break;
4444893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               default:
4447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  break;
4448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4449a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->bit_depth = 8;
4451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = 8;
4452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = row_width;
4453893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (trans_color != NULL)
4456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (row_info->bit_depth == 8)
4458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               gray = gray & 0xff;
4460893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + (png_size_t)row_width - 1;
4461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (png_size_t)(row_width << 1) - 1;
4462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4463893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4464893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
44659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                  if ((*sp & 0xffU) == gray)
4466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0;
4467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4471893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = *sp--;
4472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4474a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            else if (row_info->bit_depth == 16)
4476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               unsigned int gray_high = (gray >> 8) & 0xff;
4478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               unsigned int gray_low = gray & 0xff;
4479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               sp = row + row_info->rowbytes - 1;
4480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               dp = row + (row_info->rowbytes << 1) - 1;
4481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < row_width; i++)
4482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
44839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                  if ((*(sp - 1) & 0xffU) == gray_high &&
44849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett                      (*(sp) & 0xffU) == gray_low)
4485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0;
4487893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0;
4488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  else
4491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  {
4492893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                     *dp-- = 0xff;
4494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  }
4495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4496893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = *sp--;
4497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = *sp--;
4498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4500a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
4502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->channels = 2;
4503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
45057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis                row_width);
4506893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
45089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
45099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          trans_color != NULL)
4510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
4511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         if (row_info->bit_depth == 8)
4512893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte red = (png_byte)(trans_color->red & 0xff);
4514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte green = (png_byte)(trans_color->green & 0xff);
4515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte blue = (png_byte)(trans_color->blue & 0xff);
4516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            sp = row + (png_size_t)row_info->rowbytes - 1;
4517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            dp = row + (png_size_t)(row_width << 2) - 1;
4518893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
4519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
4521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0;
4522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
4524893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0xff;
4525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4529893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         else if (row_info->bit_depth == 16)
4532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
4533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
4534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
4535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
4536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte red_low = (png_byte)(trans_color->red & 0xff);
4537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte green_low = (png_byte)(trans_color->green & 0xff);
4538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
4539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            sp = row + row_info->rowbytes - 1;
4540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            dp = row + (png_size_t)(row_width << 3) - 1;
4541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < row_width; i++)
4542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
4543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               if (*(sp - 5) == red_high &&
4544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 4) == red_low &&
4545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 3) == green_high &&
4546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 2) == green_low &&
4547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp - 1) == blue_high &&
4548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                   *(sp    ) == blue_low)
4549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0;
4551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0;
4552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               else
4555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
4556893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0xff;
4557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  *dp-- = 0xff;
4558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
4559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4561893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4562893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4564893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               *dp-- = *sp--;
4566893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
4567893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
4568893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
4569893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->channels = 4;
4570893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
45714215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
4573893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4574893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4575893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_EXPAND_16_SUPPORTED
4578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* If the bit depth is 8 and the color type is not a palette type expand the
4579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * whole row to 16 bits.  Has no effect otherwise.
4580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */
4581b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4582b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_do_expand_16(png_row_infop row_info, png_bytep row)
4583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
4584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (row_info->bit_depth == 8 &&
4585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
4586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
4587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* The row have a sequence of bytes containing [0..255] and we need
4588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * to turn it into another row containing [0..65535], to do this we
4589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * calculate:
4590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
4591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *  (input / 255) * 65535
4592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *
4593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *  Which happens to be exactly input * 257 and this can be achieved
4594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       *  simply by byte replication in place (copying backwards).
4595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
4596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
4597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
4598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      while (dp > sp)
4599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         dp[-2] = dp[-1] = *--sp, dp -= 2;
4600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->rowbytes *= 2;
4602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->bit_depth = 16;
4603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
4605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
4606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
4607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4608b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_QUANTIZE_SUPPORTED
4609b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void
4610b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_quantize(png_row_infop row_info, png_bytep row,
4611b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
4612b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{
4613b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_bytep sp, dp;
4614b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_uint_32 i;
4615b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_uint_32 row_width=row_info->width;
4616b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4617b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_quantize");
4618b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4619b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (row_info->bit_depth == 8)
4620b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4621b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
4622b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4623b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         int r, g, b, p;
4624b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         sp = row;
4625b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         dp = row;
4626b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i = 0; i < row_width; i++)
4627b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
4628b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            r = *sp++;
4629b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            g = *sp++;
4630b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            b = *sp++;
4631b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4632b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            /* This looks real messy, but the compiler will reduce
4633b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * it down to a reasonable formula.  For example, with
4634b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * 5 bits per color, we get:
4635b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             * p = (((r >> 3) & 0x1f) << 10) |
4636b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             *    (((g >> 3) & 0x1f) << 5) |
4637b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             *    ((b >> 3) & 0x1f);
4638b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             */
4639b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4640b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4641b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4642b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4643b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4644b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_BLUE_BITS)) |
4645b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4646b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4647b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4648b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            *dp++ = palette_lookup[p];
4649b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
4650b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4651b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4652b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->channels = 1;
4653b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->pixel_depth = row_info->bit_depth;
4654b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4655b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4656b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4657b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4658b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         palette_lookup != NULL)
4659b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4660b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         int r, g, b, p;
4661b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         sp = row;
4662b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         dp = row;
4663b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i = 0; i < row_width; i++)
4664b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
4665b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            r = *sp++;
4666b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            g = *sp++;
4667b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            b = *sp++;
4668b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            sp++;
4669b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4670b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4671b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4672b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4673b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4674b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4675b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                (PNG_QUANTIZE_BLUE_BITS)) |
4676b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4677b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4678b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4679b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            *dp++ = palette_lookup[p];
4680b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
4681b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4682b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4683b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->channels = 1;
4684b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->pixel_depth = row_info->bit_depth;
4685b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4686b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4687b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4688b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4689b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         quantize_lookup)
4690b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4691b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         sp = row;
4692b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4693b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         for (i = 0; i < row_width; i++, sp++)
4694b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         {
4695b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            *sp = quantize_lookup[*sp];
4696b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         }
4697b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4698b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4699b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}
47009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_QUANTIZE */
4701b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4702b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Transform the row.  The order of transformations is significant,
4703b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * and is very touchy.  If you add a transformation, take care to
4704b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * decide how it fits in with the other transformations here.
4705b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */
4706b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarivoid /* PRIVATE */
4707b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
4708b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{
4709b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   png_debug(1, "in png_do_read_transformations");
4710b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4711b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (png_ptr->row_buf == NULL)
4712b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4713b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
4714b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * error is incredibly rare and incredibly easy to debug without this
4715b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * information.
4716b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4717b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_error(png_ptr, "NULL row buffer");
4718b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4719b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4720b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
4721b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
4722b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
4723b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * all transformations, however in practice the ROW_INIT always gets done on
4724b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * demand, if necessary.
4725b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
4726b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
47279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4728b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4729b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Application has failed to call either png_read_start_image() or
4730b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * png_read_update_info() after setting transforms that expand pixels.
4731b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
4732b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4733b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_error(png_ptr, "Uninitialized row");
4734b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4735b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4736b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_SUPPORTED
47379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4738b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4739b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4740b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4741b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
4742b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4743b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4744b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4745b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      else
4746b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
47479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett         if (png_ptr->num_trans != 0 &&
47489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4749b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_do_expand(row_info, png_ptr->row_buf + 1,
4750b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                &(png_ptr->trans_color));
4751b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4752b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         else
4753b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_do_expand(row_info, png_ptr->row_buf + 1,
4754b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                NULL);
4755b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4756b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4757b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4758b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4759b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
47609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
47619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_COMPOSE) == 0 &&
47629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
47639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4764b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
47657a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis          0 /* at_start == false, because SWAP_ALPHA happens later */);
4766b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4767b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4768b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
47699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4770b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4771b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      int rgb_error =
4772b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          png_do_rgb_to_gray(png_ptr, row_info,
4773b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari              png_ptr->row_buf + 1);
4774b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
47759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (rgb_error != 0)
4776b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      {
4777b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         png_ptr->rgb_to_gray_status=1;
4778b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4779b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             PNG_RGB_TO_GRAY_WARN)
4780b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4781b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4782b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4783b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             PNG_RGB_TO_GRAY_ERR)
4784b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4785b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      }
4786b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
4787b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4788b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4789b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
4790b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4791b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   In most cases, the "simple transparency" should be done prior to doing
4792b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
4793b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   pixel is transparent.  You would also need to make sure that the
4794b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   transparency information is upgraded to RGB.
4795b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4796b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   To summarize, the current flow is:
4797b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
4798b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   with background "in place" if transparent,
4799b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   convert to RGB if necessary
4800b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + alpha -> composite with gray background and remove alpha bytes,
4801b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   convert to RGB if necessary
4802b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4803b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   To support RGB backgrounds for gray images we need:
4804b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + simple transparency -> convert to RGB + simple transparency,
4805b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   compare 3 or 6 bytes and composite with
4806b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   background "in place" if transparent
4807b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   (3x compare/pixel compared to doing
4808b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   composite with gray bkgrnd)
4809b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *   - Gray + alpha -> convert to RGB + alpha, composite with background and
4810b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   remove alpha bytes (3x float
4811b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   operations/pixel compared with composite
4812b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *                                   on gray background)
4813b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *
4814b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  Greg's change will do this.  The reason it wasn't done before is for
4815b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  performance, as this increases the per-pixel operations.  If we would check
4816b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  in advance if the background was gray or RGB, and position the gray-to-RGB
4817b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *  transform appropriately, then it would save a lot of work/time.
4818b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */
4819b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4820b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4821b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* If gray -> RGB, do so now only if background is non-gray; else do later
4822b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * for performance reasons
4823b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
48249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
48259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4826b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4827b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4828b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
4829b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4830b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
48319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4832b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
4833b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4835b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GAMMA_SUPPORTED
48369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4837b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4838b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Because RGB_TO_GRAY does the gamma transform. */
48399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4840b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4841b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4842b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4843b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Because PNG_COMPOSE does the gamma transform if there is something to
4844b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * do (if there is an alpha channel or transparency.)
4845b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
48469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4847b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       ((png_ptr->num_trans != 0) ||
48489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4849b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4850b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      /* Because png_init_read_transformations transforms the palette, unless
4851b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       * RGB_TO_GRAY will do the transform.
4852b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       */
4853b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
4854b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
4855b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
48565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4857b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
48589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
48599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
48609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
48619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4862b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
48639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett          0 /* at_start == false, because SWAP_ALPHA happens later */);
4864b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4866b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
48679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
48689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4869b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
4870b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4872b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
48739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
4874b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
4875b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4877b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
4878b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* There is no harm in doing both of these because only one has any effect,
4879b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * by putting the 'scale' option first if the app asks for scale (either by
4880b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * calling the API or in a TRANSFORM flag) this is what happens.
4881b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
48829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4883b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_chop(row_info, png_ptr->row_buf + 1);
4884b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4886b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_QUANTIZE_SUPPORTED
48879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4888b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   {
4889b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_quantize(row_info, png_ptr->row_buf + 1,
4890b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          png_ptr->palette_lookup, png_ptr->quantize_index);
4891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4892b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (row_info->rowbytes == 0)
4893b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
4894b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   }
48959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_QUANTIZE */
4896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4897b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_16_SUPPORTED
4898b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* Do the expansion now, after all the arithmetic has been done.  Notice
4899b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * that previous transformations can handle the PNG_EXPAND_16 flag if this
4900b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * is efficient (particularly true in the case of gamma correction, where
4901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    * better accuracy results faster!)
4902b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari    */
49039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4904b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_expand_16(row_info, png_ptr->row_buf + 1);
4905b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4907b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4908b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
49099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
49109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
4911b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4914b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_SUPPORTED
49159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4916b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_invert(row_info, png_ptr->row_buf + 1);
4917b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4919b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
49209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
4921b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
4922b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4923893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4924b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SHIFT_SUPPORTED
49259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4926b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_unshift(row_info, png_ptr->row_buf + 1,
4927b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          &(png_ptr->shift));
4928b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
49295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
4930b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACK_SUPPORTED
49319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_PACK) != 0)
4932b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_unpack(row_info, png_ptr->row_buf + 1);
4933b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
4935b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
4936b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   /* Added at libpng-1.5.10 */
4937b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4938b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari       png_ptr->num_palette_max >= 0)
4939b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_check_palette_indexes(png_ptr, row_info);
4940b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4941893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4942b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_BGR_SUPPORTED
49439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_BGR) != 0)
4944b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_bgr(row_info, png_ptr->row_buf + 1);
4945b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4946a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACKSWAP_SUPPORTED
49489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4949b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_packswap(row_info, png_ptr->row_buf + 1);
4950b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4951a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4952b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_FILLER_SUPPORTED
49539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_FILLER) != 0)
4954b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_read_filler(row_info, png_ptr->row_buf + 1,
4955b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          (png_uint_32)png_ptr->filler, png_ptr->flags);
4956b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4958b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
49599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
4960b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
4961b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4963b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_16BIT_SUPPORTED
4964b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_SUPPORTED
49659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
4966b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_do_swap(row_info, png_ptr->row_buf + 1);
4967b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4968b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4969a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4970b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
49719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
49729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett   {
4973b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      if (png_ptr->read_user_transform_fn != NULL)
4974b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
4975b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             (png_ptr,     /* png_ptr */
4976b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             row_info,     /* row_info: */
4977b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_uint_32 width;       width of row */
4978b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_size_t rowbytes;     number of bytes in row */
4979b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte color_type;     color type of pixels */
4980b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte bit_depth;      bit depth of samples */
4981b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte channels;       number of channels (1-4) */
4982b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
4983b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari             png_ptr->row_buf + 1);    /* start of pixel data for row */
4984b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
49859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (png_ptr->user_transform_depth != 0)
4986b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->bit_depth = png_ptr->user_transform_depth;
4987a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
49889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett      if (png_ptr->user_transform_channels != 0)
4989b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari         row_info->channels = png_ptr->user_transform_channels;
4990b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4991b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
4992b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari          row_info->channels);
4993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
4994b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
4995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
4996b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif
4997893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
4998b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
49999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_TRANSFORMS */
50009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ */
5001