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

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

19
#include "pngpriv.h"
20

21 22
#ifdef PNG_READ_SUPPORTED

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

         return 1; /* Ok */
      }
   }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   return output_gamma;
}

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

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

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

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

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

   png_debug(1, "in png_set_alpha_mode");

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

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

288
   /* Validate the value to ensure it is in a reasonable range. The value
289 290 291
    * 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
292 293 294 295
    * values are reasonable this may have to be changed:
    *
    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit
    * gamma of 36, and its reciprocal.)
296
    */
297
   if (output_gamma < 1000 || output_gamma > 10000000)
298
      png_error(png_ptr, "output gamma out of expected range");
299

300
   /* The default file gamma is the inverse of the output gamma; the output
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
    * 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.)
    */
358 359 360 361 362
   if (png_ptr->colorspace.gamma == 0)
   {
      png_ptr->colorspace.gamma = file_gamma;
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   }
363 364 365 366

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

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

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

      png_ptr->transformations |= PNG_COMPOSE;
   }
}

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

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

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

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

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

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

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

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

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

         int i;

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

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

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

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

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

475 476 477
                  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 已提交
478 479 480
                  done = 0;
               }
            }
481

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

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

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

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

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

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

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

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

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

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

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

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

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

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

594
         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
595
             (sizeof (png_dsortp))));
G
Guy Schalnat 已提交
596 597 598

         num_new_palette = num_palette;

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

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

                  if (d <= max_d)
                  {

624
                     t = (png_dsortp)png_malloc_warn(png_ptr,
625
                         (png_uint_32)(sizeof (png_dsort)));
626

627 628
                     if (t == NULL)
                         break;
629

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

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

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

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

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

                           for (k = 0; k < num_palette; k++)
                           {
676
                              if (png_ptr->quantize_index[k] ==
677
                                  png_ptr->index_to_palette[j])
678
                                 png_ptr->quantize_index[k] =
679
                                     png_ptr->index_to_palette[next_j];
680

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

688
                        png_ptr->index_to_palette[png_ptr->palette_to_index
689
                            [num_new_palette]] = png_ptr->index_to_palette[j];
690

691
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
692
                            = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
693

694 695
                        png_ptr->index_to_palette[j] =
                            (png_byte)num_new_palette;
696

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

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

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

749
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
750
          (png_uint_32)(num_entries * (sizeof (png_byte))));
751

752
      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
753
          (sizeof (png_byte))));
754

755
      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
756 757 758

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

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

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

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

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

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

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

809
   if (png_rtran_ok(png_ptr, 0) == 0)
810
      return;
811

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

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

   if (scrn_gamma <= 0)
831
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
832 833 834 835 836

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

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

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

862
   if (png_rtran_ok(png_ptr, 0) == 0)
863
      return;
864

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

/* 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.
880
 *
881 882 883
 *  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().
884 885 886
 */

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

892
   if (png_rtran_ok(png_ptr, 0) == 0)
893
      return;
894

895 896 897 898 899
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
}

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

904
   if (png_rtran_ok(png_ptr, 0) == 0)
905
      return;
906

907
   png_ptr->transformations |= PNG_EXPAND;
908 909 910
}

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

916
   if (png_rtran_ok(png_ptr, 0) == 0)
917 918
      return;

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

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

932
   if (png_rtran_ok(png_ptr, 0) == 0)
933 934 935 936 937 938
      return;

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

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

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

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

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

966
   switch (error_action)
967
   {
968
      case PNG_ERROR_ACTION_NONE:
969 970
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
         break;
971

972
      case PNG_ERROR_ACTION_WARN:
973 974
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
975

976
      case PNG_ERROR_ACTION_ERROR:
977
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
978 979 980
         break;

      default:
981
         png_error(png_ptr, "invalid error action to rgb_to_gray");
982
   }
983

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

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

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

         png_ptr->rgb_to_gray_red_coeff   = red_int;
         png_ptr->rgb_to_gray_green_coeff = green_int;
