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

A
Andreas Dilger 已提交
2
/* pngrtran.c - transforms the data in a row for PNG readers
3
 *
4
 * Copyright (c) 2018-2019 Cosmin Truta
5
 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6 7
 * Copyright (c) 1996-1997 Andreas Dilger
 * 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
#ifdef PNG_ARM_NEON_IMPLEMENTATION
C
Cosmin Truta 已提交
22 23 24 25 26 27 28 29
#  if PNG_ARM_NEON_IMPLEMENTATION == 1
#    define PNG_ARM_NEON_INTRINSICS_AVAILABLE
#    if defined(_MSC_VER) && defined(_M_ARM64)
#      include <arm64_neon.h>
#    else
#      include <arm_neon.h>
#    endif
#  endif
30 31
#endif

32 33
#ifdef PNG_READ_SUPPORTED

34
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
35
void PNGAPI
36
png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
37
{
38
   png_debug(1, "in png_set_crc_action");
39

40 41
   if (png_ptr == NULL)
      return;
42 43

   /* Tell libpng how we react to CRC errors in critical chunks */
44 45
   switch (crit_action)
   {
46
      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
47
         break;
48

49
      case PNG_CRC_WARN_USE:                               /* Warn/use data */
50 51 52
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
         break;
53

54
      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
55 56 57 58
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
                           PNG_FLAG_CRC_CRITICAL_IGNORE;
         break;
59

60
      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
61
         png_warning(png_ptr,
62
             "Can't discard critical data on CRC error");
63
         /* FALLTHROUGH */
64
      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
65

66 67 68 69 70 71
      case PNG_CRC_DEFAULT:
      default:
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         break;
   }

72
   /* Tell libpng how we react to CRC errors in ancillary chunks */
73 74
   switch (ancil_action)
   {
75
      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
76
         break;
77

78
      case PNG_CRC_WARN_USE:                              /* Warn/use data */
79 80 81
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
         break;
82

83
      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
84 85 86 87
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
         break;
88

89
      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
90 91 92
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
         break;
93

94
      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
95

96 97 98 99 100 101 102
      case PNG_CRC_DEFAULT:
      default:
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         break;
   }
}

103 104 105
#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
106 107
 * to have been read in all cases; the need_IHDR parameter allows for this
 * check too.
108 109 110 111 112 113
 */
static int
png_rtran_ok(png_structrp png_ptr, int need_IHDR)
{
   if (png_ptr != NULL)
   {
114
      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
115
         png_app_error(png_ptr,
116
             "invalid after png_start_read_image or png_read_update_info");
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

      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 已提交
134
#ifdef PNG_READ_BACKGROUND_SUPPORTED
135
/* Handle alpha and tRNS via a background color */
G
[devel]  
Glenn Randers-Pehrson 已提交
136
void PNGFAPI
137
png_set_background_fixed(png_structrp png_ptr,
138
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
139
    int need_expand, png_fixed_point background_gamma)
G
Guy Schalnat 已提交
140
{
G
[devel]  
Glenn Randers-Pehrson 已提交
141
   png_debug(1, "in png_set_background_fixed");
142

143
   if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
144
      return;
145

A
Andreas Dilger 已提交
146 147 148 149 150 151
   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
   {
      png_warning(png_ptr, "Application must supply a known background gamma");
      return;
   }

152 153 154 155
   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

156
   png_ptr->background = *background_color;
G
[devel]  
Glenn Randers-Pehrson 已提交
157
   png_ptr->background_gamma = background_gamma;
158
   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
159
   if (need_expand != 0)
160 161 162
      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
   else
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
G
Guy Schalnat 已提交
163
}
G
[devel]  
Glenn Randers-Pehrson 已提交
164 165 166

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
167
png_set_background(png_structrp png_ptr,
168
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
169 170 171 172 173
    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"));
}
174
#  endif /* FLOATING_POINT */
G
[devel]  
Glenn Randers-Pehrson 已提交
175
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
176

177 178 179 180 181
/* 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
182
void PNGAPI
183
png_set_scale_16(png_structrp png_ptr)
G
Guy Schalnat 已提交
184
{
185
   png_debug(1, "in png_set_scale_16");
186

187
   if (png_rtran_ok(png_ptr, 0) == 0)
188
      return;
189

190
   png_ptr->transformations |= PNG_SCALE_16_TO_8;
191
}
192
#endif
193

194
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
195 196
/* Chop 16-bit depth files to 8-bit depth */
void PNGAPI
197
png_set_strip_16(png_structrp png_ptr)
198
{
199
   png_debug(1, "in png_set_strip_16");
200

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

204
   png_ptr->transformations |= PNG_16_TO_8;
G
Guy Schalnat 已提交
205
}
206
#endif
G
Guy Schalnat 已提交
207

208
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
209
void PNGAPI
210
png_set_strip_alpha(png_structrp png_ptr)
A
Andreas Dilger 已提交
211
{
212
   png_debug(1, "in png_set_strip_alpha");
213

214
   if (png_rtran_ok(png_ptr, 0) == 0)
215
      return;
216

217
   png_ptr->transformations |= PNG_STRIP_ALPHA;
A
Andreas Dilger 已提交
218 219 220
}
#endif

221 222
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
static png_fixed_point
223
translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
224
    int is_screen)
225 226 227 228 229 230 231 232 233 234 235 236 237 238
{
   /* 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;
239 240
#     else
         PNG_UNUSED(png_ptr)
241
#     endif
242
      if (is_screen != 0)
243 244 245 246 247 248 249 250
         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)
   {
251
      if (is_screen != 0)
252 253 254 255 256 257 258 259 260 261
         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
262
convert_gamma_value(png_structrp png_ptr, double output_gamma)
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
{
   /* 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 */

285 286
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
void PNGFAPI
287
png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
288
    png_fixed_point output_gamma)
289 290 291 292 293 294
{
   int compose = 0;
   png_fixed_point file_gamma;

   png_debug(1, "in png_set_alpha_mode");

295
   if (png_rtran_ok(png_ptr, 0) == 0)
296 297
      return;

298
   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
299

300
   /* Validate the value to ensure it is in a reasonable range. The value
301 302 303
    * 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
304 305
    * values are reasonable this may have to be changed:
    *
U
Unknown 已提交
306
    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
307
    * gamma of 36, and its reciprocal.)
308
    */
309
   if (output_gamma < 1000 || output_gamma > 10000000)
310
      png_error(png_ptr, "output gamma out of expected range");
311

312
   /* The default file gamma is the inverse of the output gamma; the output
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
    * 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.)
    */
370 371 372 373 374
   if (png_ptr->colorspace.gamma == 0)
   {
      png_ptr->colorspace.gamma = file_gamma;
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   }
375 376 377 378

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

379
   /* Finally, if pre-multiplying, set the background fields to achieve the
380 381
    * desired result.
    */
382
   if (compose != 0)
383 384
   {
      /* And obtain alpha pre-multiplication by composing on black: */
385 386
      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
387 388 389
      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;

390
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
391
         png_error(png_ptr,
392
             "conflicting calls to set alpha mode and background");
393 394 395 396 397 398 399

      png_ptr->transformations |= PNG_COMPOSE;
   }
}

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
400
png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
401
{
402
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
403
       output_gamma));
404 405 406 407
}
#  endif
#endif

408
#ifdef PNG_READ_QUANTIZE_SUPPORTED
409
/* Dither file to 8-bit.  Supply a palette, the current number
410 411
 * of elements in the palette, the maximum number of elements
 * allowed, and a histogram if possible.  If the current number
412
 * of colors is greater than the maximum number, the palette will be
413 414
 * modified to fit in the maximum number.  "full_quantize" indicates
 * whether we need a quantizing cube set up for RGB images, or if we
415 416
 * simply are reducing the number of colors in a paletted image.
 */
G
Guy Schalnat 已提交
417 418

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
419
{
420
   struct png_dsort_struct * next;
G
Guy Schalnat 已提交
421 422
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
423
} png_dsort;
424 425
typedef png_dsort *   png_dsortp;
typedef png_dsort * * png_dsortpp;
G
Guy Schalnat 已提交
426

427
void PNGAPI
428
png_set_quantize(png_structrp png_ptr, png_colorp palette,
429
    int num_palette, int maximum_colors, png_const_uint_16p histogram,
430
    int full_quantize)
G
Guy Schalnat 已提交
431
{
432
   png_debug(1, "in png_set_quantize");
433

434
   if (png_rtran_ok(png_ptr, 0) == 0)
435
      return;
436

437
   png_ptr->transformations |= PNG_QUANTIZE;
G
Guy Schalnat 已提交
438

439
   if (full_quantize == 0)
G
Guy Schalnat 已提交
440 441 442
   {
      int i;

443
      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
444
          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
445
      for (i = 0; i < num_palette; i++)
446
         png_ptr->quantize_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
447 448 449 450
   }

   if (num_palette > maximum_colors)
   {
A
Andreas Dilger 已提交
451
      if (histogram != NULL)
G
Guy Schalnat 已提交
452
      {
A
Andreas Dilger 已提交
453
         /* This is easy enough, just throw out the least used colors.
454 455
          * Perhaps not the best solution, but good enough.
          */
G
Guy Schalnat 已提交
456 457 458

         int i;

459
         /* Initialize an array to sort colors */
460
         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
461
             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
G
Guy Schalnat 已提交
462

463
         /* Initialize the quantize_sort array */
G
Guy Schalnat 已提交
464
         for (i = 0; i < num_palette; i++)
465
            png_ptr->quantize_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
466

A
Andreas Dilger 已提交
467
         /* Find the least used palette entries by starting a
468 469 470 471 472
          * 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 已提交
473 474 475

         for (i = num_palette - 1; i >= maximum_colors; i--)
         {
476
            int done; /* To stop early if the list is pre-sorted */
G
Guy Schalnat 已提交
477
            int j;
G
Guy Schalnat 已提交
478 479 480 481

            done = 1;
            for (j = 0; j < i; j++)
            {
482 483
               if (histogram[png_ptr->quantize_sort[j]]
                   < histogram[png_ptr->quantize_sort[j + 1]])
G
Guy Schalnat 已提交
484 485 486
               {
                  png_byte t;

487 488 489
                  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 已提交
490 491 492
                  done = 0;
               }
            }
493

494
            if (done != 0)
G
Guy Schalnat 已提交
495 496 497
               break;
         }

498
         /* Swap the palette around, and set up a table, if necessary */
499
         if (full_quantize != 0)
G
Guy Schalnat 已提交
500
         {
501
            int j = num_palette;
G
Guy Schalnat 已提交
502

503 504 505
            /* Put all the useful colors within the max, but don't
             * move the others.
             */
506
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
507
            {
508
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
509 510 511
               {
                  do
                     j--;
512
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
513

G
Guy Schalnat 已提交
514 515
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
516
            }
G
Guy Schalnat 已提交
517 518 519
         }
         else
         {
520
            int j = num_palette;
G
Guy Schalnat 已提交
521

522 523 524
            /* Move all the used colors inside the max limit, and
             * develop a translation table.
             */
525
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
526
            {
527
               /* Only move the colors we need to */
528
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
529 530 531 532 533
               {
                  png_color tmp_color;

                  do
                     j--;
534
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
535 536 537 538

                  tmp_color = palette[j];
                  palette[j] = palette[i];
                  palette[i] = tmp_color;
539
                  /* Indicate where the color went */
540 541
                  png_ptr->quantize_index[j] = (png_byte)i;
                  png_ptr->quantize_index[i] = (png_byte)j;
G
Guy Schalnat 已提交
542 543
               }
            }
A
Andreas Dilger 已提交
544

545
            /* Find closest color for those colors we are not using */
G
Guy Schalnat 已提交
546 547
            for (i = 0; i < num_palette; i++)
            {
548
               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
G
Guy Schalnat 已提交
549
               {
A
Andreas Dilger 已提交
550
                  int min_d, k, min_k, d_index;
G
Guy Schalnat 已提交
551

552
                  /* Find the closest color to one we threw out */
553
                  d_index = png_ptr->quantize_index[i];
A
Andreas Dilger 已提交
554 555
                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
                  for (k = 1, min_k = 0; k < maximum_colors; k++)
G
Guy Schalnat 已提交
556 557 558
                  {
                     int d;

A
Andreas Dilger 已提交
559
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
560 561 562 563

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
564
                        min_k = k;
G
Guy Schalnat 已提交
565 566
                     }
                  }
567
                  /* Point to closest color */
568
                  png_ptr->quantize_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
569 570 571
               }
            }
         }
572 573
         png_free(png_ptr, png_ptr->quantize_sort);
         png_ptr->quantize_sort = NULL;
G
Guy Schalnat 已提交
574 575 576
      }
      else
      {
A
Andreas Dilger 已提交
577
         /* This is much harder to do simply (and quickly).  Perhaps
578 579 580 581 582 583 584
          * 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 已提交
585 586 587
         int i;
         int max_d;
         int num_new_palette;
588
         png_dsortp t;
G
Guy Schalnat 已提交
589
         png_dsortpp hash;
590

591
         t = NULL;
G
Guy Schalnat 已提交
592

593
         /* Initialize palette index arrays */
594
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
595 596
             (png_alloc_size_t)((png_uint_32)num_palette *
             (sizeof (png_byte))));
597
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
598 599
             (png_alloc_size_t)((png_uint_32)num_palette *
             (sizeof (png_byte))));
