pngrtran.c 163.8 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.9 [(PENDING RELEASE)]
5
 * Copyright (c) 1998-2014 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
#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
 * to have been read in all cases, the parameter allows for this check too.
 */
static int
png_rtran_ok(png_structrp png_ptr, int need_IHDR)
{
   if (png_ptr != NULL)
   {
      if (png_ptr->flags & PNG_FLAG_ROW_INIT)
         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 已提交
121
#ifdef PNG_READ_BACKGROUND_SUPPORTED
122
/* Handle alpha and tRNS via a background color */
G
[devel]  
Glenn Randers-Pehrson 已提交
123
void PNGFAPI
124
png_set_background_fixed(png_structrp png_ptr,
125
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
126
    int need_expand, png_fixed_point background_gamma)
G
Guy Schalnat 已提交
127
{
G
[devel]  
Glenn Randers-Pehrson 已提交
128
   png_debug(1, "in png_set_background_fixed");
129

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

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

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

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

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

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

174
   if (!png_rtran_ok(png_ptr, 0))
175
      return;
176

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

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

188
   if (!png_rtran_ok(png_ptr, 0))
189 190
      return;

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

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

201
   if (!png_rtran_ok(png_ptr, 0))
202
      return;
203

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

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

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

   png_debug(1, "in png_set_alpha_mode");

282
   if (!png_rtran_ok(png_ptr, 0))
283 284
      return;

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

287
   /* Validate the value to ensure it is in a reasonable range. The value
288 289 290 291 292
    * is expected to be 1 or greater, but this range test allows for some
    * viewing correction values.  The intent is to weed out users of this API
    * who use the inverse of the gamma value accidentally!  Since some of these
    * values are reasonable this may have to be changed.
    */
293
   if (output_gamma < 70000 || output_gamma > 300000)
294
      png_error(png_ptr, "output gamma out of expected range");
295

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

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

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

      if (png_ptr->transformations & PNG_COMPOSE)
         png_error(png_ptr,
            "conflicting calls to set alpha mode and background");

      png_ptr->transformations |= PNG_COMPOSE;
   }
}

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

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

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

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

418
   if (!png_rtran_ok(png_ptr, 0))
419
      return;
420

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

423
   if (!full_quantize)
G
Guy Schalnat 已提交
424 425 426
   {
      int i;

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

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

         int i;

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

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

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

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

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

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

G
Guy Schalnat 已提交
478 479 480 481
            if (done)
               break;
         }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

         num_new_palette = num_palette;

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

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

                  if (d <= max_d)
                  {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

805
   if (!png_rtran_ok(png_ptr, 0))
806
      return;
807

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

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

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

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

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
840
png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
841
{
842 843
   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 已提交
844 845 846
}
#  endif /* FLOATING_POINT_SUPPORTED */
#endif /* READ_GAMMA */
G
Guy Schalnat 已提交
847

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

858
   if (!png_rtran_ok(png_ptr, 0))
859
      return;
860

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

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

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

888
   if (!png_rtran_ok(png_ptr, 0))
889
      return;
890

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

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

900
   if (!png_rtran_ok(png_ptr, 0))
901
      return;
902

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

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

912 913 914
   if (!png_rtran_ok(png_ptr, 0))
      return;

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

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

928
   if (!png_rtran_ok(png_ptr, 0))
929 930 931 932 933 934
      return;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
1090
/* Initialize everything needed for the read.  This includes modifying
1091 1092
 * the palette.
 */
1093 1094 1095 1096 1097 1098 1099

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

1113 1114 1115 1116 1117 1118
   if (png_ptr->num_trans > 0)
   {
      int i;

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

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

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

G
Guy Schalnat 已提交
1147
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1148 1149 1150 1151
   /* png_set_background handling - deals with the complexity of whether the
    * background color is in the file format or the screen format in the case
    * where an 'expand' will happen.
    */
1152

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

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

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

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

1214 1215 1216 1217 1218 1219 1220 1221 1222
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
   /* png_set_background handling - deals with the complexity of whether the
    * background color is in the file format or the screen format in the case
    * where an 'expand' will happen.
    */

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

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

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

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

1250 1251
            default:

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

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

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

         if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
         {
            png_ptr->trans_color.red = png_ptr->trans_color.green =
               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
         }
G
Guy Schalnat 已提交
1268
      }
1269 1270 1271
   } /* background expand and (therefore) no alpha association. */
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
}
1272