1013
         png_ptr->rgb_to_gray_coefficients_set = 1;
1014
      }
1015

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

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

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

1054
#endif /* RGB_TO_GRAY */
A
Andreas Dilger 已提交
1055

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1253 1254
            default:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1423
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433
   /* 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.
    *
1434
    * TODO: this code needs to be revised to avoid the complexity and
1435 1436 1437 1438
    * interdependencies.  The color type of the background should be recorded in
    * png_set_background, along with the bit depth, then the code has a record
    * of exactly what color space the background is currently in.
    */
1439
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1440 1441
   {
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1442
       * the file was grayscale the background value is gray.
1443
       */
1444
      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1445 1446 1447
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

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

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

1482 1483 1484
   else
      png_init_rgb_transformations(png_ptr);

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

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

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

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

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
1664 1665
               else
               {
1666 1667 1668
                  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 已提交
1669 1670
               }
            }
1671

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

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

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

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

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

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

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

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

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

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

1745 1746
            g_sig = png_gamma_significant(g);
            gs_sig = png_gamma_significant(gs);
1747

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

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

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

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

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

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

1778 1779
                  png_ptr->background.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, gs);
1780

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1883 1884
      png_ptr->transformations &= ~PNG_SHIFT;

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

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
1942 1943
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1944

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2106
      if (png_ptr->user_transform_channels != 0)
2107
         info_ptr->channels = png_ptr->user_transform_channels;
2108
   }
2109 2110
#endif

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

2114
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2115

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

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

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

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

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

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

G
Guy Schalnat 已提交
2164 2165 2166 2167 2168 2169 2170
               else
                  shift++;

               dp--;
            }
            break;
         }
2171

G
Guy Schalnat 已提交
2172 2173 2174
         case 2:
         {

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

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

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

               dp--;
            }
            break;
         }
2195

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

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

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

               dp--;
            }
            break;
         }
2218 2219 2220

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

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

2241
   png_debug(1, "in png_do_unshift");
2242

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

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

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

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

G
Guy Schalnat 已提交
2269
      {
2270
         int c, have_shift;
2271

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

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

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

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

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

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

            mask |= mask << 4;
2320

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2671
   png_debug(1, "in png_do_read_filler");
2672

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

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

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

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

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

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

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

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

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

2852
   png_debug(1, "in png_do_gray_to_rgb");
2853

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

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

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

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

2932
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2933
/* Reduce RGB files to grayscale, with or without alpha
2934 2935 2936 2937 2938
 * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
 * versions dated 1998 through November 2002 have been archived at
 * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
 * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
2939
 * Charles Poynton poynton at poynton.com
2940 2941 2942
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
2943
 *  which can be expressed with integers as
2944
 *
2945 2946 2947 2948 2949 2950 2951
 *     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
2952 2953 2954
 *
 *  which can be expressed with integers as
 *
2955 2956
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
 *
2957 2958 2959 2960 2961
 *  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:
2962
 *
2963
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2964
 *
2965 2966 2967 2968 2969
 *  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
2970
 *
2971 2972 2973
 *  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.
2974
 *
2975 2976 2977 2978
 *  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.
2979
 *
2980 2981 2982 2983
 *  Other integer coefficents can be used via png_set_rgb_to_gray().  Because
 *  the API takes just red and green coefficients the blue coefficient is
 *  calculated to make the sum 32768.  This will result in different rounding
 *  to that used above.
2984
 */
2985
static int
2986
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2987 2988 2989 2990

{
   int rgb_error = 0;

2991
   png_debug(1, "in png_do_rgb_to_gray");
2992

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

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

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

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

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

3042
                  *(dp++) = red;
3043
               }
3044

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

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

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

3071 3072
               else
                  *(dp++) = red;
3073

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

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

3094 3095 3096
               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));
3097

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

3104 3105
                  else
                     w = red;
3106
               }
3107 3108

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

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

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

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

3146 3147 3148
               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));
3149