G
Guy Schalnat 已提交
600

601
         /* Initialize the sort array */
G
Guy Schalnat 已提交
602 603
         for (i = 0; i < num_palette; i++)
         {
604 605
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
606 607
         }

608
         hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
609
             (sizeof (png_dsortp))));
G
Guy Schalnat 已提交
610 611 612

         num_new_palette = num_palette;

613 614 615 616 617 618 619 620
         /* 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 已提交
621 622
         max_d = 96;

G
Guy Schalnat 已提交
623
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
624 625 626 627 628 629 630 631 632
         {
            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 已提交
633
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
634 635 636 637

                  if (d <= max_d)
                  {

638
                     t = (png_dsortp)png_malloc_warn(png_ptr,
639
                         (png_alloc_size_t)(sizeof (png_dsort)));
640

641 642
                     if (t == NULL)
                         break;
643

G
Guy Schalnat 已提交
644
                     t->next = hash[d];
G
Guy Schalnat 已提交
645 646
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
647 648 649
                     hash[d] = t;
                  }
               }
650 651
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
652 653
            }

654
            if (t != NULL)
G
Guy Schalnat 已提交
655 656
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
657
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
658
               {
G
Guy Schalnat 已提交
659
                  png_dsortp p;
G
Guy Schalnat 已提交
660 661 662

                  for (p = hash[i]; p; p = p->next)
                  {
663
                     if ((int)png_ptr->index_to_palette[p->left]
664 665 666
                         < num_new_palette &&
                         (int)png_ptr->index_to_palette[p->right]
                         < num_new_palette)
G
Guy Schalnat 已提交
667 668 669
                     {
                        int j, next_j;

670
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
671 672 673 674 675 676 677 678 679 680 681
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
682
                        palette[png_ptr->index_to_palette[j]]
683
                            = palette[num_new_palette];
684
                        if (full_quantize == 0)
G
Guy Schalnat 已提交
685 686 687 688 689
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
690
                              if (png_ptr->quantize_index[k] ==
691
                                  png_ptr->index_to_palette[j])
692
                                 png_ptr->quantize_index[k] =
693
                                     png_ptr->index_to_palette[next_j];
694

695
                              if ((int)png_ptr->quantize_index[k] ==
696
                                  num_new_palette)
697
                                 png_ptr->quantize_index[k] =
698
                                     png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
699 700 701
                           }
                        }

702
                        png_ptr->index_to_palette[png_ptr->palette_to_index
703
                            [num_new_palette]] = png_ptr->index_to_palette[j];
704

705
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
706
                            = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
707

708 709
                        png_ptr->index_to_palette[j] =
                            (png_byte)num_new_palette;
710

711 712
                        png_ptr->palette_to_index[num_new_palette] =
                            (png_byte)j;
G
Guy Schalnat 已提交
713 714 715 716 717 718 719 720 721 722 723
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

            for (i = 0; i < 769; i++)
            {
A
Andreas Dilger 已提交
724
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
725
               {
726
                  png_dsortp p = hash[i];
G
Guy Schalnat 已提交
727 728 729
                  while (p)
                  {
                     t = p->next;
A
Andreas Dilger 已提交
730
                     png_free(png_ptr, p);
G
Guy Schalnat 已提交
731 732 733 734 735 736 737
                     p = t;
                  }
               }
               hash[i] = 0;
            }
            max_d += 96;
         }
A
Andreas Dilger 已提交
738
         png_free(png_ptr, hash);
739 740
         png_free(png_ptr, png_ptr->palette_to_index);
         png_free(png_ptr, png_ptr->index_to_palette);
741 742
         png_ptr->palette_to_index = NULL;
         png_ptr->index_to_palette = NULL;
G
Guy Schalnat 已提交
743 744 745
      }
      num_palette = maximum_colors;
   }
A
Andreas Dilger 已提交
746
   if (png_ptr->palette == NULL)
G
Guy Schalnat 已提交
747
   {
G
Guy Schalnat 已提交
748 749
      png_ptr->palette = palette;
   }
G
Guy Schalnat 已提交
750
   png_ptr->num_palette = (png_uint_16)num_palette;
G
Guy Schalnat 已提交
751

752
   if (full_quantize != 0)
G
Guy Schalnat 已提交
753 754
   {
      int i;
G
Guy Schalnat 已提交
755
      png_bytep distance;
756 757 758 759 760
      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);
761
      size_t num_entries = ((size_t)1 << total_bits);
G
Guy Schalnat 已提交
762

763
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
764
          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
765

766
      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
767
          (sizeof (png_byte))));
768

769
      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
770 771 772

      for (i = 0; i < num_palette; i++)
      {
773
         int ir, ig, ib;
774 775 776
         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 已提交
777 778 779

         for (ir = 0; ir < num_red; ir++)
         {
780 781
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
782 783
            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
                PNG_QUANTIZE_GREEN_BITS));
G
Guy Schalnat 已提交
784 785

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
786
            {
787 788
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
789 790
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
791
               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
G
Guy Schalnat 已提交
792 793

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
794
               {
795
                  int d_index = index_g | ib;
796 797
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
798 799
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
800

801
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
802
                  {
A
Andreas Dilger 已提交
803 804
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
805 806
                  }
               }
807 808 809
            }
         }
      }
G
Guy Schalnat 已提交
810

A
Andreas Dilger 已提交
811
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
812 813
   }
}
814
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
815

G
[devel]  
Glenn Randers-Pehrson 已提交
816 817
#ifdef PNG_READ_GAMMA_SUPPORTED
void PNGFAPI
818
png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
819
    png_fixed_point file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
820 821
{
   png_debug(1, "in png_set_gamma_fixed");
822

823
   if (png_rtran_ok(png_ptr, 0) == 0)
824
      return;
825

826
   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
827 828 829
   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);

830
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
831 832 833
    * 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
834
    * was being used; however, png_set_background itself accepted and must still
835 836 837
    * 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
838 839
    * undocumented API feature) the following checks were only enabled in
    * libpng-1.6.0.
840 841
    */
   if (file_gamma <= 0)
842
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
843 844

   if (scrn_gamma <= 0)
845
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
846 847 848 849 850

   /* 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.
    */
851 852
   png_ptr->colorspace.gamma = file_gamma;
   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
G
[devel]  
Glenn Randers-Pehrson 已提交
853
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
854
}
G
[devel]  
Glenn Randers-Pehrson 已提交
855 856 857

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
858
png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
859
{
860
   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
861
       convert_gamma_value(png_ptr, file_gamma));
G
[devel]  
Glenn Randers-Pehrson 已提交
862
}
863
#  endif /* FLOATING_POINT */
G
[devel]  
Glenn Randers-Pehrson 已提交
864
#endif /* READ_GAMMA */
G
Guy Schalnat 已提交
865

866
#ifdef PNG_READ_EXPAND_SUPPORTED
867
/* Expand paletted images to RGB, expand grayscale images of
868
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
869 870
 * to alpha channels.
 */
871
void PNGAPI
872
png_set_expand(png_structrp png_ptr)
G
Guy Schalnat 已提交
873
{
874
   png_debug(1, "in png_set_expand");
875

876
   if (png_rtran_ok(png_ptr, 0) == 0)
877
      return;
878

879
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
G
Guy Schalnat 已提交
880
}
881 882 883 884 885 886 887 888 889 890 891 892 893

/* 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.
894
 *
895 896 897
 *  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().
898 899 900
 */

/* Expand paletted images to RGB. */
901
void PNGAPI
902
png_set_palette_to_rgb(png_structrp png_ptr)
903
{
904
   png_debug(1, "in png_set_palette_to_rgb");
905

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

909 910 911 912 913
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
}

/* Expand grayscale images of less than 8-bit depth to 8 bits. */
void PNGAPI
914
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
915
{
916
   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
917

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

921
   png_ptr->transformations |= PNG_EXPAND;
922 923 924
}

/* Expand tRNS chunks to alpha channels. */
925
void PNGAPI
926
png_set_tRNS_to_alpha(png_structrp png_ptr)
927
{
928
   png_debug(1, "in png_set_tRNS_to_alpha");
929

930
   if (png_rtran_ok(png_ptr, 0) == 0)
931 932
      return;

933
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
934
}
935
#endif /* READ_EXPAND */
G
Guy Schalnat 已提交
936

937
#ifdef PNG_READ_EXPAND_16_SUPPORTED
938
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
939 940 941
 * it may not work correctly.)
 */
void PNGAPI
942
png_set_expand_16(png_structrp png_ptr)
943 944 945
{
   png_debug(1, "in png_set_expand_16");

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

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

953
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
954
void PNGAPI
955
png_set_gray_to_rgb(png_structrp png_ptr)
G
Guy Schalnat 已提交
956
{
957
   png_debug(1, "in png_set_gray_to_rgb");
958

959
   if (png_rtran_ok(png_ptr, 0) == 0)
960 961 962 963 964
      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 已提交
965
}
G
Guy Schalnat 已提交
966
#endif
G
Guy Schalnat 已提交
967

968
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
969
void PNGFAPI
970
png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
971
    png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
972
{
973
   png_debug(1, "in png_set_rgb_to_gray");
974

975 976
   /* Need the IHDR here because of the check on color_type below. */
   /* TODO: fix this */
977
   if (png_rtran_ok(png_ptr, 1) == 0)
978
      return;
979

980
   switch (error_action)
981
   {
982
      case PNG_ERROR_ACTION_NONE:
983 984
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
         break;
985

986
      case PNG_ERROR_ACTION_WARN:
987 988
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
989

990
      case PNG_ERROR_ACTION_ERROR:
991
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
992 993 994
         break;

      default:
995
         png_error(png_ptr, "invalid error action to rgb_to_gray");
996
   }
997

998
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
999
#ifdef PNG_READ_EXPAND_SUPPORTED
1000 1001 1002
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
1003 1004 1005 1006
      /* 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,
1007
          "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
1008

1009
      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
1010 1011 1012
   }
#endif
   {
1013
      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
1014
      {
1015
         png_uint_16 red_int, green_int;
1016

1017
         /* NOTE: this calculation does not round, but this behavior is retained
1018
          * for consistency; the inaccuracy is very small.  The code here always
1019 1020 1021
          * overwrites the coefficients, regardless of whether they have been
          * defaulted or set already.
          */
1022 1023
         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
1024 1025 1026

         png_ptr->rgb_to_gray_red_coeff   = red_int;
         png_ptr->rgb_to_gray_green_coeff = green_int;
1027
         png_ptr->rgb_to_gray_coefficients_set = 1;
1028
      }
1029

1030
      else
1031
      {
1032
         if (red >= 0 && green >= 0)
1033
            png_app_warning(png_ptr,
1034
                "ignoring out of range rgb_to_gray coefficients");
1035

1036 1037 1038 1039 1040
         /* 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.
1041 1042
          */
         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
1043
             png_ptr->rgb_to_gray_green_coeff == 0)
1044
         {
1045 1046 1047
            png_ptr->rgb_to_gray_red_coeff   = 6968;
            png_ptr->rgb_to_gray_green_coeff = 23434;
            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1048 1049
         }
      }
1050
   }
A
Andreas Dilger 已提交
1051
}
1052 1053 1054 1055 1056 1057 1058

#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
1059
png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
1060
    double green)
1061
{
G
[devel]  
Glenn Randers-Pehrson 已提交
1062
   png_set_rgb_to_gray_fixed(png_ptr, error_action,
1063
       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
G
[devel]  
Glenn Randers-Pehrson 已提交
1064
      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1065 1066 1067
}
#endif /* FLOATING POINT */

1068
#endif /* RGB_TO_GRAY */
A
Andreas Dilger 已提交
1069

1070
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1071
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1072
void PNGAPI
1073
png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1074
    read_user_transform_fn)
1075
{
1076
   png_debug(1, "in png_set_read_user_transform_fn");
1077

1078
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1079 1080
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1081
#endif
1082 1083 1084
}
#endif

1085
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
#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 已提交
1107
/* Initialize everything needed for the read.  This includes modifying
1108 1109
 * the palette.
 */
1110

1111
/* For the moment 'png_init_palette_transformations' and
1112 1113 1114 1115 1116
 * '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 */