1273
void /* PRIVATE */
1274
png_init_read_transformations(png_structrp png_ptr)
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
{
   png_debug(1, "in png_init_read_transformations");

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

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

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

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

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

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

      /* We have a gamma value now. */
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343

      /* 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.
       */
      if (gamma_correction)
         png_ptr->transformations |= PNG_GAMMA;

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

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

1389
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1390 1391 1392 1393
       * so transparency information would remain just so long as it wasn't
       * expanded.  This produces unexpected API changes if the set of things
       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
       * documentation - which says ask for what you want, accept what you
1394
       * get.)  This makes the behavior consistent from 1.5.4:
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
       */
      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.
    */
   if (!png_gamma_significant(png_ptr->screen_gamma))
   {
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   }
G
Guy Schalnat 已提交
1409
#endif
1410

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

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
   /* Detect gray background and attempt to enable optimization for
    * gray --> RGB case.
    *
    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
    * background color might actually be gray yet not be flagged as such.
    * This is not a problem for the current code, which uses
    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
    * png_do_gray_to_rgb() transformation.
    *
1431
    * TODO: this code needs to be revised to avoid the complexity and
1432 1433 1434 1435 1436 1437 1438
    * 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.
    */
   if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
   {
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1439
       * the file was grayscale the background value is gray.
1440 1441 1442 1443 1444 1445
       */
      if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

   else if (png_ptr->transformations & PNG_COMPOSE)
1446
   {
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.
       */
      if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1453
      {
1454 1455 1456 1457 1458 1459
         if (png_ptr->background.red == png_ptr->background.green &&
             png_ptr->background.red == png_ptr->background.blue)
         {
            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
            png_ptr->background.gray = png_ptr->background.red;
         }
1460
      }
1461
   }
1462 1463
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477

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

1479 1480 1481
   else
      png_init_rgb_transformations(png_ptr);

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

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

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

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

   /* This needs to change - in the palette image case a whole set of tables are
    * built when it would be quicker to just calculate the correct value for
    * each palette entry directly.  Also, the test is too tricky - why check
    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
    * the gamma tables will not be built even if composition is required on a
    * gamma encoded value.
    *
1553
    * In 1.5.4 this is addressed below by an additional check on the individual
1554 1555 1556 1557 1558
    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
    * tables.
    */
   if ((png_ptr->transformations & PNG_GAMMA)
      || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
1559
         && (png_gamma_significant(png_ptr->colorspace.gamma) ||
1560 1561
            png_gamma_significant(png_ptr->screen_gamma)))
      || ((png_ptr->transformations & PNG_COMPOSE)
1562
         && (png_gamma_significant(png_ptr->colorspace.gamma)
1563
            || png_gamma_significant(png_ptr->screen_gamma)
1564
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1565
            || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
1566 1567 1568
               && png_gamma_significant(png_ptr->background_gamma))
#  endif
      )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
1569 1570
         && png_gamma_significant(png_ptr->screen_gamma))
      )
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)
G
Guy Schalnat 已提交
1576
      {
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
         /* 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.
          */
         if (png_ptr->transformations & PNG_RGB_TO_GRAY)
            png_warning(png_ptr,
               "libpng does not support gamma+background+rgb_to_gray");

1587
         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
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))
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 1653 1654 1655 1656 1657 1658 1659 1660 1661
               if (png_gamma_significant(g))
               {
                  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 1747 1748 1749 1750 1751 1752
            if (g_sig)
               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, g);

            if (gs_sig)
               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 1760 1761 1762
               if (g_sig)
               {
                  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 1772 1773 1774
               if (gs_sig)
               {
                  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 /* PNG_READ_BACKGROUND_SUPPORTED */
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
G
[devel]  
Glenn Randers-Pehrson 已提交
1831
#endif /* PNG_READ_GAMMA_SUPPORTED */
1832

1833
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1834 1835 1836
   /* No GAMMA transformation (see the hanging else 4 lines above) */
   if ((png_ptr->transformations & PNG_COMPOSE) &&
       (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 /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
1871

1872
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
1873
   if ((png_ptr->transformations & PNG_SHIFT) &&
1874
      !(png_ptr->transformations & PNG_EXPAND) &&
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  /* PNG_READ_SHIFT_SUPPORTED */
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
A
Andreas Dilger 已提交
1929
   if (png_ptr->transformations & PNG_EXPAND)
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 1951
      }
      else
      {
         if (png_ptr->num_trans)
1952 1953
         {
            if (png_ptr->transformations & PNG_EXPAND_tRNS)
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 1969
#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!
    */
   if (png_ptr->transformations & PNG_COMPOSE)
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 1990 1991 1992 1993 1994 1995 1996 1997 1998
#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
         if (png_ptr->transformations & PNG_SCALE_16_TO_8)
            info_ptr->bit_depth = 8;
#     endif

#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
         if (png_ptr->transformations & PNG_16_TO_8)
            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_SUPPORTED */
2022
   }
G
Guy Schalnat 已提交
2023

2024
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2025
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
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)
2032 2033
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_COLOR);
2034 2035
#endif

2036 2037
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
2038 2039
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2040 2041
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
          png_ptr->palette_lookup && 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 2049 2050 2051 2052 2053 2054 2055
#ifdef PNG_READ_EXPAND_16_SUPPORTED
   if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
      info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
   {
      info_ptr->bit_depth = 16;
   }
#endif

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

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

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

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

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

2079 2080 2081
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

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

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

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

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

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

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

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

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

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

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

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

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

               dp--;
            }
            break;
         }
2167

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

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

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

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

               dp--;
            }
            break;
         }
