pngrtran.c 165.0 KB
Newer Older
G
Guy Schalnat 已提交
1

A
Andreas Dilger 已提交
2
/* pngrtran.c - transforms the data in a row for PNG readers
3
 *
4
 * Last changed in libpng 1.6.33 [(PENDING RELEASE)]
5
 * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 *
13
 * This file contains functions optionally called by an application
14
 * in order to tell libpng how to handle data when reading a PNG.
15
 * Transformations that are used in both reading and writing are
16 17
 * in pngtrans.c.
 */
G
Guy Schalnat 已提交
18

19
#include "pngpriv.h"
20

21 22
#ifdef PNG_READ_SUPPORTED

23
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
24
void PNGAPI
25
png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
26
{
27
   png_debug(1, "in png_set_crc_action");
28

29 30
   if (png_ptr == NULL)
      return;
31 32

   /* Tell libpng how we react to CRC errors in critical chunks */
33 34
   switch (crit_action)
   {
35
      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
36
         break;
37

38
      case PNG_CRC_WARN_USE:                               /* Warn/use data */
39 40 41
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
         break;
42

43
      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
44 45 46 47
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
                           PNG_FLAG_CRC_CRITICAL_IGNORE;
         break;
48

49
      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
50
         png_warning(png_ptr,
51
             "Can't discard critical data on CRC error");
52
         /* FALLTHROUGH */
53
      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
54

55 56 57 58 59 60
      case PNG_CRC_DEFAULT:
      default:
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         break;
   }

61
   /* Tell libpng how we react to CRC errors in ancillary chunks */
62 63
   switch (ancil_action)
   {
64
      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
65
         break;
66

67
      case PNG_CRC_WARN_USE:                              /* Warn/use data */
68 69 70
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
         break;
71

72
      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
73 74 75 76
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
         break;
77

78
      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
79 80 81
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
         break;
82

83
      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
84

85 86 87 88 89 90 91
      case PNG_CRC_DEFAULT:
      default:
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         break;
   }
}

92 93 94
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Is it OK to set a transformation now?  Only if png_start_read_image or
 * png_read_update_info have not been called.  It is not necessary for the IHDR
95 96
 * to have been read in all cases; the need_IHDR parameter allows for this
 * check too.
97 98 99 100 101 102
 */
static int
png_rtran_ok(png_structrp png_ptr, int need_IHDR)
{
   if (png_ptr != NULL)
   {
103
      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
104
         png_app_error(png_ptr,
105
             "invalid after png_start_read_image or png_read_update_info");
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
         png_app_error(png_ptr, "invalid before the PNG header has been read");

      else
      {
         /* Turn on failure to initialize correctly for all transforms. */
         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;

         return 1; /* Ok */
      }
   }

   return 0; /* no png_error possible! */
}
#endif

G
[devel]  
Glenn Randers-Pehrson 已提交
123
#ifdef PNG_READ_BACKGROUND_SUPPORTED
124
/* Handle alpha and tRNS via a background color */
G
[devel]  
Glenn Randers-Pehrson 已提交
125
void PNGFAPI
126
png_set_background_fixed(png_structrp png_ptr,
127
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
128
    int need_expand, png_fixed_point background_gamma)
G
Guy Schalnat 已提交
129
{
G
[devel]  
Glenn Randers-Pehrson 已提交
130
   png_debug(1, "in png_set_background_fixed");
131

132
   if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
133
      return;
134

A
Andreas Dilger 已提交
135 136 137 138 139 140
   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
   {
      png_warning(png_ptr, "Application must supply a known background gamma");
      return;
   }

141 142 143 144
   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

145
   png_ptr->background = *background_color;
G
[devel]  
Glenn Randers-Pehrson 已提交
146
   png_ptr->background_gamma = background_gamma;
147
   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
148
   if (need_expand != 0)
149 150 151
      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
   else
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
G
Guy Schalnat 已提交
152
}
G
[devel]  
Glenn Randers-Pehrson 已提交
153 154 155

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
156
png_set_background(png_structrp png_ptr,
157
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
158 159 160 161 162
    int need_expand, double background_gamma)
{
   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
}
163
#  endif /* FLOATING_POINT */
G
[devel]  
Glenn Randers-Pehrson 已提交
164
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
165

166 167 168 169 170
/* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
 * one that pngrtran does first (scale) happens.  This is necessary to allow the
 * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
 */
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
171
void PNGAPI
172
png_set_scale_16(png_structrp png_ptr)
G
Guy Schalnat 已提交
173
{
174
   png_debug(1, "in png_set_scale_16");
175

176
   if (png_rtran_ok(png_ptr, 0) == 0)
177
      return;
178

179
   png_ptr->transformations |= PNG_SCALE_16_TO_8;
180
}
181
#endif
182

183
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
184 185
/* Chop 16-bit depth files to 8-bit depth */
void PNGAPI
186
png_set_strip_16(png_structrp png_ptr)
187
{
188
   png_debug(1, "in png_set_strip_16");
189

190
   if (png_rtran_ok(png_ptr, 0) == 0)
191 192
      return;

193
   png_ptr->transformations |= PNG_16_TO_8;
G
Guy Schalnat 已提交
194
}
195
#endif
G
Guy Schalnat 已提交
196

197
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
198
void PNGAPI
199
png_set_strip_alpha(png_structrp png_ptr)
A
Andreas Dilger 已提交
200
{
201
   png_debug(1, "in png_set_strip_alpha");
202

203
   if (png_rtran_ok(png_ptr, 0) == 0)
204
      return;
205

206
   png_ptr->transformations |= PNG_STRIP_ALPHA;
A
Andreas Dilger 已提交
207 208 209
}
#endif

210 211
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
static png_fixed_point
212
translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
213
    int is_screen)
214 215 216 217 218 219 220 221 222 223 224 225 226 227
{
   /* Check for flag values.  The main reason for having the old Mac value as a
    * flag is that it is pretty near impossible to work out what the correct
    * value is from Apple documentation - a working Mac system is needed to
    * discover the value!
    */
   if (output_gamma == PNG_DEFAULT_sRGB ||
      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
   {
      /* If there is no sRGB support this just sets the gamma to the standard
       * sRGB value.  (This is a side effect of using this function!)
       */
#     ifdef PNG_READ_sRGB_SUPPORTED
         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
228 229
#     else
         PNG_UNUSED(png_ptr)
230
#     endif
231
      if (is_screen != 0)
232 233 234 235 236 237 238 239
         output_gamma = PNG_GAMMA_sRGB;
      else
         output_gamma = PNG_GAMMA_sRGB_INVERSE;
   }

   else if (output_gamma == PNG_GAMMA_MAC_18 ||
      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
   {
240
      if (is_screen != 0)
241 242 243 244 245 246 247 248 249 250
         output_gamma = PNG_GAMMA_MAC_OLD;
      else
         output_gamma = PNG_GAMMA_MAC_INVERSE;
   }

   return output_gamma;
}

#  ifdef PNG_FLOATING_POINT_SUPPORTED
static png_fixed_point
251
convert_gamma_value(png_structrp png_ptr, double output_gamma)
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
{
   /* The following silently ignores cases where fixed point (times 100,000)
    * gamma values are passed to the floating point API.  This is safe and it
    * means the fixed point constants work just fine with the floating point
    * API.  The alternative would just lead to undetected errors and spurious
    * bug reports.  Negative values fail inside the _fixed API unless they
    * correspond to the flag values.
    */
   if (output_gamma > 0 && output_gamma < 128)
      output_gamma *= PNG_FP_1;

   /* This preserves -1 and -2 exactly: */
   output_gamma = floor(output_gamma + .5);

   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
      png_fixed_error(png_ptr, "gamma value");

   return (png_fixed_point)output_gamma;
}
#  endif
#endif /* READ_ALPHA_MODE || READ_GAMMA */

274 275
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
void PNGFAPI
276
png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
277
    png_fixed_point output_gamma)
278 279 280 281 282 283
{
   int compose = 0;
   png_fixed_point file_gamma;

   png_debug(1, "in png_set_alpha_mode");

284
   if (png_rtran_ok(png_ptr, 0) == 0)
285 286
      return;

287
   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
288

289
   /* Validate the value to ensure it is in a reasonable range. The value
290 291 292
    * is expected to be 1 or greater, but this range test allows for some
    * viewing correction values.  The intent is to weed out users of this API
    * who use the inverse of the gamma value accidentally!  Since some of these
293 294 295 296
    * values are reasonable this may have to be changed:
    *
    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit
    * gamma of 36, and its reciprocal.)
297
    */
298
   if (output_gamma < 1000 || output_gamma > 10000000)
299
      png_error(png_ptr, "output gamma out of expected range");
300

301
   /* The default file gamma is the inverse of the output gamma; the output
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
    * gamma may be changed below so get the file value first:
    */
   file_gamma = png_reciprocal(output_gamma);

   /* There are really 8 possibilities here, composed of any combination
    * of:
    *
    *    premultiply the color channels
    *    do not encode non-opaque pixels
    *    encode the alpha as well as the color channels
    *
    * The differences disappear if the input/output ('screen') gamma is 1.0,
    * because then the encoding is a no-op and there is only the choice of
    * premultiplying the color channels or not.
    *
    * png_set_alpha_mode and png_set_background interact because both use
    * png_compose to do the work.  Calling both is only useful when
    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
    */
   switch (mode)
   {
      case PNG_ALPHA_PNG:        /* default: png standard */
         /* No compose, but it may be set by png_set_background! */
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
         break;

      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
         compose = 1;
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
         /* The output is linear: */
         output_gamma = PNG_FP_1;
         break;

      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
         compose = 1;
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
         /* output_gamma records the encoding of opaque pixels! */
         break;

      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
         compose = 1;
         png_ptr->transformations |= PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
         break;

      default:
         png_error(png_ptr, "invalid alpha mode");
   }

   /* Only set the default gamma if the file gamma has not been set (this has
    * the side effect that the gamma in a second call to png_set_alpha_mode will
    * be ignored.)
    */
359 360 361 362 363
   if (png_ptr->colorspace.gamma == 0)
   {
      png_ptr->colorspace.gamma = file_gamma;
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   }
364 365 366 367

   /* But always set the output gamma: */
   png_ptr->screen_gamma = output_gamma;

368
   /* Finally, if pre-multiplying, set the background fields to achieve the
369 370
    * desired result.
    */
371
   if (compose != 0)
372 373
   {
      /* And obtain alpha pre-multiplication by composing on black: */
374 375
      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
376 377 378
      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;

379
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
380
         png_error(png_ptr,
381
             "conflicting calls to set alpha mode and background");
382 383 384 385 386 387 388

      png_ptr->transformations |= PNG_COMPOSE;
   }
}

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
389
png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
390
{
391
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
392
       output_gamma));
393 394 395 396
}
#  endif
#endif

397
#ifdef PNG_READ_QUANTIZE_SUPPORTED
398
/* Dither file to 8-bit.  Supply a palette, the current number
399 400
 * of elements in the palette, the maximum number of elements
 * allowed, and a histogram if possible.  If the current number
401
 * of colors is greater than the maximum number, the palette will be
402 403
 * modified to fit in the maximum number.  "full_quantize" indicates
 * whether we need a quantizing cube set up for RGB images, or if we
404 405
 * simply are reducing the number of colors in a paletted image.
 */
G
Guy Schalnat 已提交
406 407

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
408
{
409
   struct png_dsort_struct * next;
G
Guy Schalnat 已提交
410 411
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
412
} png_dsort;
413 414
typedef png_dsort *   png_dsortp;
typedef png_dsort * * png_dsortpp;
G
Guy Schalnat 已提交
415

416
void PNGAPI
417
png_set_quantize(png_structrp png_ptr, png_colorp palette,
418
    int num_palette, int maximum_colors, png_const_uint_16p histogram,
419
    int full_quantize)
G
Guy Schalnat 已提交
420
{
421
   png_debug(1, "in png_set_quantize");
422

423
   if (png_rtran_ok(png_ptr, 0) == 0)
424
      return;
425

426
   png_ptr->transformations |= PNG_QUANTIZE;
G
Guy Schalnat 已提交
427

428
   if (full_quantize == 0)
G
Guy Schalnat 已提交
429 430 431
   {
      int i;

432
      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
433
          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
434
      for (i = 0; i < num_palette; i++)
435
         png_ptr->quantize_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
436 437 438 439
   }

   if (num_palette > maximum_colors)
   {
A
Andreas Dilger 已提交
440
      if (histogram != NULL)
G
Guy Schalnat 已提交
441
      {
A
Andreas Dilger 已提交
442
         /* This is easy enough, just throw out the least used colors.
443 444
          * Perhaps not the best solution, but good enough.
          */
G
Guy Schalnat 已提交
445 446 447

         int i;

448
         /* Initialize an array to sort colors */
449
         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
450
             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
451

452
         /* Initialize the quantize_sort array */
G
Guy Schalnat 已提交
453
         for (i = 0; i < num_palette; i++)
454
            png_ptr->quantize_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
455

A
Andreas Dilger 已提交
456
         /* Find the least used palette entries by starting a
457 458 459 460 461
          * bubble sort, and running it until we have sorted
          * out enough colors.  Note that we don't care about
          * sorting all the colors, just finding which are
          * least used.
          */
G
Guy Schalnat 已提交
462 463 464

         for (i = num_palette - 1; i >= maximum_colors; i--)
         {
465
            int done; /* To stop early if the list is pre-sorted */
G
Guy Schalnat 已提交
466
            int j;
G
Guy Schalnat 已提交
467 468 469 470

            done = 1;
            for (j = 0; j < i; j++)
            {
471 472
               if (histogram[png_ptr->quantize_sort[j]]
                   < histogram[png_ptr->quantize_sort[j + 1]])
G
Guy Schalnat 已提交
473 474 475
               {
                  png_byte t;

476 477 478
                  t = png_ptr->quantize_sort[j];
                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
                  png_ptr->quantize_sort[j + 1] = t;
G
Guy Schalnat 已提交
479 480 481
                  done = 0;
               }
            }
482

483
            if (done != 0)
G
Guy Schalnat 已提交
484 485 486
               break;
         }

487
         /* Swap the palette around, and set up a table, if necessary */
488
         if (full_quantize != 0)
G
Guy Schalnat 已提交
489
         {
490
            int j = num_palette;
G
Guy Schalnat 已提交
491

492 493 494
            /* Put all the useful colors within the max, but don't
             * move the others.
             */
495
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
496
            {
497
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
498 499 500
               {
                  do
                     j--;
501
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
502

G
Guy Schalnat 已提交
503 504
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
505
            }
G
Guy Schalnat 已提交
506 507 508
         }
         else
         {
509
            int j = num_palette;
G
Guy Schalnat 已提交
510

511 512 513
            /* Move all the used colors inside the max limit, and
             * develop a translation table.
             */
514
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
515
            {
516
               /* Only move the colors we need to */
517
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
518 519 520 521 522
               {
                  png_color tmp_color;

                  do
                     j--;
523
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
524 525 526 527

                  tmp_color = palette[j];
                  palette[j] = palette[i];
                  palette[i] = tmp_color;
528
                  /* Indicate where the color went */
529 530
                  png_ptr->quantize_index[j] = (png_byte)i;
                  png_ptr->quantize_index[i] = (png_byte)j;
G
Guy Schalnat 已提交
531 532
               }
            }
A
Andreas Dilger 已提交
533

534
            /* Find closest color for those colors we are not using */
G
Guy Schalnat 已提交
535 536
            for (i = 0; i < num_palette; i++)
            {
537
               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
G
Guy Schalnat 已提交
538
               {
A
Andreas Dilger 已提交
539
                  int min_d, k, min_k, d_index;
G
Guy Schalnat 已提交
540

541
                  /* Find the closest color to one we threw out */
542
                  d_index = png_ptr->quantize_index[i];
A
Andreas Dilger 已提交
543 544
                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
                  for (k = 1, min_k = 0; k < maximum_colors; k++)
G
Guy Schalnat 已提交
545 546 547
                  {
                     int d;

A
Andreas Dilger 已提交
548
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
549 550 551 552

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
553
                        min_k = k;
G
Guy Schalnat 已提交
554 555
                     }
                  }
556
                  /* Point to closest color */
557
                  png_ptr->quantize_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
558 559 560
               }
            }
         }
561 562
         png_free(png_ptr, png_ptr->quantize_sort);
         png_ptr->quantize_sort = NULL;
G
Guy Schalnat 已提交
563 564 565
      }
      else
      {
A
Andreas Dilger 已提交
566
         /* This is much harder to do simply (and quickly).  Perhaps
567 568 569 570 571 572 573
          * we need to go through a median cut routine, but those
          * don't always behave themselves with only a few colors
          * as input.  So we will just find the closest two colors,
          * and throw out one of them (chosen somewhat randomly).
          * [We don't understand this at all, so if someone wants to
          *  work on improving it, be our guest - AED, GRP]
          */
G
Guy Schalnat 已提交
574 575 576
         int i;
         int max_d;
         int num_new_palette;
577
         png_dsortp t;
G
Guy Schalnat 已提交
578
         png_dsortpp hash;
579

580
         t = NULL;
G
Guy Schalnat 已提交
581

582
         /* Initialize palette index arrays */
583
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
584 585
             (png_alloc_size_t)((png_uint_32)num_palette *
             (sizeof (png_byte))));
586
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
587 588
             (png_alloc_size_t)((png_uint_32)num_palette *
             (sizeof (png_byte))));
G
Guy Schalnat 已提交
589

590
         /* Initialize the sort array */
G
Guy Schalnat 已提交
591 592
         for (i = 0; i < num_palette; i++)
         {
593 594
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
595 596
         }

597
         hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
598
             (sizeof (png_dsortp))));