1117
png_init_palette_transformations(png_structrp png_ptr)
G
Guy Schalnat 已提交
1118
{
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
   /* 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;
1129

1130 1131 1132 1133 1134 1135
   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)
1136
      {
1137 1138 1139 1140 1141
         if (png_ptr->trans_alpha[i] == 255)
            continue;
         else if (png_ptr->trans_alpha[i] == 0)
            input_has_transparency = 1;
         else
1142 1143
         {
            input_has_transparency = 1;
1144
            input_has_alpha = 1;
1145 1146 1147
            break;
         }
      }
1148 1149 1150
   }

   /* If no alpha we can optimize. */
1151
   if (input_has_alpha == 0)
1152 1153
   {
      /* Any alpha means background and associative alpha processing is
1154
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1155 1156 1157 1158 1159
       * and ENCODE_ALPHA are irrelevant.
       */
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

1160
      if (input_has_transparency == 0)
1161 1162
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
   }
G
Guy Schalnat 已提交
1163

1164
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1165 1166 1167 1168
   /* 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.
    */
1169

1170 1171
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1172
    */
1173 1174
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) != 0)
1175
   {
1176 1177 1178 1179 1180 1181 1182 1183 1184
      {
         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
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
         if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
         {
            if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
            {
               /* 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]);
            }
         }
1199
#endif /* READ_INVERT_ALPHA */
1200 1201
      }
   } /* background expand and (therefore) no alpha association. */
1202
#endif /* READ_EXPAND && READ_BACKGROUND */
1203 1204 1205
}

static void /* PRIVATE */
1206
png_init_rgb_transformations(png_structrp png_ptr)
1207
{
1208
   /* Added to libpng-1.5.4: check the color type to determine whether there
1209 1210 1211 1212 1213
    * 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;
1214

1215
   /* If no alpha we can optimize. */
1216
   if (input_has_alpha == 0)
1217
   {
1218
      /* Any alpha means background and associative alpha processing is
1219
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1220 1221 1222 1223 1224 1225 1226
       * 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

1227
      if (input_has_transparency == 0)
1228
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1229 1230
   }

1231 1232 1233 1234 1235 1236 1237 1238 1239
#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.
    */
1240 1241 1242
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) != 0 &&
       (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1243
       /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
1244 1245
   {
      {
1246
         /* Expand background and tRNS chunks */
1247 1248 1249
         int gray = png_ptr->background.gray;
         int trans_gray = png_ptr->trans_color.gray;

G
Guy Schalnat 已提交
1250 1251 1252
         switch (png_ptr->bit_depth)
         {
            case 1:
1253 1254
               gray *= 0xff;
               trans_gray *= 0xff;
G
Guy Schalnat 已提交
1255
               break;
1256

G
Guy Schalnat 已提交
1257
            case 2:
1258 1259
               gray *= 0x55;
               trans_gray *= 0x55;
G
Guy Schalnat 已提交
1260
               break;
1261

G
Guy Schalnat 已提交
1262
            case 4:
1263 1264
               gray *= 0x11;
               trans_gray *= 0x11;
G
Guy Schalnat 已提交
1265
               break;
1266

1267 1268
            default:

G
Guy Schalnat 已提交
1269
            case 8:
1270
               /* FALLTHROUGH */ /*  (Already 8 bits) */
1271

G
Guy Schalnat 已提交
1272
            case 16:
1273
               /* Already a full 16 bits */
G
Guy Schalnat 已提交
1274 1275
               break;
         }
1276 1277 1278 1279

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

1280
         if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1281 1282 1283 1284
         {
            png_ptr->trans_color.red = png_ptr->trans_color.green =
               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
         }
G
Guy Schalnat 已提交
1285
      }
1286
   } /* background expand and (therefore) no alpha association. */
1287
#endif /* READ_EXPAND && READ_BACKGROUND */
1288
}
1289

1290
void /* PRIVATE */
1291
png_init_read_transformations(png_structrp png_ptr)
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
{
   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
1304
   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1305
    * png_set_alpha_mode and this is another source for a default file gamma so
1306
    * the test needs to be performed later - here.  In addition prior to 1.5.4
1307 1308 1309 1310 1311 1312 1313 1314
    * 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;
1315

1316
      if (png_ptr->colorspace.gamma != 0) /* has been set */
1317 1318
      {
         if (png_ptr->screen_gamma != 0) /* screen set too */
1319
            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1320
                png_ptr->screen_gamma);
1321 1322 1323 1324 1325

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

      else if (png_ptr->screen_gamma != 0)
         /* The converse - assume the file matches the screen, note that this
U
Unknown 已提交
1331
          * perhaps undesirable default can (from 1.5.4) be changed by calling
1332 1333 1334
          * png_set_alpha_mode (even if the alpha handling mode isn't required
          * or isn't changed from the default.)
          */
1335
         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
1336 1337 1338 1339 1340

      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,
1341
          * prior to 1.5.4
1342
          */
1343 1344 1345 1346
         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;
1347 1348 1349 1350 1351 1352 1353 1354 1355

      /* 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.
       */
1356
      if (gamma_correction != 0)
1357 1358 1359 1360
         png_ptr->transformations |= PNG_GAMMA;

      else
         png_ptr->transformations &= ~PNG_GAMMA;
G
Guy Schalnat 已提交
1361
   }
G
Guy Schalnat 已提交
1362
#endif
G
Guy Schalnat 已提交
1363

1364
   /* Certain transformations have the effect of preventing other
1365
    * transformations that happen afterward in png_do_read_transformations;
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
    * 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
1377 1378 1379 1380 1381 1382
    *  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
1383 1384 1385 1386 1387 1388
    * 15) PNG_INVERT_ALPHA
    * 16) PNG_SHIFT
    * 17) PNG_PACK
    * 18) PNG_BGR
    * 19) PNG_PACKSWAP
    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1389 1390 1391
    * 21) PNG_SWAP_ALPHA
    * 22) PNG_SWAP_BYTES
    * 23) PNG_USER_TRANSFORM [must be last]
1392 1393
    */
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1394 1395
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) == 0)
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
   {
      /* 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;

1406
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1407 1408 1409 1410
       * 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
1411
       * get.)  This makes the behavior consistent from 1.5.4:
1412 1413 1414 1415 1416 1417 1418 1419 1420
       */
      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.
    */
1421
   if (png_gamma_significant(png_ptr->screen_gamma) == 0)
1422 1423 1424 1425
   {
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   }
G
Guy Schalnat 已提交
1426
#endif
1427

1428 1429 1430 1431
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
   /* Make sure the coefficients for the rgb to gray conversion are set
    * appropriately.
    */
1432
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1433 1434 1435 1436 1437
      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)
1438 1439 1440 1441 1442 1443 1444 1445 1446 1447
   /* 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.
    *
1448
    * TODO: this code needs to be revised to avoid the complexity and
1449 1450 1451 1452
    * 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.
    */
1453
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1454 1455
   {
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1456
       * the file was grayscale the background value is gray.
1457
       */
1458
      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1459 1460 1461
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

1462
   else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1463
   {
1464 1465 1466 1467 1468
      /* 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.
       */
1469
      if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
1470
      {
1471 1472 1473 1474 1475 1476
         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;
         }
1477
      }
1478
   }
1479 1480
#endif /* READ_EXPAND && READ_BACKGROUND */
#endif /* READ_GRAY_TO_RGB */
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494

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

1496 1497 1498
   else
      png_init_rgb_transformations(png_ptr);

1499 1500
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   defined(PNG_READ_EXPAND_16_SUPPORTED)
1501 1502 1503 1504
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
       png_ptr->bit_depth != 16)
1505 1506 1507
   {
      /* 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
1508
       * application will supply a 16-bit value so reduce it here.
1509 1510 1511
       *
       * 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.)
1512 1513 1514
       *
       * NOTE: this discards the low 16 bits of the user supplied background
       * color, but until expand_16 works properly there is no choice!
1515
       */
1516
#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1517 1518 1519 1520
      CHOP(png_ptr->background.red);
      CHOP(png_ptr->background.green);
      CHOP(png_ptr->background.blue);
      CHOP(png_ptr->background.gray);
1521 1522
#     undef CHOP
   }
1523
#endif /* READ_BACKGROUND && READ_EXPAND_16 */
1524

1525 1526 1527
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
1528 1529 1530 1531
   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
       png_ptr->bit_depth == 16)
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
   {
      /* 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

1547 1548 1549 1550
   /* 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
1551
    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
    * 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.
    *
1570
    * In 1.5.4 this is addressed below by an additional check on the individual
1571 1572 1573
    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
    * tables.
    */
1574 1575 1576 1577 1578 1579 1580
   if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
       ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
         png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
        ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
          png_gamma_significant(png_ptr->screen_gamma) != 0
1581
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1582 1583
         || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
           png_gamma_significant(png_ptr->background_gamma) != 0)
1584
#  endif
1585 1586
        )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       png_gamma_significant(png_ptr->screen_gamma) != 0))
G
Guy Schalnat 已提交
1587
   {
1588
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1589

1590
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1591
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
G
Guy Schalnat 已提交
1592
      {
1593 1594 1595 1596 1597 1598
         /* 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.
          */
1599
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1600
            png_warning(png_ptr,
1601
                "libpng does not support gamma+background+rgb_to_gray");
1602

1603
         if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
G
Guy Schalnat 已提交
1604
         {
1605 1606 1607
            /* 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 已提交
1608
            png_color back, back_1;
1609 1610 1611
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1612 1613
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1614

A
Andreas Dilger 已提交
1615 1616 1617 1618 1619 1620 1621 1622 1623 1624
               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 已提交
1625
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1626

1627 1628 1629 1630
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
G
[devel]  
Glenn Randers-Pehrson 已提交
1631
                     gs = PNG_FP_1;
1632
                     break;
1633

1634
                  case PNG_BACKGROUND_GAMMA_FILE:
1635 1636
                     g = png_reciprocal(png_ptr->colorspace.gamma);
                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
1637
                         png_ptr->screen_gamma);
1638
                     break;
1639

1640
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1641 1642
                     g = png_reciprocal(png_ptr->background_gamma);
                     gs = png_reciprocal2(png_ptr->background_gamma,
1643
                         png_ptr->screen_gamma);
1644 1645
                     break;
                  default:
G
[devel]  
Glenn Randers-Pehrson 已提交
1646 1647
                     g = PNG_FP_1;    /* back_1 */
                     gs = PNG_FP_1;   /* back */
1648
                     break;
1649
               }
A
Andreas Dilger 已提交
1650

1651
               if (png_gamma_significant(gs) != 0)
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
               {
                  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 已提交
1662
               {
1663
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1664
                  back.green = (png_byte)png_ptr->background.green;
1665
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1666
               }
1667

1668
               if (png_gamma_significant(g) != 0)
1669 1670
               {
                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
1671
                      g);
1672
                  back_1.green = png_gamma_8bit_correct(
1673
                      png_ptr->background.green, g);
1674
                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1675
                      g);
1676 1677
               }

A
Andreas Dilger 已提交
1678 1679
               else
               {
1680 1681 1682
                  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 已提交
1683 1684
               }
            }
1685

G
Guy Schalnat 已提交
1686 1687
            for (i = 0; i < num_palette; i++)
            {
1688 1689
               if (i < (int)png_ptr->num_trans &&
                   png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1690
               {
1691
                  if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1692 1693 1694
                  {
                     palette[i] = back;
                  }
1695
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
G
Guy Schalnat 已提交
1696
                  {
A
Andreas Dilger 已提交
1697
                     png_byte v, w;
G
Guy Schalnat 已提交
1698 1699

                     v = png_ptr->gamma_to_1[palette[i].red];
1700
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
1701 1702 1703
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
1704
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
G
Guy Schalnat 已提交
1705 1706 1707
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
1708
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
                     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];
               }
            }
1719 1720 1721

            /* Prevent the transformations being done again.
             *
1722
             * NOTE: this is highly dubious; it removes the transformations in
1723 1724
             * place.  This seems inconsistent with the general treatment of the
             * transformations elsewhere.
1725
             */
1726 1727
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1728

1729
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1730
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1731
         {
1732 1733 1734
            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 已提交
1735 1736

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1737
            {
G
Guy Schalnat 已提交
1738
               case PNG_BACKGROUND_GAMMA_SCREEN:
G
[devel]  
Glenn Randers-Pehrson 已提交
1739 1740
                  g = png_ptr->screen_gamma;
                  /* gs = PNG_FP_1; */
G
Guy Schalnat 已提交
1741
                  break;
1742

G
Guy Schalnat 已提交
1743
               case PNG_BACKGROUND_GAMMA_FILE:
1744 1745
                  g = png_reciprocal(png_ptr->colorspace.gamma);
                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
1746
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1747
                  break;
1748

G
Guy Schalnat 已提交
1749
               case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1750 1751
                  g = png_reciprocal(png_ptr->background_gamma);
                  gs = png_reciprocal2(png_ptr->background_gamma,
1752
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1753
                  break;
1754 1755

               default:
1756
                  png_error(png_ptr, "invalid background gamma type");
G
Guy Schalnat 已提交
1757 1758
            }

1759 1760
            g_sig = png_gamma_significant(g);
            gs_sig = png_gamma_significant(gs);
1761

1762
            if (g_sig != 0)
1763 1764 1765
               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, g);

1766
            if (gs_sig != 0)
1767 1768
               png_ptr->background.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, gs);
1769

1770 1771 1772
            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 已提交
1773
            {
1774
               /* RGB or RGBA with color background */
1775
               if (g_sig != 0)
1776 1777 1778
               {
                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, g);
1779

1780 1781
                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, g);
1782

1783 1784 1785
                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, g);
               }
1786

1787
               if (gs_sig != 0)
1788 1789 1790
               {
                  png_ptr->background.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, gs);
1791

1792 1793
                  png_ptr->background.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, gs);
1794

1795 1796 1797
                  png_ptr->background.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, gs);
               }
G
Guy Schalnat 已提交
1798
            }
1799

G
Guy Schalnat 已提交
1800 1801
            else
            {
1802 1803
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
1804
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1805

1806
               png_ptr->background.red = png_ptr->background.green
1807
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1808
            }
1809 1810 1811

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

G
Guy Schalnat 已提交
1815
      else
1816
      /* Transformation does not include PNG_BACKGROUND */
1817
#endif /* READ_BACKGROUND */
1818 1819 1820 1821 1822 1823 1824
      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 已提交
1825
      {
1826 1827 1828
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1829

1830 1831
         /* NOTE: there are other transformations that should probably be in
          * here too.
1832
          */
G
Guy Schalnat 已提交
1833 1834 1835 1836 1837 1838
         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];
         }