2191

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

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

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

               dp--;
            }
            break;
         }
2214 2215 2216

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

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

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

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

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

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

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

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

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

2280 2281 2282
         if (!have_shift)
            return;
      }
G
Guy Schalnat 已提交
2283

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

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

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

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

            mask |= mask << 4;
2316

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

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

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

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

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

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

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

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

2381
      while (sp < ep)
G
Guy Schalnat 已提交
2382
      {
2383 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
         /* 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
          */
2414

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
         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:
2605
*/
2606 2607
            sp-=6;
            dp=sp;
2608 2609
         }
      }
2610
#endif
2611 2612 2613 2614
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2615
      {
2616
         /* This inverts the alpha channel in GA */
2617 2618 2619
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2620

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{
   int rgb_error = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

3089 3090 3091
               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3092

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

3099 3100
                  else
                     w = red;
3101
               }
3102 3103

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

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

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

3136 3137 3138
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3139

3140 3141 3142
               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3143

3144 3145
               if (red != green || red != blue)
                  rgb_error |= 1;
3146

3147
               /* From 1.5.5 in the 16 bit case do the accurate conversion even
3148 3149 3150 3151 3152 3153 3154
                * 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);
               *(dp++) = (png_byte)((gray16>>8) & 0xff);
               *(dp++) = (png_byte)(gray16 & 0xff);
3155

3156
               if (have_alpha)
3157
               {
3158
                  *(dp++) = *(sp++);
3159 3160 3161 3162 3163
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3164

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

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

3196
   png_bytep sp;
G
Guy Schalnat 已提交
3197
   png_uint_32 i;
3198
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3199
   int shift;
G
Guy Schalnat 已提交
3200

3201
   png_debug(1, "in png_do_compose");
3202

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

G
Guy Schalnat 已提交
3224 3225 3226 3227 3228
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
3229

G
Guy Schalnat 已提交
3230 3231 3232 3233 3234
                     else
                        shift--;
                  }
                  break;
               }
3235

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

3253 3254
                        else
                        {
3255 3256 3257 3258 3259 3260
                           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);
3261
                        }
3262

3263 3264 3265 3266 3267
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3268

3269 3270
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3271
                     }
3272
                  }
3273

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

3289 3290 3291 3292 3293
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3294

3295 3296
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3297 3298 3299 3300
                     }
                  }
                  break;
               }
3301

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

3319 3320
                        else
                        {
3321 3322 3323 3324 3325 3326
                           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);
3327
                        }
3328

3329 3330 3331 3332 3333
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3334

3335 3336
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3337
                     }
3338
                  }
3339

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

3355 3356 3357 3358 3359
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3360

3361 3362
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3363 3364 3365 3366
                     }
                  }
                  break;
               }
3367

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

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

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

3406
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3407

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

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

3433
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3434

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

               default:
                  break;
G
Guy Schalnat 已提交
3449 3450 3451
            }
            break;
         }
3452

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

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

3507 3508
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3509

3510 3511
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3512

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

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

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

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

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

3554 3555
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3556

3557 3558
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3559

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

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

A
Andreas Dilger 已提交
3593
                     if (a == 0xff)
3594
                        *sp = gamma_table[*sp];
3595

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

A
Andreas Dilger 已提交
3602 3603 3604
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3605

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

3622 3623
                     if (a == 0)
                        *sp = (png_byte)png_ptr->background.gray;
3624

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

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

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

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

A
Andreas Dilger 已提交
3659 3660 3661
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3662

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

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

3690
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3691 3692
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3693

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

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

                     if (a == 0xff)
                     {
3720 3721 3722
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
3723
                     }
3724

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

G
Guy Schalnat 已提交
3733 3734
                     else
                     {
A
Andreas Dilger 已提交
3735
                        png_byte v, w;
G
Guy Schalnat 已提交
3736 3737

                        v = gamma_to_1[*sp];
3738
                        png_composite(w, v, a, png_ptr->background_1.red);
3739 3740
                        if (!optimize) w = gamma_from_1[w];
                        *sp = w;
3741

G
Guy Schalnat 已提交
3742
                        v = gamma_to_1[*(sp + 1)];
3743
                        png_composite(w, v, a, png_ptr->background_1.green);
3744 3745
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 1) = w;
3746

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

3762
                     if (a == 0)
G
Guy Schalnat 已提交
3763
                     {
3764 3765 3766
                        *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 已提交
3767
                     }
3768

3769
                     else if (a < 0xff)
G
Guy Schalnat 已提交
3770
                     {
3771
                        png_composite(*sp, *sp, a, png_ptr->background.red);
3772

3773
                        png_composite(*(sp + 1), *(sp + 1), a,
3774
                            png_ptr->background.green);
3775

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

G
Guy Schalnat 已提交
3794 3795 3796 3797
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3798
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3799 3800
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3801

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

A
Andreas Dilger 已提交
3806
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3807 3808
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3809
                     }
3810

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

G
Guy Schalnat 已提交
3825 3826
                     else
                     {
3827
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
3828 3829

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3830
                        png_composite_16(w, v, a, png_ptr->background_1.red);
3831
                        if (!optimize)
3832 3833
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
                                8];
3834 3835
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
3836

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

3843 3844
                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(w & 0xff);
3845

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

3852 3853
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3854 3855 3856
                     }
                  }
               }
3857

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

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

3880
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
3881
                     {
3882
                        png_uint_16 v;
A
Andreas Dilger 已提交
3883

3884 3885 3886 3887 3888
                        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 已提交
3889

3890
                        png_composite_16(v, r, a, png_ptr->background.red);
3891 3892
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3893

3894
                        png_composite_16(v, g, a, png_ptr->background.green);
3895 3896
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3897

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

         default:
            break;
G
Guy Schalnat 已提交
3910 3911 3912
      }
   }
}
3913
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
G
Guy Schalnat 已提交
3914

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

3933
   png_debug(1, "in png_do_gamma");
3934

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

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

A
Andreas Dilger 已提交
3963
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3964 3965 3966
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
3967

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

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

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

G
Guy Schalnat 已提交
3992 3993
                  *sp = gamma_table[*sp];
                  sp++;
3994

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

G
Guy Schalnat 已提交
3998 3999 4000
                  sp++;
               }
            }
4001

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

A
Andreas Dilger 已提交
4012
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4013 4014 4015
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4016

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

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

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

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

4064
                  *sp = (png_byte)(
4065 4066 4067 4068
                      ((((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) ));
4069 4070 4071
                  sp++;
               }
            }
4072

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

4081
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4082
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4083 4084 4085
                  sp++;
               }
            }
4086

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

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

         default:
            break;
G
Guy Schalnat 已提交
4113 4114 4115
      }
   }
}
G
Guy Schalnat 已提交
4116
#endif
G
Guy Schalnat 已提交
4117

4118 4119 4120 4121 4122
#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.
 */
4123
static void
4124
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184
{
   png_uint_32 row_width = row_info->width;

   png_debug(1, "in png_do_encode_alpha");

   if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
   {
      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

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

4198
   png_debug(1, "in png_do_expand_palette");
4199

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

G
Guy Schalnat 已提交
4216 4217
                  else
                     *dp = 0;
4218

G
Guy Schalnat 已提交
4219 4220 4221 4222 4223
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4224

G
Guy Schalnat 已提交
4225 4226 4227 4228 4229 4230 4231
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4232

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

G
Guy Schalnat 已提交
4248 4249 4250 4251 4252 4253 4254
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4255

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

G
Guy Schalnat 已提交
4271 4272 4273 4274 4275 4276 4277
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4278 4279 4280

            default:
               break;
G
Guy Schalnat 已提交
4281 4282 4283
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4284
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4285
      }
4286

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

4295
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4296
               {
A
Andreas Dilger 已提交
4297
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4298
                     *dp-- = 0xff;
4299

G
Guy Schalnat 已提交
4300
                  else
4301
                     *dp-- = trans_alpha[*sp];
4302

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

G
Guy Schalnat 已提交
4315 4316
            else
            {
4317 4318
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4319

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

G
Guy Schalnat 已提交
4328 4329
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4330
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4331 4332 4333 4334 4335 4336 4337 4338
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

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

4351
   png_debug(1, "in png_do_expand");
4352

G
Guy Schalnat 已提交
4353
   {
A
Andreas Dilger 已提交
4354
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4355
      {
4356
         unsigned int gray = trans_color ? trans_color->gray : 0;
A
Andreas Dilger 已提交
4357 4358

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

A
Andreas Dilger 已提交
4373 4374
                     else
                        *dp = 0;
4375

A
Andreas Dilger 已提交
4376 4377 4378 4379 4380
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4381

A
Andreas Dilger 已提交
4382 4383
                     else
                        shift++;
G
Guy Schalnat 已提交
4384

A
Andreas Dilger 已提交
4385 4386 4387
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4388
               }
4389

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

A
Andreas Dilger 已提交
4407 4408
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4409

A
Andreas Dilger 已提交
4410 4411 4412
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4413
               }
4414

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

A
Andreas Dilger 已提交
4431 4432
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4433

A
Andreas Dilger 已提交
4434 4435 4436
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4437
               }
4438 4439 4440

               default:
                  break;
G
Guy Schalnat 已提交
4441
            }
4442

A
Andreas Dilger 已提交
4443 4444
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4445
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4446
         }
A
Andreas Dilger 已提交
4447

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

4456
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4457
               {
A
Andreas Dilger 已提交
4458 4459
                  if (*sp == gray)
                     *dp-- = 0;
4460

A
Andreas Dilger 已提交
4461 4462
                  else
                     *dp-- = 0xff;
4463

A
Andreas Dilger 已提交
4464
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4465
               }
A
Andreas Dilger 已提交
4466
            }