G
Guy Schalnat 已提交
599 600 601

         num_new_palette = num_palette;

602 603 604 605 606 607 608 609
         /* Initial wild guess at how far apart the farthest pixel
          * pair we will be eliminating will be.  Larger
          * numbers mean more areas will be allocated, Smaller
          * numbers run the risk of not saving enough data, and
          * having to do this all over again.
          *
          * I have not done extensive checking on this number.
          */
G
Guy Schalnat 已提交
610 611
         max_d = 96;

G
Guy Schalnat 已提交
612
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
613 614 615 616 617 618 619 620 621
         {
            for (i = 0; i < num_new_palette - 1; i++)
            {
               int j;

               for (j = i + 1; j < num_new_palette; j++)
               {
                  int d;

G
Guy Schalnat 已提交
622
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
623 624 625 626

                  if (d <= max_d)
                  {

627
                     t = (png_dsortp)png_malloc_warn(png_ptr,
628
                         (png_alloc_size_t)(sizeof (png_dsort)));
629

630 631
                     if (t == NULL)
                         break;
632

G
Guy Schalnat 已提交
633
                     t->next = hash[d];
G
Guy Schalnat 已提交
634 635
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
636 637 638
                     hash[d] = t;
                  }
               }
639 640
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
641 642
            }

643
            if (t != NULL)
G
Guy Schalnat 已提交
644 645
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
646
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
647
               {
G
Guy Schalnat 已提交
648
                  png_dsortp p;
G
Guy Schalnat 已提交
649 650 651

                  for (p = hash[i]; p; p = p->next)
                  {
652
                     if ((int)png_ptr->index_to_palette[p->left]
653 654 655
                         < num_new_palette &&
                         (int)png_ptr->index_to_palette[p->right]
                         < num_new_palette)
G
Guy Schalnat 已提交
656 657 658
                     {
                        int j, next_j;

659
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
660 661 662 663 664 665 666 667 668 669 670
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
671
                        palette[png_ptr->index_to_palette[j]]
672
                            = palette[num_new_palette];
673
                        if (full_quantize == 0)
G
Guy Schalnat 已提交
674 675 676 677 678
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
679
                              if (png_ptr->quantize_index[k] ==
680
                                  png_ptr->index_to_palette[j])
681
                                 png_ptr->quantize_index[k] =
682
                                     png_ptr->index_to_palette[next_j];
683

684
                              if ((int)png_ptr->quantize_index[k] ==
685
                                  num_new_palette)
686
                                 png_ptr->quantize_index[k] =
687
                                     png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
688 689 690
                           }
                        }

691
                        png_ptr->index_to_palette[png_ptr->palette_to_index
692
                            [num_new_palette]] = png_ptr->index_to_palette[j];
693

694
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
695
                            = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
696

697 698
                        png_ptr->index_to_palette[j] =
                            (png_byte)num_new_palette;
699

700 701
                        png_ptr->palette_to_index[num_new_palette] =
                            (png_byte)j;
G
Guy Schalnat 已提交
702 703 704 705 706 707 708 709 710 711 712
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

            for (i = 0; i < 769; i++)
            {
A
Andreas Dilger 已提交
713
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
714
               {
715
                  png_dsortp p = hash[i];
G
Guy Schalnat 已提交
716 717 718
                  while (p)
                  {
                     t = p->next;
A
Andreas Dilger 已提交
719
                     png_free(png_ptr, p);
G
Guy Schalnat 已提交
720 721 722 723 724 725 726
                     p = t;
                  }
               }
               hash[i] = 0;
            }
            max_d += 96;
         }
A
Andreas Dilger 已提交
727
         png_free(png_ptr, hash);
728 729
         png_free(png_ptr, png_ptr->palette_to_index);
         png_free(png_ptr, png_ptr->index_to_palette);
730 731
         png_ptr->palette_to_index = NULL;
         png_ptr->index_to_palette = NULL;
G
Guy Schalnat 已提交
732 733 734
      }
      num_palette = maximum_colors;
   }
A
Andreas Dilger 已提交
735
   if (png_ptr->palette == NULL)
G
Guy Schalnat 已提交
736
   {
G
Guy Schalnat 已提交
737 738
      png_ptr->palette = palette;
   }
G
Guy Schalnat 已提交
739
   png_ptr->num_palette = (png_uint_16)num_palette;
G
Guy Schalnat 已提交
740

741
   if (full_quantize != 0)
G
Guy Schalnat 已提交
742 743
   {
      int i;
G
Guy Schalnat 已提交
744
      png_bytep distance;
745 746 747 748 749
      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
          PNG_QUANTIZE_BLUE_BITS;
      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
750
      png_size_t num_entries = ((png_size_t)1 << total_bits);
G
Guy Schalnat 已提交
751

752
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
753
          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
754

755
      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
756
          (sizeof (png_byte))));
757

758
      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
759 760 761

      for (i = 0; i < num_palette; i++)
      {
762
         int ir, ig, ib;
763 764 765
         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
G
Guy Schalnat 已提交
766 767 768

         for (ir = 0; ir < num_red; ir++)
         {
769 770
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
771 772
            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
                PNG_QUANTIZE_GREEN_BITS));
G
Guy Schalnat 已提交
773 774

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
775
            {
776 777
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
778 779
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
780
               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
G
Guy Schalnat 已提交
781 782

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
783
               {
784
                  int d_index = index_g | ib;
785 786
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
787 788
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
789

790
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
791
                  {
A
Andreas Dilger 已提交
792 793
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
794 795
                  }
               }
796 797 798
            }
         }
      }
G
Guy Schalnat 已提交
799

A
Andreas Dilger 已提交
800
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
801 802
   }
}
803
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
804

G
[devel]  
Glenn Randers-Pehrson 已提交
805 806
#ifdef PNG_READ_GAMMA_SUPPORTED
void PNGFAPI
807
png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
808
    png_fixed_point file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
809 810
{
   png_debug(1, "in png_set_gamma_fixed");
811

812
   if (png_rtran_ok(png_ptr, 0) == 0)
813
      return;
814

815
   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
816 817 818
   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);

819
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
820 821 822
    * premultiplied alpha support; this actually hides an undocumented feature
    * of the previous implementation which allowed gamma processing to be
    * disabled in background handling.  There is no evidence (so far) that this
823
    * was being used; however, png_set_background itself accepted and must still
824 825 826
    * accept '0' for the gamma value it takes, because it isn't always used.
    *
    * Since this is an API change (albeit a very minor one that removes an
827 828
    * undocumented API feature) the following checks were only enabled in
    * libpng-1.6.0.
829 830
    */
   if (file_gamma <= 0)
831
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
832 833

   if (scrn_gamma <= 0)
834
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
835 836 837 838 839

   /* Set the gamma values unconditionally - this overrides the value in the PNG
    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
    * different, easier, way to default the file gamma.
    */
840 841
   png_ptr->colorspace.gamma = file_gamma;
   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
G
[devel]  
Glenn Randers-Pehrson 已提交
842
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
843
}
G
[devel]  
Glenn Randers-Pehrson 已提交
844 845 846

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
847
png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
848
{
849
   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
850
       convert_gamma_value(png_ptr, file_gamma));
G
[devel]  
Glenn Randers-Pehrson 已提交
851
}
852
#  endif /* FLOATING_POINT */
G
[devel]  
Glenn Randers-Pehrson 已提交
853
#endif /* READ_GAMMA */
G
Guy Schalnat 已提交
854

855
#ifdef PNG_READ_EXPAND_SUPPORTED
856
/* Expand paletted images to RGB, expand grayscale images of
857
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
858 859
 * to alpha channels.
 */
860
void PNGAPI
861
png_set_expand(png_structrp png_ptr)
G
Guy Schalnat 已提交
862
{
863
   png_debug(1, "in png_set_expand");
864

865
   if (png_rtran_ok(png_ptr, 0) == 0)
866
      return;
867

868
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
G
Guy Schalnat 已提交
869
}
870 871 872 873 874 875 876 877 878 879 880 881 882

/* GRR 19990627:  the following three functions currently are identical
 *  to png_set_expand().  However, it is entirely reasonable that someone
 *  might wish to expand an indexed image to RGB but *not* expand a single,
 *  fully transparent palette entry to a full alpha channel--perhaps instead
 *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
 *  the transparent color with a particular RGB value, or drop tRNS entirely.
 *  IOW, a future version of the library may make the transformations flag
 *  a bit more fine-grained, with separate bits for each of these three
 *  functions.
 *
 *  More to the point, these functions make it obvious what libpng will be
 *  doing, whereas "expand" can (and does) mean any number of things.
883
 *
884 885 886
 *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
 *  to expand only the sample depth but not to expand the tRNS to alpha
 *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
887 888 889
 */

/* Expand paletted images to RGB. */
890
void PNGAPI
891
png_set_palette_to_rgb(png_structrp png_ptr)
892
{
893
   png_debug(1, "in png_set_palette_to_rgb");
894

895
   if (png_rtran_ok(png_ptr, 0) == 0)
896
      return;
897

898 899 900 901 902
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
}

/* Expand grayscale images of less than 8-bit depth to 8 bits. */
void PNGAPI
903
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
904
{
905
   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
906

907
   if (png_rtran_ok(png_ptr, 0) == 0)
908
      return;
909

910
   png_ptr->transformations |= PNG_EXPAND;
911 912 913
}

/* Expand tRNS chunks to alpha channels. */
914
void PNGAPI
915
png_set_tRNS_to_alpha(png_structrp png_ptr)
916
{
917
   png_debug(1, "in png_set_tRNS_to_alpha");
918

919
   if (png_rtran_ok(png_ptr, 0) == 0)
920 921
      return;

922
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
923
}
924
#endif /* READ_EXPAND */
G
Guy Schalnat 已提交
925

926
#ifdef PNG_READ_EXPAND_16_SUPPORTED
927
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
928 929 930
 * it may not work correctly.)
 */
void PNGAPI
931
png_set_expand_16(png_structrp png_ptr)
932 933 934
{
   png_debug(1, "in png_set_expand_16");

935
   if (png_rtran_ok(png_ptr, 0) == 0)
936 937 938 939 940 941
      return;

   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
}
#endif

942
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
943
void PNGAPI
944
png_set_gray_to_rgb(png_structrp png_ptr)
G
Guy Schalnat 已提交
945
{
946
   png_debug(1, "in png_set_gray_to_rgb");
947

948
   if (png_rtran_ok(png_ptr, 0) == 0)
949 950 951 952 953
      return;

   /* Because rgb must be 8 bits or more: */
   png_set_expand_gray_1_2_4_to_8(png_ptr);
   png_ptr->transformations |= PNG_GRAY_TO_RGB;
G
Guy Schalnat 已提交
954
}
G
Guy Schalnat 已提交
955
#endif
G
Guy Schalnat 已提交
956

957
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
958
void PNGFAPI
959
png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
960
    png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
961
{
962
   png_debug(1, "in png_set_rgb_to_gray");
963

964 965
   /* Need the IHDR here because of the check on color_type below. */
   /* TODO: fix this */
966
   if (png_rtran_ok(png_ptr, 1) == 0)
967
      return;
968

969
   switch (error_action)
970
   {
971
      case PNG_ERROR_ACTION_NONE:
972 973
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
         break;
974

975
      case PNG_ERROR_ACTION_WARN:
976 977
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
978

979
      case PNG_ERROR_ACTION_ERROR:
980
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
981 982 983
         break;

      default:
984
         png_error(png_ptr, "invalid error action to rgb_to_gray");
985
   }
986

987
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
988
#ifdef PNG_READ_EXPAND_SUPPORTED
989 990 991
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
992 993 994 995
      /* Make this an error in 1.6 because otherwise the application may assume
       * that it just worked and get a memory overwrite.
       */
      png_error(png_ptr,
996
          "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
997

998
      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
999 1000 1001
   }
#endif
   {
1002
      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
1003
      {
1004
         png_uint_16 red_int, green_int;
1005

1006
         /* NOTE: this calculation does not round, but this behavior is retained
1007
          * for consistency; the inaccuracy is very small.  The code here always
1008 1009 1010
          * overwrites the coefficients, regardless of whether they have been
          * defaulted or set already.
          */
1011 1012
         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
1013 1014 1015

         png_ptr->rgb_to_gray_red_coeff   = red_int;
         png_ptr->rgb_to_gray_green_coeff = green_int;
1016
         png_ptr->rgb_to_gray_coefficients_set = 1;
1017
      }
1018

1019
      else
1020
      {
1021
         if (red >= 0 && green >= 0)
1022
            png_app_warning(png_ptr,
1023
                "ignoring out of range rgb_to_gray coefficients");
1024

1025 1026 1027 1028 1029
         /* Use the defaults, from the cHRM chunk if set, else the historical
          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
          * png_do_rgb_to_gray for more discussion of the values.  In this case
          * the coefficients are not marked as 'set' and are not overwritten if
          * something has already provided a default.
1030 1031
          */
         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
1032
             png_ptr->rgb_to_gray_green_coeff == 0)
1033
         {
1034 1035 1036
            png_ptr->rgb_to_gray_red_coeff   = 6968;
            png_ptr->rgb_to_gray_green_coeff = 23434;
            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1037 1038
         }
      }
1039
   }
A
Andreas Dilger 已提交
1040
}
1041 1042 1043 1044 1045 1046 1047

#ifdef PNG_FLOATING_POINT_SUPPORTED
/* Convert a RGB image to a grayscale of the same width.  This allows us,
 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
 */

void PNGAPI
1048
png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
1049
    double green)
1050
{
G
[devel]  
Glenn Randers-Pehrson 已提交
1051
   png_set_rgb_to_gray_fixed(png_ptr, error_action,
1052
       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
G
[devel]  
Glenn Randers-Pehrson 已提交
1053
      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1054 1055 1056
}
#endif /* FLOATING POINT */

1057
#endif /* RGB_TO_GRAY */
A
Andreas Dilger 已提交
1058

1059
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1060
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1061
void PNGAPI
1062
png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1063
    read_user_transform_fn)
1064
{
1065
   png_debug(1, "in png_set_read_user_transform_fn");
1066

1067
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1068 1069
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1070
#endif
1071 1072 1073
}
#endif

1074
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
#ifdef PNG_READ_GAMMA_SUPPORTED
/* In the case of gamma transformations only do transformations on images where
 * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
 * slows things down slightly, and also needlessly introduces small errors.
 */
static int /* PRIVATE */
png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
{
   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
    * correction as a difference of the overall transform from 1.0
    *
    * We want to compare the threshold with s*f - 1, if we get
    * overflow here it is because of wacky gamma values so we
    * turn on processing anyway.
    */
   png_fixed_point gtest;
   return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
       png_gamma_significant(gtest);
}
#endif

A
Andreas Dilger 已提交
1096
/* Initialize everything needed for the read.  This includes modifying
1097 1098
 * the palette.
 */
1099

1100
/* For the moment 'png_init_palette_transformations' and
1101 1102 1103 1104 1105
 * 'png_init_rgb_transformations' only do some flag canceling optimizations.
 * The intent is that these two routines should have palette or rgb operations
 * extracted from 'png_init_read_transformations'.
 */
