pngrtran.c 164.5 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.19 [November 12, 2015]
5
 * Copyright (c) 1998-2002,2004,2006-2015 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 51
         png_warning(png_ptr,
            "Can't discard critical data on CRC error");
52
      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
53

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

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

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

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

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

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

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

91 92 93
#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
94 95
 * to have been read in all cases; the need_IHDR parameter allows for this
 * check too.
96 97 98 99 100 101
 */
static int
png_rtran_ok(png_structrp png_ptr, int need_IHDR)
{
   if (png_ptr != NULL)
   {
102
      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
         png_app_error(png_ptr,
            "invalid after png_start_read_image or png_read_update_info");

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

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

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

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

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

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
155
png_set_background(png_structrp png_ptr,
156
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
157 158 159 160 161 162 163
    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"));
}
#  endif  /* FLOATING_POINT */
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
164

165 166 167 168 169
/* 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
170
void PNGAPI
171
png_set_scale_16(png_structrp png_ptr)
G
Guy Schalnat 已提交
172
{
173
   png_debug(1, "in png_set_scale_16");
174

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

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

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

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

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

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

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

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

209 210
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
static png_fixed_point
211
translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
   int is_screen)
{
   /* 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;
227 228
#     else
         PNG_UNUSED(png_ptr)
229
#     endif
230
      if (is_screen != 0)
231 232 233 234 235 236 237 238
         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)
   {
239
      if (is_screen != 0)
240 241 242 243 244 245 246 247 248 249
         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
250
convert_gamma_value(png_structrp png_ptr, double output_gamma)
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
{
   /* 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 */

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

   png_debug(1, "in png_set_alpha_mode");

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

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

288
   /* Validate the value to ensure it is in a reasonable range. The value
289 290 291 292 293
    * 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
    * values are reasonable this may have to be changed.
    */
294
   if (output_gamma < 70000 || output_gamma > 300000)
295
      png_error(png_ptr, "output gamma out of expected range");
296

297
   /* The default file gamma is the inverse of the output gamma; the output
298 299 300 301 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
    * 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.)
    */
355 356 357 358 359
   if (png_ptr->colorspace.gamma == 0)
   {
      png_ptr->colorspace.gamma = file_gamma;
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   }
360 361 362 363

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

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

375
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
376 377 378 379 380 381 382 383 384
         png_error(png_ptr,
            "conflicting calls to set alpha mode and background");

      png_ptr->transformations |= PNG_COMPOSE;
   }
}

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
385
png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
386
{
387 388
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
      output_gamma));
389 390 391 392
}
#  endif
#endif

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

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
404
{
405
   struct png_dsort_struct * next;
G
Guy Schalnat 已提交
406 407
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
408
} png_dsort;
409 410
typedef png_dsort *   png_dsortp;
typedef png_dsort * * png_dsortpp;
G
Guy Schalnat 已提交
411

412
void PNGAPI
413
png_set_quantize(png_structrp png_ptr, png_colorp palette,
414
    int num_palette, int maximum_colors, png_const_uint_16p histogram,
415
    int full_quantize)
G
Guy Schalnat 已提交
416
{
417
   png_debug(1, "in png_set_quantize");
418

419
   if (png_rtran_ok(png_ptr, 0) == 0)
420
      return;
421

422
   png_ptr->transformations |= PNG_QUANTIZE;
G
Guy Schalnat 已提交
423

424
   if (full_quantize == 0)
G
Guy Schalnat 已提交
425 426 427
   {
      int i;

428
      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
429
          (png_uint_32)(num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
430
      for (i = 0; i < num_palette; i++)
431
         png_ptr->quantize_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
432 433 434 435
   }

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

         int i;

444
         /* Initialize an array to sort colors */
445
         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
446
             (png_uint_32)(num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
447

448
         /* Initialize the quantize_sort array */
G
Guy Schalnat 已提交
449
         for (i = 0; i < num_palette; i++)
450
            png_ptr->quantize_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
451

A
Andreas Dilger 已提交
452
         /* Find the least used palette entries by starting a
453 454 455 456 457
          * 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 已提交
458 459 460

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

            done = 1;
            for (j = 0; j < i; j++)
            {
467 468
               if (histogram[png_ptr->quantize_sort[j]]
                   < histogram[png_ptr->quantize_sort[j + 1]])
G
Guy Schalnat 已提交
469 470 471
               {
                  png_byte t;

472 473 474
                  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 已提交
475 476 477
                  done = 0;
               }
            }
478

479
            if (done != 0)
G
Guy Schalnat 已提交
480 481 482
               break;
         }

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

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

G
Guy Schalnat 已提交
499 500
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
501
            }
G
Guy Schalnat 已提交
502 503 504
         }
         else
         {
505
            int j = num_palette;
G
Guy Schalnat 已提交
506

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

                  do
                     j--;
519
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
520 521 522 523

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

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

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

A
Andreas Dilger 已提交
544
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
545 546 547 548

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
549
                        min_k = k;
G
Guy Schalnat 已提交
550 551
                     }
                  }
552
                  /* Point to closest color */
553
                  png_ptr->quantize_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
554 555 556
               }
            }
         }
557 558
         png_free(png_ptr, png_ptr->quantize_sort);
         png_ptr->quantize_sort = NULL;
G
Guy Schalnat 已提交
559 560 561
      }
      else
      {
A
Andreas Dilger 已提交
562
         /* This is much harder to do simply (and quickly).  Perhaps
563 564 565 566 567 568 569
          * 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 已提交
570 571 572
         int i;
         int max_d;
         int num_new_palette;
573
         png_dsortp t;
G
Guy Schalnat 已提交
574
         png_dsortpp hash;
575

576
         t = NULL;
G
Guy Schalnat 已提交
577

578
         /* Initialize palette index arrays */
579
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
580
             (png_uint_32)(num_palette * (sizeof (png_byte))));
581
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
582
             (png_uint_32)(num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
583

584
         /* Initialize the sort array */
G
Guy Schalnat 已提交
585 586
         for (i = 0; i < num_palette; i++)
         {
587 588
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
589 590
         }

591
         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
592
             (sizeof (png_dsortp))));
G
Guy Schalnat 已提交
593 594 595

         num_new_palette = num_palette;

596 597 598 599 600 601 602 603
         /* 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 已提交
604 605
         max_d = 96;

G
Guy Schalnat 已提交
606
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
607 608 609 610 611 612 613 614 615
         {
            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 已提交
616
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
617 618 619 620

                  if (d <= max_d)
                  {

621
                     t = (png_dsortp)png_malloc_warn(png_ptr,
622
                         (png_uint_32)(sizeof (png_dsort)));
623

624 625
                     if (t == NULL)
                         break;
626

G
Guy Schalnat 已提交
627
                     t->next = hash[d];
G
Guy Schalnat 已提交
628 629
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
630 631 632
                     hash[d] = t;
                  }
               }
633 634
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
635 636
            }

637
            if (t != NULL)
G
Guy Schalnat 已提交
638 639
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
640
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
641
               {
G
Guy Schalnat 已提交
642
                  png_dsortp p;
G
Guy Schalnat 已提交
643 644 645

                  for (p = hash[i]; p; p = p->next)
                  {
646
                     if ((int)png_ptr->index_to_palette[p->left]
647 648 649
                         < num_new_palette &&
                         (int)png_ptr->index_to_palette[p->right]
                         < num_new_palette)
G
Guy Schalnat 已提交
650 651 652
                     {
                        int j, next_j;

653
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
654 655 656 657 658 659 660 661 662 663 664
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
665
                        palette[png_ptr->index_to_palette[j]]
666
                            = palette[num_new_palette];
667
                        if (full_quantize == 0)
G
Guy Schalnat 已提交
668 669 670 671 672
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
673
                              if (png_ptr->quantize_index[k] ==
674
                                  png_ptr->index_to_palette[j])
675
                                 png_ptr->quantize_index[k] =
676
                                     png_ptr->index_to_palette[next_j];
677

678
                              if ((int)png_ptr->quantize_index[k] ==
679
                                  num_new_palette)
680
                                 png_ptr->quantize_index[k] =
681
                                     png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
682 683 684
                           }
                        }

685
                        png_ptr->index_to_palette[png_ptr->palette_to_index
686
                            [num_new_palette]] = png_ptr->index_to_palette[j];
687

688
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
689
                            = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
690

691 692
                        png_ptr->index_to_palette[j] =
                            (png_byte)num_new_palette;
693

694 695
                        png_ptr->palette_to_index[num_new_palette] =
                            (png_byte)j;
G
Guy Schalnat 已提交
696 697 698 699 700 701 702 703 704 705 706
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

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

735
   if (full_quantize != 0)
G
Guy Schalnat 已提交
736 737
   {
      int i;
G
Guy Schalnat 已提交
738
      png_bytep distance;
739 740 741 742 743
      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);
744
      png_size_t num_entries = ((png_size_t)1 << total_bits);
G
Guy Schalnat 已提交
745

746
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
747
          (png_uint_32)(num_entries * (sizeof (png_byte))));
748

749
      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
750
          (sizeof (png_byte))));
751

752
      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
753 754 755

      for (i = 0; i < num_palette; i++)
      {
756
         int ir, ig, ib;
757 758 759
         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 已提交
760 761 762

         for (ir = 0; ir < num_red; ir++)
         {
763 764
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
765 766
            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
                PNG_QUANTIZE_GREEN_BITS));
G
Guy Schalnat 已提交
767 768

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
769
            {
770 771
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
772 773
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
774
               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
G
Guy Schalnat 已提交
775 776

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
777
               {
778
                  int d_index = index_g | ib;
779 780
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
781 782
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
783

784
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
785
                  {
A
Andreas Dilger 已提交
786 787
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
788 789
                  }
               }
790 791 792
            }
         }
      }
G
Guy Schalnat 已提交
793

A
Andreas Dilger 已提交
794
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
795 796
   }
}
797
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
798

G
[devel]  
Glenn Randers-Pehrson 已提交
799 800
#ifdef PNG_READ_GAMMA_SUPPORTED
void PNGFAPI
801
png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
G
[devel]  
Glenn Randers-Pehrson 已提交
802 803 804
   png_fixed_point file_gamma)
{
   png_debug(1, "in png_set_gamma_fixed");
805

806
   if (png_rtran_ok(png_ptr, 0) == 0)
807
      return;
808

809
   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
810 811 812
   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);

813
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
814 815 816
    * 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
817
    * was being used; however, png_set_background itself accepted and must still
818 819 820
    * 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
821 822
    * undocumented API feature) the following checks were only enabled in
    * libpng-1.6.0.
823 824
    */
   if (file_gamma <= 0)
