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.18 [July 23, 2015]
5
 * Copyright (c) 1998-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;
G
Guy Schalnat 已提交
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 979
         png_error(png_ptr, "invalid error action to rgb_to_gray");
         break;
980
   }
981

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1251 1252
            default:

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

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

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

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

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

1300
      if (png_ptr->colorspace.gamma != 0) /* has been set */
1301 1302
      {
         if (png_ptr->screen_gamma != 0) /* screen set too */
1303
            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1304 1305 1306 1307 1308 1309
               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.
             */
1310
            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
G
Guy Schalnat 已提交
1311
      }
1312 1313 1314

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

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

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

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

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

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

1412 1413 1414 1415
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
   /* Make sure the coefficients for the rgb to gray conversion are set
    * appropriately.
    */
1416
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1417 1418 1419 1420
      png_colorspace_set_rgb_coefficients(png_ptr);
#endif

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1421
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
   /* 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.
    *
1432
    * TODO: this code needs to be revised to avoid the complexity and
1433 1434 1435 1436
    * 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.
    */
1437
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1438 1439
   {
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1440
       * the file was grayscale the background value is gray.
1441
       */
1442
      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1443 1444 1445
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

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

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

1480 1481 1482
   else
      png_init_rgb_transformations(png_ptr);

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

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

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

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

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

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

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

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

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

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

1652
               if (png_gamma_significant(g) != 0)
1653 1654 1655 1656 1657 1658 1659 1660 1661
               {
                  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 已提交
1662 1663
               else
               {
1664 1665 1666
                  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 已提交
1667 1668
               }
            }
1669

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1881 1882
      png_ptr->transformations &= ~PNG_SHIFT;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2097 2098
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2099
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2100 2101
   {
      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
2102
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2103

2104
      if (info_ptr->channels < png_ptr->user_transform_channels)
2105
         info_ptr->channels = png_ptr->user_transform_channels;
2106
   }
2107 2108
#endif

G
Guy Schalnat 已提交
2109
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2110
       info_ptr->bit_depth);
2111

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

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

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

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

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

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

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

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

               dp--;
            }
            break;
         }
2169

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

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

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

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

               dp--;
            }
            break;
         }
2193

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

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

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

               dp--;
            }
            break;
         }
2216 2217 2218

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            mask |= mask << 4;
2318

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

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

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

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

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

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

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

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

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

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

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

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

      while (sp < ep)
      {
2446 2447
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2448 2449 2450 2451 2452 2453 2454
      }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{
   int rgb_error = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3102 3103
                  else
                     w = red;
3104
               }
3105 3106

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

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

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

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

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

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

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

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

3169
      row_info->channels = (png_byte)(row_info->channels - 2);
3170 3171
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
3172
      row_info->pixel_depth = (png_byte)(row_info->channels *
3173
          row_info->bit_depth);
3174
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3175 3176 3177 3178
   }
   return rgb_error;
}
#endif
G
Guy Schalnat 已提交
3179

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

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

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

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

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

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

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

3257 3258
                        else
                        {
3259 3260 3261 3262 3263 3264
                           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);
3265
                        }
3266

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

G
Guy Schalnat 已提交
3816 3817
                     else if (a == 0)
                     {
3818
                        /* Background is already in screen gamma */
3819 3820
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3821 3822 3823 3824 3825 3826
                        *(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);
3827
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3828
                     }
3829

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

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

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

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

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

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

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

3872
                     if (a == 0)
G
Guy Schalnat 已提交
3873
                     {
3874 3875
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3876 3877 3878 3879 3880 3881
                        *(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);
3882
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3883
                     }
3884

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   png_debug(1, "in png_do_encode_alpha");

4135
   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
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 4189
   {
      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

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

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

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

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

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

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

                  dp--;
               }
               break;
            }
4237

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

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

                  dp--;
               }
               break;
            }
4260

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

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

                  dp--;
               }
               break;
            }
4283 4284 4285

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4575
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4576
/* If the bit depth is 8 and the color type is not a palette type expand the
4577 4578
 * whole row to 16 bits.  Has no effect otherwise.
 */
4579
static void
4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605
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;
      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
   }
}
#endif

4606 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 4697
#ifdef PNG_READ_QUANTIZE_SUPPORTED
static void
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];
         }
      }
   }
}
4698
#endif /* READ_QUANTIZE */
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 4724

/* 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 &&
4725
       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4726 4727 4728 4729 4730 4731 4732 4733 4734
   {
      /* 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
4735
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4736 4737 4738 4739 4740 4741 4742 4743 4744
   {
      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
      {
4745 4746
         if (png_ptr->num_trans != 0 &&
             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757
            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
4758 4759 4760 4761
   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))
4762 4763 4764 4765 4766
      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
4767
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4768 4769 4770 4771 4772
   {
      int rgb_error =
          png_do_rgb_to_gray(png_ptr, row_info,
              png_ptr->row_buf + 1);

4773
      if (rgb_error != 0)
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 4821
      {
         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
    */
4822 4823
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4824 4825 4826 4827 4828
      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)
4829
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4830 4831
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4832

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4997 4998
#endif /* READ_TRANSFORMS */
#endif /* READ */