static void /* PRIVATE */
1106
png_init_palette_transformations(png_structrp png_ptr)
G
Guy Schalnat 已提交
1107
{
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
   /* Called to handle the (input) palette case.  In png_do_read_transformations
    * the first step is to expand the palette if requested, so this code must
    * take care to only make changes that are invariant with respect to the
    * palette expansion, or only do them if there is no expansion.
    *
    * STRIP_ALPHA has already been handled in the caller (by setting num_trans
    * to 0.)
    */
   int input_has_alpha = 0;
   int input_has_transparency = 0;
1118

1119 1120 1121 1122 1123 1124
   if (png_ptr->num_trans > 0)
   {
      int i;

      /* Ignore if all the entries are opaque (unlikely!) */
      for (i=0; i<png_ptr->num_trans; ++i)
1125
      {
1126 1127 1128 1129 1130
         if (png_ptr->trans_alpha[i] == 255)
            continue;
         else if (png_ptr->trans_alpha[i] == 0)
            input_has_transparency = 1;
         else
1131 1132
         {
            input_has_transparency = 1;
1133
            input_has_alpha = 1;
1134 1135 1136
            break;
         }
      }
1137 1138 1139
   }

   /* If no alpha we can optimize. */
1140
   if (input_has_alpha == 0)
1141 1142
   {
      /* Any alpha means background and associative alpha processing is
1143
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1144 1145 1146 1147 1148
       * and ENCODE_ALPHA are irrelevant.
       */
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

1149
      if (input_has_transparency == 0)
1150 1151
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
   }
G
Guy Schalnat 已提交
1152

G
Guy Schalnat 已提交
1153
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1154 1155 1156 1157
   /* png_set_background handling - deals with the complexity of whether the
    * background color is in the file format or the screen format in the case
    * where an 'expand' will happen.
    */
1158

1159 1160
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1161
    */
1162 1163
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) != 0)
1164
   {
1165 1166 1167 1168 1169 1170 1171 1172 1173
      {
         png_ptr->background.red   =
             png_ptr->palette[png_ptr->background.index].red;
         png_ptr->background.green =
             png_ptr->palette[png_ptr->background.index].green;
         png_ptr->background.blue  =
             png_ptr->palette[png_ptr->background.index].blue;

#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1174
        if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1175
        {
1176
           if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1177 1178 1179 1180 1181 1182 1183
           {
              /* Invert the alpha channel (in tRNS) unless the pixels are
               * going to be expanded, in which case leave it for later
               */
              int i, istop = png_ptr->num_trans;

              for (i=0; i<istop; i++)
1184 1185
                 png_ptr->trans_alpha[i] = (png_byte)(255 -
                    png_ptr->trans_alpha[i]);
1186 1187
           }
        }
1188
#endif /* READ_INVERT_ALPHA */
1189 1190
      }
   } /* background expand and (therefore) no alpha association. */
1191
#endif /* READ_EXPAND && READ_BACKGROUND */
1192 1193 1194
}

static void /* PRIVATE */
1195
png_init_rgb_transformations(png_structrp png_ptr)
1196
{
1197
   /* Added to libpng-1.5.4: check the color type to determine whether there
1198 1199 1200 1201 1202
    * is any alpha or transparency in the image and simply cancel the
    * background and alpha mode stuff if there isn't.
    */
   int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
   int input_has_transparency = png_ptr->num_trans > 0;
1203

1204
   /* If no alpha we can optimize. */
1205
   if (input_has_alpha == 0)
1206
   {
1207
      /* Any alpha means background and associative alpha processing is
1208
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1209 1210 1211 1212 1213 1214 1215
       * and ENCODE_ALPHA are irrelevant.
       */
#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
#     endif

1216
      if (input_has_transparency == 0)
1217
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1218 1219
   }

1220 1221 1222 1223 1224 1225 1226 1227 1228
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
   /* png_set_background handling - deals with the complexity of whether the
    * background color is in the file format or the screen format in the case
    * where an 'expand' will happen.
    */

   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
    */
1229 1230 1231
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) != 0 &&
       (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1232
       /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
1233 1234
   {
      {
1235
         /* Expand background and tRNS chunks */
1236 1237 1238
         int gray = png_ptr->background.gray;
         int trans_gray = png_ptr->trans_color.gray;

G
Guy Schalnat 已提交
1239 1240 1241
         switch (png_ptr->bit_depth)
         {
            case 1:
1242 1243
               gray *= 0xff;
               trans_gray *= 0xff;
G
Guy Schalnat 已提交
1244
               break;
1245

G
Guy Schalnat 已提交
1246
            case 2:
1247 1248
               gray *= 0x55;
               trans_gray *= 0x55;
G
Guy Schalnat 已提交
1249
               break;
1250

G
Guy Schalnat 已提交
1251
            case 4:
1252 1253
               gray *= 0x11;
               trans_gray *= 0x11;
G
Guy Schalnat 已提交
1254
               break;
1255

1256 1257
            default:

G
Guy Schalnat 已提交
1258
            case 8:
1259
               /* FALLTHROUGH */ /*  (Already 8 bits) */
1260

G
Guy Schalnat 已提交
1261
            case 16:
1262
               /* Already a full 16 bits */
G
Guy Schalnat 已提交
1263 1264
               break;
         }
1265 1266 1267 1268

         png_ptr->background.red = png_ptr->background.green =
            png_ptr->background.blue = (png_uint_16)gray;

1269
         if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1270 1271 1272 1273
         {
            png_ptr->trans_color.red = png_ptr->trans_color.green =
               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
         }
G
Guy Schalnat 已提交
1274
      }
1275
   } /* background expand and (therefore) no alpha association. */
1276
#endif /* READ_EXPAND && READ_BACKGROUND */
1277
}
1278

1279
void /* PRIVATE */
1280
png_init_read_transformations(png_structrp png_ptr)
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
{
   png_debug(1, "in png_init_read_transformations");

   /* This internal function is called from png_read_start_row in pngrutil.c
    * and it is called before the 'rowbytes' calculation is done, so the code
    * in here can change or update the transformations flags.
    *
    * First do updates that do not depend on the details of the PNG image data
    * being processed.
    */

#ifdef PNG_READ_GAMMA_SUPPORTED
1293
   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1294
    * png_set_alpha_mode and this is another source for a default file gamma so
1295
    * the test needs to be performed later - here.  In addition prior to 1.5.4
1296 1297 1298 1299 1300 1301 1302 1303
    * the tests were repeated for the PALETTE color type here - this is no
    * longer necessary (and doesn't seem to have been necessary before.)
    */
   {
      /* The following temporary indicates if overall gamma correction is
       * required.
       */
      int gamma_correction = 0;
1304

1305
      if (png_ptr->colorspace.gamma != 0) /* has been set */
1306 1307
      {
         if (png_ptr->screen_gamma != 0) /* screen set too */
1308
            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1309
                png_ptr->screen_gamma);
1310 1311 1312 1313 1314

         else
            /* Assume the output matches the input; a long time default behavior
             * of libpng, although the standard has nothing to say about this.
             */
1315
            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
G
Guy Schalnat 已提交
1316
      }
1317 1318 1319

      else if (png_ptr->screen_gamma != 0)
         /* The converse - assume the file matches the screen, note that this
1320
          * perhaps undesireable default can (from 1.5.4) be changed by calling
1321 1322 1323
          * png_set_alpha_mode (even if the alpha handling mode isn't required
          * or isn't changed from the default.)
          */
1324
         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
1325 1326 1327 1328 1329

      else /* neither are set */
         /* Just in case the following prevents any processing - file and screen
          * are both assumed to be linear and there is no way to introduce a
          * third gamma value other than png_set_background with 'UNIQUE', and,
1330
          * prior to 1.5.4
1331
          */
1332 1333 1334 1335
         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;

      /* We have a gamma value now. */
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
1336 1337 1338 1339 1340 1341 1342 1343 1344

      /* Now turn the gamma transformation on or off as appropriate.  Notice
       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
       * composition may independently cause gamma correction because it needs
       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
       * hasn't been specified.)  In any case this flag may get turned off in
       * the code immediately below if the transform can be handled outside the
       * row loop.
       */
1345
      if (gamma_correction != 0)
1346 1347 1348 1349
         png_ptr->transformations |= PNG_GAMMA;

      else
         png_ptr->transformations &= ~PNG_GAMMA;
G
Guy Schalnat 已提交
1350
   }
G
Guy Schalnat 已提交
1351
#endif
G
Guy Schalnat 已提交
1352

1353
   /* Certain transformations have the effect of preventing other
1354
    * transformations that happen afterward in png_do_read_transformations;
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
    * resolve the interdependencies here.  From the code of
    * png_do_read_transformations the order is:
    *
    *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
    *  2) PNG_STRIP_ALPHA (if no compose)
    *  3) PNG_RGB_TO_GRAY
    *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
    *  5) PNG_COMPOSE
    *  6) PNG_GAMMA
    *  7) PNG_STRIP_ALPHA (if compose)
    *  8) PNG_ENCODE_ALPHA
1366 1367 1368 1369 1370 1371
    *  9) PNG_SCALE_16_TO_8
    * 10) PNG_16_TO_8
    * 11) PNG_QUANTIZE (converts to palette)
    * 12) PNG_EXPAND_16
    * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
    * 14) PNG_INVERT_MONO
1372 1373 1374 1375 1376 1377
    * 15) PNG_INVERT_ALPHA
    * 16) PNG_SHIFT
    * 17) PNG_PACK
    * 18) PNG_BGR
    * 19) PNG_PACKSWAP
    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1378 1379 1380
    * 21) PNG_SWAP_ALPHA
    * 22) PNG_SWAP_BYTES
    * 23) PNG_USER_TRANSFORM [must be last]
1381 1382
    */
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1383 1384
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) == 0)
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
   {
      /* Stripping the alpha channel happens immediately after the 'expand'
       * transformations, before all other transformation, so it cancels out
       * the alpha handling.  It has the side effect negating the effect of
       * PNG_EXPAND_tRNS too:
       */
      png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
         PNG_EXPAND_tRNS);
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

1395
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1396 1397 1398 1399
       * so transparency information would remain just so long as it wasn't
       * expanded.  This produces unexpected API changes if the set of things
       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
       * documentation - which says ask for what you want, accept what you
1400
       * get.)  This makes the behavior consistent from 1.5.4:
1401 1402 1403 1404 1405 1406 1407 1408 1409
       */
      png_ptr->num_trans = 0;
   }
#endif /* STRIP_ALPHA supported, no COMPOSE */

#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
    * settings will have no effect.
    */
1410
   if (png_gamma_significant(png_ptr->screen_gamma) == 0)
1411 1412 1413 1414
   {
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   }
G
Guy Schalnat 已提交
1415
#endif
1416

1417 1418 1419 1420
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
   /* Make sure the coefficients for the rgb to gray conversion are set
    * appropriately.
    */
1421
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1422 1423 1424 1425 1426
      png_colorspace_set_rgb_coefficients(png_ptr);
#endif

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
   /* Detect gray background and attempt to enable optimization for
    * gray --> RGB case.
    *
    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
    * background color might actually be gray yet not be flagged as such.
    * This is not a problem for the current code, which uses
    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
    * png_do_gray_to_rgb() transformation.
    *
1437
    * TODO: this code needs to be revised to avoid the complexity and
1438 1439 1440 1441
    * interdependencies.  The color type of the background should be recorded in
    * png_set_background, along with the bit depth, then the code has a record
    * of exactly what color space the background is currently in.
    */
1442
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1443 1444
   {
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1445
       * the file was grayscale the background value is gray.
1446
       */
1447
      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1448 1449 1450
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

1451
   else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1452
   {
1453 1454 1455 1456 1457
      /* PNG_COMPOSE: png_set_background was called with need_expand false,
       * so the color is in the color space of the output or png_set_alpha_mode
       * was called and the color is black.  Ignore RGB_TO_GRAY because that
       * happens before GRAY_TO_RGB.
       */
1458
      if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
1459
      {
1460 1461 1462 1463 1464 1465
         if (png_ptr->background.red == png_ptr->background.green &&
             png_ptr->background.red == png_ptr->background.blue)
         {
            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
            png_ptr->background.gray = png_ptr->background.red;
         }
1466
      }
1467
   }
1468 1469
#endif /* READ_EXPAND && READ_BACKGROUND */
#endif /* READ_GRAY_TO_RGB */
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483

   /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
    * can be performed directly on the palette, and some (such as rgb to gray)
    * can be optimized inside the palette.  This is particularly true of the
    * composite (background and alpha) stuff, which can be pretty much all done
    * in the palette even if the result is expanded to RGB or gray afterward.
    *
    * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
    * earlier and the palette stuff is actually handled on the first row.  This
    * leads to the reported bug that the palette returned by png_get_PLTE is not
    * updated.
    */
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      png_init_palette_transformations(png_ptr);
1484

1485 1486 1487
   else
      png_init_rgb_transformations(png_ptr);

1488 1489
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   defined(PNG_READ_EXPAND_16_SUPPORTED)
1490 1491 1492 1493
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
       png_ptr->bit_depth != 16)
1494 1495 1496
   {
      /* TODO: fix this.  Because the expand_16 operation is after the compose
       * handling the background color must be 8, not 16, bits deep, but the
1497
       * application will supply a 16-bit value so reduce it here.
1498 1499 1500
       *
       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
       * present, so that case is ok (until do_expand_16 is moved.)
1501 1502 1503
       *
       * NOTE: this discards the low 16 bits of the user supplied background
       * color, but until expand_16 works properly there is no choice!
1504
       */
1505
#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1506 1507 1508 1509
      CHOP(png_ptr->background.red);
      CHOP(png_ptr->background.green);
      CHOP(png_ptr->background.blue);
      CHOP(png_ptr->background.gray);
1510 1511
#     undef CHOP
   }
1512
#endif /* READ_BACKGROUND && READ_EXPAND_16 */
1513

1514 1515 1516
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
1517 1518 1519 1520
   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
       png_ptr->bit_depth == 16)
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
   {
      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
       * component this will also happen after PNG_COMPOSE and so the background
       * color must be pre-expanded here.
       *
       * TODO: fix this too.
       */
      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
      png_ptr->background.green =
         (png_uint_16)(png_ptr->background.green * 257);
      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
   }
#endif

1536 1537 1538 1539
   /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
    * background support (see the comments in scripts/pnglibconf.dfa), this
    * allows pre-multiplication of the alpha channel to be implemented as
    * compositing on black.  This is probably sub-optimal and has been done in
1540
    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558
    * implement the new API quickly, without lots of internal changes.)
    */

#ifdef PNG_READ_GAMMA_SUPPORTED
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
      /* Includes ALPHA_MODE */
      png_ptr->background_1 = png_ptr->background;
#  endif

   /* This needs to change - in the palette image case a whole set of tables are
    * built when it would be quicker to just calculate the correct value for
    * each palette entry directly.  Also, the test is too tricky - why check
    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
    * the gamma tables will not be built even if composition is required on a
    * gamma encoded value.
    *
1559
    * In 1.5.4 this is addressed below by an additional check on the individual
1560 1561 1562
    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
    * tables.
    */
1563 1564 1565 1566 1567 1568 1569
   if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
       ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
         png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
        ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
          png_gamma_significant(png_ptr->screen_gamma) != 0
1570
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1571 1572
         || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
           png_gamma_significant(png_ptr->background_gamma) != 0)
1573
#  endif
1574 1575
        )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       png_gamma_significant(png_ptr->screen_gamma) != 0))