825
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
826 827

   if (scrn_gamma <= 0)
828
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
829 830 831 832 833

   /* 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.
    */
834 835
   png_ptr->colorspace.gamma = file_gamma;
   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
G
[devel]  
Glenn Randers-Pehrson 已提交
836
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
837
}
G
[devel]  
Glenn Randers-Pehrson 已提交
838 839 840

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
841
png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
842
{
843 844
   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
      convert_gamma_value(png_ptr, file_gamma));
G
[devel]  
Glenn Randers-Pehrson 已提交
845
}
846
#  endif /* FLOATING_POINT */
G
[devel]  
Glenn Randers-Pehrson 已提交
847
#endif /* READ_GAMMA */
G
Guy Schalnat 已提交
848

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

859
   if (png_rtran_ok(png_ptr, 0) == 0)
860
      return;
861

862
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
G
Guy Schalnat 已提交
863
}
864 865 866 867 868 869 870 871 872 873 874 875 876

/* 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.
877
 *
878 879 880
 *  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().
881 882 883
 */

/* Expand paletted images to RGB. */
884
void PNGAPI
885
png_set_palette_to_rgb(png_structrp png_ptr)
886
{
887
   png_debug(1, "in png_set_palette_to_rgb");
888

889
   if (png_rtran_ok(png_ptr, 0) == 0)
890
      return;
891

892 893 894 895 896
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
}

/* Expand grayscale images of less than 8-bit depth to 8 bits. */
void PNGAPI
897
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
898
{
899
   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
900

901
   if (png_rtran_ok(png_ptr, 0) == 0)
902
      return;
903

904
   png_ptr->transformations |= PNG_EXPAND;
905 906 907
}

/* Expand tRNS chunks to alpha channels. */
908
void PNGAPI
909
png_set_tRNS_to_alpha(png_structrp png_ptr)
910
{
911
   png_debug(1, "in png_set_tRNS_to_alpha");
912

913
   if (png_rtran_ok(png_ptr, 0) == 0)
914 915
      return;

916
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
917
}
918
#endif /* READ_EXPAND */
G
Guy Schalnat 已提交
919

920
#ifdef PNG_READ_EXPAND_16_SUPPORTED
921
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
922 923 924
 * it may not work correctly.)
 */
void PNGAPI
925
png_set_expand_16(png_structrp png_ptr)
926 927 928
{
   png_debug(1, "in png_set_expand_16");

929
   if (png_rtran_ok(png_ptr, 0) == 0)
930 931 932 933 934 935
      return;

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

936
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
937
void PNGAPI
938
png_set_gray_to_rgb(png_structrp png_ptr)
G
Guy Schalnat 已提交
939
{
940
   png_debug(1, "in png_set_gray_to_rgb");
941

942
   if (png_rtran_ok(png_ptr, 0) == 0)
943 944 945 946 947
      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 已提交
948
}
G
Guy Schalnat 已提交
949
#endif
G
Guy Schalnat 已提交
950

951
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
952
void PNGFAPI
953
png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
954
    png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
955
{
956
   png_debug(1, "in png_set_rgb_to_gray");
957

958 959
   /* Need the IHDR here because of the check on color_type below. */
   /* TODO: fix this */
960
   if (png_rtran_ok(png_ptr, 1) == 0)
961
      return;
962

963
   switch (error_action)
964
   {
965
      case PNG_ERROR_ACTION_NONE:
966 967
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
         break;
968

969
      case PNG_ERROR_ACTION_WARN:
970 971
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
972

973
      case PNG_ERROR_ACTION_ERROR:
974
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
975 976 977
         break;

      default:
978
         png_error(png_ptr, "invalid error action to rgb_to_gray");
979
   }
980

981
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
982
#ifdef PNG_READ_EXPAND_SUPPORTED
983 984 985
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
986 987 988 989
      /* 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,
990
        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
991

992
      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
993 994 995
   }
#endif
   {
996
      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
997
      {
998
         png_uint_16 red_int, green_int;
999

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

         png_ptr->rgb_to_gray_red_coeff   = red_int;
         png_ptr->rgb_to_gray_green_coeff = green_int;
1010
         png_ptr->rgb_to_gray_coefficients_set = 1;
1011
      }
1012

1013
      else
1014
      {
1015
         if (red >= 0 && green >= 0)
1016
            png_app_warning(png_ptr,
1017
               "ignoring out of range rgb_to_gray coefficients");
1018

1019 1020 1021 1022 1023
         /* 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.
1024 1025
          */
         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
1026
            png_ptr->rgb_to_gray_green_coeff == 0)
1027
         {
1028 1029 1030
            png_ptr->rgb_to_gray_red_coeff   = 6968;
            png_ptr->rgb_to_gray_green_coeff = 23434;
            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1031 1032
         }
      }
1033
   }
A
Andreas Dilger 已提交
1034
}
1035 1036 1037 1038 1039 1040 1041

#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
1042
png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
G
[devel]  
Glenn Randers-Pehrson 已提交
1043
   double green)
1044
{
G
[devel]  
Glenn Randers-Pehrson 已提交
1045 1046 1047
   png_set_rgb_to_gray_fixed(png_ptr, error_action,
      png_fixed(png_ptr, red, "rgb to gray red coefficient"),
      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1048 1049 1050
}
#endif /* FLOATING POINT */

1051
#endif /* RGB_TO_GRAY */
A
Andreas Dilger 已提交
1052

1053
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1054
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1055
void PNGAPI
1056
png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1057
    read_user_transform_fn)
1058
{
1059
   png_debug(1, "in png_set_read_user_transform_fn");
1060

1061
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1062 1063
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1064
#endif
1065 1066 1067
}
#endif

1068
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
#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 已提交
1090
/* Initialize everything needed for the read.  This includes modifying
1091 1092
 * the palette.
 */
1093

1094
/* For the moment 'png_init_palette_transformations' and
1095 1096 1097 1098 1099
 * '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 */
1100
png_init_palette_transformations(png_structrp png_ptr)
G
Guy Schalnat 已提交
1101
{
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
   /* 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;
1112

1113 1114 1115 1116 1117 1118
   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)
1119
      {
1120 1121 1122 1123 1124
         if (png_ptr->trans_alpha[i] == 255)
            continue;
         else if (png_ptr->trans_alpha[i] == 0)
            input_has_transparency = 1;
         else
1125 1126
         {
            input_has_transparency = 1;
1127
            input_has_alpha = 1;
1128 1129 1130
            break;
         }
      }
1131 1132 1133
   }

   /* If no alpha we can optimize. */
1134
   if (input_has_alpha == 0)
1135 1136
   {
      /* Any alpha means background and associative alpha processing is
1137
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1138 1139 1140 1141 1142
       * and ENCODE_ALPHA are irrelevant.
       */
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

1143
      if (input_has_transparency == 0)
1144 1145
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
   }
G
Guy Schalnat 已提交
1146

G
Guy Schalnat 已提交
1147
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1148 1149 1150 1151
   /* 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.
    */
1152

1153 1154
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1155
    */
1156 1157
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) != 0)
1158
   {
1159 1160 1161 1162 1163 1164 1165 1166 1167
      {
         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
1168
        if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1169
        {
1170
           if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1171 1172 1173 1174 1175 1176 1177
           {
              /* 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++)
1178 1179
                 png_ptr->trans_alpha[i] = (png_byte)(255 -
                    png_ptr->trans_alpha[i]);
1180 1181
           }
        }
1182
#endif /* READ_INVERT_ALPHA */
1183 1184
      }
   } /* background expand and (therefore) no alpha association. */
1185
#endif /* READ_EXPAND && READ_BACKGROUND */
1186 1187 1188
}

static void /* PRIVATE */
1189
png_init_rgb_transformations(png_structrp png_ptr)
1190
{
1191
   /* Added to libpng-1.5.4: check the color type to determine whether there
1192 1193 1194 1195 1196
    * 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;
1197

1198
   /* If no alpha we can optimize. */
1199
   if (input_has_alpha == 0)
1200
   {
1201
      /* Any alpha means background and associative alpha processing is
1202
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1203 1204 1205 1206 1207 1208 1209
       * 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

1210
      if (input_has_transparency == 0)
1211
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1212 1213
   }

1214 1215 1216 1217 1218 1219 1220 1221 1222
#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.
    */
1223 1224 1225
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) != 0 &&
       (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1226
       /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
1227 1228
   {
      {
1229
         /* Expand background and tRNS chunks */
1230 1231 1232
         int gray = png_ptr->background.gray;
         int trans_gray = png_ptr->trans_color.gray;

G
Guy Schalnat 已提交
1233 1234 1235
         switch (png_ptr->bit_depth)
         {
            case 1:
1236 1237
               gray *= 0xff;
               trans_gray *= 0xff;
G
Guy Schalnat 已提交
1238
               break;
1239

G
Guy Schalnat 已提交
1240
            case 2:
1241 1242
               gray *= 0x55;
               trans_gray *= 0x55;
G
Guy Schalnat 已提交
1243
               break;
1244

G
Guy Schalnat 已提交
1245
            case 4:
1246 1247
               gray *= 0x11;
               trans_gray *= 0x11;
G
Guy Schalnat 已提交
1248
               break;
1249

1250 1251
            default:

G
Guy Schalnat 已提交
1252
            case 8:
1253
               /* FALL THROUGH (Already 8 bits) */
1254

G
Guy Schalnat 已提交
1255
            case 16:
1256
               /* Already a full 16 bits */
G
Guy Schalnat 已提交
1257 1258
               break;
         }
1259 1260 1261 1262

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

1263
         if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1264 1265 1266 1267
         {
            png_ptr->trans_color.red = png_ptr->trans_color.green =
               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
         }
G
Guy Schalnat 已提交
1268
      }
1269
   } /* background expand and (therefore) no alpha association. */
1270
#endif /* READ_EXPAND && READ_BACKGROUND */
1271
}
1272

1273
void /* PRIVATE */
1274
png_init_read_transformations(png_structrp png_ptr)
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
{
   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
1287
   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1288
    * png_set_alpha_mode and this is another source for a default file gamma so
1289
    * the test needs to be performed later - here.  In addition prior to 1.5.4
1290 1291 1292 1293 1294 1295 1296 1297
    * 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;
1298

1299
      if (png_ptr->colorspace.gamma != 0) /* has been set */
1300 1301
      {
         if (png_ptr->screen_gamma != 0) /* screen set too */
1302
            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1303 1304 1305 1306 1307 1308
               png_ptr->screen_gamma);

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

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

      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,
1324
          * prior to 1.5.4
1325
          */
1326 1327 1328 1329
         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;
1330 1331 1332 1333 1334 1335 1336 1337 1338

      /* 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.
       */
1339
      if (gamma_correction != 0)
1340 1341 1342 1343
         png_ptr->transformations |= PNG_GAMMA;

      else
         png_ptr->transformations &= ~PNG_GAMMA;
G
Guy Schalnat 已提交
1344
   }
G
Guy Schalnat 已提交
1345
#endif
G
Guy Schalnat 已提交
1346

1347
   /* Certain transformations have the effect of preventing other
1348
    * transformations that happen afterward in png_do_read_transformations;
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
    * 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
1360 1361 1362 1363 1364 1365
    *  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
1366 1367 1368 1369 1370 1371
    * 15) PNG_INVERT_ALPHA
    * 16) PNG_SHIFT
    * 17) PNG_PACK
    * 18) PNG_BGR
    * 19) PNG_PACKSWAP
    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1372 1373 1374
    * 21) PNG_SWAP_ALPHA
    * 22) PNG_SWAP_BYTES
    * 23) PNG_USER_TRANSFORM [must be last]
1375 1376
    */
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1377 1378
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) == 0)
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
   {
      /* 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;

1389
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1390 1391 1392 1393
       * 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
1394
       * get.)  This makes the behavior consistent from 1.5.4:
1395 1396 1397 1398 1399 1400 1401 1402 1403
       */
      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.
    */
1404
   if (png_gamma_significant(png_ptr->screen_gamma) == 0)
1405 1406 1407 1408
   {
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   }
G
Guy Schalnat 已提交
1409
#endif
1410

1411 1412 1413 1414
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
   /* Make sure the coefficients for the rgb to gray conversion are set
    * appropriately.
    */
1415
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1416 1417 1418 1419 1420
      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)
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
   /* 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.
    *
1431
    * TODO: this code needs to be revised to avoid the complexity and
1432 1433 1434 1435
    * 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.
    */