1839

1840 1841
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
1842
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
G
Guy Schalnat 已提交
1843
   }
1844
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1845
   else
G
Guy Schalnat 已提交
1846
#endif
1847
#endif /* READ_GAMMA */
1848

1849
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1850
   /* No GAMMA transformation (see the hanging else 4 lines above) */
1851
   if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1852
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1853
   {
1854 1855
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
1856
      png_color back;
1857
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
1858 1859 1860 1861 1862

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

1863
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1864
      {
1865
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1866 1867 1868
         {
            palette[i] = back;
         }
1869

1870
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1871
         {
1872
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1873
            png_composite(palette[i].red, palette[i].red,
1874
                png_ptr->trans_alpha[i], back.red);
1875

A
Andreas Dilger 已提交
1876
            png_composite(palette[i].green, palette[i].green,
1877
                png_ptr->trans_alpha[i], back.green);
1878

A
Andreas Dilger 已提交
1879
            png_composite(palette[i].blue, palette[i].blue,
1880
                png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1881 1882
         }
      }
1883

1884
      png_ptr->transformations &= ~PNG_COMPOSE;
G
Guy Schalnat 已提交
1885
   }
1886
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
1887

1888
#ifdef PNG_READ_SHIFT_SUPPORTED
1889 1890
   if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
       (png_ptr->transformations & PNG_EXPAND) == 0 &&
1891
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1892
   {
1893 1894 1895
      int i;
      int istop = png_ptr->num_palette;
      int shift = 8 - png_ptr->sig_bit.red;
G
Guy Schalnat 已提交
1896

1897 1898
      png_ptr->transformations &= ~PNG_SHIFT;

U
Unknown 已提交
1899
      /* significant bits can be in the range 1 to 7 for a meaningful result, if
1900 1901 1902
       * the number of significant bits is 0 then no shift is done (this is an
       * error condition which is silently ignored.)
       */
1903 1904 1905 1906
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].red;
1907

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

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

1918 1919 1920
            component >>= shift;
            png_ptr->palette[i].green = (png_byte)component;
         }
1921 1922

      shift = 8 - png_ptr->sig_bit.blue;
1923 1924 1925 1926
      if (shift > 0 && shift < 8)
         for (i=0; i<istop; ++i)
         {
            int component = png_ptr->palette[i].blue;
1927

1928 1929 1930
            component >>= shift;
            png_ptr->palette[i].blue = (png_byte)component;
         }
G
Guy Schalnat 已提交
1931
   }
1932
#endif /* READ_SHIFT */
G
Guy Schalnat 已提交
1933 1934
}

A
Andreas Dilger 已提交
1935
/* Modify the info structure to reflect the transformations.  The
1936 1937 1938
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1939
void /* PRIVATE */
1940
png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
1941
{
1942
   png_debug(1, "in png_read_transform_info");
1943

1944
#ifdef PNG_READ_EXPAND_SUPPORTED
1945
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
G
Guy Schalnat 已提交
1946
   {
A
Andreas Dilger 已提交
1947 1948
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
1949
         /* This check must match what actually happens in
1950
          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1951 1952 1953
          * it is all opaque we must do the same (at present it does not.)
          */
         if (png_ptr->num_trans > 0)
A
Andreas Dilger 已提交
1954
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1955

A
Andreas Dilger 已提交
1956 1957
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1958

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

         if (png_ptr->palette == NULL)
            png_error (png_ptr, "Palette is NULL in indexed image");
A
Andreas Dilger 已提交
1964 1965 1966
      }
      else
      {
1967
         if (png_ptr->num_trans != 0)
1968
         {
1969
            if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
1970
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1971
         }
A
Andreas Dilger 已提交
1972 1973
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1974

A
Andreas Dilger 已提交
1975 1976
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1977 1978 1979
   }
#endif

1980 1981 1982 1983 1984
#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!
    */
1985
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
G
Guy Schalnat 已提交
1986 1987 1988
      info_ptr->background = png_ptr->background;
#endif

1989
#ifdef PNG_READ_GAMMA_SUPPORTED
1990
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1991 1992 1993
    * 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.
1994 1995 1996 1997
    *
    * 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.
1998
    */
1999
   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
2000
#endif
2001

2002 2003
   if (info_ptr->bit_depth == 16)
   {
2004
#  ifdef PNG_READ_16BIT_SUPPORTED
2005
#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2006
         if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
2007 2008 2009 2010
            info_ptr->bit_depth = 8;
#     endif

#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2011
         if ((png_ptr->transformations & PNG_16_TO_8) != 0)
2012 2013 2014
            info_ptr->bit_depth = 8;
#     endif

2015
#  else
2016
      /* No 16-bit support: force chopping 16-bit input down to 8, in this case
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
       * 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
2028

2029
#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2030 2031 2032 2033 2034 2035
            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
2036
#    endif
2037
#endif /* !READ_16BIT */
2038
   }
G
Guy Schalnat 已提交
2039

2040
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2041
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
2042 2043
      info_ptr->color_type = (png_byte)(info_ptr->color_type |
         PNG_COLOR_MASK_COLOR);
2044 2045
#endif

2046
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2047
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
2048 2049
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_COLOR);
2050 2051
#endif

2052
#ifdef PNG_READ_QUANTIZE_SUPPORTED
2053
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
G
Guy Schalnat 已提交
2054 2055
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2056
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2057
          png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
2058 2059 2060
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
2061
   }
G
Guy Schalnat 已提交
2062 2063
#endif

2064
#ifdef PNG_READ_EXPAND_16_SUPPORTED
2065 2066 2067
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
       info_ptr->bit_depth == 8 &&
       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2068 2069 2070 2071 2072
   {
      info_ptr->bit_depth = 16;
   }
#endif

2073
#ifdef PNG_READ_PACK_SUPPORTED
2074 2075
   if ((png_ptr->transformations & PNG_PACK) != 0 &&
       (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
2076 2077 2078
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
2079
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2080
      info_ptr->channels = 1;
2081

2082
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
2083
      info_ptr->channels = 3;
2084

G
Guy Schalnat 已提交
2085 2086
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
2087

2088
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2089
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
2090
   {
2091 2092
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_ALPHA);
2093 2094
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
2095 2096
#endif

2097
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
2098 2099
      info_ptr->channels++;

2100
#ifdef PNG_READ_FILLER_SUPPORTED
2101
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
2102 2103 2104
   if ((png_ptr->transformations & PNG_FILLER) != 0 &&
       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
       info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
2105
   {
2106
      info_ptr->channels++;
2107
      /* If adding a true alpha channel not just filler */
2108
      if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
2109
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2110
   }
A
Andreas Dilger 已提交
2111 2112
#endif

2113 2114
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2115
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2116
   {
J
John Bowler 已提交
2117
      if (png_ptr->user_transform_depth != 0)
2118
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2119

J
John Bowler 已提交
2120
      if (png_ptr->user_transform_channels != 0)
2121
         info_ptr->channels = png_ptr->user_transform_channels;
2122
   }
2123 2124
#endif

2125 2126
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
       info_ptr->bit_depth);
2127

2128
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2129

2130
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2131 2132 2133 2134 2135 2136 2137
    * 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;

2138
#ifndef PNG_READ_EXPAND_SUPPORTED
2139
   if (png_ptr != NULL)
2140 2141
      return;
#endif
G
Guy Schalnat 已提交
2142 2143
}

2144
#ifdef PNG_READ_PACK_SUPPORTED
2145 2146 2147 2148 2149 2150
/* 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.
 */
2151
static void
G
Guy Schalnat 已提交
2152
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2153
{
2154
   png_debug(1, "in png_do_unpack");
2155

A
Andreas Dilger 已提交
2156
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2157
   {
2158
      png_uint_32 i;
2159
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2160

G
Guy Schalnat 已提交
2161 2162 2163 2164
      switch (row_info->bit_depth)
      {
         case 1:
         {
2165 2166
            png_bytep sp = row + (size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (size_t)row_width - 1;
2167
            png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);
2168
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2169
            {
2170
               *dp = (png_byte)((*sp >> shift) & 0x01);
2171

G
Guy Schalnat 已提交
2172 2173 2174 2175
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2176
               }
2177

G
Guy Schalnat 已提交
2178 2179 2180 2181 2182 2183 2184
               else
                  shift++;

               dp--;
            }
            break;
         }
2185

G
Guy Schalnat 已提交
2186 2187 2188
         case 2:
         {

2189 2190
            png_bytep sp = row + (size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (size_t)row_width - 1;
2191
            png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);
2192
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2193
            {
2194
               *dp = (png_byte)((*sp >> shift) & 0x03);
2195

G
Guy Schalnat 已提交
2196 2197 2198 2199 2200
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2201

G
Guy Schalnat 已提交
2202 2203 2204 2205 2206 2207 2208
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2209

G
Guy Schalnat 已提交
2210 2211
         case 4:
         {
2212 2213
            png_bytep sp = row + (size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (size_t)row_width - 1;
2214
            png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);
2215
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2216
            {
2217
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2218

G
Guy Schalnat 已提交
2219 2220 2221 2222 2223
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2224

G
Guy Schalnat 已提交
2225 2226 2227 2228 2229 2230 2231
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2232 2233 2234

         default:
            break;
G
Guy Schalnat 已提交
2235 2236
      }
      row_info->bit_depth = 8;
2237
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2238
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2239 2240
   }
}
G
Guy Schalnat 已提交
2241
#endif
G
Guy Schalnat 已提交
2242

2243
#ifdef PNG_READ_SHIFT_SUPPORTED
2244 2245 2246 2247 2248
/* 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.
 */
2249
static void
2250 2251
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2252
{
2253 2254
   int color_type;

2255
   png_debug(1, "in png_do_unshift");
2256

2257 2258 2259 2260
   /* 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 已提交
2261 2262
   {
      int shift[4];
2263
      int channels = 0;
2264
      int bit_depth = row_info->bit_depth;
G
Guy Schalnat 已提交
2265

2266
      if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
2267
      {
2268 2269 2270
         shift[channels++] = bit_depth - sig_bits->red;
         shift[channels++] = bit_depth - sig_bits->green;
         shift[channels++] = bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2271
      }
2272

G
Guy Schalnat 已提交
2273 2274
      else
      {
2275
         shift[channels++] = bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2276
      }
2277

2278
      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
G
Guy Schalnat 已提交
2279
      {
2280
         shift[channels++] = bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2281
      }
G
Guy Schalnat 已提交
2282

G
Guy Schalnat 已提交
2283
      {
2284
         int c, have_shift;
2285

2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296
         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 已提交
2297

2298
         if (have_shift == 0)
2299 2300
            return;
      }
G
Guy Schalnat 已提交
2301

2302
      switch (bit_depth)
G
Guy Schalnat 已提交
2303
      {
2304
         default:
2305 2306
         /* Must be 1bpp gray: should not be here! */
            /* NOTREACHED */
2307
            break;
2308

G
Guy Schalnat 已提交
2309
         case 2:
2310 2311
         /* Must be 2bpp gray */
         /* assert(channels == 1 && shift[0] == 1) */
G
Guy Schalnat 已提交
2312
         {
2313 2314
            png_bytep bp = row;
            png_bytep bp_end = bp + row_info->rowbytes;
A
Andreas Dilger 已提交
2315

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

G
Guy Schalnat 已提交
2324
         case 4:
2325 2326
         /* Must be 4bpp gray */
         /* assert(channels == 1) */
G
Guy Schalnat 已提交
2327
         {
2328
            png_bytep bp = row;
2329 2330 2331 2332 2333
            png_bytep bp_end = bp + row_info->rowbytes;
            int gray_shift = shift[0];
            int mask =  0xf >> gray_shift;

            mask |= mask << 4;
2334

2335
            while (bp < bp_end)
G
Guy Schalnat 已提交
2336
            {
2337 2338
               int b = (*bp >> gray_shift) & mask;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2339 2340 2341
            }
            break;
         }
2342

G
Guy Schalnat 已提交
2343
         case 8:
2344
         /* Single 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
               int b = *bp >> shift[channel];
2353 2354
               if (++channel >= channels)
                  channel = 0;
2355
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2356 2357 2358
            }
            break;
         }
2359

2360
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2361
         case 16:
2362
         /* Double byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2363
         {
2364
            png_bytep bp = row;
2365 2366
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2367

2368
            while (bp < bp_end)
A
Andreas Dilger 已提交
2369
            {
2370 2371 2372 2373 2374
               int value = (bp[0] << 8) + bp[1];

               value >>= shift[channel];
               if (++channel >= channels)
                  channel = 0;
2375
               *bp++ = (png_byte)(value >> 8);
2376
               *bp++ = (png_byte)value;
G
Guy Schalnat 已提交
2377 2378 2379
            }
            break;
         }
2380
#endif
G
Guy Schalnat 已提交
2381 2382 2383
      }
   }
}
G
Guy Schalnat 已提交
2384
#endif
G
Guy Schalnat 已提交
2385

2386
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2387
/* Scale rows of bit depth 16 down to 8 accurately */
2388
static void
2389
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2390
{
2391
   png_debug(1, "in png_do_scale_16_to_8");
2392

A
Andreas Dilger 已提交
2393
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2394
   {
2395
      png_bytep sp = row; /* source */
2396
      png_bytep dp = row; /* destination */
2397
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2398

2399
      while (sp < ep)
G
Guy Schalnat 已提交
2400
      {
2401 2402
         /* 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
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422
          * 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
2423
          * 0.  This gives 128 errors.  The exact answer (correct for all 16-bit
2424 2425 2426 2427 2428 2429 2430 2431
          * input values) is:
          *
          *    error = (vlo-vhi+128)*65535 >> 24;
          *
          * An alternative arithmetic calculation which also gives no errors is:
          *
          *    (V * 255 + 32895) >> 16
          */
2432

2433
         png_int_32 tmp = *sp++; /* must be signed! */
2434
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2435
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2436
      }
2437

G
Guy Schalnat 已提交
2438
      row_info->bit_depth = 8;
2439
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2440
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2441 2442
   }
}
2443
#endif
2444

2445
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2446
static void
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456
/* 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 */
2457
      png_bytep dp = row; /* destination */
2458 2459 2460 2461
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
2462 2463
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2464 2465 2466
      }

      row_info->bit_depth = 8;
2467
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2468 2469 2470
      row_info->rowbytes = row_info->width * row_info->channels;
   }
}
2471
#endif
A
Andreas Dilger 已提交
2472

2473
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2474
static void
A
Andreas Dilger 已提交
2475 2476
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2477 2478
   png_uint_32 row_width = row_info->width;

2479
   png_debug(1, "in png_do_read_swap_alpha");
2480

2481
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
A
Andreas Dilger 已提交
2482
   {
2483 2484
      /* This converts from RGBA to ARGB */
      if (row_info->bit_depth == 8)
A
Andreas Dilger 已提交
2485
      {
2486 2487 2488 2489
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_byte save;
         png_uint_32 i;
2490

2491 2492 2493 2494 2495 2496 2497
         for (i = 0; i < row_width; i++)
         {
            save = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = save;
A
Andreas Dilger 已提交
2498
         }
2499
      }
2500 2501

#ifdef PNG_READ_16BIT_SUPPORTED
2502 2503 2504 2505 2506 2507 2508
      /* This converts from RRGGBBAA to AARRGGBB */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_byte save[2];
         png_uint_32 i;
2509

2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
         for (i = 0; i < row_width; i++)
         {
            save[0] = *(--sp);
            save[1] = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = save[0];
            *(--dp) = save[1];
A
Andreas Dilger 已提交
2522 2523
         }
      }
2524 2525
#endif
   }
2526

2527 2528 2529 2530
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      /* This converts from GA to AG */
      if (row_info->bit_depth == 8)
A
Andreas Dilger 已提交
2531
      {
2532 2533 2534 2535
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_byte save;
         png_uint_32 i;
2536

2537 2538 2539 2540 2541
         for (i = 0; i < row_width; i++)
         {
            save = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = save;
A
Andreas Dilger 已提交
2542
         }
2543
      }
2544 2545

#ifdef PNG_READ_16BIT_SUPPORTED
2546 2547 2548 2549 2550 2551 2552
      /* This converts from GGAA to AAGG */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_byte save[2];
         png_uint_32 i;
A
Andreas Dilger 已提交
2553

2554 2555 2556 2557 2558 2559 2560 2561
         for (i = 0; i < row_width; i++)
         {
            save[0] = *(--sp);
            save[1] = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = save[0];
            *(--dp) = save[1];
A
Andreas Dilger 已提交
2562 2563
         }
      }
2564
#endif
G
Guy Schalnat 已提交
2565 2566
   }
}
G
Guy Schalnat 已提交
2567
#endif
G
Guy Schalnat 已提交
2568