G
Guy Schalnat 已提交
1576
   {
1577
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1578

1579
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1580
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
G
Guy Schalnat 已提交
1581
      {
1582 1583 1584 1585 1586 1587
         /* Issue a warning about this combination: because RGB_TO_GRAY is
          * optimized to do the gamma transform if present yet do_background has
          * to do the same thing if both options are set a
          * double-gamma-correction happens.  This is true in all versions of
          * libpng to date.
          */
1588
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1589
            png_warning(png_ptr,
1590
                "libpng does not support gamma+background+rgb_to_gray");
1591

1592
         if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
G
Guy Schalnat 已提交
1593
         {
1594 1595 1596
            /* We don't get to here unless there is a tRNS chunk with non-opaque
             * entries - see the checking code at the start of this function.
             */
G
Guy Schalnat 已提交
1597
            png_color back, back_1;
1598 1599 1600
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1601 1602
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1603

A
Andreas Dilger 已提交
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
               back.red = png_ptr->gamma_table[png_ptr->background.red];
               back.green = png_ptr->gamma_table[png_ptr->background.green];
               back.blue = png_ptr->gamma_table[png_ptr->background.blue];

               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
            }
            else
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1614
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1615

1616 1617 1618 1619
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
G
[devel]  
Glenn Randers-Pehrson 已提交
1620
                     gs = PNG_FP_1;
1621
                     break;
1622

1623
                  case PNG_BACKGROUND_GAMMA_FILE:
1624 1625
                     g = png_reciprocal(png_ptr->colorspace.gamma);
                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
1626
                         png_ptr->screen_gamma);
1627
                     break;
1628

1629
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1630 1631
                     g = png_reciprocal(png_ptr->background_gamma);
                     gs = png_reciprocal2(png_ptr->background_gamma,
1632
                         png_ptr->screen_gamma);
1633 1634
                     break;
                  default:
G
[devel]  
Glenn Randers-Pehrson 已提交
1635 1636
                     g = PNG_FP_1;    /* back_1 */
                     gs = PNG_FP_1;   /* back */
1637
                     break;
1638
               }
A
Andreas Dilger 已提交
1639

1640
               if (png_gamma_significant(gs) != 0)
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
               {
                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
                      gs);
                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
                      gs);
                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
                      gs);
               }

               else
A
Andreas Dilger 已提交
1651
               {
1652
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1653
                  back.green = (png_byte)png_ptr->background.green;
1654
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1655
               }
1656

1657
               if (png_gamma_significant(g) != 0)
1658 1659
               {
                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
1660
                      g);
1661
                  back_1.green = png_gamma_8bit_correct(
1662
                      png_ptr->background.green, g);
1663
                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1664
                      g);
1665 1666
               }

A
Andreas Dilger 已提交
1667 1668
               else
               {
1669 1670 1671
                  back_1.red   = (png_byte)png_ptr->background.red;
                  back_1.green = (png_byte)png_ptr->background.green;
                  back_1.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1672 1673
               }
            }
1674

G
Guy Schalnat 已提交
1675 1676
            for (i = 0; i < num_palette; i++)
            {
1677 1678
               if (i < (int)png_ptr->num_trans &&
                   png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1679
               {
1680
                  if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1681 1682 1683
                  {
                     palette[i] = back;
                  }
1684
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
G
Guy Schalnat 已提交
1685
                  {
A
Andreas Dilger 已提交
1686
                     png_byte v, w;
G
Guy Schalnat 已提交
1687 1688

                     v = png_ptr->gamma_to_1[palette[i].red];
1689
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
1690 1691 1692
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
1693
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
G
Guy Schalnat 已提交
1694 1695 1696
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
1697
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
                     palette[i].blue = png_ptr->gamma_from_1[w];
                  }
               }
               else
               {
                  palette[i].red = png_ptr->gamma_table[palette[i].red];
                  palette[i].green = png_ptr->gamma_table[palette[i].green];
                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
               }
            }
1708 1709 1710

            /* Prevent the transformations being done again.
             *
1711
             * NOTE: this is highly dubious; it removes the transformations in
1712 1713
             * place.  This seems inconsistent with the general treatment of the
             * transformations elsewhere.
1714
             */
1715 1716
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1717

1718
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1719
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1720
         {
1721 1722 1723
            int gs_sig, g_sig;
            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
G
Guy Schalnat 已提交
1724 1725

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1726
            {
G
Guy Schalnat 已提交
1727
               case PNG_BACKGROUND_GAMMA_SCREEN:
G
[devel]  
Glenn Randers-Pehrson 已提交
1728 1729
                  g = png_ptr->screen_gamma;
                  /* gs = PNG_FP_1; */
G
Guy Schalnat 已提交
1730
                  break;
1731

G
Guy Schalnat 已提交
1732
               case PNG_BACKGROUND_GAMMA_FILE:
1733 1734
                  g = png_reciprocal(png_ptr->colorspace.gamma);
                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
1735
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1736
                  break;
1737

G
Guy Schalnat 已提交
1738
               case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1739 1740
                  g = png_reciprocal(png_ptr->background_gamma);
                  gs = png_reciprocal2(png_ptr->background_gamma,
1741
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1742
                  break;
1743 1744

               default:
1745
                  png_error(png_ptr, "invalid background gamma type");
G
Guy Schalnat 已提交
1746 1747
            }

1748 1749
            g_sig = png_gamma_significant(g);
            gs_sig = png_gamma_significant(gs);
1750

1751
            if (g_sig != 0)
1752 1753 1754
               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, g);

1755
            if (gs_sig != 0)
1756 1757
               png_ptr->background.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, gs);
1758

1759 1760 1761
            if ((png_ptr->background.red != png_ptr->background.green) ||
                (png_ptr->background.red != png_ptr->background.blue) ||
                (png_ptr->background.red != png_ptr->background.gray))
G
Guy Schalnat 已提交
1762
            {
1763
               /* RGB or RGBA with color background */
1764
               if (g_sig != 0)
1765 1766 1767
               {
                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, g);
1768

1769 1770
                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, g);
1771

1772 1773 1774
                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, g);
               }
1775

1776
               if (gs_sig != 0)
1777 1778 1779
               {
                  png_ptr->background.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, gs);
1780

1781 1782
                  png_ptr->background.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, gs);
1783

1784 1785 1786
                  png_ptr->background.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, gs);
               }
G
Guy Schalnat 已提交
1787
            }
1788

G
Guy Schalnat 已提交
1789 1790
            else
            {
1791 1792
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
1793
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1794

1795
               png_ptr->background.red = png_ptr->background.green
1796
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1797
            }
1798 1799 1800

            /* The background is now in screen gamma: */
            png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
1801 1802 1803
         } /* color_type != PNG_COLOR_TYPE_PALETTE */
      }/* png_ptr->transformations & PNG_BACKGROUND */

G
Guy Schalnat 已提交
1804
      else
1805
      /* Transformation does not include PNG_BACKGROUND */
1806
#endif /* READ_BACKGROUND */
1807 1808 1809 1810 1811 1812 1813
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
#endif
         )
G
Guy Schalnat 已提交
1814
      {
1815 1816 1817
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1818

1819 1820
         /* NOTE: there are other transformations that should probably be in
          * here too.
1821
          */
G
Guy Schalnat 已提交
1822 1823 1824 1825 1826 1827
         for (i = 0; i < num_palette; i++)
         {
            palette[i].red = png_ptr->gamma_table[palette[i].red];
            palette[i].green = png_ptr->gamma_table[palette[i].green];
            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
         }
1828

1829 1830
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
1831
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
G
Guy Schalnat 已提交
1832
   }
1833
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1834
   else
G
Guy Schalnat 已提交
1835
#endif
1836
#endif /* READ_GAMMA */
1837

1838
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1839
   /* No GAMMA transformation (see the hanging else 4 lines above) */
1840
   if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1841
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1842
   {
1843 1844
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
1845
      png_color back;
1846
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
1847 1848 1849 1850 1851

      back.red   = (png_byte)png_ptr->background.red;
      back.green = (png_byte)png_ptr->background.green;
      back.blue  = (png_byte)png_ptr->background.blue;

1852
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1853
      {
1854
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1855 1856 1857
         {
            palette[i] = back;
         }
1858

1859
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1860
         {
1861
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1862
            png_composite(palette[i].red, palette[i].red,
1863
                png_ptr->trans_alpha[i], back.red);
1864

A
Andreas Dilger 已提交
1865
            png_composite(palette[i].green, palette[i].green,
1866
                png_ptr->trans_alpha[i], back.green);
1867

A
Andreas Dilger 已提交
1868
            png_composite(palette[i].blue, palette[i].blue,
1869
                png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1870 1871
         }
      }
1872

1873
      png_ptr->transformations &= ~PNG_COMPOSE;
G
Guy Schalnat 已提交
1874
   }
1875
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
1876

1877
#ifdef PNG_READ_SHIFT_SUPPORTED
1878 1879
   if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) == 0 &&
1880
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1881
   {
1882 1883 1884
      int i;
      int istop = png_ptr->num_palette;
      int shift = 8 - png_ptr->sig_bit.red;
G
Guy Schalnat 已提交
1885

1886 1887
      png_ptr->transformations &= ~PNG_SHIFT;

1888 1889 1890 1891
      /* significant bits can be in the range 1 to 7 for a meaninful result, if
       * the number of significant bits is 0 then no shift is done (this is an
       * error condition which is silently ignored.)
       */
1892 1893 1894 1895
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].red;
1896

1897 1898 1899
            component >>= shift;
            png_ptr->palette[i].red = (png_byte)component;
         }
1900

1901
      shift = 8 - png_ptr->sig_bit.green;
1902 1903 1904 1905
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].green;
1906

1907 1908 1909
            component >>= shift;
            png_ptr->palette[i].green = (png_byte)component;
         }
1910 1911

      shift = 8 - png_ptr->sig_bit.blue;
1912 1913 1914 1915
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].blue;
1916

1917 1918 1919
            component >>= shift;
            png_ptr->palette[i].blue = (png_byte)component;
         }
G
Guy Schalnat 已提交
1920
   }
1921
#endif /* READ_SHIFT */
G
Guy Schalnat 已提交
1922 1923
}

A
Andreas Dilger 已提交
1924
/* Modify the info structure to reflect the transformations.  The
1925 1926 1927
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1928
void /* PRIVATE */
1929
png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
1930
{
1931
   png_debug(1, "in png_read_transform_info");
1932

1933
#ifdef PNG_READ_EXPAND_SUPPORTED
1934
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
G
Guy Schalnat 已提交
1935
   {
A
Andreas Dilger 已提交
1936 1937
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
1938
         /* This check must match what actually happens in
1939
          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1940 1941 1942
          * it is all opaque we must do the same (at present it does not.)
          */
         if (png_ptr->num_trans > 0)
A
Andreas Dilger 已提交
1943
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1944

A
Andreas Dilger 已提交
1945 1946
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1947

G
Guy Schalnat 已提交
1948
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1949
         info_ptr->num_trans = 0;
1950 1951 1952

         if (png_ptr->palette == NULL)
            png_error (png_ptr, "Palette is NULL in indexed image");
A
Andreas Dilger 已提交
1953 1954 1955
      }
      else
      {
1956
         if (png_ptr->num_trans != 0)
1957
         {
1958
            if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
1959
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1960
         }
A
Andreas Dilger 已提交
1961 1962
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1963

A
Andreas Dilger 已提交
1964 1965
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1966 1967 1968
   }
#endif

1969 1970 1971 1972 1973
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
   /* The following is almost certainly wrong unless the background value is in
    * the screen space!
    */
1974
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
G
Guy Schalnat 已提交
1975 1976 1977
      info_ptr->background = png_ptr->background;
#endif

1978
#ifdef PNG_READ_GAMMA_SUPPORTED
1979
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1980 1981 1982
    * however it seems that the code in png_init_read_transformations, which has
    * been called before this from png_read_update_info->png_read_start_row
    * sometimes does the gamma transform and cancels the flag.
1983 1984 1985 1986
    *
    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
    * the screen_gamma value.  The following probably results in weirdness if
    * the info_ptr is used by the app after the rows have been read.
1987
    */
1988
   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
1989
#endif
1990

1991 1992
   if (info_ptr->bit_depth == 16)
   {
1993
#  ifdef PNG_READ_16BIT_SUPPORTED
1994
#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
1995
         if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
1996 1997 1998 1999
            info_ptr->bit_depth = 8;
#     endif

#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2000
         if ((png_ptr->transformations & PNG_16_TO_8) != 0)
2001 2002 2003
            info_ptr->bit_depth = 8;
#     endif

2004
#  else
2005
      /* No 16-bit support: force chopping 16-bit input down to 8, in this case
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
       * the app program can chose if both APIs are available by setting the
       * correct scaling to use.
       */
#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
         /* For compatibility with previous versions use the strip method by
          * default.  This code works because if PNG_SCALE_16_TO_8 is already
          * set the code below will do that in preference to the chop.
          */
         png_ptr->transformations |= PNG_16_TO_8;
         info_ptr->bit_depth = 8;
#     else
2017

2018
#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2019 2020 2021 2022 2023 2024
            png_ptr->transformations |= PNG_SCALE_16_TO_8;
            info_ptr->bit_depth = 8;
#        else

            CONFIGURATION ERROR: you must enable at least one 16 to 8 method
#        endif
2025
#    endif
2026
#endif /* !READ_16BIT */
2027
   }
G
Guy Schalnat 已提交
2028

2029
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2030
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
2031 2032
      info_ptr->color_type = (png_byte)(info_ptr->color_type |
         PNG_COLOR_MASK_COLOR);
2033 2034
#endif

2035
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2036
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
2037 2038
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_COLOR);
2039 2040
#endif

2041
#ifdef PNG_READ_QUANTIZE_SUPPORTED
2042
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
G
Guy Schalnat 已提交
2043 2044
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2045
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2046
          png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
2047 2048 2049
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
2050
   }
G
Guy Schalnat 已提交
2051 2052
#endif

2053
#ifdef PNG_READ_EXPAND_16_SUPPORTED
2054 2055 2056
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
       info_ptr->bit_depth == 8 &&
       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2057 2058 2059 2060 2061
   {
      info_ptr->bit_depth = 16;
   }
#endif