1436
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1437 1438
   {
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1439
       * the file was grayscale the background value is gray.
1440
       */
1441
      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1442 1443 1444
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

1445
   else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1446
   {
1447 1448 1449 1450 1451
      /* 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.
       */
1452
      if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
1453
      {
1454 1455 1456 1457 1458 1459
         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;
         }
1460
      }
1461
   }
1462 1463
#endif /* READ_EXPAND && READ_BACKGROUND */
#endif /* READ_GRAY_TO_RGB */
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477

   /* 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);
1478

1479 1480 1481
   else
      png_init_rgb_transformations(png_ptr);

1482 1483
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   defined(PNG_READ_EXPAND_16_SUPPORTED)
1484 1485 1486 1487
   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)
1488 1489 1490
   {
      /* 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
1491
       * application will supply a 16-bit value so reduce it here.
1492 1493 1494
       *
       * 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.)
1495 1496 1497
       *
       * NOTE: this discards the low 16 bits of the user supplied background
       * color, but until expand_16 works properly there is no choice!
1498
       */
1499
#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1500 1501 1502 1503
      CHOP(png_ptr->background.red);
      CHOP(png_ptr->background.green);
      CHOP(png_ptr->background.blue);
      CHOP(png_ptr->background.gray);
1504 1505
#     undef CHOP
   }
1506
#endif /* READ_BACKGROUND && READ_EXPAND_16 */
1507

1508 1509 1510
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
1511 1512 1513 1514
   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)
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
   {
      /* 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

1530 1531 1532 1533
   /* 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
1534
    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
    * 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.
    *
1553
    * In 1.5.4 this is addressed below by an additional check on the individual
1554 1555 1556
    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
    * tables.
    */
1557 1558 1559 1560 1561 1562 1563
   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
1564
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1565 1566
         || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
           png_gamma_significant(png_ptr->background_gamma) != 0)
1567
#  endif
1568 1569
        )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       png_gamma_significant(png_ptr->screen_gamma) != 0))
G
Guy Schalnat 已提交
1570
   {
1571
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1572

1573
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1574
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
G
Guy Schalnat 已提交
1575
      {
1576 1577 1578 1579 1580 1581
         /* 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.
          */
1582
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1583 1584 1585
            png_warning(png_ptr,
               "libpng does not support gamma+background+rgb_to_gray");

1586
         if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
G
Guy Schalnat 已提交
1587
         {
1588 1589 1590
            /* 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 已提交
1591
            png_color back, back_1;
1592 1593 1594
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1595 1596
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1597

A
Andreas Dilger 已提交
1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
               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 已提交
1608
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1609

1610 1611 1612 1613
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
G
[devel]  
Glenn Randers-Pehrson 已提交
1614
                     gs = PNG_FP_1;
1615
                     break;
1616

1617
                  case PNG_BACKGROUND_GAMMA_FILE:
1618 1619
                     g = png_reciprocal(png_ptr->colorspace.gamma);
                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
1620
                        png_ptr->screen_gamma);
1621
                     break;
1622

1623
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1624 1625
                     g = png_reciprocal(png_ptr->background_gamma);
                     gs = png_reciprocal2(png_ptr->background_gamma,
1626
                        png_ptr->screen_gamma);
1627 1628
                     break;
                  default:
G
[devel]  
Glenn Randers-Pehrson 已提交
1629 1630
                     g = PNG_FP_1;    /* back_1 */
                     gs = PNG_FP_1;   /* back */
1631
                     break;
1632
               }
A
Andreas Dilger 已提交
1633

1634
               if (png_gamma_significant(gs) != 0)
1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
               {
                  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 已提交
1645
               {
1646
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1647
                  back.green = (png_byte)png_ptr->background.green;
1648
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1649
               }
1650

1651
               if (png_gamma_significant(g) != 0)
1652 1653 1654 1655 1656 1657 1658 1659 1660
               {
                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
                     g);
                  back_1.green = png_gamma_8bit_correct(
                     png_ptr->background.green, g);
                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
                     g);
               }

A
Andreas Dilger 已提交
1661 1662
               else
               {
1663 1664 1665
                  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 已提交
1666 1667
               }
            }
1668

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

                     v = png_ptr->gamma_to_1[palette[i].red];
1683
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
1684 1685 1686
                     palette[i].red = png_ptr->gamma_from_1[w];

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

                     v = png_ptr->gamma_to_1[palette[i].blue];
1691
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701
                     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];
               }
            }
1702 1703 1704

            /* Prevent the transformations being done again.
             *
1705
             * NOTE: this is highly dubious; it removes the transformations in
1706 1707
             * place.  This seems inconsistent with the general treatment of the
             * transformations elsewhere.
1708
             */
1709 1710
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1711

1712
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1713
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1714
         {
1715 1716 1717
            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 已提交
1718 1719

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1720
            {
G
Guy Schalnat 已提交
1721
               case PNG_BACKGROUND_GAMMA_SCREEN:
G
[devel]  
Glenn Randers-Pehrson 已提交
1722 1723
                  g = png_ptr->screen_gamma;
                  /* gs = PNG_FP_1; */
G
Guy Schalnat 已提交
1724
                  break;
1725

G
Guy Schalnat 已提交
1726
               case PNG_BACKGROUND_GAMMA_FILE:
1727 1728 1729
                  g = png_reciprocal(png_ptr->colorspace.gamma);
                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
                     png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1730
                  break;
1731

G
Guy Schalnat 已提交
1732
               case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1733 1734
                  g = png_reciprocal(png_ptr->background_gamma);
                  gs = png_reciprocal2(png_ptr->background_gamma,
1735
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1736
                  break;
1737 1738

               default:
1739
                  png_error(png_ptr, "invalid background gamma type");
G
Guy Schalnat 已提交
1740 1741
            }

1742 1743
            g_sig = png_gamma_significant(g);
            gs_sig = png_gamma_significant(gs);
1744

1745
            if (g_sig != 0)
1746 1747 1748
               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, g);

1749
            if (gs_sig != 0)
1750 1751
               png_ptr->background.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, gs);
1752

1753 1754 1755
            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 已提交
1756
            {
1757
               /* RGB or RGBA with color background */
1758
               if (g_sig != 0)
1759 1760 1761
               {
                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, g);
1762

1763 1764
                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, g);
1765

1766 1767 1768
                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, g);
               }
1769

1770
               if (gs_sig != 0)
1771 1772 1773
               {
                  png_ptr->background.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, gs);
1774

1775 1776
                  png_ptr->background.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, gs);
1777

1778 1779 1780
                  png_ptr->background.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, gs);
               }
G
Guy Schalnat 已提交
1781
            }
1782

G
Guy Schalnat 已提交
1783 1784
            else
            {
1785 1786
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
1787
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1788

1789
               png_ptr->background.red = png_ptr->background.green
1790
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1791
            }
1792 1793 1794

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

G
Guy Schalnat 已提交
1798
      else
1799
      /* Transformation does not include PNG_BACKGROUND */
1800
#endif /* READ_BACKGROUND */
1801 1802 1803 1804 1805 1806 1807
      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 已提交
1808
      {
1809 1810 1811
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1812

1813 1814
         /* NOTE: there are other transformations that should probably be in
          * here too.
1815
          */
G
Guy Schalnat 已提交
1816 1817 1818 1819 1820 1821
         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];
         }
1822

1823 1824
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
1825
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
G
Guy Schalnat 已提交
1826
   }
1827
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1828
   else
G
Guy Schalnat 已提交
1829
#endif
1830
#endif /* READ_GAMMA */
1831

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

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

1846
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1847
      {
1848
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1849 1850 1851
         {
            palette[i] = back;
         }
1852

1853
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1854
         {
1855
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1856
            png_composite(palette[i].red, palette[i].red,
1857
                png_ptr->trans_alpha[i], back.red);
1858

A
Andreas Dilger 已提交
1859
            png_composite(palette[i].green, palette[i].green,
1860
                png_ptr->trans_alpha[i], back.green);
1861

A
Andreas Dilger 已提交
1862
            png_composite(palette[i].blue, palette[i].blue,
1863
                png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1864 1865
         }
      }
1866

1867
      png_ptr->transformations &= ~PNG_COMPOSE;
G
Guy Schalnat 已提交
1868
   }
1869
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
1870

1871
#ifdef PNG_READ_SHIFT_SUPPORTED
1872 1873
   if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) == 0 &&