3150 3151
               if (red != green || red != blue)
                  rgb_error |= 1;
3152

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

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

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

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

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

3207
   png_debug(1, "in png_do_compose");
3208

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

3231
                     if (shift == 0)
G
Guy Schalnat 已提交
3232 3233 3234 3235
                     {
                        shift = 7;
                        sp++;
                     }
3236

G
Guy Schalnat 已提交
3237 3238 3239 3240 3241
                     else
                        shift--;
                  }
                  break;
               }
3242

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

3261 3262
                        else
                        {
3263 3264 3265 3266
                           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));
3267
                           tmp |= (unsigned int)(g << shift);
3268
                           *sp = (png_byte)(tmp & 0xff);
3269
                        }
3270

3271
                        if (shift == 0)
3272 3273 3274 3275
                        {
                           shift = 6;
                           sp++;
                        }
3276

3277 3278
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3279
                     }
3280
                  }
3281

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

3298
                        if (shift == 0)
3299 3300 3301 3302
                        {
                           shift = 6;
                           sp++;
                        }
3303

3304 3305
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3306 3307 3308 3309
                     }
                  }
                  break;
               }
3310

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

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

3339
                        if (shift == 0)
3340 3341 3342 3343
                        {
                           shift = 4;
                           sp++;
                        }
3344

3345 3346
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3347
                     }
3348
                  }
3349

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

3366
                        if (shift == 0)
3367 3368 3369 3370
                        {
                           shift = 4;
                           sp++;
                        }
3371

3372 3373
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3374 3375 3376 3377
                     }
                  }
                  break;
               }
3378

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

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

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

3417
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3418

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

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

3444
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3445

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

               default:
                  break;
G
Guy Schalnat 已提交
3460 3461 3462
            }
            break;
         }
3463

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

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

3518 3519
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3520

3521 3522
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3523

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

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

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

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

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

3565 3566
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3567

3568 3569
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3570

3571 3572 3573
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3574
                     {
3575 3576
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3577 3578 3579 3580 3581 3582
                        *(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);
3583
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3584 3585 3586 3587 3588 3589
                     }
                  }
               }
            }
            break;
         }
3590

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

A
Andreas Dilger 已提交
3604
                     if (a == 0xff)
3605
                        *sp = gamma_table[*sp];
3606

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

A
Andreas Dilger 已提交
3613 3614 3615
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3616

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

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

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

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

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

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

A
Andreas Dilger 已提交
3670 3671 3672
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3673

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

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

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

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

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

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

G
Guy Schalnat 已提交
3737 3738
                     else if (a == 0)
                     {
3739
                        /* Background is already in screen gamma */
3740 3741 3742
                        *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 已提交
3743
                     }
3744

G
Guy Schalnat 已提交
3745 3746
                     else
                     {
A
Andreas Dilger 已提交
3747
                        png_byte v, w;
G
Guy Schalnat 已提交
3748 3749

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

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

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

3774
                     if (a == 0)
G
Guy Schalnat 已提交
3775
                     {
3776 3777 3778
                        *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 已提交
3779
                     }
3780

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

3785
                        png_composite(*(sp + 1), *(sp + 1), a,
3786
                            png_ptr->background.green);
3787

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

G
Guy Schalnat 已提交
3806 3807 3808 3809
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

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

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

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

G
Guy Schalnat 已提交
3823 3824
                     else if (a == 0)
                     {
3825
                        /* Background is already in screen gamma */
3826 3827
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3828 3829 3830 3831 3832 3833
                        *(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);
3834
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3835
                     }
3836

G
Guy Schalnat 已提交
3837 3838
                     else
                     {
3839
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
3840 3841

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

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

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

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

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

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

3879
                     if (a == 0)
G
Guy Schalnat 已提交
3880
                     {
3881 3882
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3883 3884 3885 3886 3887 3888
                        *(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);
3889
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3890
                     }
3891

3892
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
3893
                     {
3894
                        png_uint_16 v;
A
Andreas Dilger 已提交
3895

3896 3897 3898 3899 3900
                        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 已提交
3901

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

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

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

         default:
            break;
G
Guy Schalnat 已提交
3922 3923 3924
      }
   }
}
3925
#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
G
Guy Schalnat 已提交
3926

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