2569
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2570
static void
2571 2572
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2573
   png_uint_32 row_width;
2574
   png_debug(1, "in png_do_read_invert_alpha");
2575

2576 2577
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2578
   {
2579
      if (row_info->bit_depth == 8)
2580 2581
      {
         /* This inverts the alpha channel in RGBA */
2582 2583 2584
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2585

2586 2587
         for (i = 0; i < row_width; i++)
         {
2588
            *(--dp) = (png_byte)(255 - *(--sp));
2589

2590 2591 2592 2593 2594
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2595
*/
2596 2597
            sp-=3;
            dp=sp;
2598
         }
2599
      }
2600 2601

#ifdef PNG_READ_16BIT_SUPPORTED
2602 2603 2604 2605 2606 2607
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2608

2609 2610
         for (i = 0; i < row_width; i++)
         {
2611 2612
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2613 2614 2615 2616 2617 2618 2619 2620 2621

/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2622
*/
2623 2624
            sp-=6;
            dp=sp;
2625 2626
         }
      }
2627
#endif
2628 2629 2630 2631
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2632
      {
2633
         /* This inverts the alpha channel in GA */
2634 2635 2636
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2637

2638 2639
         for (i = 0; i < row_width; i++)
         {
2640
            *(--dp) = (png_byte)(255 - *(--sp));
2641
            *(--dp) = *(--sp);
2642
         }
2643
      }
2644 2645

#ifdef PNG_READ_16BIT_SUPPORTED
2646 2647
      else
      {
2648
         /* This inverts the alpha channel in GGAA */
2649 2650 2651
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2652

2653 2654
         for (i = 0; i < row_width; i++)
         {
2655 2656
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2657
/*
2658 2659
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2660
*/
2661 2662
            sp-=2;
            dp=sp;
2663 2664
         }
      }
2665
#endif
2666 2667 2668 2669
   }
}
#endif

2670
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2671
/* Add filler channel if we have RGB color */
2672
static void
G
Guy Schalnat 已提交
2673
png_do_read_filler(png_row_infop row_info, png_bytep row,
2674
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2675
{
G
Guy Schalnat 已提交
2676
   png_uint_32 i;
2677 2678
   png_uint_32 row_width = row_info->width;

2679
#ifdef PNG_READ_16BIT_SUPPORTED
2680
   png_byte hi_filler = (png_byte)(filler>>8);
2681
#endif
2682
   png_byte lo_filler = (png_byte)filler;
A
Andreas Dilger 已提交
2683

2684
   png_debug(1, "in png_do_read_filler");
2685

A
Andreas Dilger 已提交
2686
   if (
2687
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2688
   {
2689
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2690
      {
2691
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
G
Guy Schalnat 已提交
2692
         {
2693
            /* This changes the data from G to GX */
2694 2695
            png_bytep sp = row + (size_t)row_width;
            png_bytep dp =  sp + (size_t)row_width;
2696 2697
            for (i = 1; i < row_width; i++)
            {
2698
               *(--dp) = lo_filler;
2699 2700
               *(--dp) = *(--sp);
            }
2701
            *(--dp) = lo_filler;
2702 2703 2704 2705
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
2706

2707 2708
         else
         {
2709
            /* This changes the data from G to XG */
2710 2711
            png_bytep sp = row + (size_t)row_width;
            png_bytep dp = sp  + (size_t)row_width;
2712 2713 2714
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2715
               *(--dp) = lo_filler;
2716 2717 2718 2719 2720 2721
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2722

2723
#ifdef PNG_READ_16BIT_SUPPORTED
2724
      else if (row_info->bit_depth == 16)
2725
      {
2726
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2727
         {
2728
            /* This changes the data from GG to GGXX */
2729 2730
            png_bytep sp = row + (size_t)row_width * 2;
            png_bytep dp = sp  + (size_t)row_width * 2;
2731 2732
            for (i = 1; i < row_width; i++)
            {
2733
               *(--dp) = lo_filler;
2734
               *(--dp) = hi_filler;
2735 2736 2737
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2738
            *(--dp) = lo_filler;
2739
            *(--dp) = hi_filler;
2740 2741
            row_info->channels = 2;
            row_info->pixel_depth = 32;
2742
            row_info->rowbytes = row_width * 4;
2743
         }
2744

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

2786 2787
         else
         {
2788
            /* This changes the data from RGB to XRGB */
2789 2790
            png_bytep sp = row + (size_t)row_width * 3;
            png_bytep dp = sp + (size_t)row_width;
2791 2792 2793 2794 2795
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2796
               *(--dp) = lo_filler;
2797 2798 2799 2800 2801 2802
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
2803

2804
#ifdef PNG_READ_16BIT_SUPPORTED
2805
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2806
      {
2807
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
G
Guy Schalnat 已提交
2808
         {
2809
            /* This changes the data from RRGGBB to RRGGBBXX */
2810 2811
            png_bytep sp = row + (size_t)row_width * 6;
            png_bytep dp = sp  + (size_t)row_width * 2;
2812 2813
            for (i = 1; i < row_width; i++)
            {
2814
               *(--dp) = lo_filler;
2815
               *(--dp) = hi_filler;
2816 2817 2818 2819 2820 2821 2822
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2823
            *(--dp) = lo_filler;
2824
            *(--dp) = hi_filler;
2825 2826
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2827
            row_info->rowbytes = row_width * 8;
2828
         }
2829

2830 2831
         else
         {
2832
            /* This changes the data from RRGGBB to XXRRGGBB */
2833 2834
            png_bytep sp = row + (size_t)row_width * 6;
            png_bytep dp = sp  + (size_t)row_width * 2;
2835 2836 2837 2838 2839 2840 2841 2842
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2843
               *(--dp) = lo_filler;
2844
               *(--dp) = hi_filler;
2845
            }
2846

2847 2848
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2849
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2850
         }
G
Guy Schalnat 已提交
2851
      }
2852
#endif
2853
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2854
}
G
Guy Schalnat 已提交
2855
#endif
G
Guy Schalnat 已提交
2856

2857
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2858
/* Expand grayscale files to RGB, with or without alpha */
2859
static void
G
Guy Schalnat 已提交
2860
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2861
{
G
Guy Schalnat 已提交
2862
   png_uint_32 i;
2863
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2864

2865
   png_debug(1, "in png_do_gray_to_rgb");
2866

A
Andreas Dilger 已提交
2867
   if (row_info->bit_depth >= 8 &&
2868
       (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
G
Guy Schalnat 已提交
2869 2870 2871 2872 2873
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
2874
            /* This changes G to RGB */
2875 2876
            png_bytep sp = row + (size_t)row_width - 1;
            png_bytep dp = sp  + (size_t)row_width * 2;
2877
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2878 2879 2880
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
2881
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2882 2883
            }
         }
2884

G
Guy Schalnat 已提交
2885 2886
         else
         {
2887
            /* This changes GG to RRGGBB */
2888 2889
            png_bytep sp = row + (size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (size_t)row_width * 4;
2890
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2891 2892 2893 2894 2895
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2896 2897
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2898 2899 2900
            }
         }
      }
2901

G
Guy Schalnat 已提交
2902 2903 2904 2905
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
2906
            /* This changes GA to RGBA */
2907 2908
            png_bytep sp = row + (size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (size_t)row_width * 2;
2909
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2910 2911 2912 2913
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
2914
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2915 2916
            }
         }
2917

G
Guy Schalnat 已提交
2918 2919
         else
         {
2920
            /* This changes GGAA to RRGGBBAA */
2921 2922
            png_bytep sp = row + (size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (size_t)row_width * 4;
2923
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2924 2925 2926 2927 2928 2929 2930
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2931 2932
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2933 2934 2935
            }
         }
      }
2936
      row_info->channels = (png_byte)(row_info->channels + 2);
G
Guy Schalnat 已提交
2937
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
2938 2939
      row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
2940
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
2941 2942
   }
}
G
Guy Schalnat 已提交
2943
#endif
G
Guy Schalnat 已提交
2944

2945
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2946
/* Reduce RGB files to grayscale, with or without alpha
2947 2948 2949
 * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
 * versions dated 1998 through November 2002 have been archived at
V
Viktor Szakats 已提交
2950
 * https://web.archive.org/web/20000816232553/www.inforamp.net/
2951
 * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
2952
 * Charles Poynton poynton at poynton.com
2953 2954 2955
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
2956
 *  which can be expressed with integers as
2957
 *
2958 2959 2960 2961 2962 2963 2964
 *     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
2965 2966 2967
 *
 *  which can be expressed with integers as
 *
2968 2969
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
 *
2970 2971 2972 2973 2974
 *  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:
2975
 *
2976
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2977
 *
2978 2979 2980 2981 2982
 *  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
2983
 *
2984 2985 2986
 *  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.
2987
 *
2988 2989 2990 2991
 *  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.
2992
 *
L
luz.paz 已提交
2993
 *  Other integer coefficients can be used via png_set_rgb_to_gray().  Because
2994 2995 2996
 *  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.
2997
 */
2998
static int
2999
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
3000 3001 3002
{
   int rgb_error = 0;

3003
   png_debug(1, "in png_do_rgb_to_gray");
3004

3005 3006
   if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
3007
   {
3008 3009 3010 3011 3012
      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
      png_uint_32 bc = 32768 - rc - gc;
      png_uint_32 row_width = row_info->width;
      int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3013

3014
      if (row_info->bit_depth == 8)
3015
      {
3016
#ifdef PNG_READ_GAMMA_SUPPORTED
3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028
         /* 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++)
3029
            {
3030 3031 3032
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3033

3034
               if (red != green || red != blue)
3035
               {
3036 3037 3038
                  red = png_ptr->gamma_to_1[red];
                  green = png_ptr->gamma_to_1[green];
                  blue = png_ptr->gamma_to_1[blue];
3039

3040 3041 3042
                  rgb_error |= 1;
                  *(dp++) = png_ptr->gamma_from_1[
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3043
               }
3044

3045 3046 3047 3048 3049 3050 3051
               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];
3052

3053
                  *(dp++) = red;
3054
               }
3055

3056
               if (have_alpha != 0)
3057
                  *(dp++) = *(sp++);
3058 3059
            }
         }
3060 3061
         else
#endif
3062
         {
3063 3064 3065
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3066

3067
            for (i = 0; i < row_width; i++)
3068
            {
3069 3070 3071
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3072

3073 3074 3075
               if (red != green || red != blue)
               {
                  rgb_error |= 1;
3076
                  /* NOTE: this is the historical approach which simply
3077 3078
                   * truncates the results.
                   */
3079
                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3080
               }
3081

3082 3083
               else
                  *(dp++) = red;
3084

3085
               if (have_alpha != 0)
3086
                  *(dp++) = *(sp++);
3087 3088 3089
            }
         }
      }
3090 3091

      else /* RGB bit_depth == 16 */
3092
      {
3093
#ifdef PNG_READ_GAMMA_SUPPORTED
3094 3095 3096 3097 3098 3099 3100
         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++)
3101
            {
3102
               png_uint_16 red, green, blue, w;
3103
               png_byte hi,lo;
3104

3105 3106 3107
               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3108

3109 3110 3111
               if (red == green && red == blue)
               {
                  if (png_ptr->gamma_16_table != NULL)
3112 3113
                     w = png_ptr->gamma_16_table[(red & 0xff)
                         >> png_ptr->gamma_shift][red >> 8];
3114

3115 3116
                  else
                     w = red;
3117
               }
3118 3119

               else
3120
               {
3121
                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red & 0xff)
3122 3123
                      >> png_ptr->gamma_shift][red>>8];
                  png_uint_16 green_1 =
3124
                      png_ptr->gamma_16_to_1[(green & 0xff) >>
3125
                      png_ptr->gamma_shift][green>>8];
3126
                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue & 0xff)
3127 3128 3129
                      >> png_ptr->gamma_shift][blue>>8];
                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
                      + bc*blue_1 + 16384)>>15);