1874
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1875
   {
1876 1877 1878
      int i;
      int istop = png_ptr->num_palette;
      int shift = 8 - png_ptr->sig_bit.red;
G
Guy Schalnat 已提交
1879

1880 1881
      png_ptr->transformations &= ~PNG_SHIFT;

1882 1883 1884 1885
      /* 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.)
       */
1886 1887 1888 1889
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].red;
1890

1891 1892 1893
            component >>= shift;
            png_ptr->palette[i].red = (png_byte)component;
         }
1894

1895
      shift = 8 - png_ptr->sig_bit.green;
1896 1897 1898 1899
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].green;
1900

1901 1902 1903
            component >>= shift;
            png_ptr->palette[i].green = (png_byte)component;
         }
1904 1905

      shift = 8 - png_ptr->sig_bit.blue;
1906 1907 1908 1909
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].blue;
1910

1911 1912 1913
            component >>= shift;
            png_ptr->palette[i].blue = (png_byte)component;
         }
G
Guy Schalnat 已提交
1914
   }
1915
#endif  /* READ_SHIFT */
G
Guy Schalnat 已提交
1916 1917
}

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

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

A
Andreas Dilger 已提交
1939 1940
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1941

G
Guy Schalnat 已提交
1942
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1943
         info_ptr->num_trans = 0;
1944 1945 1946

         if (png_ptr->palette == NULL)
            png_error (png_ptr, "Palette is NULL in indexed image");
A
Andreas Dilger 已提交
1947 1948 1949
      }
      else
      {
1950
         if (png_ptr->num_trans != 0)
1951
         {
1952
            if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
1953
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1954
         }
A
Andreas Dilger 已提交
1955 1956
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1957

A
Andreas Dilger 已提交
1958 1959
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1960 1961 1962
   }
#endif

1963 1964 1965 1966 1967
#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!
    */
1968
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
G
Guy Schalnat 已提交
1969 1970 1971
      info_ptr->background = png_ptr->background;
#endif

1972
#ifdef PNG_READ_GAMMA_SUPPORTED
1973
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1974 1975 1976
    * 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.
1977 1978 1979 1980
    *
    * 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.
1981
    */
1982
   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
1983
#endif
1984

1985 1986
   if (info_ptr->bit_depth == 16)
   {
1987
#  ifdef PNG_READ_16BIT_SUPPORTED
1988
#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
1989
         if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
1990 1991 1992 1993
            info_ptr->bit_depth = 8;
#     endif

#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
1994
         if ((png_ptr->transformations & PNG_16_TO_8) != 0)
1995 1996 1997
            info_ptr->bit_depth = 8;
#     endif

1998
#  else
1999
      /* No 16-bit support: force chopping 16-bit input down to 8, in this case
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
       * 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
2011

2012
#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2013 2014 2015 2016 2017 2018
            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
2019
#    endif
2020
#endif /* !READ_16BIT */
2021
   }
G
Guy Schalnat 已提交
2022

2023
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2024
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
2025 2026
      info_ptr->color_type = (png_byte)(info_ptr->color_type |
         PNG_COLOR_MASK_COLOR);
2027 2028
#endif

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

2035
#ifdef PNG_READ_QUANTIZE_SUPPORTED
2036
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
G
Guy Schalnat 已提交
2037 2038
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2039
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2040
          png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
2041 2042 2043
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
2044
   }
G
Guy Schalnat 已提交
2045 2046
#endif

2047
#ifdef PNG_READ_EXPAND_16_SUPPORTED
2048 2049 2050
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
       info_ptr->bit_depth == 8 &&
       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2051 2052 2053 2054 2055
   {
      info_ptr->bit_depth = 16;
   }
#endif

2056
#ifdef PNG_READ_PACK_SUPPORTED
2057 2058
   if ((png_ptr->transformations & PNG_PACK) != 0 &&
       (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
2059 2060 2061
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
2062
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2063
      info_ptr->channels = 1;
2064

2065
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
2066
      info_ptr->channels = 3;
2067

G
Guy Schalnat 已提交
2068 2069
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
2070

2071
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2072
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
2073
   {
2074 2075
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_ALPHA);
2076 2077
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
2078 2079
#endif

2080
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
2081 2082
      info_ptr->channels++;

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

2096 2097
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2098
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2099
   {
J
John Bowler 已提交
2100
      if (png_ptr->user_transform_depth != 0)
2101
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2102

J
John Bowler 已提交
2103
      if (png_ptr->user_transform_channels != 0)
2104
         info_ptr->channels = png_ptr->user_transform_channels;
2105
   }
2106 2107
#endif

2108 2109
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
       info_ptr->bit_depth);
2110

2111
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2112

2113
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2114 2115 2116 2117 2118 2119 2120
    * 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;

2121
#ifndef PNG_READ_EXPAND_SUPPORTED
2122
   if (png_ptr != NULL)
2123 2124
      return;
#endif
G
Guy Schalnat 已提交
2125 2126
}

2127
#ifdef PNG_READ_PACK_SUPPORTED
2128 2129 2130 2131 2132 2133
/* 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.
 */
2134
static void
G
Guy Schalnat 已提交
2135
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2136
{
2137
   png_debug(1, "in png_do_unpack");
2138

A
Andreas Dilger 已提交
2139
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2140
   {
2141
      png_uint_32 i;
2142
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2143

G
Guy Schalnat 已提交
2144 2145 2146 2147
      switch (row_info->bit_depth)
      {
         case 1:
         {
2148 2149
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2150
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2151
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2152
            {
2153
               *dp = (png_byte)((*sp >> shift) & 0x01);
2154

G
Guy Schalnat 已提交
2155 2156 2157 2158
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2159
               }
2160

G
Guy Schalnat 已提交
2161 2162 2163 2164 2165 2166 2167
               else
                  shift++;

               dp--;
            }
            break;
         }
2168

G
Guy Schalnat 已提交
2169 2170 2171
         case 2:
         {

2172 2173
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2174
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2175
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2176
            {
2177
               *dp = (png_byte)((*sp >> shift) & 0x03);
2178

G
Guy Schalnat 已提交
2179 2180 2181 2182 2183
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2184

G
Guy Schalnat 已提交
2185 2186 2187 2188 2189 2190 2191
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2192

G
Guy Schalnat 已提交
2193 2194
         case 4:
         {
2195 2196
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2197
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2198
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2199
            {
2200
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2201

G
Guy Schalnat 已提交
2202 2203 2204 2205 2206
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2207

G
Guy Schalnat 已提交
2208 2209 2210 2211 2212 2213 2214
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2215 2216 2217

         default:
            break;
G
Guy Schalnat 已提交
2218 2219
      }
      row_info->bit_depth = 8;
2220
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2221
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2222 2223
   }
}
G
Guy Schalnat 已提交
2224
#endif
G
Guy Schalnat 已提交
2225

2226
#ifdef PNG_READ_SHIFT_SUPPORTED
2227 2228 2229 2230 2231
/* 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.
 */
2232
static void
2233 2234
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2235
{
2236 2237
   int color_type;

2238
   png_debug(1, "in png_do_unshift");
2239

2240 2241 2242 2243
   /* 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 已提交
2244 2245
   {
      int shift[4];
2246
      int channels = 0;
2247
      int bit_depth = row_info->bit_depth;
G
Guy Schalnat 已提交
2248

2249
      if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
2250
      {
2251 2252 2253
         shift[channels++] = bit_depth - sig_bits->red;
         shift[channels++] = bit_depth - sig_bits->green;
         shift[channels++] = bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2254
      }
2255

G
Guy Schalnat 已提交
2256 2257
      else
      {
2258
         shift[channels++] = bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2259
      }
2260

2261
      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
G
Guy Schalnat 已提交
2262
      {
2263
         shift[channels++] = bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2264
      }
G
Guy Schalnat 已提交
2265

G
Guy Schalnat 已提交
2266
      {
2267
         int c, have_shift;
2268

2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
         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 已提交
2280

2281
         if (have_shift == 0)
2282 2283
            return;
      }
G
Guy Schalnat 已提交
2284

2285
      switch (bit_depth)
G
Guy Schalnat 已提交
2286
      {
2287
         default:
2288 2289
         /* Must be 1bpp gray: should not be here! */
            /* NOTREACHED */
2290
            break;
2291

G
Guy Schalnat 已提交
2292
         case 2:
2293 2294
         /* Must be 2bpp gray */
         /* assert(channels == 1 && shift[0] == 1) */
G
Guy Schalnat 已提交
2295
         {
2296 2297
            png_bytep bp = row;
            png_bytep bp_end = bp + row_info->rowbytes;
A
Andreas Dilger 已提交
2298

2299
            while (bp < bp_end)
G
Guy Schalnat 已提交
2300
            {
2301 2302
               int b = (*bp >> 1) & 0x55;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2303 2304 2305
            }
            break;
         }
2306

G
Guy Schalnat 已提交
2307
         case 4:
2308 2309
         /* Must be 4bpp gray */
         /* assert(channels == 1) */
G
Guy Schalnat 已提交
2310
         {
2311
            png_bytep bp = row;
2312 2313 2314 2315 2316
            png_bytep bp_end = bp + row_info->rowbytes;
            int gray_shift = shift[0];
            int mask =  0xf >> gray_shift;

            mask |= mask << 4;
2317

2318
            while (bp < bp_end)
G
Guy Schalnat 已提交
2319
            {
2320 2321
               int b = (*bp >> gray_shift) & mask;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2322 2323 2324
            }
            break;
         }
2325

G
Guy Schalnat 已提交
2326
         case 8:
2327
         /* Single byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2328
         {
2329
            png_bytep bp = row;
2330 2331
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2332

2333
            while (bp < bp_end)
A
Andreas Dilger 已提交
2334
            {
2335
               int b = *bp >> shift[channel];
2336 2337
               if (++channel >= channels)
                  channel = 0;
2338
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2339 2340 2341
            }
            break;
         }
2342

2343
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2344
         case 16:
2345
         /* Double byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2346
         {
2347
            png_bytep bp = row;
2348 2349
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2350

2351
            while (bp < bp_end)
A
Andreas Dilger 已提交
2352
            {
2353 2354 2355 2356 2357
               int value = (bp[0] << 8) + bp[1];

               value >>= shift[channel];
               if (++channel >= channels)
                  channel = 0;
2358
               *bp++ = (png_byte)(value >> 8);
2359
               *bp++ = (png_byte)value;
G
Guy Schalnat 已提交
2360 2361 2362
            }
            break;
         }
2363
#endif
G
Guy Schalnat 已提交
2364 2365 2366
      }
   }
}
G
Guy Schalnat 已提交
2367
#endif
G
Guy Schalnat 已提交
2368

2369
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2370
/* Scale rows of bit depth 16 down to 8 accurately */
2371
static void
2372
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2373
{
2374
   png_debug(1, "in png_do_scale_16_to_8");
2375

A
Andreas Dilger 已提交
2376
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2377
   {
2378
      png_bytep sp = row; /* source */
2379
      png_bytep dp = row; /* destination */
2380
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2381

2382
      while (sp < ep)
G
Guy Schalnat 已提交
2383
      {
2384 2385
         /* 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
2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405
          * 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
2406
          * 0.  This gives 128 errors.  The exact answer (correct for all 16-bit
2407 2408 2409 2410 2411 2412 2413 2414
          * input values) is:
          *
          *    error = (vlo-vhi+128)*65535 >> 24;
          *
          * An alternative arithmetic calculation which also gives no errors is:
          *
          *    (V * 255 + 32895) >> 16
          */
2415

2416
         png_int_32 tmp = *sp++; /* must be signed! */
2417
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2418
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2419
      }
2420

G
Guy Schalnat 已提交
2421
      row_info->bit_depth = 8;
2422
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2423
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2424 2425
   }
}
2426
#endif
2427

2428
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2429
static void
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
/* 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 */
2440
      png_bytep dp = row; /* destination */
2441 2442 2443 2444
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
2445 2446
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2447 2448 2449
      }

      row_info->bit_depth = 8;
2450
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2451 2452 2453
      row_info->rowbytes = row_info->width * row_info->channels;
   }
}
2454
#endif
A
Andreas Dilger 已提交
2455

2456
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2457
static void
A
Andreas Dilger 已提交
2458 2459
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2460
   png_debug(1, "in png_do_read_swap_alpha");
2461

A
Andreas Dilger 已提交
2462
   {
2463
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2464 2465 2466 2467 2468
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2469 2470
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2471 2472
            png_byte save;
            png_uint_32 i;
2473

2474
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2475 2476 2477 2478 2479 2480 2481 2482
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2483 2484

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2485 2486 2487
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2488 2489
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2490 2491
            png_byte save[2];
            png_uint_32 i;
2492

2493
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2507
#endif
A
Andreas Dilger 已提交
2508
      }
2509

A
Andreas Dilger 已提交
2510 2511 2512 2513 2514
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2515 2516
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2517 2518
            png_byte save;
            png_uint_32 i;
2519

2520
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2521 2522 2523 2524 2525 2526
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2527 2528

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2529 2530 2531
         /* This converts from GGAA to AAGG */
         else
         {
2532 2533
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2534 2535 2536
            png_byte save[2];
            png_uint_32 i;

2537
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2538 2539 2540 2541 2542 2543 2544 2545 2546
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2547
#endif
A
Andreas Dilger 已提交
2548
      }
G
Guy Schalnat 已提交
2549 2550
   }
}
G
Guy Schalnat 已提交
2551
#endif
G
Guy Schalnat 已提交
2552