3945
   png_debug(1, "in png_do_gamma");
3946

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

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

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

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

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

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

G
Guy Schalnat 已提交
4004 4005
                  *sp = gamma_table[*sp];
                  sp++;
4006

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

G
Guy Schalnat 已提交
4010 4011 4012
                  sp++;
               }
            }
4013

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

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

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

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

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

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

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

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

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

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

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

         default:
            break;
G
Guy Schalnat 已提交
4125 4126 4127
      }
   }
}
G
Guy Schalnat 已提交
4128
#endif
G
Guy Schalnat 已提交
4129

4130 4131 4132 4133 4134
#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.
 */
4135
static void
4136
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4137 4138 4139 4140 4141
{
   png_uint_32 row_width = row_info->width;

   png_debug(1, "in png_do_encode_alpha");

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

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

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

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

            return;
         }
      }

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

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

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

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

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

            return;
         }
      }
   }

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

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

4210
   png_debug(1, "in png_do_expand_palette");
4211

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

G
Guy Schalnat 已提交
4228 4229
                  else
                     *dp = 0;
4230

G
Guy Schalnat 已提交
4231 4232 4233 4234 4235
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4236

G
Guy Schalnat 已提交
4237 4238 4239 4240 4241 4242 4243
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4244

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

G
Guy Schalnat 已提交
4260 4261 4262 4263 4264 4265 4266
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4267

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

G
Guy Schalnat 已提交
4283 4284 4285 4286 4287 4288 4289
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4290 4291 4292

            default:
               break;
G
Guy Schalnat 已提交
4293 4294 4295
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4296
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4297
      }
4298

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

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

G
Guy Schalnat 已提交
4312
                  else
4313
                     *dp-- = trans_alpha[*sp];
4314

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

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

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

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

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

4363
   png_debug(1, "in png_do_expand");
4364

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

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

A
Andreas Dilger 已提交
4385 4386
                     else
                        *dp = 0;
4387

A
Andreas Dilger 已提交
4388 4389 4390 4391 4392
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4393

A
Andreas Dilger 已提交
4394 4395
                     else
                        shift++;
G
Guy Schalnat 已提交
4396

A
Andreas Dilger 已提交
4397 4398 4399
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4400
               }
4401

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

A
Andreas Dilger 已提交
4419 4420
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4421

A
Andreas Dilger 已提交
4422 4423 4424
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4425
               }
4426

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

A
Andreas Dilger 已提交
4443 4444
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4445

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

               default:
                  break;
G
Guy Schalnat 已提交
4453
            }
4454

A
Andreas Dilger 已提交
4455 4456
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4457
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4458
         }
A
Andreas Dilger 已提交
4459

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

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

A
Andreas Dilger 已提交
4473 4474
                  else
                     *dp-- = 0xff;
4475

A
Andreas Dilger 已提交
4476
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4477
               }
A
Andreas Dilger 已提交
4478
            }
4479

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

A
Andreas Dilger 已提交
4495 4496 4497 4498 4499
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4500

A
Andreas Dilger 已提交
4501 4502
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4503 4504
               }
            }
4505

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

G
Guy Schalnat 已提交
4528 4529
               else
                  *dp-- = 0xff;
4530

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

G
Guy Schalnat 已提交
4559 4560 4561 4562 4563
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4564

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

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

      row_info->rowbytes *= 2;
      row_info->bit_depth = 16;
      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
   }
}
#endif

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

   png_debug(1, "in png_do_quantize");

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

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

            *dp++ = palette_lookup[p];
         }

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

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

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

            *dp++ = palette_lookup[p];
         }

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

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

         for (i = 0; i < row_width; i++, sp++)
         {
            *sp = quantize_lookup[*sp];
         }
      }
   }
}
4705
#endif /* READ_QUANTIZE */
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