2062
#ifdef PNG_READ_PACK_SUPPORTED
2063 2064
   if ((png_ptr->transformations & PNG_PACK) != 0 &&
       (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
2065 2066 2067
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
2068
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2069
      info_ptr->channels = 1;
2070

2071
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
2072
      info_ptr->channels = 3;
2073

G
Guy Schalnat 已提交
2074 2075
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
2076

2077
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2078
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
2079
   {
2080 2081
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_ALPHA);
2082 2083
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
2084 2085
#endif

2086
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
2087 2088
      info_ptr->channels++;

2089
#ifdef PNG_READ_FILLER_SUPPORTED
2090
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
2091 2092 2093
   if ((png_ptr->transformations & PNG_FILLER) != 0 &&
       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
       info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
2094
   {
2095
      info_ptr->channels++;
2096
      /* If adding a true alpha channel not just filler */
2097
      if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
2098
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2099
   }
A
Andreas Dilger 已提交
2100 2101
#endif

2102 2103
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2104
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2105
   {
J
John Bowler 已提交
2106
      if (png_ptr->user_transform_depth != 0)
2107
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2108

J
John Bowler 已提交
2109
      if (png_ptr->user_transform_channels != 0)
2110
         info_ptr->channels = png_ptr->user_transform_channels;
2111
   }
2112 2113
#endif

2114 2115
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
       info_ptr->bit_depth);
2116

2117
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2118

2119
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2120 2121 2122 2123 2124 2125 2126
    * check in png_rowbytes that the user buffer won't get overwritten.  Note
    * that the field is not always set - if png_read_update_info isn't called
    * the application has to either not do any transforms or get the calculation
    * right itself.
    */
   png_ptr->info_rowbytes = info_ptr->rowbytes;

2127
#ifndef PNG_READ_EXPAND_SUPPORTED
2128
   if (png_ptr != NULL)
2129 2130
      return;
#endif
G
Guy Schalnat 已提交
2131 2132
}

2133
#ifdef PNG_READ_PACK_SUPPORTED
2134 2135 2136 2137 2138 2139
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
 * without changing the actual values.  Thus, if you had a row with
 * a bit depth of 1, you would end up with bytes that only contained
 * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
 * png_do_shift() after this.
 */
2140
static void
G
Guy Schalnat 已提交
2141
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2142
{
2143
   png_debug(1, "in png_do_unpack");
2144

A
Andreas Dilger 已提交
2145
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2146
   {
2147
      png_uint_32 i;
2148
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2149

G
Guy Schalnat 已提交
2150 2151 2152 2153
      switch (row_info->bit_depth)
      {
         case 1:
         {
2154 2155
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2156
            png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);
2157
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2158
            {
2159
               *dp = (png_byte)((*sp >> shift) & 0x01);
2160

G
Guy Schalnat 已提交
2161 2162 2163 2164
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2165
               }
2166

G
Guy Schalnat 已提交
2167 2168 2169 2170 2171 2172 2173
               else
                  shift++;

               dp--;
            }
            break;
         }
2174

G
Guy Schalnat 已提交
2175 2176 2177
         case 2:
         {

2178 2179
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2180
            png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);
2181
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2182
            {
2183
               *dp = (png_byte)((*sp >> shift) & 0x03);
2184

G
Guy Schalnat 已提交
2185 2186 2187 2188 2189
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2190

G
Guy Schalnat 已提交
2191 2192 2193 2194 2195 2196 2197
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2198

G
Guy Schalnat 已提交
2199 2200
         case 4:
         {
2201 2202
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2203
            png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);
2204
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2205
            {
2206
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2207

G
Guy Schalnat 已提交
2208 2209 2210 2211 2212
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2213

G
Guy Schalnat 已提交
2214 2215 2216 2217 2218 2219 2220
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2221 2222 2223

         default:
            break;
G
Guy Schalnat 已提交
2224 2225
      }
      row_info->bit_depth = 8;
2226
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2227
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2228 2229
   }
}
G
Guy Schalnat 已提交
2230
#endif
G
Guy Schalnat 已提交
2231

2232
#ifdef PNG_READ_SHIFT_SUPPORTED
2233 2234 2235 2236 2237
/* Reverse the effects of png_do_shift.  This routine merely shifts the
 * pixels back to their significant bits values.  Thus, if you have
 * a row of bit depth 8, but only 5 are significant, this will shift
 * the values back to 0 through 31.
 */
2238
static void
2239 2240
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2241
{
2242 2243
   int color_type;

2244
   png_debug(1, "in png_do_unshift");
2245

2246 2247 2248 2249
   /* The palette case has already been handled in the _init routine. */
   color_type = row_info->color_type;

   if (color_type != PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2250 2251
   {
      int shift[4];
2252
      int channels = 0;
2253
      int bit_depth = row_info->bit_depth;
G
Guy Schalnat 已提交
2254

2255
      if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
2256
      {
2257 2258 2259
         shift[channels++] = bit_depth - sig_bits->red;
         shift[channels++] = bit_depth - sig_bits->green;
         shift[channels++] = bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2260
      }
2261

G
Guy Schalnat 已提交
2262 2263
      else
      {
2264
         shift[channels++] = bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2265
      }
2266

2267
      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
G
Guy Schalnat 已提交
2268
      {
2269
         shift[channels++] = bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2270
      }
G
Guy Schalnat 已提交
2271

G
Guy Schalnat 已提交
2272
      {
2273
         int c, have_shift;
2274

2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
         for (c = have_shift = 0; c < channels; ++c)
         {
            /* A shift of more than the bit depth is an error condition but it
             * gets ignored here.
             */
            if (shift[c] <= 0 || shift[c] >= bit_depth)
               shift[c] = 0;

            else
               have_shift = 1;
         }
G
Guy Schalnat 已提交
2286

2287
         if (have_shift == 0)
2288 2289
            return;
      }
G
Guy Schalnat 已提交
2290

2291
      switch (bit_depth)
G
Guy Schalnat 已提交
2292
      {
2293
         default:
2294 2295
         /* Must be 1bpp gray: should not be here! */
            /* NOTREACHED */
2296
            break;
2297

G
Guy Schalnat 已提交
2298
         case 2:
2299 2300
         /* Must be 2bpp gray */
         /* assert(channels == 1 && shift[0] == 1) */
G
Guy Schalnat 已提交
2301
         {
2302 2303
            png_bytep bp = row;
            png_bytep bp_end = bp + row_info->rowbytes;
A
Andreas Dilger 已提交
2304

2305
            while (bp < bp_end)
G
Guy Schalnat 已提交
2306
            {
2307 2308
               int b = (*bp >> 1) & 0x55;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2309 2310 2311
            }
            break;
         }
2312

G
Guy Schalnat 已提交
2313
         case 4:
2314 2315
         /* Must be 4bpp gray */
         /* assert(channels == 1) */
G
Guy Schalnat 已提交
2316
         {
2317
            png_bytep bp = row;
2318 2319 2320 2321 2322
            png_bytep bp_end = bp + row_info->rowbytes;
            int gray_shift = shift[0];
            int mask =  0xf >> gray_shift;

            mask |= mask << 4;
2323

2324
            while (bp < bp_end)
G
Guy Schalnat 已提交
2325
            {
2326 2327
               int b = (*bp >> gray_shift) & mask;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2328 2329 2330
            }
            break;
         }
2331

G
Guy Schalnat 已提交
2332
         case 8:
2333
         /* Single byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2334
         {
2335
            png_bytep bp = row;
2336 2337
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2338

2339
            while (bp < bp_end)
A
Andreas Dilger 已提交
2340
            {
2341
               int b = *bp >> shift[channel];
2342 2343
               if (++channel >= channels)
                  channel = 0;
2344
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2345 2346 2347
            }
            break;
         }
2348

2349
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2350
         case 16:
2351
         /* Double byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2352
         {
2353
            png_bytep bp = row;
2354 2355
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2356

2357
            while (bp < bp_end)
A
Andreas Dilger 已提交
2358
            {
2359 2360 2361 2362 2363
               int value = (bp[0] << 8) + bp[1];

               value >>= shift[channel];
               if (++channel >= channels)
                  channel = 0;
2364
               *bp++ = (png_byte)(value >> 8);
2365
               *bp++ = (png_byte)value;
G
Guy Schalnat 已提交
2366 2367 2368
            }
            break;
         }
2369
#endif
G
Guy Schalnat 已提交
2370 2371 2372
      }
   }
}
G
Guy Schalnat 已提交
2373
#endif
G
Guy Schalnat 已提交
2374

2375
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2376
/* Scale rows of bit depth 16 down to 8 accurately */
2377
static void
2378
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2379
{
2380
   png_debug(1, "in png_do_scale_16_to_8");
2381

A
Andreas Dilger 已提交
2382
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2383
   {
2384
      png_bytep sp = row; /* source */
2385
      png_bytep dp = row; /* destination */
2386
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2387

2388
      while (sp < ep)
G
Guy Schalnat 已提交
2389
      {
2390 2391
         /* The input is an array of 16-bit components, these must be scaled to
          * 8 bits each.  For a 16-bit value V the required value (from the PNG
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411
          * specification) is:
          *
          *    (V * 255) / 65535
          *
          * This reduces to round(V / 257), or floor((V + 128.5)/257)
          *
          * Represent V as the two byte value vhi.vlo.  Make a guess that the
          * result is the top byte of V, vhi, then the correction to this value
          * is:
          *
          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
          *          = floor(((vlo-vhi) + 128.5) / 257)
          *
          * This can be approximated using integer arithmetic (and a signed
          * shift):
          *
          *    error = (vlo-vhi+128) >> 8;
          *
          * The approximate differs from the exact answer only when (vlo-vhi) is
          * 128; it then gives a correction of +1 when the exact correction is
2412
          * 0.  This gives 128 errors.  The exact answer (correct for all 16-bit
2413 2414 2415 2416 2417 2418 2419 2420
          * input values) is:
          *
          *    error = (vlo-vhi+128)*65535 >> 24;
          *
          * An alternative arithmetic calculation which also gives no errors is:
          *
          *    (V * 255 + 32895) >> 16
          */
2421

2422
         png_int_32 tmp = *sp++; /* must be signed! */
2423
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2424
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2425
      }
2426

G
Guy Schalnat 已提交
2427
      row_info->bit_depth = 8;
2428
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2429
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2430 2431
   }
}
2432
#endif
2433

2434
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2435
static void
2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
/* Simply discard the low byte.  This was the default behavior prior
 * to libpng-1.5.4.
 */
png_do_chop(png_row_infop row_info, png_bytep row)
{
   png_debug(1, "in png_do_chop");

   if (row_info->bit_depth == 16)
   {
      png_bytep sp = row; /* source */
2446
      png_bytep dp = row; /* destination */
2447 2448 2449 2450
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
2451 2452
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2453 2454 2455
      }

      row_info->bit_depth = 8;
2456
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2457 2458 2459
      row_info->rowbytes = row_info->width * row_info->channels;
   }
}
2460
#endif
A
Andreas Dilger 已提交
2461

2462
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2463
static void
A
Andreas Dilger 已提交
2464 2465
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2466
   png_debug(1, "in png_do_read_swap_alpha");
2467

A
Andreas Dilger 已提交
2468
   {
2469
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2470 2471 2472 2473 2474
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2475 2476
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2477 2478
            png_byte save;
            png_uint_32 i;
2479

2480
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2481 2482 2483 2484 2485 2486 2487 2488
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2489 2490

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2491 2492 2493
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2494 2495
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2496 2497
            png_byte save[2];
            png_uint_32 i;
2498

2499
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2513
#endif
A
Andreas Dilger 已提交
2514
      }
2515

A
Andreas Dilger 已提交
2516 2517 2518 2519 2520
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2521 2522
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2523 2524
            png_byte save;
            png_uint_32 i;
2525

2526
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2527 2528 2529 2530 2531 2532
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2533 2534

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2535 2536 2537
         /* This converts from GGAA to AAGG */
         else
         {
2538 2539
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2540 2541 2542
            png_byte save[2];
            png_uint_32 i;

2543
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2544 2545 2546 2547 2548 2549 2550 2551 2552
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2553
#endif
A
Andreas Dilger 已提交
2554
      }
G
Guy Schalnat 已提交
2555 2556
   }
}
G
Guy Schalnat 已提交
2557
#endif
G
Guy Schalnat 已提交
2558

2559
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2560
static void
2561 2562
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2563
   png_uint_32 row_width;
2564
   png_debug(1, "in png_do_read_invert_alpha");
2565

2566 2567
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2568
   {
2569
      if (row_info->bit_depth == 8)
2570 2571
      {
         /* This inverts the alpha channel in RGBA */
2572 2573 2574
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2575

2576 2577
         for (i = 0; i < row_width; i++)
         {
2578
            *(--dp) = (png_byte)(255 - *(--sp));
2579

2580 2581 2582 2583 2584
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2585
*/
2586 2587
            sp-=3;
            dp=sp;
2588
         }
2589
      }
2590 2591

#ifdef PNG_READ_16BIT_SUPPORTED
2592 2593 2594 2595 2596 2597
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2598

2599 2600
         for (i = 0; i < row_width; i++)
         {
2601 2602
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2603 2604 2605 2606 2607 2608 2609 2610 2611

/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2612
*/
2613 2614
            sp-=6;
            dp=sp;
2615 2616
         }
      }
2617
#endif
2618 2619 2620 2621
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2622
      {
2623
         /* This inverts the alpha channel in GA */
2624 2625 2626
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2627

2628 2629
         for (i = 0; i < row_width; i++)
         {
2630
            *(--dp) = (png_byte)(255 - *(--sp));
2631
            *(--dp) = *(--sp);
2632
         }
2633
      }
2634 2635

#ifdef PNG_READ_16BIT_SUPPORTED
2636 2637
      else
      {
2638
         /* This inverts the alpha channel in GGAA */
2639 2640 2641
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2642

2643 2644
         for (i = 0; i < row_width; i++)
         {
2645 2646
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2647
/*
2648 2649
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2650
*/
2651 2652
            sp-=2;
            dp=sp;
2653 2654
         }
      }
2655
#endif
2656 2657 2658 2659
   }
}
#endif