3130
                  w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
3131 3132 3133 3134 3135 3136 3137
                      png_ptr->gamma_shift][gray16 >> 8];
                  rgb_error |= 1;
               }

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

3138
               if (have_alpha != 0)
3139 3140 3141
               {
                  *(dp++) = *(sp++);
                  *(dp++) = *(sp++);
3142 3143 3144
               }
            }
         }
3145 3146
         else
#endif
3147
         {
3148 3149 3150
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3151

3152 3153 3154
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3155
               png_byte hi,lo;
3156

3157 3158 3159
               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3160

3161 3162
               if (red != green || red != blue)
                  rgb_error |= 1;
3163

3164
               /* From 1.5.5 in the 16-bit case do the accurate conversion even
3165
                * in the 'fast' case - this is because this is where the code
3166
                * ends up when handling linear 16-bit data.
3167 3168 3169
                */
               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
                  15);
3170
               *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
3171
               *(dp++) = (png_byte)(gray16 & 0xff);
3172

3173
               if (have_alpha != 0)
3174
               {
3175
                  *(dp++) = *(sp++);
3176 3177 3178 3179 3180
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3181

3182 3183 3184 3185 3186
      row_info->channels = (png_byte)(row_info->channels - 2);
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
      row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
3187
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3188 3189 3190 3191
   }
   return rgb_error;
}
#endif
G
Guy Schalnat 已提交
3192

3193 3194
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
A
Andreas Dilger 已提交
3195
/* Replace any alpha or transparency with the supplied background color.
3196 3197 3198
 * "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.
 */
3199
static void
3200
png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3201
{
3202
#ifdef PNG_READ_GAMMA_SUPPORTED
3203 3204 3205 3206 3207 3208 3209
   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;
3210
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3211
#endif
3212

3213
   png_bytep sp;
G
Guy Schalnat 已提交
3214
   png_uint_32 i;
3215
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3216
   int shift;
G
Guy Schalnat 已提交
3217

3218
   png_debug(1, "in png_do_compose");
3219

3220
   switch (row_info->color_type)
G
Guy Schalnat 已提交
3221
   {
3222
      case PNG_COLOR_TYPE_GRAY:
G
Guy Schalnat 已提交
3223
      {
3224
         switch (row_info->bit_depth)
G
Guy Schalnat 已提交
3225
         {
3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253
            case 1:
            {
               sp = row;
               shift = 7;
               for (i = 0; i < row_width; i++)
               {
                  if ((png_uint_16)((*sp >> shift) & 0x01)
                     == png_ptr->trans_color.gray)
                  {
                     unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
                     tmp |=
                         (unsigned int)(png_ptr->background.gray << shift);
                     *sp = (png_byte)(tmp & 0xff);
                  }

                  if (shift == 0)
                  {
                     shift = 7;
                     sp++;
                  }

                  else
                     shift--;
               }
               break;
            }

            case 2:
G
Guy Schalnat 已提交
3254
            {
3255 3256
#ifdef PNG_READ_GAMMA_SUPPORTED
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3257 3258
               {
                  sp = row;
3259
                  shift = 6;
3260
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3261
                  {
3262 3263
                     if ((png_uint_16)((*sp >> shift) & 0x03)
                         == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3264
                     {
3265
                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3266
                        tmp |=
3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277
                           (unsigned int)png_ptr->background.gray << shift;
                        *sp = (png_byte)(tmp & 0xff);
                     }

                     else
                     {
                        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 |= (unsigned int)(g << shift);
3278
                        *sp = (png_byte)(tmp & 0xff);
G
Guy Schalnat 已提交
3279
                     }
3280

3281
                     if (shift == 0)
G
Guy Schalnat 已提交
3282
                     {
3283
                        shift = 6;
G
Guy Schalnat 已提交
3284 3285
                        sp++;
                     }
3286

G
Guy Schalnat 已提交
3287
                     else
3288
                        shift -= 2;
G
Guy Schalnat 已提交
3289 3290
                  }
               }
3291

3292 3293
               else
#endif
G
Guy Schalnat 已提交
3294
               {
3295 3296 3297
                  sp = row;
                  shift = 6;
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3298
                  {
3299 3300
                     if ((png_uint_16)((*sp >> shift) & 0x03)
                         == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3301
                     {
3302 3303 3304 3305
                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
                        tmp |=
                            (unsigned int)png_ptr->background.gray << shift;
                        *sp = (png_byte)(tmp & 0xff);
G
Guy Schalnat 已提交
3306
                     }
3307

3308
                     if (shift == 0)
G
Guy Schalnat 已提交
3309
                     {
3310 3311
                        shift = 6;
                        sp++;
G
Guy Schalnat 已提交
3312
                     }
3313 3314 3315

                     else
                        shift -= 2;
G
Guy Schalnat 已提交
3316 3317
                  }
               }
3318 3319
               break;
            }
3320

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

3339
                     else
G
Guy Schalnat 已提交
3340
                     {
3341 3342 3343 3344 3345 3346
                        unsigned int p = (*sp >> shift) & 0x0f;
                        unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
                           0x0f;
                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
                        tmp |= (unsigned int)(g << shift);
                        *sp = (png_byte)(tmp & 0xff);
G
Guy Schalnat 已提交
3347
                     }
3348

3349
                     if (shift == 0)
G
Guy Schalnat 已提交
3350
                     {
3351 3352
                        shift = 4;
                        sp++;
G
Guy Schalnat 已提交
3353
                     }
3354 3355 3356

                     else
                        shift -= 4;
G
Guy Schalnat 已提交
3357 3358
                  }
               }
3359

3360 3361
               else
#endif
G
Guy Schalnat 已提交
3362
               {
3363 3364 3365
                  sp = row;
                  shift = 4;
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3366
                  {
3367 3368
                     if ((png_uint_16)((*sp >> shift) & 0x0f)
                         == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3369
                     {
3370 3371 3372 3373
                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
                        tmp |=
                           (unsigned int)(png_ptr->background.gray << shift);
                        *sp = (png_byte)(tmp & 0xff);
G
Guy Schalnat 已提交
3374
                     }
G
Guy Schalnat 已提交
3375

3376 3377 3378 3379
                     if (shift == 0)
                     {
                        shift = 4;
                        sp++;
G
Guy Schalnat 已提交
3380
                     }
3381 3382 3383

                     else
                        shift -= 4;
G
Guy Schalnat 已提交
3384 3385
                  }
               }
3386
               break;
G
Guy Schalnat 已提交
3387
            }
3388

3389
            case 8:
G
Guy Schalnat 已提交
3390
            {
3391
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3392
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3393
               {
3394
                  sp = row;
3395
                  for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3396
                  {
3397 3398
                     if (*sp == png_ptr->trans_color.gray)
                        *sp = (png_byte)png_ptr->background.gray;
3399

G
Guy Schalnat 已提交
3400 3401 3402 3403 3404
                     else
                        *sp = gamma_table[*sp];
                  }
               }
               else
G
Guy Schalnat 已提交
3405
#endif
G
Guy Schalnat 已提交
3406
               {
3407
                  sp = row;
3408
                  for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3409
                  {
3410 3411
                     if (*sp == png_ptr->trans_color.gray)
                        *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3412 3413
                  }
               }
3414
               break;
G
Guy Schalnat 已提交
3415
            }
3416 3417

            case 16:
G
Guy Schalnat 已提交
3418
            {
3419
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3420
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3421
               {
3422
                  sp = row;
3423
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3424
                  {
3425
                     png_uint_16 v;
3426

3427
                     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3428

3429
                     if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3430
                     {
3431
                        /* Background is already in screen gamma */
3432 3433 3434 3435
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                             & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray
                             & 0xff);
G
Guy Schalnat 已提交
3436
                     }
3437

G
Guy Schalnat 已提交
3438 3439
                     else
                     {
3440
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3441
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3442
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3443 3444 3445 3446
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3447
#endif
G
Guy Schalnat 已提交
3448
               {
3449
                  sp = row;
3450
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3451
                  {
3452
                     png_uint_16 v;
3453

3454
                     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
G
Guy Schalnat 已提交
3455

3456
                     if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3457
                     {
3458 3459 3460 3461
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                             & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray
                             & 0xff);
G
Guy Schalnat 已提交
3462 3463 3464
                     }
                  }
               }
3465
               break;
G
Guy Schalnat 已提交
3466
            }
3467 3468 3469

            default:
               break;
G
Guy Schalnat 已提交
3470
         }
3471 3472
         break;
      }
3473

3474 3475 3476
      case PNG_COLOR_TYPE_RGB:
      {
         if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3477
         {
3478
#ifdef PNG_READ_GAMMA_SUPPORTED
3479 3480 3481 3482
            if (gamma_table != NULL)
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 3)
A
Andreas Dilger 已提交
3483
               {
3484 3485 3486
                  if (*sp == png_ptr->trans_color.red &&
                      *(sp + 1) == png_ptr->trans_color.green &&
                      *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3487
                  {
3488 3489 3490 3491
                     *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 已提交
3492

3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526
                  else
                  {
                     *sp = gamma_table[*sp];
                     *(sp + 1) = gamma_table[*(sp + 1)];
                     *(sp + 2) = gamma_table[*(sp + 2)];
                  }
               }
            }
            else
#endif
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 3)
               {
                  if (*sp == png_ptr->trans_color.red &&
                      *(sp + 1) == png_ptr->trans_color.green &&
                      *(sp + 2) == png_ptr->trans_color.blue)
                  {
                     *sp = (png_byte)png_ptr->background.red;
                     *(sp + 1) = (png_byte)png_ptr->background.green;
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
                  }
               }
            }
         }
         else /* if (row_info->bit_depth == 16) */
         {
#ifdef PNG_READ_GAMMA_SUPPORTED
            if (gamma_16 != NULL)
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 6)
               {
                  png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3527

3528 3529
                  png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                      + *(sp + 3));
3530

3531 3532
                  png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                      + *(sp + 5));
G
Guy Schalnat 已提交
3533

3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562
                  if (r == png_ptr->trans_color.red &&
                      g == png_ptr->trans_color.green &&
                      b == png_ptr->trans_color.blue)
                  {
                     /* Background is already in screen gamma */
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                             & 0xff);
                     *(sp + 3) = (png_byte)(png_ptr->background.green
                             & 0xff);
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                             & 0xff);
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                  }

                  else
                  {
                     png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                     *sp = (png_byte)((v >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(v & 0xff);

                     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                     *(sp + 3) = (png_byte)(v & 0xff);

                     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                     *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3563
                  }
A
Andreas Dilger 已提交
3564
               }
3565 3566 3567
            }

            else
G
Guy Schalnat 已提交
3568
#endif
3569 3570 3571
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 6)
A
Andreas Dilger 已提交
3572
               {
3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
                  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));

                  if (r == png_ptr->trans_color.red &&
                      g == png_ptr->trans_color.green &&
                      b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3584
                  {
3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                             & 0xff);
                     *(sp + 3) = (png_byte)(png_ptr->background.green
                             & 0xff);
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                             & 0xff);
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                  }
               }
            }
         }
         break;
      }
G
Guy Schalnat 已提交
3600