2553
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2554
static void
2555 2556
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2557
   png_uint_32 row_width;
2558
   png_debug(1, "in png_do_read_invert_alpha");
2559

2560 2561
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2562
   {
2563
      if (row_info->bit_depth == 8)
2564 2565
      {
         /* This inverts the alpha channel in RGBA */
2566 2567 2568
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2569

2570 2571
         for (i = 0; i < row_width; i++)
         {
2572
            *(--dp) = (png_byte)(255 - *(--sp));
2573

2574 2575 2576 2577 2578
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2579
*/
2580 2581
            sp-=3;
            dp=sp;
2582
         }
2583
      }
2584 2585

#ifdef PNG_READ_16BIT_SUPPORTED
2586 2587 2588 2589 2590 2591
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2592

2593 2594
         for (i = 0; i < row_width; i++)
         {
2595 2596
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2597 2598 2599 2600 2601 2602 2603 2604 2605

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

2622 2623
         for (i = 0; i < row_width; i++)
         {
2624
            *(--dp) = (png_byte)(255 - *(--sp));
2625
            *(--dp) = *(--sp);
2626
         }
2627
      }
2628 2629

#ifdef PNG_READ_16BIT_SUPPORTED
2630 2631
      else
      {
2632
         /* This inverts the alpha channel in GGAA */
2633 2634 2635
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2636

2637 2638
         for (i = 0; i < row_width; i++)
         {
2639 2640
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2641
/*
2642 2643
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2644
*/
2645 2646
            sp-=2;
            dp=sp;
2647 2648
         }
      }
2649
#endif
2650 2651 2652 2653
   }
}
#endif

2654
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2655
/* Add filler channel if we have RGB color */
2656
static void
G
Guy Schalnat 已提交
2657
png_do_read_filler(png_row_infop row_info, png_bytep row,
2658
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2659
{
G
Guy Schalnat 已提交
2660
   png_uint_32 i;
2661 2662
   png_uint_32 row_width = row_info->width;

2663
#ifdef PNG_READ_16BIT_SUPPORTED
2664
   png_byte hi_filler = (png_byte)(filler>>8);
2665
#endif
2666
   png_byte lo_filler = (png_byte)filler;
A
Andreas Dilger 已提交
2667

2668
   png_debug(1, "in png_do_read_filler");
2669

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

2691 2692
         else
         {
2693
            /* This changes the data from G to XG */
2694 2695
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2696 2697 2698
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2699
               *(--dp) = lo_filler;
2700 2701 2702 2703 2704 2705
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2706

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

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

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

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

2814 2815
         else
         {
2816
            /* This changes the data from RRGGBB to XXRRGGBB */
2817 2818
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2819 2820 2821 2822 2823 2824 2825 2826
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2827
               *(--dp) = lo_filler;
2828
               *(--dp) = hi_filler;
2829
            }
2830

2831 2832
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2833
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2834
         }
G
Guy Schalnat 已提交
2835
      }
2836
#endif
2837
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2838
}
G
Guy Schalnat 已提交
2839
#endif
G
Guy Schalnat 已提交
2840

2841
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2842
/* Expand grayscale files to RGB, with or without alpha */
2843
static void
G
Guy Schalnat 已提交
2844
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2845
{
G
Guy Schalnat 已提交
2846
   png_uint_32 i;
2847
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2848

2849
   png_debug(1, "in png_do_gray_to_rgb");
2850

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

G
Guy Schalnat 已提交
2869 2870
         else
         {
2871
            /* This changes GG to RRGGBB */
2872 2873
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2874
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2875 2876 2877 2878 2879
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2880 2881
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2882 2883 2884
            }
         }
      }
2885

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

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

2929
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2930
/* Reduce RGB files to grayscale, with or without alpha
2931 2932 2933 2934 2935
 * 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
 * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
 * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
2936
 * Charles Poynton poynton at poynton.com
2937 2938 2939
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
2940
 *  which can be expressed with integers as
2941
 *
2942 2943 2944 2945 2946 2947 2948
 *     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
2949 2950 2951
 *
 *  which can be expressed with integers as
 *
2952 2953
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
 *
2954 2955 2956 2957 2958
 *  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:
2959
 *
2960
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2961
 *
2962 2963 2964 2965 2966
 *  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
2967
 *
2968 2969 2970
 *  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.
2971
 *
2972 2973 2974 2975
 *  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.
2976
 *
2977 2978 2979 2980
 *  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.
2981
 */
2982
static int
2983
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2984 2985 2986 2987

{
   int rgb_error = 0;

2988
   png_debug(1, "in png_do_rgb_to_gray");
2989

2990 2991
   if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
2992
   {
2993 2994 2995 2996 2997 2998
      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;
2999

3000
      if (row_info->bit_depth == 8)
3001
      {
3002
#ifdef PNG_READ_GAMMA_SUPPORTED
3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014
         /* 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++)
3015
            {
3016 3017 3018
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3019

3020
               if (red != green || red != blue)
3021
               {
3022 3023 3024
                  red = png_ptr->gamma_to_1[red];
                  green = png_ptr->gamma_to_1[green];
                  blue = png_ptr->gamma_to_1[blue];
3025

3026 3027 3028
                  rgb_error |= 1;
                  *(dp++) = png_ptr->gamma_from_1[
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3029
               }
3030

3031 3032 3033 3034 3035 3036 3037
               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];
3038

3039
                  *(dp++) = red;
3040
               }
3041

3042
               if (have_alpha != 0)
3043
                  *(dp++) = *(sp++);
3044 3045
            }
         }
3046 3047
         else
#endif
3048
         {
3049 3050 3051
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3052

3053
            for (i = 0; i < row_width; i++)
3054
            {
3055 3056 3057
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3058

3059 3060 3061
               if (red != green || red != blue)
               {
                  rgb_error |= 1;
3062
                  /* NOTE: this is the historical approach which simply
3063 3064
                   * truncates the results.
                   */
3065
                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3066
               }
3067

3068 3069
               else
                  *(dp++) = red;
3070

3071
               if (have_alpha != 0)
3072
                  *(dp++) = *(sp++);
3073 3074 3075
            }
         }
      }
3076 3077

      else /* RGB bit_depth == 16 */
3078
      {
3079
#ifdef PNG_READ_GAMMA_SUPPORTED
3080 3081 3082 3083 3084 3085 3086
         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++)
3087
            {
3088
               png_uint_16 red, green, blue, w;
3089
               png_byte hi,lo;
3090

3091 3092 3093
               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));
3094

3095 3096 3097
               if (red == green && red == blue)
               {
                  if (png_ptr->gamma_16_table != NULL)
3098 3099
                     w = png_ptr->gamma_16_table[(red & 0xff)
                         >> png_ptr->gamma_shift][red >> 8];
3100

3101 3102
                  else
                     w = red;
3103
               }
3104 3105

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

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

3124
               if (have_alpha != 0)
3125 3126 3127
               {
                  *(dp++) = *(sp++);
                  *(dp++) = *(sp++);
3128 3129 3130
               }
            }
         }
3131 3132
         else
#endif
3133
         {
3134 3135 3136
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3137

3138 3139 3140
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3141
               png_byte hi,lo;
3142

3143 3144 3145
               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));
3146

3147 3148
               if (red != green || red != blue)
                  rgb_error |= 1;
3149

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

3159
               if (have_alpha != 0)