/* 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 &&
4732
       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4733 4734 4735 4736 4737 4738 4739 4740 4741
   {
      /* 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
4742
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4743 4744 4745 4746 4747 4748 4749 4750 4751
   {
      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
      }

      else
      {
4752 4753
         if (png_ptr->num_trans != 0 &&
             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764
            png_do_expand(row_info, png_ptr->row_buf + 1,
                &(png_ptr->trans_color));

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

#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4765 4766 4767 4768
   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))
4769
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4770
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4771 4772 4773
#endif

#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4774
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4775 4776 4777 4778 4779
   {
      int rgb_error =
          png_do_rgb_to_gray(png_ptr, row_info,
              png_ptr->row_buf + 1);

4780
      if (rgb_error != 0)
4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828
      {
         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
    */
4829 4830
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4831 4832 4833 4834 4835
      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)
4836
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4837 4838
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4839

4840
#ifdef PNG_READ_GAMMA_SUPPORTED
4841
   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4842 4843
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
      /* Because RGB_TO_GRAY does the gamma transform. */
4844
      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4845 4846 4847 4848 4849 4850
#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.)
       */
4851
       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4852
       ((png_ptr->num_trans != 0) ||
4853
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4854 4855 4856 4857 4858 4859 4860
#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
4861

4862
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4863 4864 4865 4866
   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))
4867
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4868
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4869
#endif
G
Guy Schalnat 已提交
4870

4871
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4872 4873
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4874 4875
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
G
Guy Schalnat 已提交
4876

4877
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
4878
   if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
4879 4880
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
#endif
4881

4882 4883 4884 4885 4886
#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.
    */
4887
   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4888 4889
      png_do_chop(row_info, png_ptr->row_buf + 1);
#endif
4890

4891
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4892
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4893 4894 4895
   {
      png_do_quantize(row_info, png_ptr->row_buf + 1,
          png_ptr->palette_lookup, png_ptr->quantize_index);
G
Guy Schalnat 已提交
4896

4897 4898 4899
      if (row_info->rowbytes == 0)
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
   }
4900
#endif /* READ_QUANTIZE */
G
Guy Schalnat 已提交
4901

4902 4903 4904 4905 4906 4907
#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!)
    */
4908
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4909 4910
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
#endif
4911

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

4919
#ifdef PNG_READ_INVERT_SUPPORTED
4920
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4921 4922
      png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
4923

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

4929
#ifdef PNG_READ_SHIFT_SUPPORTED
4930
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4931 4932 4933
      png_do_unshift(row_info, png_ptr->row_buf + 1,
          &(png_ptr->shift));
#endif
G
Guy Schalnat 已提交
4934

4935
#ifdef PNG_READ_PACK_SUPPORTED
4936
   if ((png_ptr->transformations & PNG_PACK) != 0)
4937 4938
      png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
4939

4940 4941 4942 4943 4944 4945
#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
4946

4947
#ifdef PNG_READ_BGR_SUPPORTED
4948
   if ((png_ptr->transformations & PNG_BGR) != 0)
4949 4950
      png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
4951

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

4957
#ifdef PNG_READ_FILLER_SUPPORTED
4958
   if ((png_ptr->transformations & PNG_FILLER) != 0)
4959 4960 4961
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif
4962

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

4968 4969
#ifdef PNG_READ_16BIT_SUPPORTED
#ifdef PNG_READ_SWAP_SUPPORTED
4970
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
4971 4972 4973
      png_do_swap(row_info, png_ptr->row_buf + 1);
#endif
#endif
4974

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

4993
      if (png_ptr->user_transform_channels != 0)
4994 4995 4996 4997
         row_info->channels = png_ptr->user_transform_channels;
#endif
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
4998

4999
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
5000
   }
5001
#endif
5002
}
5003

5004 5005
#endif /* READ_TRANSFORMS */
#endif /* READ */