4467

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

A
Andreas Dilger 已提交
4482 4483 4484 4485 4486
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4487

A
Andreas Dilger 已提交
4488 4489
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4490 4491
               }
            }
4492

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

G
Guy Schalnat 已提交
4514 4515
               else
                  *dp-- = 0xff;
4516

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

G
Guy Schalnat 已提交
4545 4546 4547 4548 4549
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4550

G
Guy Schalnat 已提交
4551 4552 4553 4554
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4555
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4556 4557 4558 4559 4560
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
4561
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4562
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4563 4564 4565
      }
   }
}
G
Guy Schalnat 已提交
4566
#endif
G
Guy Schalnat 已提交
4567

4568
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4569
/* If the bit depth is 8 and the color type is not a palette type expand the
4570 4571
 * whole row to 16 bits.  Has no effect otherwise.
 */
4572
static void
4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598
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

4599
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4600
static void
4601 4602 4603 4604 4605 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 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824
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];
         }
      }
   }
}
#endif /* PNG_READ_QUANTIZE_SUPPORTED */

/* 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 &&
      !(png_ptr->flags & PNG_FLAG_ROW_INIT))
   {
      /* 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
   if (png_ptr->transformations & PNG_EXPAND)
   {
      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
      {
         if (png_ptr->num_trans &&
             (png_ptr->transformations & PNG_EXPAND_tRNS))
            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
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
      !(png_ptr->transformations & PNG_COMPOSE) &&
      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
      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
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
   {
      int rgb_error =
          png_do_rgb_to_gray(png_ptr, row_info,
              png_ptr->row_buf + 1);

      if (rgb_error)
      {
         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
    */
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
      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)
   if (png_ptr->transformations & PNG_COMPOSE)
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4825

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