3160
               {
3161
                  *(dp++) = *(sp++);
3162 3163 3164 3165 3166
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3167

3168 3169 3170 3171 3172
      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);
3173
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3174 3175 3176 3177
   }
   return rgb_error;
}
#endif
G
Guy Schalnat 已提交
3178

3179 3180
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
A
Andreas Dilger 已提交
3181
/* Replace any alpha or transparency with the supplied background color.
3182 3183 3184
 * "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.
 */
3185
static void
3186
png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3187
{
3188
#ifdef PNG_READ_GAMMA_SUPPORTED
3189 3190 3191 3192 3193 3194 3195
   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;
3196
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3197
#endif
3198

3199
   png_bytep sp;
G
Guy Schalnat 已提交
3200
   png_uint_32 i;
3201
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3202
   int shift;
G
Guy Schalnat 已提交
3203

3204
   png_debug(1, "in png_do_compose");
3205

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

3227
                     if (shift == 0)
G
Guy Schalnat 已提交
3228 3229 3230 3231
                     {
                        shift = 7;
                        sp++;
                     }
3232

G
Guy Schalnat 已提交
3233 3234 3235 3236 3237
                     else
                        shift--;
                  }
                  break;
               }
3238

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

3256 3257
                        else
                        {
3258 3259 3260 3261 3262 3263
                           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));
                           tmp |= g << shift;
                           *sp = (png_byte)(tmp & 0xff);
3264
                        }
3265

3266
                        if (shift == 0)
3267 3268 3269 3270
                        {
                           shift = 6;
                           sp++;
                        }
3271

3272 3273
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3274
                     }
3275
                  }
3276

3277 3278 3279 3280 3281 3282
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3283
                     {
3284
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3285
                            == png_ptr->trans_color.gray)
3286
                        {
3287 3288 3289
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3290
                        }
3291

3292
                        if (shift == 0)
3293 3294 3295 3296
                        {
                           shift = 6;
                           sp++;
                        }
3297

3298 3299
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3300 3301 3302 3303
                     }
                  }
                  break;
               }
3304

G
Guy Schalnat 已提交
3305 3306
               case 4:
               {
3307
#ifdef PNG_READ_GAMMA_SUPPORTED
3308
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3309
                  {
3310 3311 3312
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3313
                     {
3314
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3315
                            == png_ptr->trans_color.gray)
3316
                        {
3317
                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3318 3319
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3320
                        }
3321

3322 3323
                        else
                        {
3324 3325 3326
                           unsigned int p = (*sp >> shift) & 0x0f;
                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
                              0x0f;
3327
                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3328 3329
                           tmp |= g << shift;
                           *sp = (png_byte)(tmp & 0xff);
3330
                        }
3331

3332
                        if (shift == 0)
3333 3334 3335 3336
                        {
                           shift = 4;
                           sp++;
                        }
3337

3338 3339
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3340
                     }
3341
                  }
3342

3343 3344 3345 3346 3347 3348
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3349
                     {
3350
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3351
                            == png_ptr->trans_color.gray)
3352
                        {
3353
                           unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3354 3355
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3356
                        }
3357

3358
                        if (shift == 0)
3359 3360 3361 3362
                        {
                           shift = 4;
                           sp++;
                        }
3363

3364 3365
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3366 3367 3368 3369
                     }
                  }
                  break;
               }
3370

G
Guy Schalnat 已提交
3371 3372
               case 8:
               {
3373
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3374
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3375
                  {
3376 3377
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3378
                     {
3379 3380
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3381

G
Guy Schalnat 已提交
3382 3383 3384 3385 3386
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3387
#endif
G
Guy Schalnat 已提交
3388
                  {
3389 3390
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3391
                     {
3392 3393
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3394 3395 3396 3397
                     }
                  }
                  break;
               }
3398

G
Guy Schalnat 已提交
3399 3400
               case 16:
               {
3401
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3402
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3403
                  {
3404 3405
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3406 3407 3408
                     {
                        png_uint_16 v;

3409
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3410

3411
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3412
                        {
3413
                           /* Background is already in screen gamma */
3414 3415 3416 3417
                           *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray
                                & 0xff);
G
Guy Schalnat 已提交
3418
                        }
3419

G
Guy Schalnat 已提交
3420 3421
                        else
                        {
A
Andreas Dilger 已提交
3422
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3423
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3424
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3425
                        }
G
Guy Schalnat 已提交
3426
                     }
G
Guy Schalnat 已提交
3427 3428
                  }
                  else
G
Guy Schalnat 已提交
3429
#endif
G
Guy Schalnat 已提交
3430
                  {
3431 3432
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3433 3434 3435
                     {
                        png_uint_16 v;

3436
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3437

3438
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3439
                        {
3440 3441 3442 3443
                           *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray
                                & 0xff);
G
Guy Schalnat 已提交
3444 3445 3446 3447 3448
                        }
                     }
                  }
                  break;
               }
3449 3450 3451

               default:
                  break;
G
Guy Schalnat 已提交
3452 3453 3454
            }
            break;
         }
3455

G
Guy Schalnat 已提交
3456 3457 3458 3459
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3460
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3461
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3462
               {
3463 3464
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3465
                  {
3466 3467 3468
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3469
                     {
3470 3471 3472
                        *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 已提交
3473
                     }
3474

G
Guy Schalnat 已提交
3475 3476 3477 3478 3479 3480 3481 3482 3483
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3484
#endif
G
Guy Schalnat 已提交
3485
               {
3486 3487
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3488
                  {
3489 3490 3491
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3492
                     {
3493 3494 3495
                        *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 已提交
3496 3497 3498 3499
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3500
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3501
            {
3502
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3503
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3504
               {
3505 3506
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3507
                  {
3508
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3509

3510 3511
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3512

3513 3514
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3515

3516 3517 3518
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3519
                     {
3520
                        /* Background is already in screen gamma */
3521 3522 3523 3524 3525 3526 3527 3528 3529
                        *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 已提交
3530
                     }
3531

G
Guy Schalnat 已提交
3532 3533
                     else
                     {
3534
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3535
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3536
                        *(sp + 1) = (png_byte)(v & 0xff);
3537

A
Andreas Dilger 已提交
3538
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3539 3540
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3541

A
Andreas Dilger 已提交
3542
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3543 3544
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3545 3546 3547
                     }
                  }
               }
3548

G
Guy Schalnat 已提交
3549
               else
G
Guy Schalnat 已提交
3550
#endif
G
Guy Schalnat 已提交
3551
               {
3552 3553
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3554
                  {
3555
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3556

3557 3558
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3559

3560 3561
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3562

3563 3564 3565
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3566
                     {
3567 3568 3569 3570 3571 3572 3573 3574 3575
                        *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 已提交
3576 3577 3578 3579 3580 3581
                     }
                  }
               }
            }
            break;
         }
3582

G
Guy Schalnat 已提交
3583
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3584
         {
A
Andreas Dilger 已提交
3585
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3586
            {
3587
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3588 3589 3590
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3591
                  sp = row;
3592
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3593
                  {
3594
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3595

A
Andreas Dilger 已提交
3596
                     if (a == 0xff)
3597
                        *sp = gamma_table[*sp];
3598

A
Andreas Dilger 已提交
3599 3600
                     else if (a == 0)
                     {
3601
                        /* Background is already in screen gamma */
3602
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3603
                     }
3604

A
Andreas Dilger 已提交
3605 3606 3607
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3608

A
Andreas Dilger 已提交
3609
                        v = gamma_to_1[*sp];
3610
                        png_composite(w, v, a, png_ptr->background_1.gray);
3611
                        if (optimize == 0)
3612 3613
                           w = gamma_from_1[w];
                        *sp = w;
G
Guy Schalnat 已提交
3614 3615
                     }
                  }
A
Andreas Dilger 已提交
3616 3617
               }
               else
G
Guy Schalnat 已提交
3618
#endif
A
Andreas Dilger 已提交
3619
               {
3620
                  sp = row;
3621
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3622
                  {
3623
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3624

3625 3626
                     if (a == 0)
                        *sp = (png_byte)png_ptr->background.gray;
3627

3628
                     else if (a < 0xff)
3629
                        png_composite(*sp, *sp, a, png_ptr->background.gray);
G
Guy Schalnat 已提交
3630 3631
                  }
               }
A
Andreas Dilger 已提交
3632 3633 3634
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3635
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3636 3637 3638
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3639
                  sp = row;
3640
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3641
                  {
3642 3643
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
A
Andreas Dilger 已提交
3644

3645
                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3646
                     {
A
Andreas Dilger 已提交
3647
                        png_uint_16 v;
G
Guy Schalnat 已提交
3648

A
Andreas Dilger 已提交
3649
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3650 3651
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3652
                     }
3653

A
Andreas Dilger 已提交
3654 3655
                     else if (a == 0)
                     {
3656
                        /* Background is already in screen gamma */
3657 3658 3659
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3660
                     }
3661

A
Andreas Dilger 已提交
3662 3663 3664
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3665

A
Andreas Dilger 已提交
3666
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3667
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3668
                        if (optimize != 0)
3669 3670
                           w = v;
                        else
3671 3672
                           w = gamma_16_from_1[(v & 0xff) >>
                               gamma_shift][v >> 8];
3673 3674
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3675 3676
                     }
                  }
A
Andreas Dilger 已提交
3677 3678
               }
               else
G
Guy Schalnat 已提交
3679
#endif
A
Andreas Dilger 已提交
3680
               {
3681
                  sp = row;
3682
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3683
                  {
3684 3685
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3686

3687
                     if (a == 0)
A
Andreas Dilger 已提交
3688
                     {
3689 3690 3691
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3692
                     }
3693

3694
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3695 3696
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3697

3698
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3699
                        png_composite_16(v, g, a, png_ptr->background.gray);
3700 3701
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3702 3703 3704 3705 3706 3707
                     }
                  }
               }
            }
            break;
         }
3708