2660
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2661
/* Add filler channel if we have RGB color */
2662
static void
G
Guy Schalnat 已提交
2663
png_do_read_filler(png_row_infop row_info, png_bytep row,
2664
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2665
{
G
Guy Schalnat 已提交
2666
   png_uint_32 i;
2667 2668
   png_uint_32 row_width = row_info->width;

2669
#ifdef PNG_READ_16BIT_SUPPORTED
2670
   png_byte hi_filler = (png_byte)(filler>>8);
2671
#endif
2672
   png_byte lo_filler = (png_byte)filler;
A
Andreas Dilger 已提交
2673

2674
   png_debug(1, "in png_do_read_filler");
2675

A
Andreas Dilger 已提交
2676
   if (
2677
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2678
   {
2679
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2680
      {
2681
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
G
Guy Schalnat 已提交
2682
         {
2683
            /* This changes the data from G to GX */
2684 2685
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
2686 2687
            for (i = 1; i < row_width; i++)
            {
2688
               *(--dp) = lo_filler;
2689 2690
               *(--dp) = *(--sp);
            }
2691
            *(--dp) = lo_filler;
2692 2693 2694 2695
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
2696

2697 2698
         else
         {
2699
            /* This changes the data from G to XG */
2700 2701
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2702 2703 2704
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2705
               *(--dp) = lo_filler;
2706 2707 2708 2709 2710 2711
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2712

2713
#ifdef PNG_READ_16BIT_SUPPORTED
2714
      else if (row_info->bit_depth == 16)
2715
      {
2716
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2717
         {
2718
            /* This changes the data from GG to GGXX */
2719 2720
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2721 2722
            for (i = 1; i < row_width; i++)
            {
2723
               *(--dp) = lo_filler;
2724
               *(--dp) = hi_filler;
2725 2726 2727
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2728
            *(--dp) = lo_filler;
2729
            *(--dp) = hi_filler;
2730 2731
            row_info->channels = 2;
            row_info->pixel_depth = 32;
2732
            row_info->rowbytes = row_width * 4;
2733
         }
2734

2735 2736
         else
         {
2737
            /* This changes the data from GG to XXGG */
2738 2739
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2740 2741 2742 2743
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2744
               *(--dp) = lo_filler;
2745
               *(--dp) = hi_filler;
2746 2747
            }
            row_info->channels = 2;
2748 2749
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
2750
         }
G
Guy Schalnat 已提交
2751
      }
2752
#endif
2753 2754 2755
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
2756
      if (row_info->bit_depth == 8)
2757
      {
2758
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2759
         {
2760
            /* This changes the data from RGB to RGBX */
2761 2762
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
2763 2764
            for (i = 1; i < row_width; i++)
            {
2765
               *(--dp) = lo_filler;
2766 2767 2768 2769
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2770
            *(--dp) = lo_filler;
2771 2772 2773 2774
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
2775

2776 2777
         else
         {
2778
            /* This changes the data from RGB to XRGB */
2779 2780
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
2781 2782 2783 2784 2785
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2786
               *(--dp) = lo_filler;
2787 2788 2789 2790 2791 2792
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
2793

2794
#ifdef PNG_READ_16BIT_SUPPORTED
2795
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2796
      {
2797
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
G
Guy Schalnat 已提交
2798
         {
2799
            /* This changes the data from RRGGBB to RRGGBBXX */
2800 2801
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2802 2803
            for (i = 1; i < row_width; i++)
            {
2804
               *(--dp) = lo_filler;
2805
               *(--dp) = hi_filler;
2806 2807 2808 2809 2810 2811 2812
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2813
            *(--dp) = lo_filler;
2814
            *(--dp) = hi_filler;
2815 2816
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2817
            row_info->rowbytes = row_width * 8;
2818
         }
2819

2820 2821
         else
         {
2822
            /* This changes the data from RRGGBB to XXRRGGBB */
2823 2824
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2825 2826 2827 2828 2829 2830 2831 2832
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2833
               *(--dp) = lo_filler;
2834
               *(--dp) = hi_filler;
2835
            }
2836

2837 2838
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2839
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2840
         }
G
Guy Schalnat 已提交
2841
      }
2842
#endif
2843
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2844
}
G
Guy Schalnat 已提交
2845
#endif
G
Guy Schalnat 已提交
2846

2847
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2848
/* Expand grayscale files to RGB, with or without alpha */
2849
static void
G
Guy Schalnat 已提交
2850
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2851
{
G
Guy Schalnat 已提交
2852
   png_uint_32 i;
2853
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2854

2855
   png_debug(1, "in png_do_gray_to_rgb");
2856

A
Andreas Dilger 已提交
2857
   if (row_info->bit_depth >= 8 &&
2858
       (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
G
Guy Schalnat 已提交
2859 2860 2861 2862 2863
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
2864
            /* This changes G to RGB */
2865 2866
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2867
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2868 2869 2870
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
2871
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2872 2873
            }
         }
2874

G
Guy Schalnat 已提交
2875 2876
         else
         {
2877
            /* This changes GG to RRGGBB */
2878 2879
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2880
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2881 2882 2883 2884 2885
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2886 2887
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2888 2889 2890
            }
         }
      }
2891

G
Guy Schalnat 已提交
2892 2893 2894 2895
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
2896
            /* This changes GA to RGBA */
2897 2898
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2899
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2900 2901 2902 2903
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
2904
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2905 2906
            }
         }
2907

G
Guy Schalnat 已提交
2908 2909
         else
         {
2910
            /* This changes GGAA to RRGGBBAA */
2911 2912
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2913
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2914 2915 2916 2917 2918 2919 2920
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2921 2922
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2923 2924 2925
            }
         }
      }
2926
      row_info->channels = (png_byte)(row_info->channels + 2);
G
Guy Schalnat 已提交
2927
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
2928 2929
      row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
2930
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
2931 2932
   }
}
G
Guy Schalnat 已提交
2933
#endif
G
Guy Schalnat 已提交
2934

2935
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2936
/* Reduce RGB files to grayscale, with or without alpha
2937 2938 2939
 * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
 * versions dated 1998 through November 2002 have been archived at
V
Viktor Szakats 已提交
2940
 * https://web.archive.org/web/20000816232553/www.inforamp.net/
2941
 * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
2942
 * Charles Poynton poynton at poynton.com
2943 2944 2945
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
2946
 *  which can be expressed with integers as
2947
 *
2948 2949 2950 2951 2952 2953 2954
 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
 *
 * Poynton's current link (as of January 2003 through July 2011):
 * <http://www.poynton.com/notes/colour_and_gamma/>
 * has changed the numbers slightly:
 *
 *     Y = 0.2126*R + 0.7152*G + 0.0722*B
2955 2956 2957
 *
 *  which can be expressed with integers as
 *
2958 2959
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
 *
2960 2961 2962 2963 2964
 *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
 *  end point chromaticities and the D65 white point.  Depending on the
 *  precision used for the D65 white point this produces a variety of different
 *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
 *  used (0.3127,0.3290) the Y calculation would be:
2965
 *
2966
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2967
 *
2968 2969 2970 2971 2972
 *  While this is correct the rounding results in an overflow for white, because
 *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
 *  libpng uses, instead, the closest non-overflowing approximation:
 *
 *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
2973
 *
2974 2975 2976
 *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
 *  (including an sRGB chunk) then the chromaticities are used to calculate the
 *  coefficients.  See the chunk handling in pngrutil.c for more information.
2977
 *
2978 2979 2980 2981
 *  In all cases the calculation is to be done in a linear colorspace.  If no
 *  gamma information is available to correct the encoding of the original RGB
 *  values this results in an implicit assumption that the original PNG RGB
 *  values were linear.
2982
 *
2983 2984 2985 2986
 *  Other integer coefficents can be used via png_set_rgb_to_gray().  Because
 *  the API takes just red and green coefficients the blue coefficient is
 *  calculated to make the sum 32768.  This will result in different rounding
 *  to that used above.
2987
 */
2988
static int
2989
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2990 2991 2992 2993

{
   int rgb_error = 0;

2994
   png_debug(1, "in png_do_rgb_to_gray");
2995

2996 2997
   if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
2998
   {
2999 3000 3001 3002 3003 3004
      PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
      PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
      PNG_CONST png_uint_32 bc = 32768 - rc - gc;
      PNG_CONST png_uint_32 row_width = row_info->width;
      PNG_CONST int have_alpha =
         (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3005

3006
      if (row_info->bit_depth == 8)
3007
      {
3008
#ifdef PNG_READ_GAMMA_SUPPORTED
3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020
         /* Notice that gamma to/from 1 are not necessarily inverses (if
          * there is an overall gamma correction).  Prior to 1.5.5 this code
          * checked the linearized values for equality; this doesn't match
          * the documentation, the original values must be checked.
          */
         if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
         {
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;

            for (i = 0; i < row_width; i++)
3021
            {
3022 3023 3024
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3025

3026
               if (red != green || red != blue)
3027
               {
3028 3029 3030
                  red = png_ptr->gamma_to_1[red];
                  green = png_ptr->gamma_to_1[green];
                  blue = png_ptr->gamma_to_1[blue];
3031

3032 3033 3034
                  rgb_error |= 1;
                  *(dp++) = png_ptr->gamma_from_1[
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3035
               }
3036

3037 3038 3039 3040 3041 3042 3043
               else
               {
                  /* If there is no overall correction the table will not be
                   * set.
                   */
                  if (png_ptr->gamma_table != NULL)
                     red = png_ptr->gamma_table[red];
3044

3045
                  *(dp++) = red;
3046
               }
3047

3048
               if (have_alpha != 0)
3049
                  *(dp++) = *(sp++);
3050 3051
            }
         }
3052 3053
         else
#endif
3054
         {
3055 3056 3057
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3058

3059
            for (i = 0; i < row_width; i++)
3060
            {
3061 3062 3063
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3064

3065 3066 3067
               if (red != green || red != blue)
               {
                  rgb_error |= 1;
3068
                  /* NOTE: this is the historical approach which simply
3069 3070
                   * truncates the results.
                   */
3071
                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3072
               }
3073

3074 3075
               else
                  *(dp++) = red;
3076

3077
               if (have_alpha != 0)
3078
                  *(dp++) = *(sp++);
3079 3080 3081
            }
         }
      }
3082 3083

      else /* RGB bit_depth == 16 */
3084
      {
3085
#ifdef PNG_READ_GAMMA_SUPPORTED
3086 3087 3088 3089 3090 3091 3092
         if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
         {
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;

            for (i = 0; i < row_width; i++)
3093
            {
3094
               png_uint_16 red, green, blue, w;
3095
               png_byte hi,lo;
3096

3097 3098 3099
               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3100

3101 3102 3103
               if (red == green && red == blue)
               {
                  if (png_ptr->gamma_16_table != NULL)
3104 3105
                     w = png_ptr->gamma_16_table[(red & 0xff)
                         >> png_ptr->gamma_shift][red >> 8];
3106

3107 3108
                  else
                     w = red;
3109
               }
3110 3111

               else
3112
               {
3113
                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red & 0xff)
3114 3115
                      >> png_ptr->gamma_shift][red>>8];
                  png_uint_16 green_1 =
3116
                      png_ptr->gamma_16_to_1[(green & 0xff) >>
3117
                      png_ptr->gamma_shift][green>>8];
3118
                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue & 0xff)
3119 3120 3121
                      >> png_ptr->gamma_shift][blue>>8];
                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
                      + bc*blue_1 + 16384)>>15);
3122
                  w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
3123 3124 3125 3126 3127 3128 3129
                      png_ptr->gamma_shift][gray16 >> 8];
                  rgb_error |= 1;
               }

               *(dp++) = (png_byte)((w>>8) & 0xff);
               *(dp++) = (png_byte)(w & 0xff);

3130
               if (have_alpha != 0)
3131 3132 3133
               {
                  *(dp++) = *(sp++);
                  *(dp++) = *(sp++);
3134 3135 3136
               }
            }
         }
3137 3138
         else
#endif
3139
         {
3140 3141 3142
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3143

3144 3145 3146
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3147
               png_byte hi,lo;
3148

3149 3150 3151
               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3152

3153 3154
               if (red != green || red != blue)
                  rgb_error |= 1;
3155

3156
               /* From 1.5.5 in the 16-bit case do the accurate conversion even
3157
                * in the 'fast' case - this is because this is where the code
3158
                * ends up when handling linear 16-bit data.
3159 3160 3161
                */
               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
                  15);
3162
               *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
3163
               *(dp++) = (png_byte)(gray16 & 0xff);
3164

3165
               if (have_alpha != 0)
3166
               {
3167
                  *(dp++) = *(sp++);
3168 3169 3170 3171 3172
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3173

3174 3175 3176 3177 3178
      row_info->channels = (png_byte)(row_info->channels - 2);
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
      row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
3179
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3180 3181 3182 3183
   }
   return rgb_error;
}
#endif
G
Guy Schalnat 已提交
3184

3185 3186
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
A
Andreas Dilger 已提交
3187
/* Replace any alpha or transparency with the supplied background color.
3188 3189 3190
 * "background" is already in the screen gamma, while "background_1" is
 * at a gamma of 1.0.  Paletted files have already been taken care of.
 */
3191
static void
3192
png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3193
{
3194
#ifdef PNG_READ_GAMMA_SUPPORTED
3195 3196 3197 3198 3199 3200 3201
   png_const_bytep gamma_table = png_ptr->gamma_table;
   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
   png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
   png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
   int gamma_shift = png_ptr->gamma_shift;
3202
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3203
#endif
3204

3205
   png_bytep sp;
G
Guy Schalnat 已提交
3206
   png_uint_32 i;
3207
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3208
   int shift;
G
Guy Schalnat 已提交
3209

3210
   png_debug(1, "in png_do_compose");
3211

G
Guy Schalnat 已提交
3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
3223
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3224
                  {
3225
                     if ((png_uint_16)((*sp >> shift) & 0x01)
3226
                        == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3227
                     {
3228
                        unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
3229 3230
                        tmp |=
                            (unsigned int)(png_ptr->background.gray << shift);
3231
                        *sp = (png_byte)(tmp & 0xff);
G
Guy Schalnat 已提交
3232
                     }
3233

3234
                     if (shift == 0)
G
Guy Schalnat 已提交
3235 3236 3237 3238
                     {
                        shift = 7;
                        sp++;
                     }
3239

G
Guy Schalnat 已提交
3240 3241 3242 3243 3244
                     else
                        shift--;
                  }
                  break;
               }
3245

G
Guy Schalnat 已提交
3246 3247
               case 2:
               {
3248
#ifdef PNG_READ_GAMMA_SUPPORTED
3249
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3250
                  {
3251 3252 3253
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3254
                     {
3255
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3256
                            == png_ptr->trans_color.gray)
3257
                        {
3258
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3259 3260
                           tmp |=
                              (unsigned int)png_ptr->background.gray << shift;
3261
                           *sp = (png_byte)(tmp & 0xff);
3262
                        }
3263

3264 3265
                        else
                        {
3266 3267 3268 3269
                           unsigned int p = (*sp >> shift) & 0x03;
                           unsigned int g = (gamma_table [p | (p << 2) |
                               (p << 4) | (p << 6)] >> 6) & 0x03;
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3270
                           tmp |= (unsigned int)(g << shift);
3271
                           *sp = (png_byte)(tmp & 0xff);
3272
                        }
3273

3274
                        if (shift == 0)
3275 3276 3277 3278
                        {
                           shift = 6;
                           sp++;
                        }
3279

3280 3281
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3282
                     }
3283
                  }
3284

3285 3286 3287 3288 3289 3290
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3291
                     {
3292
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3293
                            == png_ptr->trans_color.gray)
3294
                        {
3295
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3296 3297
                           tmp |=
                               (unsigned int)png_ptr->background.gray << shift;
3298
                           *sp = (png_byte)(tmp & 0xff);
3299
                        }
3300

3301
                        if (shift == 0)
3302 3303 3304 3305
                        {
                           shift = 6;
                           sp++;
                        }
3306

3307 3308
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3309 3310 3311 3312
                     }
                  }
                  break;
               }
3313

G
Guy Schalnat 已提交
3314 3315
               case 4:
               {
3316
#ifdef PNG_READ_GAMMA_SUPPORTED
3317
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3318
                  {
3319 3320 3321
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3322
                     {
3323
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3324
                            == png_ptr->trans_color.gray)
3325
                        {
3326
                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3327
                           tmp |=
3328
                              (unsigned int)(png_ptr->background.gray << shift);
3329
                           *sp = (png_byte)(tmp & 0xff);
3330
                        }
3331

3332 3333
                        else
                        {
3334 3335 3336
                           unsigned int p = (*sp >> shift) & 0x0f;
                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
                              0x0f;
3337
                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3338
                           tmp |= (unsigned int)(g << shift);
3339
                           *sp = (png_byte)(tmp & 0xff);
3340
                        }
3341

3342
                        if (shift == 0)
3343 3344 3345 3346
                        {
                           shift = 4;
                           sp++;
                        }
3347

3348 3349
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3350
                     }
3351
                  }
3352

3353 3354 3355 3356 3357 3358
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3359
                     {
3360
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3361
                            == png_ptr->trans_color.gray)
3362
                        {
3363
                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3364 3365
                           tmp |=
                              (unsigned int)(png_ptr->background.gray << shift);
3366
                           *sp = (png_byte)(tmp & 0xff);
3367
                        }
3368

3369
                        if (shift == 0)
3370 3371 3372 3373
                        {
                           shift = 4;
                           sp++;
                        }
3374

3375 3376
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3377 3378 3379 3380
                     }
                  }
                  break;
               }
3381

G
Guy Schalnat 已提交
3382 3383
               case 8:
               {
3384
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3385
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3386
                  {
3387 3388
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3389
                     {
3390 3391
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3392

G
Guy Schalnat 已提交
3393 3394 3395 3396 3397
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3398
#endif
G
Guy Schalnat 已提交
3399
                  {
3400 3401
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3402
                     {
3403 3404
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3405 3406 3407 3408
                     }
                  }
                  break;
               }
3409

G
Guy Schalnat 已提交
3410 3411
               case 16:
               {
3412
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3413
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3414
                  {
3415 3416
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3417 3418 3419
                     {
                        png_uint_16 v;

3420
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3421

3422
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3423
                        {
3424
                           /* Background is already in screen gamma */
3425 3426 3427 3428
                           *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray
                                & 0xff);
G
Guy Schalnat 已提交
3429
                        }
3430

G
Guy Schalnat 已提交
3431 3432
                        else
                        {
A
Andreas Dilger 已提交
3433
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3434
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3435
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3436
                        }
G
Guy Schalnat 已提交
3437
                     }
G
Guy Schalnat 已提交
3438 3439
                  }
                  else
G
Guy Schalnat 已提交
3440
#endif
G
Guy Schalnat 已提交
3441
                  {
3442 3443
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3444 3445 3446
                     {
                        png_uint_16 v;

3447
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3448

3449
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3450
                        {
3451 3452 3453 3454
                           *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray
                                & 0xff);
G
Guy Schalnat 已提交
3455 3456 3457 3458 3459
                        }
                     }
                  }
                  break;
               }
3460 3461 3462

               default:
                  break;
G
Guy Schalnat 已提交
3463 3464 3465
            }
            break;
         }
3466