4848 4849 4850 4851 4852 4853 4854 4855
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
      (png_ptr->transformations & PNG_COMPOSE) &&
      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
         0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif
G
Guy Schalnat 已提交
4856

4857 4858 4859 4860 4861
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
      (row_info->color_type & PNG_COLOR_MASK_ALPHA))
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4862

4863 4864 4865 4866
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
   if (png_ptr->transformations & PNG_SCALE_16_TO_8)
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
#endif
4867

4868 4869 4870 4871 4872 4873 4874 4875
#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.
    */
   if (png_ptr->transformations & PNG_16_TO_8)
      png_do_chop(row_info, png_ptr->row_buf + 1);
#endif
4876

4877 4878 4879 4880 4881
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
   {
      png_do_quantize(row_info, png_ptr->row_buf + 1,
          png_ptr->palette_lookup, png_ptr->quantize_index);
G
Guy Schalnat 已提交
4882

4883 4884 4885 4886
      if (row_info->rowbytes == 0)
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
   }
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
4887

4888 4889 4890 4891 4892 4893 4894 4895 4896
#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!)
    */
   if (png_ptr->transformations & PNG_EXPAND_16)
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
#endif
4897

4898 4899 4900 4901 4902 4903
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
4904

4905 4906 4907 4908
#ifdef PNG_READ_INVERT_SUPPORTED
   if (png_ptr->transformations & PNG_INVERT_MONO)
      png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