G
Guy Schalnat 已提交
3709 3710 3711 3712
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3713
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3714 3715
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3716
               {
3717
                  sp = row;
3718
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3719
                  {
3720
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3721 3722 3723

                     if (a == 0xff)
                     {
3724 3725 3726
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
3727
                     }
3728

G
Guy Schalnat 已提交
3729 3730
                     else if (a == 0)
                     {
3731
                        /* Background is already in screen gamma */
3732 3733 3734
                        *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 已提交
3735
                     }
3736

G
Guy Schalnat 已提交
3737 3738
                     else
                     {
A
Andreas Dilger 已提交
3739
                        png_byte v, w;
G
Guy Schalnat 已提交
3740 3741

                        v = gamma_to_1[*sp];
3742
                        png_composite(w, v, a, png_ptr->background_1.red);
3743
                        if (optimize == 0) w = gamma_from_1[w];
3744
                        *sp = w;
3745

G
Guy Schalnat 已提交
3746
                        v = gamma_to_1[*(sp + 1)];
3747
                        png_composite(w, v, a, png_ptr->background_1.green);
3748
                        if (optimize == 0) w = gamma_from_1[w];
3749
                        *(sp + 1) = w;
3750

G
Guy Schalnat 已提交
3751
                        v = gamma_to_1[*(sp + 2)];
3752
                        png_composite(w, v, a, png_ptr->background_1.blue);
3753
                        if (optimize == 0) w = gamma_from_1[w];
3754
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
3755 3756 3757 3758
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3759
#endif
G
Guy Schalnat 已提交
3760
               {
3761
                  sp = row;
3762
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3763
                  {
3764
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3765

3766
                     if (a == 0)
G
Guy Schalnat 已提交
3767
                     {
3768 3769 3770
                        *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 已提交
3771
                     }
3772

3773
                     else if (a < 0xff)
G
Guy Schalnat 已提交
3774
                     {
3775
                        png_composite(*sp, *sp, a, png_ptr->background.red);
3776

3777
                        png_composite(*(sp + 1), *(sp + 1), a,
3778
                            png_ptr->background.green);
3779

3780
                        png_composite(*(sp + 2), *(sp + 2), a,
3781
                            png_ptr->background.blue);
G
Guy Schalnat 已提交
3782 3783 3784 3785
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3786
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3787
            {
3788
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3789 3790
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
3791
               {
3792
                  sp = row;
3793
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3794
                  {
3795 3796
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
3797

3798
                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3799 3800 3801
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3802
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3803 3804
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3805

A
Andreas Dilger 已提交
3806
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3807 3808
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3809

A
Andreas Dilger 已提交
3810
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3811 3812
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3813
                     }
3814

G
Guy Schalnat 已提交
3815 3816
                     else if (a == 0)
                     {
3817
                        /* Background is already in screen gamma */
3818 3819 3820 3821 3822 3823 3824 3825 3826
                        *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 已提交
3827
                     }
3828

G
Guy Schalnat 已提交
3829 3830
                     else
                     {
3831
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
3832 3833

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3834
                        png_composite_16(w, v, a, png_ptr->background_1.red);
3835
                        if (optimize == 0)
3836
                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3837
                                8];
3838 3839
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
3840

A
Andreas Dilger 已提交
3841
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3842
                        png_composite_16(w, v, a, png_ptr->background_1.green);
3843
                        if (optimize == 0)
3844
                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3845
                                8];
3846

3847 3848
                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(w & 0xff);
3849

A
Andreas Dilger 已提交
3850
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3851
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
3852
                        if (optimize == 0)
3853
                           w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3854
                                8];
3855

3856 3857
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3858 3859 3860
                     }
                  }
               }
3861

G
Guy Schalnat 已提交
3862
               else
G
Guy Schalnat 已提交
3863
#endif
G
Guy Schalnat 已提交
3864
               {
3865
                  sp = row;
3866
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3867
                  {
3868
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3869
                         << 8) + (png_uint_16)(*(sp + 7)));
3870

3871
                     if (a == 0)
G
Guy Schalnat 已提交
3872
                     {
3873 3874 3875 3876 3877 3878 3879 3880 3881
                        *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 已提交
3882
                     }
3883

3884
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
3885
                     {
3886
                        png_uint_16 v;
A
Andreas Dilger 已提交
3887

3888 3889 3890 3891 3892
                        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 已提交
3893

3894
                        png_composite_16(v, r, a, png_ptr->background.red);
3895 3896
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3897

3898
                        png_composite_16(v, g, a, png_ptr->background.green);
3899 3900
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3901

3902
                        png_composite_16(v, b, a, png_ptr->background.blue);
3903 3904
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3905 3906 3907 3908 3909 3910
                     }
                  }
               }
            }
            break;
         }
3911 3912 3913

         default:
            break;
G
Guy Schalnat 已提交
3914 3915 3916
      }
   }
}
3917
#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
G
Guy Schalnat 已提交
3918

3919
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3920
/* Gamma correct the image, avoiding the alpha channel.  Make sure
3921
 * you do this after you deal with the transparency issue on grayscale
3922
 * or RGB images. If your bit depth is 8, use gamma_table, if it
3923 3924 3925
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
3926
static void
3927
png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
G
Guy Schalnat 已提交
3928
{
3929 3930 3931 3932
   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 已提交
3933
   png_bytep sp;
G
Guy Schalnat 已提交
3934
   png_uint_32 i;
3935
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3936

3937
   png_debug(1, "in png_do_gamma");
3938

3939
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3940
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
3941 3942 3943 3944 3945 3946 3947
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3948 3949
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3950 3951 3952 3953 3954 3955 3956 3957 3958
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
3959

A
Andreas Dilger 已提交
3960
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3961
            {
3962 3963
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3964 3965 3966
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
3967
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3968 3969 3970
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
3971

A
Andreas Dilger 已提交
3972
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3973 3974
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3975
                  sp += 2;
3976

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

G
Guy Schalnat 已提交
3986 3987 3988 3989
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3990 3991
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3992
               {
G
Guy Schalnat 已提交
3993 3994
                  *sp = gamma_table[*sp];
                  sp++;
3995

G
Guy Schalnat 已提交
3996 3997
                  *sp = gamma_table[*sp];
                  sp++;
3998

G
Guy Schalnat 已提交
3999 4000
                  *sp = gamma_table[*sp];
                  sp++;
4001

G
Guy Schalnat 已提交
4002 4003 4004
                  sp++;
               }
            }
4005

A
Andreas Dilger 已提交
4006
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4007
            {
4008 4009
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4010
               {
4011
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4012 4013
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4014
                  sp += 2;
4015

A
Andreas Dilger 已提交
4016
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4017 4018 4019
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4020

A
Andreas Dilger 已提交
4021
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4022 4023 4024 4025 4026
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4027 4028
            break;
         }
4029

G
Guy Schalnat 已提交
4030 4031 4032 4033
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4034 4035
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4036 4037
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4038
                  sp += 2;
G
Guy Schalnat 已提交
4039 4040
               }
            }
4041

A
Andreas Dilger 已提交
4042
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4043
            {
4044 4045
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4046
               {
4047
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4048 4049
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4050 4051 4052 4053 4054
                  sp += 4;
               }
            }
            break;
         }
4055

G
Guy Schalnat 已提交
4056 4057
         case PNG_COLOR_TYPE_GRAY:
         {
4058 4059
            if (row_info->bit_depth == 2)
            {
4060 4061
               sp = row;
               for (i = 0; i < row_width; i += 4)
4062 4063 4064 4065 4066 4067
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4068 4069
                  *sp = (png_byte)(
                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
4070 4071
                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
4072
                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4073 4074 4075
                  sp++;
               }
            }
4076

A
Andreas Dilger 已提交
4077
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4078
            {
4079 4080
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4081 4082 4083 4084
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4085
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4086
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4087 4088 4089
                  sp++;
               }
            }
4090

A
Andreas Dilger 已提交
4091 4092
            else if (row_info->bit_depth == 8)
            {
4093 4094
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4095 4096 4097 4098 4099
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4100

G
Guy Schalnat 已提交
4101 4102
            else if (row_info->bit_depth == 16)
            {
4103 4104
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4105
               {
4106
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4107 4108
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4109 4110 4111 4112 4113
                  sp += 2;
               }
            }
            break;
         }
4114 4115 4116

         default:
            break;
G
Guy Schalnat 已提交
4117 4118 4119
      }
   }
}
G
Guy Schalnat 已提交
4120
#endif
G
Guy Schalnat 已提交
4121

4122 4123 4124 4125 4126
#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.
 */