G
Guy Schalnat 已提交
3467 3468 3469 3470
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3471
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3472
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3473
               {
3474 3475
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3476
                  {
3477 3478 3479
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3480
                     {
3481 3482 3483
                        *sp = (png_byte)png_ptr->background.red;
                        *(sp + 1) = (png_byte)png_ptr->background.green;
                        *(sp + 2) = (png_byte)png_ptr->background.blue;
G
Guy Schalnat 已提交
3484
                     }
3485

G
Guy Schalnat 已提交
3486 3487 3488 3489 3490 3491 3492 3493 3494
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3495
#endif
G
Guy Schalnat 已提交
3496
               {
3497 3498
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3499
                  {
3500 3501 3502
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3503
                     {
3504 3505 3506
                        *sp = (png_byte)png_ptr->background.red;
                        *(sp + 1) = (png_byte)png_ptr->background.green;
                        *(sp + 2) = (png_byte)png_ptr->background.blue;
G
Guy Schalnat 已提交
3507 3508 3509 3510
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3511
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3512
            {
3513
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3514
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3515
               {
3516 3517
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3518
                  {
3519
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3520

3521 3522
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3523

3524 3525
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3526

3527 3528 3529
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3530
                     {
3531
                        /* Background is already in screen gamma */
3532 3533 3534 3535 3536 3537 3538 3539 3540
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                                & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green
                                & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                                & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3541
                     }
3542

G
Guy Schalnat 已提交
3543 3544
                     else
                     {
3545
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3546
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3547
                        *(sp + 1) = (png_byte)(v & 0xff);
3548

A
Andreas Dilger 已提交
3549
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3550 3551
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3552

A
Andreas Dilger 已提交
3553
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3554 3555
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3556 3557 3558
                     }
                  }
               }
3559

G
Guy Schalnat 已提交
3560
               else
G
Guy Schalnat 已提交
3561
#endif
G
Guy Schalnat 已提交
3562
               {
3563 3564
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3565
                  {
3566
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3567

3568 3569
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3570

3571 3572
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3573

3574 3575 3576
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3577
                     {
3578 3579 3580 3581 3582 3583 3584 3585 3586
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                                & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green
                                & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                                & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3587 3588 3589 3590 3591 3592
                     }
                  }
               }
            }
            break;
         }
3593

G
Guy Schalnat 已提交
3594
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3595
         {
A
Andreas Dilger 已提交
3596
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3597
            {
3598
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3599 3600 3601
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3602
                  sp = row;
3603
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3604
                  {
3605
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3606

A
Andreas Dilger 已提交
3607
                     if (a == 0xff)
3608
                        *sp = gamma_table[*sp];
3609

A
Andreas Dilger 已提交
3610 3611
                     else if (a == 0)
                     {
3612
                        /* Background is already in screen gamma */
3613
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3614
                     }
3615

A
Andreas Dilger 已提交
3616 3617 3618
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3619

A
Andreas Dilger 已提交
3620
                        v = gamma_to_1[*sp];
3621
                        png_composite(w, v, a, png_ptr->background_1.gray);
3622
                        if (optimize == 0)
3623 3624
                           w = gamma_from_1[w];
                        *sp = w;
G
Guy Schalnat 已提交
3625 3626
                     }
                  }
A
Andreas Dilger 已提交
3627 3628
               }
               else
G
Guy Schalnat 已提交
3629
#endif
A
Andreas Dilger 已提交
3630
               {
3631
                  sp = row;
3632
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3633
                  {
3634
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3635

3636 3637
                     if (a == 0)
                        *sp = (png_byte)png_ptr->background.gray;
3638

3639
                     else if (a < 0xff)
3640
                        png_composite(*sp, *sp, a, png_ptr->background.gray);
G
Guy Schalnat 已提交
3641 3642
                  }
               }
A
Andreas Dilger 已提交
3643 3644 3645
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3646
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3647 3648 3649
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3650
                  sp = row;
3651
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3652
                  {
3653 3654
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
A
Andreas Dilger 已提交
3655

3656
                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3657
                     {
A
Andreas Dilger 已提交
3658
                        png_uint_16 v;
G
Guy Schalnat 已提交
3659

A
Andreas Dilger 已提交
3660
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3661 3662
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3663
                     }
3664

A
Andreas Dilger 已提交
3665 3666
                     else if (a == 0)
                     {
3667
                        /* Background is already in screen gamma */
3668 3669 3670
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3671
                     }
3672

A
Andreas Dilger 已提交
3673 3674 3675
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3676

A
Andreas Dilger 已提交
3677
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3678
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3679
                        if (optimize != 0)
3680 3681
                           w = v;
                        else
3682 3683
                           w = gamma_16_from_1[(v & 0xff) >>
                               gamma_shift][v >> 8];
3684 3685
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3686 3687
                     }
                  }
A
Andreas Dilger 已提交
3688 3689
               }
               else
G
Guy Schalnat 已提交
3690
#endif
A
Andreas Dilger 已提交
3691
               {
3692
                  sp = row;
3693
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3694
                  {
3695 3696
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3697

3698
                     if (a == 0)
A
Andreas Dilger 已提交
3699
                     {
3700 3701 3702
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3703
                     }
3704

3705
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3706 3707
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3708

3709
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3710
                        png_composite_16(v, g, a, png_ptr->background.gray);
3711 3712
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3713 3714 3715 3716 3717 3718
                     }
                  }
               }
            }
            break;
         }
3719

G
Guy Schalnat 已提交
3720 3721 3722 3723
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3724
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3725 3726
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3727
               {
3728
                  sp = row;
3729
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3730
                  {
3731
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3732 3733 3734

                     if (a == 0xff)
                     {
3735 3736 3737
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
3738
                     }
3739

G
Guy Schalnat 已提交
3740 3741
                     else if (a == 0)
                     {
3742
                        /* Background is already in screen gamma */
3743 3744 3745
                        *sp = (png_byte)png_ptr->background.red;
                        *(sp + 1) = (png_byte)png_ptr->background.green;
                        *(sp + 2) = (png_byte)png_ptr->background.blue;
G
Guy Schalnat 已提交
3746
                     }
3747

G
Guy Schalnat 已提交
3748 3749
                     else
                     {
A
Andreas Dilger 已提交
3750
                        png_byte v, w;
G
Guy Schalnat 已提交
3751 3752

                        v = gamma_to_1[*sp];
3753
                        png_composite(w, v, a, png_ptr->background_1.red);
3754
                        if (optimize == 0) w = gamma_from_1[w];
3755
                        *sp = w;
3756

G
Guy Schalnat 已提交
3757
                        v = gamma_to_1[*(sp + 1)];
3758
                        png_composite(w, v, a, png_ptr->background_1.green);
3759
                        if (optimize == 0) w = gamma_from_1[w];
3760
                        *(sp + 1) = w;
3761

G
Guy Schalnat 已提交
3762
                        v = gamma_to_1[*(sp + 2)];
3763
                        png_composite(w, v, a, png_ptr->background_1.blue);
3764
                        if (optimize == 0) w = gamma_from_1[w];
3765
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
3766 3767 3768 3769
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3770
#endif
G
Guy Schalnat 已提交
3771
               {
3772
                  sp = row;
3773
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3774
                  {
3775
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3776

3777
                     if (a == 0)
G
Guy Schalnat 已提交
3778
                     {
3779 3780 3781
                        *sp = (png_byte)png_ptr->background.red;
                        *(sp + 1) = (png_byte)png_ptr->background.green;
                        *(sp + 2) = (png_byte)png_ptr->background.blue;
G
Guy Schalnat 已提交
3782
                     }
3783

3784
                     else if (a < 0xff)
G
Guy Schalnat 已提交
3785
                     {
3786
                        png_composite(*sp, *sp, a, png_ptr->background.red);
3787

3788
                        png_composite(*(sp + 1), *(sp + 1), a,
3789
                            png_ptr->background.green);
3790

3791
                        png_composite(*(sp + 2), *(sp + 2), a,
3792
                            png_ptr->background.blue);
G
Guy Schalnat 已提交
3793 3794 3795 3796
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3797
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3798
            {
3799
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3800 3801
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
3802
               {
3803
                  sp = row;
3804
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3805
                  {
3806 3807
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
3808

3809
                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3810 3811 3812
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3813
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3814 3815
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3816

A
Andreas Dilger 已提交
3817
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3818 3819
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3820

A
Andreas Dilger 已提交
3821
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3822 3823
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3824
                     }
3825

G
Guy Schalnat 已提交
3826 3827
                     else if (a == 0)
                     {
3828
                        /* Background is already in screen gamma */
3829 3830 3831 3832 3833 3834 3835 3836 3837
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                                & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green
                                & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                                & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3838
                     }
3839

G
Guy Schalnat 已提交
3840 3841
                     else
                     {
3842
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
3843 3844

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3845
                        png_composite_16(w, v, a, png_ptr->background_1.red);
3846
                        if (optimize == 0)
3847
                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3848
                                8];
3849 3850
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
3851

A
Andreas Dilger 已提交
3852
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3853
                        png_composite_16(w, v, a, png_ptr->background_1.green);
3854
                        if (optimize == 0)
3855
                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3856
                                8];
3857

3858 3859
                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(w & 0xff);
3860

A
Andreas Dilger 已提交
3861
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3862
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
3863
                        if (optimize == 0)
3864
                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3865
                                8];
3866

3867 3868
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3869 3870 3871
                     }
                  }
               }
3872

G
Guy Schalnat 已提交
3873
               else
G
Guy Schalnat 已提交
3874
#endif
G
Guy Schalnat 已提交
3875
               {
3876
                  sp = row;
3877
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3878
                  {
3879
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3880
                         << 8) + (png_uint_16)(*(sp + 7)));
3881

3882
                     if (a == 0)
G
Guy Schalnat 已提交
3883
                     {
3884 3885 3886 3887 3888 3889 3890 3891 3892
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                                & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green
                                & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                                & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3893
                     }
3894

3895
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
3896
                     {
3897
                        png_uint_16 v;
A
Andreas Dilger 已提交
3898

3899 3900 3901 3902 3903
                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                            + *(sp + 3));
                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                            + *(sp + 5));
A
Andreas Dilger 已提交
3904

3905
                        png_composite_16(v, r, a, png_ptr->background.red);
3906 3907
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3908

3909
                        png_composite_16(v, g, a, png_ptr->background.green);
3910 3911
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3912

3913
                        png_composite_16(v, b, a, png_ptr->background.blue);
3914 3915
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3916 3917 3918 3919 3920 3921
                     }
                  }
               }
            }
            break;
         }
3922 3923 3924

         default:
            break;
G
Guy Schalnat 已提交
3925 3926 3927
      }
   }
}
3928
#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
G
Guy Schalnat 已提交
3929

3930
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3931
/* Gamma correct the image, avoiding the alpha channel.  Make sure
3932
 * you do this after you deal with the transparency issue on grayscale
3933
 * or RGB images. If your bit depth is 8, use gamma_table, if it
3934 3935 3936
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
3937
static void
3938
png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
G
Guy Schalnat 已提交
3939
{
3940 3941 3942 3943
   png_const_bytep gamma_table = png_ptr->gamma_table;
   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
   int gamma_shift = png_ptr->gamma_shift;

G
Guy Schalnat 已提交
3944
   png_bytep sp;
G
Guy Schalnat 已提交
3945
   png_uint_32 i;
3946
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3947

3948
   png_debug(1, "in png_do_gamma");
3949

3950
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3951
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
3952 3953 3954 3955 3956 3957 3958
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3959 3960
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3961 3962 3963 3964 3965 3966 3967 3968 3969
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
3970

A
Andreas Dilger 已提交
3971
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3972
            {
3973 3974
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3975 3976 3977
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
3978
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3979 3980 3981
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
3982

A
Andreas Dilger 已提交
3983
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3984 3985
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3986
                  sp += 2;
3987

A
Andreas Dilger 已提交
3988
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3989 3990 3991 3992 3993 3994 3995
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
3996

G
Guy Schalnat 已提交
3997 3998 3999 4000
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4001 4002
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4003
               {
G
Guy Schalnat 已提交
4004 4005
                  *sp = gamma_table[*sp];
                  sp++;
4006

G
Guy Schalnat 已提交
4007 4008
                  *sp = gamma_table[*sp];
                  sp++;
4009

G
Guy Schalnat 已提交
4010 4011
                  *sp = gamma_table[*sp];
                  sp++;
4012

G
Guy Schalnat 已提交
4013 4014 4015
                  sp++;
               }
            }
4016

A
Andreas Dilger 已提交
4017
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4018
            {
4019 4020
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4021
               {
4022
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4023 4024
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4025
                  sp += 2;
4026

A
Andreas Dilger 已提交
4027
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4028 4029 4030
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4031

A
Andreas Dilger 已提交
4032
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4033 4034 4035 4036 4037
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4038 4039
            break;
         }
4040

G
Guy Schalnat 已提交
4041 4042 4043 4044
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4045 4046
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4047 4048
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4049
                  sp += 2;
G
Guy Schalnat 已提交
4050 4051
               }
            }
4052

A
Andreas Dilger 已提交
4053
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4054
            {
4055 4056
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4057
               {
4058
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4059 4060
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4061 4062 4063 4064 4065
                  sp += 4;
               }
            }
            break;
         }
4066

G
Guy Schalnat 已提交
4067 4068
         case PNG_COLOR_TYPE_GRAY:
         {
4069 4070
            if (row_info->bit_depth == 2)
            {
4071 4072
               sp = row;
               for (i = 0; i < row_width; i += 4)
4073 4074 4075 4076 4077 4078
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4079 4080
                  *sp = (png_byte)(
                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
4081 4082
                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
4083
                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4084 4085 4086
                  sp++;
               }
            }
4087

A
Andreas Dilger 已提交
4088
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4089
            {
4090 4091
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4092 4093 4094 4095
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4096
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4097
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4098 4099 4100
                  sp++;
               }
            }
4101

A
Andreas Dilger 已提交
4102 4103
            else if (row_info->bit_depth == 8)
            {
4104 4105
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4106 4107 4108 4109 4110
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4111

G
Guy Schalnat 已提交
4112 4113
            else if (row_info->bit_depth == 16)
            {
4114 4115
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4116
               {
4117
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4118 4119
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4120 4121 4122 4123 4124
                  sp += 2;
               }
            }
            break;
         }
4125 4126 4127

         default:
            break;
G
Guy Schalnat 已提交
4128 4129 4130
      }
   }
}
G
Guy Schalnat 已提交
4131
#endif
G
Guy Schalnat 已提交
4132

4133 4134 4135 4136 4137
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
/* Encode the alpha channel to the output gamma (the input channel is always
 * linear.)  Called only with color types that have an alpha channel.  Needs the
 * from_1 tables.
 */
4138
static void
4139
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4140 4141 4142 4143 4144
{
   png_uint_32 row_width = row_info->width;

   png_debug(1, "in png_do_encode_alpha");

4145
   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199
   {
      if (row_info->bit_depth == 8)
      {
         PNG_CONST png_bytep table = png_ptr->gamma_from_1;

         if (table != NULL)
         {
            PNG_CONST int step =
               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;

            /* The alpha channel is the last component: */
            row += step - 1;

            for (; row_width > 0; --row_width, row += step)
               *row = table[*row];

            return;
         }
      }

      else if (row_info->bit_depth == 16)
      {
         PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
         PNG_CONST int gamma_shift = png_ptr->gamma_shift;

         if (table != NULL)
         {
            PNG_CONST int step =
               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;

            /* The alpha channel is the last component: */
            row += step - 2;

            for (; row_width > 0; --row_width, row += step)
            {
               png_uint_16 v;

               v = table[*(row + 1) >> gamma_shift][*row];
               *row = (png_byte)((v >> 8) & 0xff);
               *(row + 1) = (png_byte)(v & 0xff);
            }

            return;
         }
      }
   }

   /* Only get to here if called with a weird row_info; no harm has been done,
    * so just issue a warning.
    */
   png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
}
#endif

4200
#ifdef PNG_READ_EXPAND_SUPPORTED
4201
/* Expands a palette row to an RGB or RGBA row depending
4202 4203
 * upon whether you supply trans and num_trans.
 */
4204
static void
G
Guy Schalnat 已提交
4205
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4206
    png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