4909

4910 4911 4912 4913 4914
#ifdef PNG_READ_SHIFT_SUPPORTED
   if (png_ptr->transformations & PNG_SHIFT)
      png_do_unshift(row_info, png_ptr->row_buf + 1,
          &(png_ptr->shift));
#endif
G
Guy Schalnat 已提交
4915

4916 4917 4918 4919
#ifdef PNG_READ_PACK_SUPPORTED
   if (png_ptr->transformations & PNG_PACK)
      png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
4920

4921 4922 4923 4924 4925 4926
#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
4927

4928 4929 4930 4931
#ifdef PNG_READ_BGR_SUPPORTED
   if (png_ptr->transformations & PNG_BGR)
      png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
4932

4933 4934 4935 4936
#ifdef PNG_READ_PACKSWAP_SUPPORTED
   if (png_ptr->transformations & PNG_PACKSWAP)
      png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
4937

4938 4939 4940 4941 4942
#ifdef PNG_READ_FILLER_SUPPORTED
   if (png_ptr->transformations & PNG_FILLER)
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif
4943

4944 4945 4946 4947
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif
4948

4949 4950 4951 4952
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
4953

4954 4955 4956 4957 4958 4959
#ifdef PNG_READ_16BIT_SUPPORTED
#ifdef PNG_READ_SWAP_SUPPORTED
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_do_swap(row_info, png_ptr->row_buf + 1);
#endif
#endif
4960

4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
    {
      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
      if (png_ptr->user_transform_depth)
         row_info->bit_depth = png_ptr->user_transform_depth;
4978

4979 4980 4981 4982 4983
      if (png_ptr->user_transform_channels)
         row_info->channels = png_ptr->user_transform_channels;
#endif
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
4984

4985
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
4986
   }
4987
#endif
4988
}
4989 4990

#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
4991
#endif /* PNG_READ_SUPPORTED */