4127
static void
4128
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4129 4130 4131 4132 4133
{
   png_uint_32 row_width = row_info->width;

   png_debug(1, "in png_do_encode_alpha");

4134
   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 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
   {
      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

4189
#ifdef PNG_READ_EXPAND_SUPPORTED
4190
/* Expands a palette row to an RGB or RGBA row depending
4191 4192
 * upon whether you supply trans and num_trans.
 */
4193
static void
G
Guy Schalnat 已提交
4194
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4195
   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
4196
{
G
Guy Schalnat 已提交
4197
   int shift, value;
G
Guy Schalnat 已提交
4198
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4199
   png_uint_32 i;
4200
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4201

4202
   png_debug(1, "in png_do_expand_palette");
4203

4204
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4205 4206 4207 4208 4209 4210 4211
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4212 4213
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4214
               shift = 7 - (int)((row_width + 7) & 0x07);
4215
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4216
               {
4217
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4218
                     *dp = 1;
4219

G
Guy Schalnat 已提交
4220 4221
                  else
                     *dp = 0;
4222

G
Guy Schalnat 已提交
4223 4224 4225 4226 4227
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4228

G
Guy Schalnat 已提交
4229 4230 4231 4232 4233 4234 4235
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4236

G
Guy Schalnat 已提交
4237 4238
            case 2:
            {
4239 4240
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4241
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4242
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4243
               {
4244
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4245
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4246 4247 4248 4249 4250
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4251

G
Guy Schalnat 已提交
4252 4253 4254 4255 4256 4257 4258
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4259

G
Guy Schalnat 已提交
4260 4261
            case 4:
            {
4262 4263
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4264
               shift = (int)((row_width & 0x01) << 2);
4265
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4266
               {
4267
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4268
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4269 4270 4271 4272 4273
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4274

G
Guy Schalnat 已提交
4275 4276 4277 4278 4279 4280 4281
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4282 4283 4284

            default:
               break;
G
Guy Schalnat 已提交
4285 4286 4287
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4288
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4289
      }
4290

4291
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4292 4293
      {
         {
4294
            if (num_trans > 0)
G
Guy Schalnat 已提交
4295
            {
4296 4297
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
4298

4299
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4300
               {
A
Andreas Dilger 已提交
4301
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4302
                     *dp-- = 0xff;
4303

G
Guy Schalnat 已提交
4304
                  else
4305
                     *dp-- = trans_alpha[*sp];
4306

G
Guy Schalnat 已提交
4307 4308 4309 4310 4311 4312 4313
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4314
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4315 4316 4317
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4318

G
Guy Schalnat 已提交
4319 4320
            else
            {
4321 4322
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4323

4324
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4325 4326 4327 4328 4329 4330
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4331

G
Guy Schalnat 已提交
4332 4333
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4334
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4335 4336 4337 4338 4339 4340 4341 4342
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4343 4344
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4345
 */
4346
static void
G
Guy Schalnat 已提交
4347
png_do_expand(png_row_infop row_info, png_bytep row,
4348
    png_const_color_16p trans_color)
G
Guy Schalnat 已提交
4349
{
G
Guy Schalnat 已提交
4350
   int shift, value;
G
Guy Schalnat 已提交
4351
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4352
   png_uint_32 i;
4353
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4354

4355
   png_debug(1, "in png_do_expand");
4356

G
Guy Schalnat 已提交
4357
   {
A
Andreas Dilger 已提交
4358
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4359
      {
4360
         unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
A
Andreas Dilger 已提交
4361 4362

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4363
         {
A
Andreas Dilger 已提交
4364
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4365
            {
A
Andreas Dilger 已提交
4366
               case 1:
G
Guy Schalnat 已提交
4367
               {
4368
                  gray = (gray & 0x01) * 0xff;
4369 4370
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4371
                  shift = 7 - (int)((row_width + 7) & 0x07);
4372
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4373
                  {
4374
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4375
                        *dp = 0xff;
4376

A
Andreas Dilger 已提交
4377 4378
                     else
                        *dp = 0;
4379

A
Andreas Dilger 已提交
4380 4381 4382 4383 4384
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4385

A
Andreas Dilger 已提交
4386 4387
                     else
                        shift++;
G
Guy Schalnat 已提交
4388

A
Andreas Dilger 已提交
4389 4390 4391
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4392
               }
4393

A
Andreas Dilger 已提交
4394
               case 2:
G
Guy Schalnat 已提交
4395
               {
4396
                  gray = (gray & 0x03) * 0x55;
4397 4398
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
4399
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4400
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4401
                  {
4402
                     value = (*sp >> shift) & 0x03;
4403 4404
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
A
Andreas Dilger 已提交
4405 4406 4407 4408 4409
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
4410

A
Andreas Dilger 已提交
4411 4412
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4413

A
Andreas Dilger 已提交
4414 4415 4416
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4417
               }
4418

A
Andreas Dilger 已提交
4419
               case 4:
G
Guy Schalnat 已提交
4420
               {
4421
                  gray = (gray & 0x0f) * 0x11;
4422 4423
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4424
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4425
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4426
                  {
4427
                     value = (*sp >> shift) & 0x0f;
4428
                     *dp = (png_byte)(value | (value << 4));
A
Andreas Dilger 已提交
4429 4430 4431 4432 4433
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4434

A
Andreas Dilger 已提交
4435 4436
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4437

A
Andreas Dilger 已提交
4438 4439 4440
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4441
               }
4442 4443 4444

               default:
                  break;
G
Guy Schalnat 已提交
4445
            }
4446

A
Andreas Dilger 已提交
4447 4448
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4449
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4450
         }
A
Andreas Dilger 已提交
4451

4452
         if (trans_color != NULL)
G
Guy Schalnat 已提交
4453
         {
A
Andreas Dilger 已提交
4454
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4455
            {
4456
               gray = gray & 0xff;
4457 4458
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
4459

4460
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4461
               {
4462
                  if ((*sp & 0xffU) == gray)
A
Andreas Dilger 已提交
4463
                     *dp-- = 0;
4464

A
Andreas Dilger 已提交
4465 4466
                  else
                     *dp-- = 0xff;
4467

A
Andreas Dilger 已提交
4468
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4469
               }
A
Andreas Dilger 已提交
4470
            }
4471

A
Andreas Dilger 已提交
4472 4473
            else if (row_info->bit_depth == 16)
            {
4474 4475
               unsigned int gray_high = (gray >> 8) & 0xff;
               unsigned int gray_low = gray & 0xff;
A
Andreas Dilger 已提交
4476 4477
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4478
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4479
               {
4480 4481
                  if ((*(sp - 1) & 0xffU) == gray_high &&
                      (*(sp) & 0xffU) == gray_low)
A
Andreas Dilger 已提交
4482 4483 4484 4485
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4486

A
Andreas Dilger 已提交
4487 4488 4489 4490 4491
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4492

A
Andreas Dilger 已提交
4493 4494
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4495 4496
               }
            }
4497

A
Andreas Dilger 已提交
4498 4499
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
4500
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4501 4502
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
4503 4504
         }
      }
4505 4506
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
          trans_color != NULL)
G
Guy Schalnat 已提交
4507 4508 4509
      {
         if (row_info->bit_depth == 8)
         {
4510 4511 4512
            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 已提交
4513
            sp = row + (png_size_t)row_info->rowbytes - 1;
4514 4515
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4516
            {
4517
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
4518
                  *dp-- = 0;
4519

G
Guy Schalnat 已提交
4520 4521
               else
                  *dp-- = 0xff;
4522

G
Guy Schalnat 已提交
4523 4524 4525 4526 4527 4528 4529
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
4530 4531 4532 4533 4534 4535
            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 已提交
4536
            sp = row + row_info->rowbytes - 1;
4537 4538
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4539
            {
4540
               if (*(sp - 5) == red_high &&
4541 4542 4543 4544 4545
                   *(sp - 4) == red_low &&
                   *(sp - 3) == green_high &&
                   *(sp - 2) == green_low &&
                   *(sp - 1) == blue_high &&
                   *(sp    ) == blue_low)
G
Guy Schalnat 已提交
4546 4547 4548 4549
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4550

G
Guy Schalnat 已提交
4551 4552 4553 4554 4555
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4556

G
Guy Schalnat 已提交
4557 4558 4559 4560
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4561
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4562 4563 4564 4565 4566
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
4567
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4568
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4569 4570 4571
      }
   }
}
G
Guy Schalnat 已提交
4572
#endif
G
Guy Schalnat 已提交
4573

4574
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4575
/* If the bit depth is 8 and the color type is not a palette type expand the
4576 4577
 * whole row to 16 bits.  Has no effect otherwise.
 */
4578
static void
4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599
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)
         dp[-2] = dp[-1] = *--sp, dp -= 2;

      row_info->rowbytes *= 2;
      row_info->bit_depth = 16;
4600
      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4601 4602 4603 4604
   }
}
#endif

4605
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4606
static void
4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 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
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];
         }
      }
   }
}
4697
#endif /* READ_QUANTIZE */
4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723

/* 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 &&
4724
       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4725 4726 4727 4728 4729 4730 4731 4732 4733
   {
      /* 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
4734
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4735 4736 4737 4738 4739 4740 4741 4742 4743
   {
      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
      {
4744 4745
         if (png_ptr->num_trans != 0 &&
             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756
            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
4757 4758 4759 4760
   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))
4761 4762 4763 4764 4765
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
         0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif

#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4766
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4767 4768 4769 4770 4771
   {
      int rgb_error =
          png_do_rgb_to_gray(png_ptr, row_info,
              png_ptr->row_buf + 1);

4772
      if (rgb_error != 0)
4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 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
      {
         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
    */
4821 4822
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4823 4824 4825 4826 4827
      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)
4828
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4829 4830
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4831

4832
#ifdef PNG_READ_GAMMA_SUPPORTED
4833
   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4834 4835
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
      /* Because RGB_TO_GRAY does the gamma transform. */
4836
      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4837 4838 4839 4840 4841 4842
#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.)
       */
4843
       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4844
       ((png_ptr->num_trans != 0) ||
4845
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4846 4847 4848 4849 4850 4851 4852
#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
4853

4854
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4855 4856 4857 4858
   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))
4859
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4860
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4861
#endif
G
Guy Schalnat 已提交
4862

4863
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4864 4865
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4866 4867
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4868

4869
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
4870
   if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
4871 4872
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
#endif
4873

4874 4875 4876 4877 4878
#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.
    */
4879
   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4880 4881
      png_do_chop(row_info, png_ptr->row_buf + 1);
#endif
4882

4883
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4884
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4885 4886 4887
   {
      png_do_quantize(row_info, png_ptr->row_buf + 1,
          png_ptr->palette_lookup, png_ptr->quantize_index);
G
Guy Schalnat 已提交
4888

4889 4890 4891
      if (row_info->rowbytes == 0)
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
   }
4892
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
4893

4894 4895 4896 4897 4898 4899
#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!)
    */
4900
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4901 4902
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
#endif
4903

4904 4905
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
4906 4907
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
4908 4909
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
4910

4911
#ifdef PNG_READ_INVERT_SUPPORTED
4912
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4913 4914
      png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
4915

4916
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
4917
   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
4918 4919 4920
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif

4921
#ifdef PNG_READ_SHIFT_SUPPORTED
4922
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4923 4924 4925
      png_do_unshift(row_info, png_ptr->row_buf + 1,
          &(png_ptr->shift));
#endif
G
Guy Schalnat 已提交
4926

4927
#ifdef PNG_READ_PACK_SUPPORTED
4928
   if ((png_ptr->transformations & PNG_PACK) != 0)
4929 4930
      png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
4931

4932 4933 4934 4935 4936 4937
#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
4938

4939
#ifdef PNG_READ_BGR_SUPPORTED
4940
   if ((png_ptr->transformations & PNG_BGR) != 0)
4941 4942
      png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
4943

4944
#ifdef PNG_READ_PACKSWAP_SUPPORTED
4945
   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4946 4947
      png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
4948

4949
#ifdef PNG_READ_FILLER_SUPPORTED
4950
   if ((png_ptr->transformations & PNG_FILLER) != 0)
4951 4952 4953
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif
4954

4955
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
4956
   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
4957 4958
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
4959

4960 4961
#ifdef PNG_READ_16BIT_SUPPORTED
#ifdef PNG_READ_SWAP_SUPPORTED
4962
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
4963 4964 4965
      png_do_swap(row_info, png_ptr->row_buf + 1);
#endif
#endif
4966

4967
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
4968
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
4969
   {
4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981
      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
4982
      if (png_ptr->user_transform_depth != 0)
4983
         row_info->bit_depth = png_ptr->user_transform_depth;
4984

4985
      if (png_ptr->user_transform_channels != 0)
4986 4987
         row_info->channels = png_ptr->user_transform_channels;
#endif
4988 4989
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
4990

4991
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
4992
   }
4993
#endif
4994
}
4995

4996 4997
#endif /* READ_TRANSFORMS */
#endif /* READ */