3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612
      case PNG_COLOR_TYPE_GRAY_ALPHA:
      {
         if (row_info->bit_depth == 8)
         {
#ifdef PNG_READ_GAMMA_SUPPORTED
            if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                gamma_table != NULL)
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 2)
               {
                  png_uint_16 a = *(sp + 1);
3613

3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631
                  if (a == 0xff)
                     *sp = gamma_table[*sp];

                  else if (a == 0)
                  {
                     /* Background is already in screen gamma */
                     *sp = (png_byte)png_ptr->background.gray;
                  }

                  else
                  {
                     png_byte v, w;

                     v = gamma_to_1[*sp];
                     png_composite(w, v, a, png_ptr->background_1.gray);
                     if (optimize == 0)
                        w = gamma_from_1[w];
                     *sp = w;
G
Guy Schalnat 已提交
3632 3633
                  }
               }
A
Andreas Dilger 已提交
3634
            }
3635 3636
            else
#endif
A
Andreas Dilger 已提交
3637
            {
3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652
               sp = row;
               for (i = 0; i < row_width; i++, sp += 2)
               {
                  png_byte a = *(sp + 1);

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

                  else if (a < 0xff)
                     png_composite(*sp, *sp, a, png_ptr->background.gray);
               }
            }
         }
         else /* if (png_ptr->bit_depth == 16) */
         {
3653
#ifdef PNG_READ_GAMMA_SUPPORTED
3654 3655 3656 3657 3658
            if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                gamma_16_to_1 != NULL)
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 4)
A
Andreas Dilger 已提交
3659
               {
3660 3661 3662 3663
                  png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                      + *(sp + 3));

                  if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3664
                  {
3665
                     png_uint_16 v;
A
Andreas Dilger 已提交
3666

3667 3668 3669 3670
                     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                     *sp = (png_byte)((v >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(v & 0xff);
                  }
G
Guy Schalnat 已提交
3671

3672 3673 3674 3675 3676 3677 3678
                  else if (a == 0)
                  {
                     /* Background is already in screen gamma */
                     *sp = (png_byte)((png_ptr->background.gray >> 8)
                             & 0xff);
                     *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                  }
3679

3680 3681 3682
                  else
                  {
                     png_uint_16 g, v, w;
3683

3684 3685 3686 3687
                     g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
                     png_composite_16(v, g, a, png_ptr->background_1.gray);
                     if (optimize != 0)
                        w = v;
A
Andreas Dilger 已提交
3688
                     else
3689 3690 3691 3692
                        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 已提交
3693
                  }
A
Andreas Dilger 已提交
3694
               }
3695 3696
            }
            else
G
Guy Schalnat 已提交
3697
#endif
3698 3699 3700
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 4)
A
Andreas Dilger 已提交
3701
               {
3702 3703
                  png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                      + *(sp + 3));
3704

3705 3706 3707 3708 3709 3710
                  if (a == 0)
                  {
                     *sp = (png_byte)((png_ptr->background.gray >> 8)
                             & 0xff);
                     *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                  }
3711

3712 3713 3714
                  else if (a < 0xffff)
                  {
                     png_uint_16 g, v;
G
Guy Schalnat 已提交
3715

3716 3717 3718 3719
                     g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
                     png_composite_16(v, g, a, png_ptr->background.gray);
                     *sp = (png_byte)((v >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3720 3721 3722 3723
                  }
               }
            }
         }
3724 3725
         break;
      }
3726

3727 3728 3729
      case PNG_COLOR_TYPE_RGB_ALPHA:
      {
         if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3730
         {
3731
#ifdef PNG_READ_GAMMA_SUPPORTED
3732 3733 3734 3735 3736
            if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                gamma_table != NULL)
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3737
               {
3738 3739 3740
                  png_byte a = *(sp + 3);

                  if (a == 0xff)
G
Guy Schalnat 已提交
3741
                  {
3742 3743 3744 3745
                     *sp = gamma_table[*sp];
                     *(sp + 1) = gamma_table[*(sp + 1)];
                     *(sp + 2) = gamma_table[*(sp + 2)];
                  }
G
Guy Schalnat 已提交
3746

3747 3748 3749 3750 3751 3752 3753
                  else if (a == 0)
                  {
                     /* Background is already in screen gamma */
                     *sp = (png_byte)png_ptr->background.red;
                     *(sp + 1) = (png_byte)png_ptr->background.green;
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
                  }
3754

3755 3756 3757
                  else
                  {
                     png_byte v, w;
3758

3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
                     v = gamma_to_1[*sp];
                     png_composite(w, v, a, png_ptr->background_1.red);
                     if (optimize == 0) w = gamma_from_1[w];
                     *sp = w;

                     v = gamma_to_1[*(sp + 1)];
                     png_composite(w, v, a, png_ptr->background_1.green);
                     if (optimize == 0) w = gamma_from_1[w];
                     *(sp + 1) = w;

                     v = gamma_to_1[*(sp + 2)];
                     png_composite(w, v, a, png_ptr->background_1.blue);
                     if (optimize == 0) w = gamma_from_1[w];
                     *(sp + 2) = w;
G
Guy Schalnat 已提交
3773 3774
                  }
               }
3775 3776
            }
            else
G
Guy Schalnat 已提交
3777
#endif
3778 3779 3780
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3781
               {
3782
                  png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3783

3784 3785 3786 3787 3788 3789
                  if (a == 0)
                  {
                     *sp = (png_byte)png_ptr->background.red;
                     *(sp + 1) = (png_byte)png_ptr->background.green;
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
                  }
3790

3791 3792 3793
                  else if (a < 0xff)
                  {
                     png_composite(*sp, *sp, a, png_ptr->background.red);
3794

3795 3796
                     png_composite(*(sp + 1), *(sp + 1), a,
                         png_ptr->background.green);
3797

3798 3799
                     png_composite(*(sp + 2), *(sp + 2), a,
                         png_ptr->background.blue);
G
Guy Schalnat 已提交
3800 3801 3802
                  }
               }
            }
3803 3804 3805
         }
         else /* if (row_info->bit_depth == 16) */
         {
3806
#ifdef PNG_READ_GAMMA_SUPPORTED
3807 3808 3809 3810 3811
            if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                gamma_16_to_1 != NULL)
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3812
               {
3813 3814
                  png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                      << 8) + (png_uint_16)(*(sp + 7)));
3815

3816 3817 3818
                  if (a == (png_uint_16)0xffff)
                  {
                     png_uint_16 v;
G
Guy Schalnat 已提交
3819

3820 3821 3822
                     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                     *sp = (png_byte)((v >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(v & 0xff);
3823

3824 3825 3826
                     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                     *(sp + 3) = (png_byte)(v & 0xff);
3827

3828 3829 3830 3831
                     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                     *(sp + 5) = (png_byte)(v & 0xff);
                  }
3832

3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845
                  else if (a == 0)
                  {
                     /* Background is already in screen gamma */
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                             & 0xff);
                     *(sp + 3) = (png_byte)(png_ptr->background.green
                             & 0xff);
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                             & 0xff);
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                  }
3846

3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875
                  else
                  {
                     png_uint_16 v, w;

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

                     v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
                     png_composite_16(w, v, a, png_ptr->background_1.green);
                     if (optimize == 0)
                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
                             8];

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

                     v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
                     png_composite_16(w, v, a, png_ptr->background_1.blue);
                     if (optimize == 0)
                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
                             8];

                     *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                     *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3876 3877
                  }
               }
3878
            }
3879

3880
            else
G
Guy Schalnat 已提交
3881
#endif
3882 3883 3884
            {
               sp = row;
               for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3885
               {
3886 3887
                  png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                      << 8) + (png_uint_16)(*(sp + 7)));
3888

3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900
                  if (a == 0)
                  {
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
                             & 0xff);
                     *(sp + 3) = (png_byte)(png_ptr->background.green
                             & 0xff);
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
                             & 0xff);
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                  }
3901

3902 3903 3904
                  else if (a < 0xffff)
                  {
                     png_uint_16 v;
A
Andreas Dilger 已提交
3905

3906 3907 3908 3909 3910
                     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 已提交
3911

3912 3913 3914
                     png_composite_16(v, r, a, png_ptr->background.red);
                     *sp = (png_byte)((v >> 8) & 0xff);
                     *(sp + 1) = (png_byte)(v & 0xff);
3915

3916 3917 3918
                     png_composite_16(v, g, a, png_ptr->background.green);
                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                     *(sp + 3) = (png_byte)(v & 0xff);
3919

3920 3921 3922
                     png_composite_16(v, b, a, png_ptr->background.blue);
                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                     *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3923 3924 3925 3926
                  }
               }
            }
         }
3927
         break;
G
Guy Schalnat 已提交
3928
      }
3929 3930 3931

      default:
         break;
G
Guy Schalnat 已提交
3932 3933
   }
}
3934
#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
G
Guy Schalnat 已提交
3935

3936
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3937
/* Gamma correct the image, avoiding the alpha channel.  Make sure
3938
 * you do this after you deal with the transparency issue on grayscale
3939
 * or RGB images. If your bit depth is 8, use gamma_table, if it
3940 3941 3942
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
3943
static void
3944
png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
G
Guy Schalnat 已提交
3945
{
3946 3947 3948 3949
   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 已提交
3950
   png_bytep sp;
G
Guy Schalnat 已提交
3951
   png_uint_32 i;
3952
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3953

3954
   png_debug(1, "in png_do_gamma");
3955

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

A
Andreas Dilger 已提交
3977
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3978
            {
3979 3980
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3981 3982 3983
               {
                  png_uint_16 v;

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

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

A
Andreas Dilger 已提交
3994
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3995 3996 3997 3998 3999 4000 4001
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
4002

G
Guy Schalnat 已提交
4003 4004 4005 4006
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4007 4008
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4009
               {
G
Guy Schalnat 已提交
4010 4011
                  *sp = gamma_table[*sp];
                  sp++;
4012

G
Guy Schalnat 已提交
4013 4014
                  *sp = gamma_table[*sp];
                  sp++;
4015

G
Guy Schalnat 已提交
4016 4017
                  *sp = gamma_table[*sp];
                  sp++;
4018

G
Guy Schalnat 已提交
4019 4020 4021
                  sp++;
               }
            }
4022

A
Andreas Dilger 已提交
4023
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4024
            {
4025 4026
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4027
               {
4028
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4029 4030
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4031
                  sp += 2;
4032

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

A
Andreas Dilger 已提交
4038
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4039 4040 4041 4042 4043
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4044 4045
            break;
         }
4046

G
Guy Schalnat 已提交
4047 4048 4049 4050
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4051 4052
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4053 4054
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4055
                  sp += 2;
G
Guy Schalnat 已提交
4056 4057
               }
            }
4058

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

G
Guy Schalnat 已提交
4073 4074
         case PNG_COLOR_TYPE_GRAY:
         {
4075 4076
            if (row_info->bit_depth == 2)
            {
4077 4078
               sp = row;
               for (i = 0; i < row_width; i += 4)
4079 4080 4081 4082 4083 4084
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4085 4086
                  *sp = (png_byte)(
                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
4087 4088
                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
4089
                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4090 4091 4092
                  sp++;
               }
            }
4093

A
Andreas Dilger 已提交
4094
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4095
            {
4096 4097
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4098 4099 4100 4101
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4102
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4103
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4104 4105 4106
                  sp++;
               }
            }
4107

A
Andreas Dilger 已提交
4108 4109
            else if (row_info->bit_depth == 8)
            {
4110 4111
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4112 4113 4114 4115 4116
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4117

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

         default:
            break;
G
Guy Schalnat 已提交
4134 4135 4136
      }
   }
}
G
Guy Schalnat 已提交
4137
#endif
G
Guy Schalnat 已提交
4138

4139 4140 4141 4142 4143
#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.
 */