4207
{
G
Guy Schalnat 已提交
4208
   int shift, value;
G
Guy Schalnat 已提交
4209
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4210
   png_uint_32 i;
4211
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4212

4213
   png_debug(1, "in png_do_expand_palette");
4214

4215
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4216 4217 4218 4219 4220 4221 4222
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4223 4224
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4225
               shift = 7 - (int)((row_width + 7) & 0x07);
4226
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4227
               {
4228
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4229
                     *dp = 1;
4230

G
Guy Schalnat 已提交
4231 4232
                  else
                     *dp = 0;
4233

G
Guy Schalnat 已提交
4234 4235 4236 4237 4238
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4239

G
Guy Schalnat 已提交
4240 4241 4242 4243 4244 4245 4246
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4247

G
Guy Schalnat 已提交
4248 4249
            case 2:
            {
4250 4251
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4252
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4253
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4254
               {
4255
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4256
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4257 4258 4259 4260 4261
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4262

G
Guy Schalnat 已提交
4263 4264 4265 4266 4267 4268 4269
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4270

G
Guy Schalnat 已提交
4271 4272
            case 4:
            {
4273 4274
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4275
               shift = (int)((row_width & 0x01) << 2);
4276
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4277
               {
4278
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4279
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4280 4281 4282 4283 4284
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4285

G
Guy Schalnat 已提交
4286 4287 4288 4289 4290 4291 4292
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4293 4294 4295

            default:
               break;
G
Guy Schalnat 已提交
4296 4297 4298
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4299
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4300
      }
4301

4302
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4303 4304
      {
         {
4305
            if (num_trans > 0)
G
Guy Schalnat 已提交
4306
            {
4307
               sp = row + (png_size_t)row_width - 1;
4308
               dp = row + ((png_size_t)row_width << 2) - 1;
G
Guy Schalnat 已提交
4309

4310
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4311
               {
A
Andreas Dilger 已提交
4312
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4313
                     *dp-- = 0xff;
4314

G
Guy Schalnat 已提交
4315
                  else
4316
                     *dp-- = trans_alpha[*sp];
4317

G
Guy Schalnat 已提交
4318 4319 4320 4321 4322 4323 4324
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4325
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4326 4327 4328
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4329

G
Guy Schalnat 已提交
4330 4331
            else
            {
4332 4333
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4334

4335
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4336 4337 4338 4339 4340 4341
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4342

G
Guy Schalnat 已提交
4343 4344
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4345
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4346 4347 4348 4349 4350 4351 4352 4353
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4354 4355
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4356
 */
4357
static void
G
Guy Schalnat 已提交
4358
png_do_expand(png_row_infop row_info, png_bytep row,
4359
    png_const_color_16p trans_color)
G
Guy Schalnat 已提交
4360
{
G
Guy Schalnat 已提交
4361
   int shift, value;
G
Guy Schalnat 已提交
4362
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4363
   png_uint_32 i;
4364
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4365

4366
   png_debug(1, "in png_do_expand");
4367

G
Guy Schalnat 已提交
4368
   {
A
Andreas Dilger 已提交
4369
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4370
      {
4371
         unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
A
Andreas Dilger 已提交
4372 4373

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4374
         {
A
Andreas Dilger 已提交
4375
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4376
            {
A
Andreas Dilger 已提交
4377
               case 1:
G
Guy Schalnat 已提交
4378
               {
4379
                  gray = (gray & 0x01) * 0xff;
4380 4381
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4382
                  shift = 7 - (int)((row_width + 7) & 0x07);
4383
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4384
                  {
4385
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4386
                        *dp = 0xff;
4387

A
Andreas Dilger 已提交
4388 4389
                     else
                        *dp = 0;
4390

A
Andreas Dilger 已提交
4391 4392 4393 4394 4395
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4396

A
Andreas Dilger 已提交
4397 4398
                     else
                        shift++;
G
Guy Schalnat 已提交
4399

A
Andreas Dilger 已提交
4400 4401 4402
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4403
               }
4404

A
Andreas Dilger 已提交
4405
               case 2:
G
Guy Schalnat 已提交
4406
               {
4407
                  gray = (gray & 0x03) * 0x55;
4408 4409
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
4410
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4411
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4412
                  {
4413
                     value = (*sp >> shift) & 0x03;
4414 4415
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
A
Andreas Dilger 已提交
4416 4417 4418 4419 4420
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
4421

A
Andreas Dilger 已提交
4422 4423
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4424

A
Andreas Dilger 已提交
4425 4426 4427
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4428
               }
4429

A
Andreas Dilger 已提交
4430
               case 4:
G
Guy Schalnat 已提交
4431
               {
4432
                  gray = (gray & 0x0f) * 0x11;
4433 4434
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4435
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4436
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4437
                  {
4438
                     value = (*sp >> shift) & 0x0f;
4439
                     *dp = (png_byte)(value | (value << 4));
A
Andreas Dilger 已提交
4440 4441 4442 4443 4444
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4445

A
Andreas Dilger 已提交
4446 4447
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4448

A
Andreas Dilger 已提交
4449 4450 4451
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4452
               }
4453 4454 4455

               default:
                  break;
G
Guy Schalnat 已提交
4456
            }
4457

A
Andreas Dilger 已提交
4458 4459
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4460
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4461
         }
A
Andreas Dilger 已提交
4462

4463
         if (trans_color != NULL)
G
Guy Schalnat 已提交
4464
         {
A
Andreas Dilger 已提交
4465
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4466
            {
4467
               gray = gray & 0xff;
4468
               sp = row + (png_size_t)row_width - 1;
4469
               dp = row + ((png_size_t)row_width << 1) - 1;
4470

4471
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4472
               {
4473
                  if ((*sp & 0xffU) == gray)
A
Andreas Dilger 已提交
4474
                     *dp-- = 0;
4475

A
Andreas Dilger 已提交
4476 4477
                  else
                     *dp-- = 0xff;
4478

A
Andreas Dilger 已提交
4479
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4480
               }
A
Andreas Dilger 已提交
4481
            }
4482

A
Andreas Dilger 已提交
4483 4484
            else if (row_info->bit_depth == 16)
            {
4485 4486
               unsigned int gray_high = (gray >> 8) & 0xff;
               unsigned int gray_low = gray & 0xff;
A
Andreas Dilger 已提交
4487 4488
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4489
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4490
               {
4491 4492
                  if ((*(sp - 1) & 0xffU) == gray_high &&
                      (*(sp) & 0xffU) == gray_low)
A
Andreas Dilger 已提交
4493 4494 4495 4496
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4497

A
Andreas Dilger 已提交
4498 4499 4500 4501 4502
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4503

A
Andreas Dilger 已提交
4504 4505
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4506 4507
               }
            }
4508

A
Andreas Dilger 已提交
4509 4510
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
4511
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4512
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
4513
                row_width);
G
Guy Schalnat 已提交
4514 4515
         }
      }
4516 4517
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
          trans_color != NULL)
G
Guy Schalnat 已提交
4518 4519 4520
      {
         if (row_info->bit_depth == 8)
         {
4521 4522 4523
            png_byte red = (png_byte)(trans_color->red & 0xff);
            png_byte green = (png_byte)(trans_color->green & 0xff);
            png_byte blue = (png_byte)(trans_color->blue & 0xff);
G
Guy Schalnat 已提交
4524
            sp = row + (png_size_t)row_info->rowbytes - 1;
4525
            dp = row + ((png_size_t)row_width << 2) - 1;
4526
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4527
            {
4528
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
4529
                  *dp-- = 0;
4530

G
Guy Schalnat 已提交
4531 4532
               else
                  *dp-- = 0xff;
4533

G
Guy Schalnat 已提交
4534 4535 4536 4537 4538 4539 4540
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
4541 4542 4543 4544 4545 4546
            png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
            png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
            png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
            png_byte red_low = (png_byte)(trans_color->red & 0xff);
            png_byte green_low = (png_byte)(trans_color->green & 0xff);
            png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
A
Andreas Dilger 已提交
4547
            sp = row + row_info->rowbytes - 1;
4548
            dp = row + ((png_size_t)row_width << 3) - 1;
4549
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4550
            {
4551
               if (*(sp - 5) == red_high &&
4552 4553 4554 4555 4556
                   *(sp - 4) == red_low &&
                   *(sp - 3) == green_high &&
                   *(sp - 2) == green_low &&
                   *(sp - 1) == blue_high &&
                   *(sp    ) == blue_low)
G
Guy Schalnat 已提交
4557 4558 4559 4560
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4561

G
Guy Schalnat 已提交
4562 4563 4564 4565 4566
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4567

G
Guy Schalnat 已提交
4568 4569 4570 4571
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4572
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4573 4574 4575 4576 4577
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
4578
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4579
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4580 4581 4582
      }
   }
}
G
Guy Schalnat 已提交
4583
#endif
G
Guy Schalnat 已提交
4584

4585
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4586
/* If the bit depth is 8 and the color type is not a palette type expand the
4587 4588
 * whole row to 16 bits.  Has no effect otherwise.
 */
4589
static void
4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
   if (row_info->bit_depth == 8 &&
      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
   {
      /* The row have a sequence of bytes containing [0..255] and we need
       * to turn it into another row containing [0..65535], to do this we
       * calculate:
       *
       *  (input / 255) * 65535
       *
       *  Which happens to be exactly input * 257 and this can be achieved
       *  simply by byte replication in place (copying backwards).
       */
      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
      while (dp > sp)
V
Viktor Szakats 已提交
4607 4608 4609
      {
         dp[-2] = dp[-1] = *--sp; dp -= 2;
      }
4610 4611 4612

      row_info->rowbytes *= 2;
      row_info->bit_depth = 16;
4613
      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4614 4615 4616 4617
   }
}
#endif

4618
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4619
static void
4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709
png_do_quantize(png_row_infop row_info, png_bytep row,
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
{
   png_bytep sp, dp;
   png_uint_32 i;
   png_uint_32 row_width=row_info->width;

   png_debug(1, "in png_do_quantize");

   if (row_info->bit_depth == 8)
   {
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
      {
         int r, g, b, p;
         sp = row;
         dp = row;
         for (i = 0; i < row_width; i++)
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

            /* This looks real messy, but the compiler will reduce
             * it down to a reasonable formula.  For example, with
             * 5 bits per color, we get:
             * p = (((r >> 3) & 0x1f) << 10) |
             *    (((g >> 3) & 0x1f) << 5) |
             *    ((b >> 3) & 0x1f);
             */
            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
                (PNG_QUANTIZE_BLUE_BITS)) |
                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));

            *dp++ = palette_lookup[p];
         }

         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
      }

      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
         palette_lookup != NULL)
      {
         int r, g, b, p;
         sp = row;
         dp = row;
         for (i = 0; i < row_width; i++)
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
                (PNG_QUANTIZE_BLUE_BITS)) |
                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));

            *dp++ = palette_lookup[p];
         }

         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
      }

      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
         quantize_lookup)
      {
         sp = row;

         for (i = 0; i < row_width; i++, sp++)
         {
            *sp = quantize_lookup[*sp];
         }
      }
   }
}
4710
#endif /* READ_QUANTIZE */
4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736

/* Transform the row.  The order of transformations is significant,
 * and is very touchy.  If you add a transformation, take care to
 * decide how it fits in with the other transformations here.
 */
void /* PRIVATE */
png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
   png_debug(1, "in png_do_read_transformations");

   if (png_ptr->row_buf == NULL)
   {
      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
       * error is incredibly rare and incredibly easy to debug without this
       * information.
       */
      png_error(png_ptr, "NULL row buffer");
   }

   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
    * all transformations, however in practice the ROW_INIT always gets done on
    * demand, if necessary.
    */
   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
4737
       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4738 4739 4740 4741 4742 4743 4744 4745 4746
   {
      /* Application has failed to call either png_read_start_image() or
       * png_read_update_info() after setting transforms that expand pixels.
       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
       */
      png_error(png_ptr, "Uninitialized row");
   }

#ifdef PNG_READ_EXPAND_SUPPORTED
4747
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4748 4749 4750 4751 4752 4753 4754 4755 4756
   {
      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
      }

      else
      {
4757 4758
         if (png_ptr->num_trans != 0 &&
             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769
            png_do_expand(row_info, png_ptr->row_buf + 1,
                &(png_ptr->trans_color));

         else
            png_do_expand(row_info, png_ptr->row_buf + 1,
                NULL);
      }
   }
#endif

#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4770 4771 4772 4773
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) == 0 &&
       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4774
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4775
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4776 4777 4778
#endif

#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4779
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4780 4781 4782 4783 4784
   {
      int rgb_error =
          png_do_rgb_to_gray(png_ptr, row_info,
              png_ptr->row_buf + 1);

4785
      if (rgb_error != 0)
4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833
      {
         png_ptr->rgb_to_gray_status=1;
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_WARN)
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");

         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_ERR)
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
 *
 *   In most cases, the "simple transparency" should be done prior to doing
 *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
 *   pixel is transparent.  You would also need to make sure that the
 *   transparency information is upgraded to RGB.
 *
 *   To summarize, the current flow is:
 *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
 *                                   with background "in place" if transparent,
 *                                   convert to RGB if necessary
 *   - Gray + alpha -> composite with gray background and remove alpha bytes,
 *                                   convert to RGB if necessary
 *
 *   To support RGB backgrounds for gray images we need:
 *   - Gray + simple transparency -> convert to RGB + simple transparency,
 *                                   compare 3 or 6 bytes and composite with
 *                                   background "in place" if transparent
 *                                   (3x compare/pixel compared to doing
 *                                   composite with gray bkgrnd)
 *   - Gray + alpha -> convert to RGB + alpha, composite with background and
 *                                   remove alpha bytes (3x float
 *                                   operations/pixel compared with composite
 *                                   on gray background)
 *
 *  Greg's change will do this.  The reason it wasn't done before is for
 *  performance, as this increases the per-pixel operations.  If we would check
 *  in advance if the background was gray or RGB, and position the gray-to-RGB
 *  transform appropriately, then it would save a lot of work/time.
 */

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /* If gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons
    */
4834 4835
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4836 4837 4838 4839 4840
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4841
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4842 4843
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4844

4845
#ifdef PNG_READ_GAMMA_SUPPORTED
4846
   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4847 4848
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
      /* Because RGB_TO_GRAY does the gamma transform. */
4849
      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4850 4851 4852 4853 4854 4855
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
      /* Because PNG_COMPOSE does the gamma transform if there is something to
       * do (if there is an alpha channel or transparency.)
       */
4856
       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4857
       ((png_ptr->num_trans != 0) ||
4858
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4859 4860 4861 4862 4863 4864 4865
#endif
      /* Because png_init_read_transformations transforms the palette, unless
       * RGB_TO_GRAY will do the transform.
       */
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
4866

4867
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4868 4869 4870 4871
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4872
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4873
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4874
#endif
G
Guy Schalnat 已提交
4875

4876
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4877 4878
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4879 4880
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4881

4882
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
4883
   if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
4884 4885
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
#endif
4886

4887 4888 4889 4890 4891
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
   /* There is no harm in doing both of these because only one has any effect,
    * by putting the 'scale' option first if the app asks for scale (either by
    * calling the API or in a TRANSFORM flag) this is what happens.
    */
4892
   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4893 4894
      png_do_chop(row_info, png_ptr->row_buf + 1);
#endif
4895

4896
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4897
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4898 4899 4900
   {
      png_do_quantize(row_info, png_ptr->row_buf + 1,
          png_ptr->palette_lookup, png_ptr->quantize_index);
G
Guy Schalnat 已提交
4901

4902 4903 4904
      if (row_info->rowbytes == 0)
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
   }
4905
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
4906

4907 4908 4909 4910 4911 4912
#ifdef PNG_READ_EXPAND_16_SUPPORTED
   /* Do the expansion now, after all the arithmetic has been done.  Notice
    * that previous transformations can handle the PNG_EXPAND_16 flag if this
    * is efficient (particularly true in the case of gamma correction, where
    * better accuracy results faster!)
    */
4913
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4914 4915
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
#endif
4916

4917 4918
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
4919 4920
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
4921 4922
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
4923

4924
#ifdef PNG_READ_INVERT_SUPPORTED
4925
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4926 4927
      png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
4928

4929
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
4930
   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
4931 4932 4933
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif

4934
#ifdef PNG_READ_SHIFT_SUPPORTED
4935
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4936 4937 4938
      png_do_unshift(row_info, png_ptr->row_buf + 1,
          &(png_ptr->shift));
#endif
G
Guy Schalnat 已提交
4939

4940
#ifdef PNG_READ_PACK_SUPPORTED
4941
   if ((png_ptr->transformations & PNG_PACK) != 0)
4942 4943
      png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
4944

4945 4946 4947 4948 4949 4950
#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
   /* Added at libpng-1.5.10 */
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
       png_ptr->num_palette_max >= 0)
      png_do_check_palette_indexes(png_ptr, row_info);
#endif
4951

4952
#ifdef PNG_READ_BGR_SUPPORTED
4953
   if ((png_ptr->transformations & PNG_BGR) != 0)
4954 4955
      png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
4956

4957
#ifdef PNG_READ_PACKSWAP_SUPPORTED
4958
   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4959 4960
      png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
4961

4962
#ifdef PNG_READ_FILLER_SUPPORTED
4963
   if ((png_ptr->transformations & PNG_FILLER) != 0)
4964 4965 4966
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif
4967

4968
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
4969
   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
4970 4971
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
4972

4973 4974
#ifdef PNG_READ_16BIT_SUPPORTED
#ifdef PNG_READ_SWAP_SUPPORTED
4975
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
4976 4977 4978
      png_do_swap(row_info, png_ptr->row_buf + 1);
#endif
#endif
4979

4980
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
4981
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
4982
   {
4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994
      if (png_ptr->read_user_transform_fn != NULL)
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
             (png_ptr,     /* png_ptr */
             row_info,     /* row_info: */
                /*  png_uint_32 width;       width of row */
                /*  png_size_t rowbytes;     number of bytes in row */
                /*  png_byte color_type;     color type of pixels */
                /*  png_byte bit_depth;      bit depth of samples */
                /*  png_byte channels;       number of channels (1-4) */
                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
             png_ptr->row_buf + 1);    /* start of pixel data for row */
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
4995
      if (png_ptr->user_transform_depth != 0)
4996
         row_info->bit_depth = png_ptr->user_transform_depth;
4997

4998
      if (png_ptr->user_transform_channels != 0)
4999 5000
         row_info->channels = png_ptr->user_transform_channels;
#endif
5001 5002
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
5003

5004
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
5005
   }
5006
#endif
5007
}
5008

5009 5010
#endif /* READ_TRANSFORMS */
#endif /* READ */