4144
static void
4145
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4146 4147 4148 4149 4150
{
   png_uint_32 row_width = row_info->width;

   png_debug(1, "in png_do_encode_alpha");

4151
   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4152 4153 4154
   {
      if (row_info->bit_depth == 8)
      {
4155
         png_bytep table = png_ptr->gamma_from_1;
4156 4157 4158

         if (table != NULL)
         {
4159
            int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172

            /* 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)
      {
4173 4174
         png_uint_16pp table = png_ptr->gamma_16_from_1;
         int gamma_shift = png_ptr->gamma_shift;
4175 4176 4177

         if (table != NULL)
         {
4178
            int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203

            /* 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

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

4218
   png_debug(1, "in png_do_expand_palette");
4219

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

G
Guy Schalnat 已提交
4236 4237
                  else
                     *dp = 0;
4238

G
Guy Schalnat 已提交
4239 4240 4241 4242 4243
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4244

G
Guy Schalnat 已提交
4245 4246 4247 4248 4249 4250 4251
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4252

G
Guy Schalnat 已提交
4253 4254
            case 2:
            {
4255 4256
               sp = row + (size_t)((row_width - 1) >> 2);
               dp = row + (size_t)row_width - 1;
4257
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4258
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4259
               {
4260
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4261
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4262 4263 4264 4265 4266
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4267

G
Guy Schalnat 已提交
4268 4269 4270 4271 4272 4273 4274
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4275

G
Guy Schalnat 已提交
4276 4277
            case 4:
            {
4278 4279
               sp = row + (size_t)((row_width - 1) >> 1);
               dp = row + (size_t)row_width - 1;
4280
               shift = (int)((row_width & 0x01) << 2);
4281
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4282
               {
4283
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4284
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4285 4286 4287 4288 4289
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4290

G
Guy Schalnat 已提交
4291 4292 4293 4294 4295 4296 4297
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4298 4299 4300

            default:
               break;
G
Guy Schalnat 已提交
4301 4302 4303
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4304
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4305
      }
4306

4307
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4308 4309
      {
         {
4310
            if (num_trans > 0)
G
Guy Schalnat 已提交
4311
            {
4312 4313
               sp = row + (size_t)row_width - 1;
               dp = row + ((size_t)row_width << 2) - 1;
G
Guy Schalnat 已提交
4314

4315 4316
               i = 0;
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4317 4318
               if (png_ptr->riffled_palette != NULL)
               {
4319
                  /* The RGBA optimization works with png_ptr->bit_depth == 8
4320 4321 4322
                   * but sometimes row_info->bit_depth has been changed to 8.
                   * In these cases, the palette hasn't been riffled.
                   */
4323
                  i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
4324
                      &sp, &dp);
4325
               }
4326 4327
#else
               PNG_UNUSED(png_ptr)
4328 4329 4330
#endif

               for (; i < row_width; i++)
G
Guy Schalnat 已提交
4331
               {
A
Andreas Dilger 已提交
4332
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4333 4334
                     *dp-- = 0xff;
                  else
4335
                     *dp-- = trans_alpha[*sp];
G
Guy Schalnat 已提交
4336 4337 4338 4339 4340 4341 4342
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4343
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4344 4345 4346
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4347

G
Guy Schalnat 已提交
4348 4349
            else
            {
4350 4351
               sp = row + (size_t)row_width - 1;
               dp = row + (size_t)(row_width * 3) - 1;
4352 4353
               i = 0;
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4354
               i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
4355
                   &sp, &dp);
4356 4357
#else
               PNG_UNUSED(png_ptr)
4358
#endif
G
Guy Schalnat 已提交
4359

4360
               for (; i < row_width; i++)
G
Guy Schalnat 已提交
4361 4362 4363 4364 4365 4366
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4367

G
Guy Schalnat 已提交
4368 4369
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4370
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4371 4372 4373 4374 4375 4376 4377 4378
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4379 4380
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4381
 */
4382
static void
G
Guy Schalnat 已提交
4383
png_do_expand(png_row_infop row_info, png_bytep row,
4384
    png_const_color_16p trans_color)
G
Guy Schalnat 已提交
4385
{
G
Guy Schalnat 已提交
4386
   int shift, value;
G
Guy Schalnat 已提交
4387
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4388
   png_uint_32 i;
4389
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4390

4391
   png_debug(1, "in png_do_expand");
4392

4393
   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4394
   {
4395
      unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
A
Andreas Dilger 已提交
4396

4397 4398 4399
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4400
         {
4401
            case 1:
G
Guy Schalnat 已提交
4402
            {
4403
               gray = (gray & 0x01) * 0xff;
4404 4405
               sp = row + (size_t)((row_width - 1) >> 3);
               dp = row + (size_t)row_width - 1;
4406 4407
               shift = 7 - (int)((row_width + 7) & 0x07);
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4408
               {
4409 4410
                  if ((*sp >> shift) & 0x01)
                     *dp = 0xff;
G
Guy Schalnat 已提交
4411

4412 4413
                  else
                     *dp = 0;
4414

4415
                  if (shift == 7)
G
Guy Schalnat 已提交
4416
                  {
4417 4418
                     shift = 0;
                     sp--;
A
Andreas Dilger 已提交
4419
                  }
4420

4421 4422
                  else
                     shift++;
G
Guy Schalnat 已提交
4423

4424
                  dp--;
G
Guy Schalnat 已提交
4425
               }
4426
               break;
G
Guy Schalnat 已提交
4427
            }
4428

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

A
Andreas Dilger 已提交
4446
                  else
4447
                     shift += 2;
4448

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

4454
            case 4:
A
Andreas Dilger 已提交
4455
            {
4456
               gray = (gray & 0x0f) * 0x11;
4457 4458
               sp = row + (size_t)((row_width - 1) >> 1);
               dp = row + (size_t)row_width - 1;
4459
               shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4460
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4461
               {
4462 4463 4464
                  value = (*sp >> shift) & 0x0f;
                  *dp = (png_byte)(value | (value << 4));
                  if (shift == 4)
A
Andreas Dilger 已提交
4465
                  {
4466 4467
                     shift = 0;
                     sp--;
A
Andreas Dilger 已提交
4468
                  }
4469

A
Andreas Dilger 已提交
4470
                  else
4471
                     shift = 4;
4472

4473
                  dp--;
G
Guy Schalnat 已提交
4474
               }
4475
               break;
G
Guy Schalnat 已提交
4476
            }
4477

4478 4479
            default:
               break;
G
Guy Schalnat 已提交
4480
         }
4481 4482 4483 4484

         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4485
      }
4486 4487

      if (trans_color != NULL)
G
Guy Schalnat 已提交
4488 4489 4490
      {
         if (row_info->bit_depth == 8)
         {
4491
            gray = gray & 0xff;
4492 4493
            sp = row + (size_t)row_width - 1;
            dp = row + ((size_t)row_width << 1) - 1;
4494

4495
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4496
            {
4497
               if ((*sp & 0xffU) == gray)
G
Guy Schalnat 已提交
4498
                  *dp-- = 0;
4499

G
Guy Schalnat 已提交
4500 4501
               else
                  *dp-- = 0xff;
4502

G
Guy Schalnat 已提交
4503 4504 4505
               *dp-- = *sp--;
            }
         }
4506

G
Guy Schalnat 已提交
4507 4508
         else if (row_info->bit_depth == 16)
         {
4509 4510
            unsigned int gray_high = (gray >> 8) & 0xff;
            unsigned int gray_low = gray & 0xff;
A
Andreas Dilger 已提交
4511
            sp = row + row_info->rowbytes - 1;
4512
            dp = row + (row_info->rowbytes << 1) - 1;
4513
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4514
            {
4515 4516
               if ((*(sp - 1) & 0xffU) == gray_high &&
                   (*(sp) & 0xffU) == gray_low)
G
Guy Schalnat 已提交
4517 4518 4519 4520
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4521

G
Guy Schalnat 已提交
4522 4523 4524 4525 4526
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4527

G
Guy Schalnat 已提交
4528 4529 4530 4531
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547

         row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
         row_info->channels = 2;
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
             row_width);
      }
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
       trans_color != NULL)
   {
      if (row_info->bit_depth == 8)
      {
         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);
4548 4549
         sp = row + (size_t)row_info->rowbytes - 1;
         dp = row + ((size_t)row_width << 2) - 1;
4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
         for (i = 0; i < row_width; i++)
         {
            if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
               *dp-- = 0;

            else
               *dp-- = 0xff;

            *dp-- = *sp--;
            *dp-- = *sp--;
            *dp-- = *sp--;
         }
      }
      else if (row_info->bit_depth == 16)
      {
         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);
         sp = row + row_info->rowbytes - 1;
4572
         dp = row + ((size_t)row_width << 3) - 1;
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
         for (i = 0; i < row_width; i++)
         {
            if (*(sp - 5) == red_high &&
                *(sp - 4) == red_low &&
                *(sp - 3) == green_high &&
                *(sp - 2) == green_low &&
                *(sp - 1) == blue_high &&
                *(sp    ) == blue_low)
            {
               *dp-- = 0;
               *dp-- = 0;
            }

            else
            {
               *dp-- = 0xff;
               *dp-- = 0xff;
            }

            *dp-- = *sp--;
            *dp-- = *sp--;
            *dp-- = *sp--;
            *dp-- = *sp--;
            *dp-- = *sp--;
            *dp-- = *sp--;
         }
G
Guy Schalnat 已提交
4599
      }
4600 4601 4602 4603
      row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
      row_info->channels = 4;
      row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4604 4605
   }
}
G
Guy Schalnat 已提交
4606
#endif
G
Guy Schalnat 已提交
4607

4608
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4609
/* If the bit depth is 8 and the color type is not a palette type expand the
4610 4611
 * whole row to 16 bits.  Has no effect otherwise.
 */
4612
static void
4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
   if (row_info->bit_depth == 8 &&
      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
   {
      /* The row have a sequence of bytes containing [0..255] and we need
       * to turn it into another row containing [0..65535], to do this we
       * calculate:
       *
       *  (input / 255) * 65535
       *
       *  Which happens to be exactly input * 257 and this can be achieved
       *  simply by byte replication in place (copying backwards).
       */
      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
      while (dp > sp)
V
Viktor Szakats 已提交
4630 4631 4632
      {
         dp[-2] = dp[-1] = *--sp; dp -= 2;
      }
4633 4634 4635

      row_info->rowbytes *= 2;
      row_info->bit_depth = 16;
4636
      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4637 4638 4639 4640
   }
}
#endif

4641
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4642
static void
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
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];
         }
      }
   }
}
4733
#endif /* READ_QUANTIZE */
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

/* 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 &&
4760
       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4761 4762 4763 4764 4765 4766 4767 4768 4769
   {
      /* 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
4770
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4771 4772 4773
   {
      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
      {
4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
         if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
         {
            if (png_ptr->riffled_palette == NULL)
            {
               /* Initialize the accelerated palette expansion. */
               png_ptr->riffled_palette =
                   (png_bytep)png_malloc(png_ptr, 256 * 4);
               png_riffle_palette_neon(png_ptr);
            }
         }
#endif
4786
         png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
4787
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4788 4789 4790 4791
      }

      else
      {
4792 4793
         if (png_ptr->num_trans != 0 &&
             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4794 4795 4796 4797
            png_do_expand(row_info, png_ptr->row_buf + 1,
                &(png_ptr->trans_color));

         else
4798
            png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
4799 4800 4801 4802 4803
      }
   }
#endif

#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4804 4805 4806 4807
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) == 0 &&
       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4808
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4809
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4810 4811 4812
#endif

#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4813
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4814 4815 4816 4817 4818
   {
      int rgb_error =
          png_do_rgb_to_gray(png_ptr, row_info,
              png_ptr->row_buf + 1);

4819
      if (rgb_error != 0)
4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867
      {
         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
    */
4868 4869
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4870 4871 4872 4873 4874
      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)
4875
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4876 4877
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4878

4879
#ifdef PNG_READ_GAMMA_SUPPORTED
4880
   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4881 4882
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
      /* Because RGB_TO_GRAY does the gamma transform. */
4883
      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4884 4885 4886 4887 4888 4889
#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.)
       */
4890
       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4891
       ((png_ptr->num_trans != 0) ||
4892
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4893 4894 4895 4896 4897 4898 4899
#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
4900

4901
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4902 4903 4904 4905
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4906
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4907
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4908
#endif
G
Guy Schalnat 已提交
4909

4910
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4911 4912
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4913 4914
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4915

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

4921 4922 4923 4924 4925
#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.
    */
4926
   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4927 4928
      png_do_chop(row_info, png_ptr->row_buf + 1);
#endif
4929

4930
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4931
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4932 4933 4934
   {
      png_do_quantize(row_info, png_ptr->row_buf + 1,
          png_ptr->palette_lookup, png_ptr->quantize_index);
G
Guy Schalnat 已提交
4935

4936 4937 4938
      if (row_info->rowbytes == 0)
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
   }
4939
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
4940

4941 4942 4943 4944 4945 4946
#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!)
    */
4947
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4948 4949
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
#endif
4950

4951 4952
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
4953 4954
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
4955 4956
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
4957

4958
#ifdef PNG_READ_INVERT_SUPPORTED
4959
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4960 4961
      png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
4962

4963
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
4964
   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
4965 4966 4967
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif

4968
#ifdef PNG_READ_SHIFT_SUPPORTED
4969
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4970 4971 4972
      png_do_unshift(row_info, png_ptr->row_buf + 1,
          &(png_ptr->shift));
#endif
G
Guy Schalnat 已提交
4973

4974
#ifdef PNG_READ_PACK_SUPPORTED
4975
   if ((png_ptr->transformations & PNG_PACK) != 0)
4976 4977
      png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
4978

4979 4980 4981 4982 4983 4984
#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
4985

4986
#ifdef PNG_READ_BGR_SUPPORTED
4987
   if ((png_ptr->transformations & PNG_BGR) != 0)
4988 4989
      png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
4990

4991
#ifdef PNG_READ_PACKSWAP_SUPPORTED
4992
   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4993 4994
      png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
4995

4996
#ifdef PNG_READ_FILLER_SUPPORTED
4997
   if ((png_ptr->transformations & PNG_FILLER) != 0)
4998 4999 5000
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif
5001

5002
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
5003
   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
5004 5005
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
5006

5007 5008
#ifdef PNG_READ_16BIT_SUPPORTED
#ifdef PNG_READ_SWAP_SUPPORTED
5009
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
5010 5011 5012
      png_do_swap(row_info, png_ptr->row_buf + 1);
#endif
#endif
5013

5014
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
5015
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
5016
   {
5017 5018 5019 5020 5021
      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 */
5022
                /*  size_t rowbytes;         number of bytes in row */
5023 5024 5025 5026 5027 5028
                /*  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
5029
      if (png_ptr->user_transform_depth != 0)
5030
         row_info->bit_depth = png_ptr->user_transform_depth;
5031

5032
      if (png_ptr->user_transform_channels != 0)
5033 5034
         row_info->channels = png_ptr->user_transform_channels;
#endif
5035 5036
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
5037

5038
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
5039
   }
5040
#endif
5041
}
5042

5043 5044
#endif /* READ_TRANSFORMS */
#endif /* READ */