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

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

19
#include "pngpriv.h"
20

21 22
#ifdef PNG_READ_SUPPORTED

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

         return 1; /* Ok */
      }
   }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   else if (output_gamma == PNG_GAMMA_MAC_18 ||
      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
   {
      if (is_screen)
         output_gamma = PNG_GAMMA_MAC_OLD;
      else
         output_gamma = PNG_GAMMA_MAC_INVERSE;
   }

   return output_gamma;
}

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

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

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

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

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

   png_debug(1, "in png_set_alpha_mode");

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

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

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

296
   /* The default file gamma is the inverse of the output gamma; the output
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    * gamma may be changed below so get the file value first:
    */
   file_gamma = png_reciprocal(output_gamma);

   /* There are really 8 possibilities here, composed of any combination
    * of:
    *
    *    premultiply the color channels
    *    do not encode non-opaque pixels
    *    encode the alpha as well as the color channels
    *
    * The differences disappear if the input/output ('screen') gamma is 1.0,
    * because then the encoding is a no-op and there is only the choice of
    * premultiplying the color channels or not.
    *
    * png_set_alpha_mode and png_set_background interact because both use
    * png_compose to do the work.  Calling both is only useful when
    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
    */
   switch (mode)
   {
      case PNG_ALPHA_PNG:        /* default: png standard */
         /* No compose, but it may be set by png_set_background! */
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
         break;

      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
         compose = 1;
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
         /* The output is linear: */
         output_gamma = PNG_FP_1;
         break;

      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
         compose = 1;
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
         /* output_gamma records the encoding of opaque pixels! */
         break;

      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
         compose = 1;
         png_ptr->transformations |= PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
         break;

      default:
         png_error(png_ptr, "invalid alpha mode");
   }

   /* Only set the default gamma if the file gamma has not been set (this has
    * the side effect that the gamma in a second call to png_set_alpha_mode will
    * be ignored.)
    */
354 355 356 357 358
   if (png_ptr->colorspace.gamma == 0)
   {
      png_ptr->colorspace.gamma = file_gamma;
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   }
359 360 361 362

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

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

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

      png_ptr->transformations |= PNG_COMPOSE;
   }
}

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

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

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

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

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

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

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

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

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

         int i;

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

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

A
Andreas Dilger 已提交
451
         /* Find the least used palette entries by starting a
452 453 454 455 456
          * bubble sort, and running it until we have sorted
          * out enough colors.  Note that we don't care about
          * sorting all the colors, just finding which are
          * least used.
          */
G
Guy Schalnat 已提交
457 458 459

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

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

471 472 473
                  t = png_ptr->quantize_sort[j];
                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
                  png_ptr->quantize_sort[j + 1] = t;
G
Guy Schalnat 已提交
474 475 476
                  done = 0;
               }
            }
477

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

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

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

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

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

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

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

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

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

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

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
548
                        min_k = k;
G
Guy Schalnat 已提交
549 550
                     }
                  }
551
                  /* Point to closest color */
552
                  png_ptr->quantize_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
553 554 555
               }
            }
         }
556 557
         png_free(png_ptr, png_ptr->quantize_sort);
         png_ptr->quantize_sort = NULL;
G
Guy Schalnat 已提交
558 559 560
      }
      else
      {
A
Andreas Dilger 已提交
561
         /* This is much harder to do simply (and quickly).  Perhaps
562 563 564 565 566 567 568
          * we need to go through a median cut routine, but those
          * don't always behave themselves with only a few colors
          * as input.  So we will just find the closest two colors,
          * and throw out one of them (chosen somewhat randomly).
          * [We don't understand this at all, so if someone wants to
          *  work on improving it, be our guest - AED, GRP]
          */
G
Guy Schalnat 已提交
569 570 571
         int i;
         int max_d;
         int num_new_palette;
572
         png_dsortp t;
G
Guy Schalnat 已提交
573
         png_dsortpp hash;
574

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

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

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

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

         num_new_palette = num_palette;

595 596 597 598 599 600 601 602
         /* Initial wild guess at how far apart the farthest pixel
          * pair we will be eliminating will be.  Larger
          * numbers mean more areas will be allocated, Smaller
          * numbers run the risk of not saving enough data, and
          * having to do this all over again.
          *
          * I have not done extensive checking on this number.
          */
G
Guy Schalnat 已提交
603 604
         max_d = 96;

G
Guy Schalnat 已提交
605
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
606 607 608 609 610 611 612 613 614
         {
            for (i = 0; i < num_new_palette - 1; i++)
            {
               int j;

               for (j = i + 1; j < num_new_palette; j++)
               {
                  int d;

G
Guy Schalnat 已提交
615
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
616 617 618 619

                  if (d <= max_d)
                  {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

734
   if (full_quantize)
G
Guy Schalnat 已提交
735 736
   {
      int i;
G
Guy Schalnat 已提交
737
      png_bytep distance;
738 739 740 741 742
      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
          PNG_QUANTIZE_BLUE_BITS;
      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
743
      png_size_t num_entries = ((png_size_t)1 << total_bits);
G
Guy Schalnat 已提交
744

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

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

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

      for (i = 0; i < num_palette; i++)
      {
755
         int ir, ig, ib;
756 757 758
         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
G
Guy Schalnat 已提交
759 760 761

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

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

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

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

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

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

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

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

812
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
813 814 815
    * premultiplied alpha support; this actually hides an undocumented feature
    * of the previous implementation which allowed gamma processing to be
    * disabled in background handling.  There is no evidence (so far) that this
816
    * was being used; however, png_set_background itself accepted and must still
817 818 819
    * accept '0' for the gamma value it takes, because it isn't always used.
    *
    * Since this is an API change (albeit a very minor one that removes an
820 821
    * undocumented API feature) the following checks were only enabled in
    * libpng-1.6.0.
822 823
    */
   if (file_gamma <= 0)
824
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
825 826

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

   /* Set the gamma values unconditionally - this overrides the value in the PNG
    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
    * different, easier, way to default the file gamma.
    */
833 834
   png_ptr->colorspace.gamma = file_gamma;
   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
G
[devel]  
Glenn Randers-Pehrson 已提交
835
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
836
}
G
[devel]  
Glenn Randers-Pehrson 已提交
837 838 839

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

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

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

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

/* GRR 19990627:  the following three functions currently are identical
 *  to png_set_expand().  However, it is entirely reasonable that someone
 *  might wish to expand an indexed image to RGB but *not* expand a single,
 *  fully transparent palette entry to a full alpha channel--perhaps instead
 *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
 *  the transparent color with a particular RGB value, or drop tRNS entirely.
 *  IOW, a future version of the library may make the transformations flag
 *  a bit more fine-grained, with separate bits for each of these three
 *  functions.
 *
 *  More to the point, these functions make it obvious what libpng will be
 *  doing, whereas "expand" can (and does) mean any number of things.
876
 *
877 878 879
 *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
 *  to expand only the sample depth but not to expand the tRNS to alpha
 *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
880 881 882
 */

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

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

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

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

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

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

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

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

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

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

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

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

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

941 942 943 944 945 946
   if (!png_rtran_ok(png_ptr, 0))
      return;

   /* Because rgb must be 8 bits or more: */
   png_set_expand_gray_1_2_4_to_8(png_ptr);
   png_ptr->transformations |= PNG_GRAY_TO_RGB;
G
Guy Schalnat 已提交
947
}
G
Guy Schalnat 已提交
948
#endif
G
Guy Schalnat 已提交
949

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1153 1154
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1155 1156
    */
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1157
       (png_ptr->transformations & PNG_EXPAND))
1158
   {
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
      {
         png_ptr->background.red   =
             png_ptr->palette[png_ptr->background.index].red;
         png_ptr->background.green =
             png_ptr->palette[png_ptr->background.index].green;
         png_ptr->background.blue  =
             png_ptr->palette[png_ptr->background.index].blue;

#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
        if (png_ptr->transformations & PNG_INVERT_ALPHA)
        {
           if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
           {
              /* Invert the alpha channel (in tRNS) unless the pixels are
               * going to be expanded, in which case leave it for later
               */
              int i, istop = png_ptr->num_trans;

              for (i=0; i<istop; i++)
                 png_ptr->trans_alpha[i] = (png_byte)(255 -
                    png_ptr->trans_alpha[i]);
           }
        }
#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
      }
   } /* background expand and (therefore) no alpha association. */
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
}

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

1198 1199
   /* If no alpha we can optimize. */
   if (!input_has_alpha)
1200
   {
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
      /* Any alpha means background and associative alpha processing is
       * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
       * and ENCODE_ALPHA are irrelevant.
       */
#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
#     endif

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

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

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

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

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

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

1250 1251
            default:

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

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

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

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

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

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

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

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

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

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

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

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

      /* Now turn the gamma transformation on or off as appropriate.  Notice
       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
       * composition may independently cause gamma correction because it needs
       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
       * hasn't been specified.)  In any case this flag may get turned off in
       * the code immediately below if the transform can be handled outside the
       * row loop.
       */
      if (gamma_correction)
         png_ptr->transformations |= PNG_GAMMA;

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

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

1389
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1390 1391 1392 1393
       * so transparency information would remain just so long as it wasn't
       * expanded.  This produces unexpected API changes if the set of things
       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
       * documentation - which says ask for what you want, accept what you
1394
       * get.)  This makes the behavior consistent from 1.5.4:
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
       */
      png_ptr->num_trans = 0;
   }
#endif /* STRIP_ALPHA supported, no COMPOSE */

#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
    * settings will have no effect.
    */
   if (!png_gamma_significant(png_ptr->screen_gamma))
   {
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
   }
G
Guy Schalnat 已提交
1409
#endif
1410

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

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

   else if (png_ptr->transformations & PNG_COMPOSE)
1446
   {
1447 1448 1449 1450 1451 1452
      /* PNG_COMPOSE: png_set_background was called with need_expand false,
       * so the color is in the color space of the output or png_set_alpha_mode
       * was called and the color is black.  Ignore RGB_TO_GRAY because that
       * happens before GRAY_TO_RGB.
       */
      if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1453
      {
1454 1455 1456 1457 1458 1459
         if (png_ptr->background.red == png_ptr->background.green &&
             png_ptr->background.red == png_ptr->background.blue)
         {
            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
            png_ptr->background.gray = png_ptr->background.red;
         }
1460
      }
1461
   }
1462 1463
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477

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

1479 1480 1481
   else
      png_init_rgb_transformations(png_ptr);

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

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

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

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

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

1574
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1575
      if (png_ptr->transformations & PNG_COMPOSE)
G
Guy Schalnat 已提交
1576
      {
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
         /* Issue a warning about this combination: because RGB_TO_GRAY is
          * optimized to do the gamma transform if present yet do_background has
          * to do the same thing if both options are set a
          * double-gamma-correction happens.  This is true in all versions of
          * libpng to date.
          */
         if (png_ptr->transformations & PNG_RGB_TO_GRAY)
            png_warning(png_ptr,
               "libpng does not support gamma+background+rgb_to_gray");

1587
         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1588
         {
1589 1590 1591
            /* We don't get to here unless there is a tRNS chunk with non-opaque
             * entries - see the checking code at the start of this function.
             */
G
Guy Schalnat 已提交
1592
            png_color back, back_1;
1593 1594 1595
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1596 1597
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1598

A
Andreas Dilger 已提交
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608
               back.red = png_ptr->gamma_table[png_ptr->background.red];
               back.green = png_ptr->gamma_table[png_ptr->background.green];
               back.blue = png_ptr->gamma_table[png_ptr->background.blue];

               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
            }
            else
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1609
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1610

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

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

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

1635
               if (png_gamma_significant(gs))
1636 1637 1638 1639 1640 1641 1642 1643 1644 1645
               {
                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
                      gs);
                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
                      gs);
                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
                      gs);
               }

               else
A
Andreas Dilger 已提交
1646
               {
1647
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1648
                  back.green = (png_byte)png_ptr->background.green;
1649
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1650
               }
1651

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

A
Andreas Dilger 已提交
1662 1663
               else
               {
1664 1665 1666
                  back_1.red   = (png_byte)png_ptr->background.red;
                  back_1.green = (png_byte)png_ptr->background.green;
                  back_1.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1667 1668
               }
            }
1669

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

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

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

                     v = png_ptr->gamma_to_1[palette[i].blue];
1692
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
                     palette[i].blue = png_ptr->gamma_from_1[w];
                  }
               }
               else
               {
                  palette[i].red = png_ptr->gamma_table[palette[i].red];
                  palette[i].green = png_ptr->gamma_table[palette[i].green];
                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
               }
            }
1703 1704 1705

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

1713
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1714
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1715
         {
1716 1717 1718
            int gs_sig, g_sig;
            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
G
Guy Schalnat 已提交
1719 1720

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

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

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

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

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

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

            if (gs_sig)
               png_ptr->background.gray = png_gamma_correct(png_ptr,
                   png_ptr->background.gray, gs);
1753

1754 1755 1756
            if ((png_ptr->background.red != png_ptr->background.green) ||
                (png_ptr->background.red != png_ptr->background.blue) ||
                (png_ptr->background.red != png_ptr->background.gray))
G
Guy Schalnat 已提交
1757
            {
1758
               /* RGB or RGBA with color background */
1759 1760 1761 1762
               if (g_sig)
               {
                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, g);
1763

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

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

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

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

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

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

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

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

G
Guy Schalnat 已提交
1799
      else
1800
      /* Transformation does not include PNG_BACKGROUND */
1801
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1802 1803 1804 1805 1806 1807 1808
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
#endif
         )
G
Guy Schalnat 已提交
1809
      {
1810 1811 1812
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1813

1814 1815
         /* NOTE: there are other transformations that should probably be in
          * here too.
1816
          */
G
Guy Schalnat 已提交
1817 1818 1819 1820 1821 1822
         for (i = 0; i < num_palette; i++)
         {
            palette[i].red = png_ptr->gamma_table[palette[i].red];
            palette[i].green = png_ptr->gamma_table[palette[i].green];
            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
         }
1823

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

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

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

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

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

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

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

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

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

1881 1882
      png_ptr->transformations &= ~PNG_SHIFT;

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

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
1937 1938
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1939

G
Guy Schalnat 已提交
1940
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1941 1942 1943 1944 1945
         info_ptr->num_trans = 0;
      }
      else
      {
         if (png_ptr->num_trans)
1946 1947
         {
            if (png_ptr->transformations & PNG_EXPAND_tRNS)
1948
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1949
         }
A
Andreas Dilger 已提交
1950 1951
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1952

A
Andreas Dilger 已提交
1953 1954
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1955 1956 1957
   }
#endif

1958 1959 1960 1961 1962 1963
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
   /* The following is almost certainly wrong unless the background value is in
    * the screen space!
    */
   if (png_ptr->transformations & PNG_COMPOSE)
G
Guy Schalnat 已提交
1964 1965 1966
      info_ptr->background = png_ptr->background;
#endif

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

1980 1981
   if (info_ptr->bit_depth == 16)
   {
1982
#  ifdef PNG_READ_16BIT_SUPPORTED
1983 1984 1985 1986 1987 1988 1989 1990 1991 1992
#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
         if (png_ptr->transformations & PNG_SCALE_16_TO_8)
            info_ptr->bit_depth = 8;
#     endif

#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
         if (png_ptr->transformations & PNG_16_TO_8)
            info_ptr->bit_depth = 8;
#     endif

1993
#  else
1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
      /* No 16 bit support: force chopping 16-bit input down to 8, in this case
       * the app program can chose if both APIs are available by setting the
       * correct scaling to use.
       */
#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
         /* For compatibility with previous versions use the strip method by
          * default.  This code works because if PNG_SCALE_16_TO_8 is already
          * set the code below will do that in preference to the chop.
          */
         png_ptr->transformations |= PNG_16_TO_8;
         info_ptr->bit_depth = 8;
#     else
2006

2007
#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2008 2009 2010 2011 2012 2013
            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
2014
#    endif
2015
#endif /* !READ_16BIT_SUPPORTED */
2016
   }
G
Guy Schalnat 已提交
2017

2018
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2019
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2020 2021
      info_ptr->color_type = (png_byte)(info_ptr->color_type |
         PNG_COLOR_MASK_COLOR);
2022 2023
#endif

2024
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2025
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
2026 2027
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_COLOR);
2028 2029
#endif

2030 2031
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
2032 2033
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2034 2035
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
2036 2037 2038
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
2039
   }
G
Guy Schalnat 已提交
2040 2041
#endif

2042 2043 2044 2045 2046 2047 2048 2049
#ifdef PNG_READ_EXPAND_16_SUPPORTED
   if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
      info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
   {
      info_ptr->bit_depth = 16;
   }
#endif

2050
#ifdef PNG_READ_PACK_SUPPORTED
2051
   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
2052 2053 2054
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
2055
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2056
      info_ptr->channels = 1;
2057

G
Guy Schalnat 已提交
2058 2059
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
2060

G
Guy Schalnat 已提交
2061 2062
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
2063

2064
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2065
   if (png_ptr->transformations & PNG_STRIP_ALPHA)
2066
   {
2067 2068
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_ALPHA);
2069 2070
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
2071 2072
#endif

2073 2074 2075
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

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

2089 2090
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2091
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2092 2093
   {
      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
2094
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2095

2096
      if (info_ptr->channels < png_ptr->user_transform_channels)
2097
         info_ptr->channels = png_ptr->user_transform_channels;
2098
   }
2099 2100
#endif

G
Guy Schalnat 已提交
2101
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2102
       info_ptr->bit_depth);
2103

2104
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2105

2106
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2107 2108 2109 2110 2111 2112 2113
    * 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;

2114
#ifndef PNG_READ_EXPAND_SUPPORTED
2115
   if (png_ptr)
2116 2117
      return;
#endif
G
Guy Schalnat 已提交
2118 2119
}

2120 2121 2122 2123
/* 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.
 */
2124
void /* PRIVATE */
2125
png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
G
Guy Schalnat 已提交
2126
{
2127
   png_debug(1, "in png_do_read_transformations");
2128

A
Andreas Dilger 已提交
2129
   if (png_ptr->row_buf == NULL)
G
Guy Schalnat 已提交
2130
   {
2131
      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
2132 2133 2134
       * error is incredibly rare and incredibly easy to debug without this
       * information.
       */
2135
      png_error(png_ptr, "NULL row buffer");
G
Guy Schalnat 已提交
2136
   }
2137

2138 2139
   /* 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
2140 2141 2142
    * 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.
2143 2144 2145 2146 2147 2148
    */
   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
      !(png_ptr->flags & PNG_FLAG_ROW_INIT))
   {
      /* Application has failed to call either png_read_start_image() or
       * png_read_update_info() after setting transforms that expand pixels.
2149
       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
2150
       */
2151
      png_error(png_ptr, "Uninitialized row");
2152
   }
A
Andreas Dilger 已提交
2153

2154
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
2155
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
2156
   {
2157
      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
A
Andreas Dilger 已提交
2158
      {
2159
         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
2160
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
A
Andreas Dilger 已提交
2161
      }
2162

2163
      else
A
Andreas Dilger 已提交
2164
      {
2165 2166
         if (png_ptr->num_trans &&
             (png_ptr->transformations & PNG_EXPAND_tRNS))
2167
            png_do_expand(row_info, png_ptr->row_buf + 1,
2168
                &(png_ptr->trans_color));
2169

2170
         else
2171
            png_do_expand(row_info, png_ptr->row_buf + 1,
2172
                NULL);
A
Andreas Dilger 已提交
2173
      }
G
Guy Schalnat 已提交
2174
   }
G
Guy Schalnat 已提交
2175 2176
#endif

2177
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2178
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
2179
      !(png_ptr->transformations & PNG_COMPOSE) &&
2180 2181 2182
      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
2183
         0 /* at_start == false, because SWAP_ALPHA happens later */);
A
Andreas Dilger 已提交
2184 2185
#endif

2186
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2187 2188 2189
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
   {
      int rgb_error =
2190
          png_do_rgb_to_gray(png_ptr, row_info,
2191 2192
              png_ptr->row_buf + 1);

2193
      if (rgb_error)
2194 2195
      {
         png_ptr->rgb_to_gray_status=1;
2196
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
2197
             PNG_RGB_TO_GRAY_WARN)
2198
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
2199

2200 2201
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_ERR)
2202 2203 2204 2205 2206
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

2207
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
2208
 *
2209 2210 2211 2212
 *   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.
2213
 *
2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235
 *   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.
2236 2237
 */

2238
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2239 2240 2241
   /* If gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons
    */
2242
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
2243
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
2244
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
2245 2246
#endif

2247 2248
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
2249
   if (png_ptr->transformations & PNG_COMPOSE)
2250
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2251 2252
#endif

2253
#ifdef PNG_READ_GAMMA_SUPPORTED
G
Guy Schalnat 已提交
2254
   if ((png_ptr->transformations & PNG_GAMMA) &&
2255 2256 2257 2258
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
      /* Because RGB_TO_GRAY does the gamma transform. */
      !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
#endif
2259 2260
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
2261 2262 2263
      /* Because PNG_COMPOSE does the gamma transform if there is something to
       * do (if there is an alpha channel or transparency.)
       */
2264
       !((png_ptr->transformations & PNG_COMPOSE) &&
2265 2266
       ((png_ptr->num_trans != 0) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
2267
#endif
2268 2269 2270
      /* Because png_init_read_transformations transforms the palette, unless
       * RGB_TO_GRAY will do the transform.
       */
2271
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
2272
      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2273 2274
#endif

2275 2276 2277
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
      (png_ptr->transformations & PNG_COMPOSE) &&
2278 2279 2280
      (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
      row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
2281 2282 2283 2284 2285
         0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif

#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
2286 2287
      (row_info->color_type & PNG_COLOR_MASK_ALPHA))
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
2288 2289
#endif

2290
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2291
   if (png_ptr->transformations & PNG_SCALE_16_TO_8)
2292
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
2293
#endif
2294

2295
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2296 2297 2298 2299
   /* 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.
    */
2300
   if (png_ptr->transformations & PNG_16_TO_8)
2301
      png_do_chop(row_info, png_ptr->row_buf + 1);
2302 2303
#endif

2304 2305
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
2306
   {
2307
      png_do_quantize(row_info, png_ptr->row_buf + 1,
2308
          png_ptr->palette_lookup, png_ptr->quantize_index);
2309

2310
      if (row_info->rowbytes == 0)
2311
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
A
Andreas Dilger 已提交
2312
   }
2313
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
2314

2315 2316 2317 2318 2319 2320 2321
#ifdef PNG_READ_EXPAND_16_SUPPORTED
   /* Do the expansion now, after all the arithmetic has been done.  Notice
    * that previous transformations can handle the PNG_EXPAND_16 flag if this
    * is efficient (particularly true in the case of gamma correction, where
    * better accuracy results faster!)
    */
   if (png_ptr->transformations & PNG_EXPAND_16)
2322
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
2323
#endif
2324 2325

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2326
   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
2327 2328
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
2329
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
2330
#endif
2331

2332
#ifdef PNG_READ_INVERT_SUPPORTED
G
Guy Schalnat 已提交
2333
   if (png_ptr->transformations & PNG_INVERT_MONO)
2334
      png_do_invert(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2335 2336
#endif

2337
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
2338
   if (png_ptr->transformations & PNG_SHIFT)
2339
      png_do_unshift(row_info, png_ptr->row_buf + 1,
2340
          &(png_ptr->shift));
G
Guy Schalnat 已提交
2341 2342
#endif

2343
#ifdef PNG_READ_PACK_SUPPORTED
G
Guy Schalnat 已提交
2344
   if (png_ptr->transformations & PNG_PACK)
2345
      png_do_unpack(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2346 2347
#endif

2348 2349 2350 2351 2352 2353 2354
#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

2355
#ifdef PNG_READ_BGR_SUPPORTED
G
Guy Schalnat 已提交
2356
   if (png_ptr->transformations & PNG_BGR)
2357
      png_do_bgr(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2358 2359
#endif

2360
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2361
   if (png_ptr->transformations & PNG_PACKSWAP)
2362
      png_do_packswap(row_info, png_ptr->row_buf + 1);
A
Andreas Dilger 已提交
2363 2364
#endif

2365
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
2366
   if (png_ptr->transformations & PNG_FILLER)
2367
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
2368
          (png_uint_32)png_ptr->filler, png_ptr->flags);
A
Andreas Dilger 已提交
2369 2370
#endif

2371
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2372
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
2373
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
2374 2375
#endif

2376
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2377
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
2378
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
2379 2380
#endif

2381
#ifdef PNG_READ_16BIT_SUPPORTED
2382
#ifdef PNG_READ_SWAP_SUPPORTED
A
Andreas Dilger 已提交
2383
   if (png_ptr->transformations & PNG_SWAP_BYTES)
2384
      png_do_swap(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2385
#endif
2386
#endif
2387

2388
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
2389
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2390
    {
2391
      if (png_ptr->read_user_transform_fn != NULL)
2392
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
2393 2394
             (png_ptr,     /* png_ptr */
             row_info,     /* row_info: */
2395
                /*  png_uint_32 width;       width of row */
2396
                /*  png_size_t rowbytes;     number of bytes in row */
2397 2398 2399 2400 2401
                /*  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 */
2402
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
2403
      if (png_ptr->user_transform_depth)
2404
         row_info->bit_depth = png_ptr->user_transform_depth;
2405

2406
      if (png_ptr->user_transform_channels)
2407
         row_info->channels = png_ptr->user_transform_channels;
2408
#endif
2409 2410
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
2411

2412
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
2413
   }
2414
#endif
G
Guy Schalnat 已提交
2415 2416
}

2417
#ifdef PNG_READ_PACK_SUPPORTED
2418 2419 2420 2421 2422 2423
/* 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.
 */
2424
void /* PRIVATE */
G
Guy Schalnat 已提交
2425
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2426
{
2427
   png_debug(1, "in png_do_unpack");
2428

A
Andreas Dilger 已提交
2429
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2430
   {
2431
      png_uint_32 i;
2432
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2433

G
Guy Schalnat 已提交
2434 2435 2436 2437
      switch (row_info->bit_depth)
      {
         case 1:
         {
2438 2439
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2440
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2441
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2442
            {
2443
               *dp = (png_byte)((*sp >> shift) & 0x01);
2444

G
Guy Schalnat 已提交
2445 2446 2447 2448
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2449
               }
2450

G
Guy Schalnat 已提交
2451 2452 2453 2454 2455 2456 2457
               else
                  shift++;

               dp--;
            }
            break;
         }
2458

G
Guy Schalnat 已提交
2459 2460 2461
         case 2:
         {

2462 2463
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2464
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2465
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2466
            {
2467
               *dp = (png_byte)((*sp >> shift) & 0x03);
2468

G
Guy Schalnat 已提交
2469 2470 2471 2472 2473
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2474

G
Guy Schalnat 已提交
2475 2476 2477 2478 2479 2480 2481
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2482

G
Guy Schalnat 已提交
2483 2484
         case 4:
         {
2485 2486
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2487
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2488
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2489
            {
2490
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2491

G
Guy Schalnat 已提交
2492 2493 2494 2495 2496
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2497

G
Guy Schalnat 已提交
2498 2499 2500 2501 2502 2503 2504
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2505 2506 2507

         default:
            break;
G
Guy Schalnat 已提交
2508 2509
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2510
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2511
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2512 2513
   }
}
G
Guy Schalnat 已提交
2514
#endif
G
Guy Schalnat 已提交
2515

2516
#ifdef PNG_READ_SHIFT_SUPPORTED
2517 2518 2519 2520 2521
/* 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.
 */
2522
void /* PRIVATE */
2523 2524
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2525
{
2526 2527
   int color_type;

2528
   png_debug(1, "in png_do_unshift");
2529

2530 2531 2532 2533
   /* 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 已提交
2534 2535
   {
      int shift[4];
2536
      int channels = 0;
2537
      int bit_depth = row_info->bit_depth;
G
Guy Schalnat 已提交
2538

2539
      if (color_type & PNG_COLOR_MASK_COLOR)
G
Guy Schalnat 已提交
2540
      {
2541 2542 2543
         shift[channels++] = bit_depth - sig_bits->red;
         shift[channels++] = bit_depth - sig_bits->green;
         shift[channels++] = bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2544
      }
2545

G
Guy Schalnat 已提交
2546 2547
      else
      {
2548
         shift[channels++] = bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2549
      }
2550

2551
      if (color_type & PNG_COLOR_MASK_ALPHA)
G
Guy Schalnat 已提交
2552
      {
2553
         shift[channels++] = bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2554
      }
G
Guy Schalnat 已提交
2555

G
Guy Schalnat 已提交
2556
      {
2557
         int c, have_shift;
2558

2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
         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 已提交
2570

2571 2572 2573
         if (!have_shift)
            return;
      }
G
Guy Schalnat 已提交
2574

2575
      switch (bit_depth)
G
Guy Schalnat 已提交
2576
      {
2577
         default:
2578 2579
         /* Must be 1bpp gray: should not be here! */
            /* NOTREACHED */
2580
            break;
2581

G
Guy Schalnat 已提交
2582
         case 2:
2583 2584
         /* Must be 2bpp gray */
         /* assert(channels == 1 && shift[0] == 1) */
G
Guy Schalnat 已提交
2585
         {
2586 2587
            png_bytep bp = row;
            png_bytep bp_end = bp + row_info->rowbytes;
A
Andreas Dilger 已提交
2588

2589
            while (bp < bp_end)
G
Guy Schalnat 已提交
2590
            {
2591 2592
               int b = (*bp >> 1) & 0x55;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2593 2594 2595
            }
            break;
         }
2596

G
Guy Schalnat 已提交
2597
         case 4:
2598 2599
         /* Must be 4bpp gray */
         /* assert(channels == 1) */
G
Guy Schalnat 已提交
2600
         {
2601
            png_bytep bp = row;
2602 2603 2604 2605 2606
            png_bytep bp_end = bp + row_info->rowbytes;
            int gray_shift = shift[0];
            int mask =  0xf >> gray_shift;

            mask |= mask << 4;
2607

2608
            while (bp < bp_end)
G
Guy Schalnat 已提交
2609
            {
2610 2611
               int b = (*bp >> gray_shift) & mask;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2612 2613 2614
            }
            break;
         }
2615

G
Guy Schalnat 已提交
2616
         case 8:
2617
         /* Single byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2618
         {
2619
            png_bytep bp = row;
2620 2621
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2622

2623
            while (bp < bp_end)
A
Andreas Dilger 已提交
2624
            {
2625
               int b = *bp >> shift[channel];
2626 2627
               if (++channel >= channels)
                  channel = 0;
2628
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2629 2630 2631
            }
            break;
         }
2632

2633
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2634
         case 16:
2635
         /* Double byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2636
         {
2637
            png_bytep bp = row;
2638 2639
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2640

2641
            while (bp < bp_end)
A
Andreas Dilger 已提交
2642
            {
2643 2644 2645 2646 2647
               int value = (bp[0] << 8) + bp[1];

               value >>= shift[channel];
               if (++channel >= channels)
                  channel = 0;
2648 2649
               *bp++ = (png_byte)(value >> 8);
               *bp++ = (png_byte)(value & 0xff);
G
Guy Schalnat 已提交
2650 2651 2652
            }
            break;
         }
2653
#endif
G
Guy Schalnat 已提交
2654 2655 2656
      }
   }
}
G
Guy Schalnat 已提交
2657
#endif
G
Guy Schalnat 已提交
2658

2659
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2660
/* Scale rows of bit depth 16 down to 8 accurately */
2661
void /* PRIVATE */
2662
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2663
{
2664
   png_debug(1, "in png_do_scale_16_to_8");
2665

A
Andreas Dilger 已提交
2666
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2667
   {
2668
      png_bytep sp = row; /* source */
2669
      png_bytep dp = row; /* destination */
2670
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2671

2672
      while (sp < ep)
G
Guy Schalnat 已提交
2673
      {
2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704
         /* The input is an array of 16 bit components, these must be scaled to
          * 8 bits each.  For a 16 bit value V the required value (from the PNG
          * specification) is:
          *
          *    (V * 255) / 65535
          *
          * This reduces to round(V / 257), or floor((V + 128.5)/257)
          *
          * Represent V as the two byte value vhi.vlo.  Make a guess that the
          * result is the top byte of V, vhi, then the correction to this value
          * is:
          *
          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
          *          = floor(((vlo-vhi) + 128.5) / 257)
          *
          * This can be approximated using integer arithmetic (and a signed
          * shift):
          *
          *    error = (vlo-vhi+128) >> 8;
          *
          * The approximate differs from the exact answer only when (vlo-vhi) is
          * 128; it then gives a correction of +1 when the exact correction is
          * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit
          * input values) is:
          *
          *    error = (vlo-vhi+128)*65535 >> 24;
          *
          * An alternative arithmetic calculation which also gives no errors is:
          *
          *    (V * 255 + 32895) >> 16
          */
2705

2706
         png_int_32 tmp = *sp++; /* must be signed! */
2707
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2708
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2709
      }
2710

G
Guy Schalnat 已提交
2711
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2712
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2713
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2714 2715
   }
}
2716
#endif
2717

2718
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
void /* PRIVATE */
/* 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 */
2730
      png_bytep dp = row; /* destination */
2731 2732 2733 2734
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
2735 2736
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2737 2738 2739 2740 2741 2742 2743
      }

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

2746
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2747
void /* PRIVATE */
A
Andreas Dilger 已提交
2748 2749
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2750
   png_debug(1, "in png_do_read_swap_alpha");
2751

A
Andreas Dilger 已提交
2752
   {
2753
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2754 2755 2756 2757 2758
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2759 2760
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2761 2762
            png_byte save;
            png_uint_32 i;
2763

2764
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2765 2766 2767 2768 2769 2770 2771 2772
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2773 2774

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2775 2776 2777
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2778 2779
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2780 2781
            png_byte save[2];
            png_uint_32 i;
2782

2783
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2797
#endif
A
Andreas Dilger 已提交
2798
      }
2799

A
Andreas Dilger 已提交
2800 2801 2802 2803 2804
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2805 2806
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2807 2808
            png_byte save;
            png_uint_32 i;
2809

2810
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2811 2812 2813 2814 2815 2816
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2817 2818

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2819 2820 2821
         /* This converts from GGAA to AAGG */
         else
         {
2822 2823
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2824 2825 2826
            png_byte save[2];
            png_uint_32 i;

2827
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2828 2829 2830 2831 2832 2833 2834 2835 2836
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2837
#endif
A
Andreas Dilger 已提交
2838
      }
G
Guy Schalnat 已提交
2839 2840
   }
}
G
Guy Schalnat 已提交
2841
#endif
G
Guy Schalnat 已提交
2842

2843
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2844
void /* PRIVATE */
2845 2846
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2847
   png_uint_32 row_width;
2848
   png_debug(1, "in png_do_read_invert_alpha");
2849

2850 2851
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2852
   {
2853
      if (row_info->bit_depth == 8)
2854 2855
      {
         /* This inverts the alpha channel in RGBA */
2856 2857 2858
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2859

2860 2861 2862
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
2863

2864 2865 2866 2867 2868
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2869
*/
2870 2871
            sp-=3;
            dp=sp;
2872
         }
2873
      }
2874 2875

#ifdef PNG_READ_16BIT_SUPPORTED
2876 2877 2878 2879 2880 2881
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2882

2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895
         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:
2896
*/
2897 2898
            sp-=6;
            dp=sp;
2899 2900
         }
      }
2901
#endif
2902 2903 2904 2905
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2906
      {
2907
         /* This inverts the alpha channel in GA */
2908 2909 2910
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2911

2912 2913 2914 2915
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = *(--sp);
2916
         }
2917
      }
2918 2919

#ifdef PNG_READ_16BIT_SUPPORTED
2920 2921
      else
      {
2922
         /* This inverts the alpha channel in GGAA */
2923 2924 2925
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2926

2927 2928 2929 2930
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2931
/*
2932 2933
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2934
*/
2935 2936
            sp-=2;
            dp=sp;
2937 2938
         }
      }
2939
#endif
2940 2941 2942 2943
   }
}
#endif

2944
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2945
/* Add filler channel if we have RGB color */
2946
void /* PRIVATE */
G
Guy Schalnat 已提交
2947
png_do_read_filler(png_row_infop row_info, png_bytep row,
2948
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2949
{
G
Guy Schalnat 已提交
2950
   png_uint_32 i;
2951 2952
   png_uint_32 row_width = row_info->width;

2953
#ifdef PNG_READ_16BIT_SUPPORTED
2954
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2955
#endif
2956
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
2957

2958
   png_debug(1, "in png_do_read_filler");
2959

A
Andreas Dilger 已提交
2960
   if (
2961
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2962
   {
2963
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2964
      {
2965
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2966
         {
2967
            /* This changes the data from G to GX */
2968 2969
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
2970 2971
            for (i = 1; i < row_width; i++)
            {
2972
               *(--dp) = lo_filler;
2973 2974
               *(--dp) = *(--sp);
            }
2975
            *(--dp) = lo_filler;
2976 2977 2978 2979
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
2980

2981 2982
         else
         {
2983
            /* This changes the data from G to XG */
2984 2985
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2986 2987 2988
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2989
               *(--dp) = lo_filler;
2990 2991 2992 2993 2994 2995
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2996

2997
#ifdef PNG_READ_16BIT_SUPPORTED
2998
      else if (row_info->bit_depth == 16)
2999 3000 3001
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
3002
            /* This changes the data from GG to GGXX */
3003 3004
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3005 3006 3007
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
3008
               *(--dp) = lo_filler;
3009 3010 3011
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
3012 3013
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
3014 3015
            row_info->channels = 2;
            row_info->pixel_depth = 32;
3016
            row_info->rowbytes = row_width * 4;
3017
         }
3018

3019 3020
         else
         {
3021
            /* This changes the data from GG to XXGG */
3022 3023
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3024 3025 3026 3027 3028
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
3029
               *(--dp) = lo_filler;
3030 3031
            }
            row_info->channels = 2;
3032 3033
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
3034
         }
G
Guy Schalnat 已提交
3035
      }
3036
#endif
3037 3038 3039
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
3040
      if (row_info->bit_depth == 8)
3041 3042 3043
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
3044
            /* This changes the data from RGB to RGBX */
3045 3046
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
3047 3048
            for (i = 1; i < row_width; i++)
            {
3049
               *(--dp) = lo_filler;
3050 3051 3052 3053
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
3054
            *(--dp) = lo_filler;
3055 3056 3057 3058
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
3059

3060 3061
         else
         {
3062
            /* This changes the data from RGB to XRGB */
3063 3064
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
3065 3066 3067 3068 3069
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
3070
               *(--dp) = lo_filler;
3071 3072 3073 3074 3075 3076
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
3077

3078
#ifdef PNG_READ_16BIT_SUPPORTED
3079
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
3080
      {
3081
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
3082
         {
3083
            /* This changes the data from RRGGBB to RRGGBBXX */
3084 3085
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3086 3087 3088
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
3089
               *(--dp) = lo_filler;
3090 3091 3092 3093 3094 3095 3096
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
3097 3098
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
3099 3100
            row_info->channels = 4;
            row_info->pixel_depth = 64;
3101
            row_info->rowbytes = row_width * 8;
3102
         }
3103

3104 3105
         else
         {
3106
            /* This changes the data from RRGGBB to XXRRGGBB */
3107 3108
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3109 3110 3111 3112 3113 3114 3115 3116 3117
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
3118
               *(--dp) = lo_filler;
3119
            }
3120

3121 3122
            row_info->channels = 4;
            row_info->pixel_depth = 64;
3123
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
3124
         }
G
Guy Schalnat 已提交
3125
      }
3126
#endif
3127
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
3128
}
G
Guy Schalnat 已提交
3129
#endif
G
Guy Schalnat 已提交
3130

3131
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
3132
/* Expand grayscale files to RGB, with or without alpha */
3133
void /* PRIVATE */
G
Guy Schalnat 已提交
3134
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
3135
{
G
Guy Schalnat 已提交
3136
   png_uint_32 i;
3137
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3138

3139
   png_debug(1, "in png_do_gray_to_rgb");
3140

A
Andreas Dilger 已提交
3141
   if (row_info->bit_depth >= 8 &&
3142
       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
G
Guy Schalnat 已提交
3143 3144 3145 3146 3147
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
3148
            /* This changes G to RGB */
3149 3150
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3151
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3152 3153 3154
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
3155
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3156 3157
            }
         }
3158

G
Guy Schalnat 已提交
3159 3160
         else
         {
3161
            /* This changes GG to RRGGBB */
3162 3163
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
3164
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3165 3166 3167 3168 3169
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
3170 3171
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3172 3173 3174
            }
         }
      }
3175

G
Guy Schalnat 已提交
3176 3177 3178 3179
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
3180
            /* This changes GA to RGBA */
3181 3182
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3183
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3184 3185 3186 3187
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
3188
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3189 3190
            }
         }
3191

G
Guy Schalnat 已提交
3192 3193
         else
         {
3194
            /* This changes GGAA to RRGGBBAA */
3195 3196
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
3197
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3198 3199 3200 3201 3202 3203 3204
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
3205 3206
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3207 3208 3209
            }
         }
      }
3210
      row_info->channels = (png_byte)(row_info->channels + 2);
G
Guy Schalnat 已提交
3211
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
G
Guy Schalnat 已提交
3212
      row_info->pixel_depth = (png_byte)(row_info->channels *
3213
          row_info->bit_depth);
3214
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3215 3216
   }
}
G
Guy Schalnat 已提交
3217
#endif
G
Guy Schalnat 已提交
3218

3219
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
3220
/* Reduce RGB files to grayscale, with or without alpha
3221 3222 3223 3224 3225
 * 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 )
3226
 * Charles Poynton poynton at poynton.com
3227 3228 3229
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
3230
 *  which can be expressed with integers as
3231
 *
3232 3233 3234 3235 3236 3237 3238
 *     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
3239 3240 3241
 *
 *  which can be expressed with integers as
 *
3242 3243
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
 *
3244 3245 3246 3247 3248
 *  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:
3249
 *
3250
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
3251
 *
3252 3253 3254 3255 3256
 *  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
3257
 *
3258 3259 3260
 *  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.
3261
 *
3262 3263 3264 3265
 *  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.
3266
 *
3267 3268 3269 3270
 *  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.
3271
 */
3272
int /* PRIVATE */
3273
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
3274 3275 3276 3277

{
   int rgb_error = 0;

3278
   png_debug(1, "in png_do_rgb_to_gray");
3279

3280
   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
3281
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
3282
   {
3283 3284 3285 3286 3287 3288
      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;
3289

3290
      if (row_info->bit_depth == 8)
3291
      {
3292
#ifdef PNG_READ_GAMMA_SUPPORTED
3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304
         /* 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++)
3305
            {
3306 3307 3308
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3309

3310
               if (red != green || red != blue)
3311
               {
3312 3313 3314
                  red = png_ptr->gamma_to_1[red];
                  green = png_ptr->gamma_to_1[green];
                  blue = png_ptr->gamma_to_1[blue];
3315

3316 3317 3318
                  rgb_error |= 1;
                  *(dp++) = png_ptr->gamma_from_1[
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3319
               }
3320

3321 3322 3323 3324 3325 3326 3327
               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];
3328

3329
                  *(dp++) = red;
3330
               }
3331 3332 3333

               if (have_alpha)
                  *(dp++) = *(sp++);
3334 3335
            }
         }
3336 3337
         else
#endif
3338
         {
3339 3340 3341
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3342

3343
            for (i = 0; i < row_width; i++)
3344
            {
3345 3346 3347
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3348

3349 3350 3351
               if (red != green || red != blue)
               {
                  rgb_error |= 1;
3352
                  /* NOTE: this is the historical approach which simply
3353 3354 3355 3356
                   * truncates the results.
                   */
                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
               }
3357

3358 3359
               else
                  *(dp++) = red;
3360

3361 3362
               if (have_alpha)
                  *(dp++) = *(sp++);
3363 3364 3365
            }
         }
      }
3366 3367

      else /* RGB bit_depth == 16 */
3368
      {
3369
#ifdef PNG_READ_GAMMA_SUPPORTED
3370 3371 3372 3373 3374 3375 3376
         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++)
3377
            {
3378
               png_uint_16 red, green, blue, w;
3379

3380 3381 3382
               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3383

3384 3385 3386 3387 3388
               if (red == green && red == blue)
               {
                  if (png_ptr->gamma_16_table != NULL)
                     w = png_ptr->gamma_16_table[(red&0xff)
                         >> png_ptr->gamma_shift][red>>8];
3389

3390 3391
                  else
                     w = red;
3392
               }
3393 3394

               else
3395
               {
3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416
                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
                      >> png_ptr->gamma_shift][red>>8];
                  png_uint_16 green_1 =
                      png_ptr->gamma_16_to_1[(green&0xff) >>
                      png_ptr->gamma_shift][green>>8];
                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
                      >> png_ptr->gamma_shift][blue>>8];
                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
                      + bc*blue_1 + 16384)>>15);
                  w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                      png_ptr->gamma_shift][gray16 >> 8];
                  rgb_error |= 1;
               }

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

               if (have_alpha)
               {
                  *(dp++) = *(sp++);
                  *(dp++) = *(sp++);
3417 3418 3419
               }
            }
         }
3420 3421
         else
#endif
3422
         {
3423 3424 3425
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3426

3427 3428 3429
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3430

3431 3432 3433
               red   = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
               blue  = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
3434

3435 3436
               if (red != green || red != blue)
                  rgb_error |= 1;
3437

3438
               /* From 1.5.5 in the 16 bit case do the accurate conversion even
3439 3440 3441 3442 3443 3444 3445
                * in the 'fast' case - this is because this is where the code
                * ends up when handling linear 16 bit data.
                */
               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
                  15);
               *(dp++) = (png_byte)((gray16>>8) & 0xff);
               *(dp++) = (png_byte)(gray16 & 0xff);
3446

3447
               if (have_alpha)
3448
               {
3449
                  *(dp++) = *(sp++);
3450 3451 3452 3453 3454
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3455

3456
      row_info->channels = (png_byte)(row_info->channels - 2);
3457 3458
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
3459
      row_info->pixel_depth = (png_byte)(row_info->channels *
3460
          row_info->bit_depth);
3461
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3462 3463 3464 3465
   }
   return rgb_error;
}
#endif
3466
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
3467

3468
#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
3469 3470 3471
/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
 * large of png_color.  This lets grayscale images be treated as
 * paletted.  Most useful for gamma correction and simplification
3472
 * of code.  This API is not used internally.
3473
 */
3474
void PNGAPI
G
Guy Schalnat 已提交
3475
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
3476 3477 3478 3479 3480 3481
{
   int num_palette;
   int color_inc;
   int i;
   int v;

3482
   png_debug(1, "in png_do_build_grayscale_palette");
3483

A
Andreas Dilger 已提交
3484
   if (palette == NULL)
G
Guy Schalnat 已提交
3485 3486 3487 3488 3489 3490 3491 3492
      return;

   switch (bit_depth)
   {
      case 1:
         num_palette = 2;
         color_inc = 0xff;
         break;
3493

G
Guy Schalnat 已提交
3494 3495 3496 3497
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
3498

G
Guy Schalnat 已提交
3499 3500 3501 3502
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
3503

G
Guy Schalnat 已提交
3504 3505 3506 3507
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
3508

G
Guy Schalnat 已提交
3509
      default:
G
Guy Schalnat 已提交
3510
         num_palette = 0;
G
Guy Schalnat 已提交
3511
         color_inc = 0;
G
Guy Schalnat 已提交
3512 3513 3514 3515 3516
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
3517 3518 3519
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
3520 3521
   }
}
3522
#endif
G
Guy Schalnat 已提交
3523 3524


3525
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
3526 3527
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
A
Andreas Dilger 已提交
3528
/* Replace any alpha or transparency with the supplied background color.
3529 3530 3531
 * "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.
 */
3532
void /* PRIVATE */
3533
png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3534
{
3535
#ifdef PNG_READ_GAMMA_SUPPORTED
3536 3537 3538 3539 3540 3541 3542
   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;
3543
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3544
#endif
3545

3546
   png_bytep sp;
G
Guy Schalnat 已提交
3547
   png_uint_32 i;
3548
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3549
   int shift;
G
Guy Schalnat 已提交
3550

3551
   png_debug(1, "in png_do_compose");
3552

G
Guy Schalnat 已提交
3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
3564
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3565
                  {
3566
                     if ((png_uint_16)((*sp >> shift) & 0x01)
3567
                        == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3568
                     {
3569 3570 3571
                        unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
                        tmp |= png_ptr->background.gray << shift;
                        *sp = (png_byte)(tmp & 0xff);
G
Guy Schalnat 已提交
3572
                     }
3573

G
Guy Schalnat 已提交
3574 3575 3576 3577 3578
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
3579

G
Guy Schalnat 已提交
3580 3581 3582 3583 3584
                     else
                        shift--;
                  }
                  break;
               }
3585

G
Guy Schalnat 已提交
3586 3587
               case 2:
               {
3588
#ifdef PNG_READ_GAMMA_SUPPORTED
3589
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3590
                  {
3591 3592 3593
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3594
                     {
3595
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3596
                            == png_ptr->trans_color.gray)
3597
                        {
3598 3599 3600
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3601
                        }
3602

3603 3604
                        else
                        {
3605 3606 3607 3608 3609 3610
                           unsigned int p = (*sp >> shift) & 0x03;
                           unsigned int g = (gamma_table [p | (p << 2) |
                               (p << 4) | (p << 6)] >> 6) & 0x03;
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
                           tmp |= g << shift;
                           *sp = (png_byte)(tmp & 0xff);
3611
                        }
3612

3613 3614 3615 3616 3617
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3618

3619 3620
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3621
                     }
3622
                  }
3623

3624 3625 3626 3627 3628 3629
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3630
                     {
3631
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3632
                            == png_ptr->trans_color.gray)
3633
                        {
3634 3635 3636
                           unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3637
                        }
3638

3639 3640 3641 3642 3643
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3644

3645 3646
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3647 3648 3649 3650
                     }
                  }
                  break;
               }
3651

G
Guy Schalnat 已提交
3652 3653
               case 4:
               {
3654
#ifdef PNG_READ_GAMMA_SUPPORTED
3655
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3656
                  {
3657 3658 3659
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3660
                     {
3661
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3662
                            == png_ptr->trans_color.gray)
3663
                        {
3664 3665 3666
                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3667
                        }
3668

3669 3670
                        else
                        {
3671 3672 3673 3674 3675 3676
                           unsigned int p = (*sp >> shift) & 0x0f;
                           unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
                              0x0f;
                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
                           tmp |= g << shift;
                           *sp = (png_byte)(tmp & 0xff);
3677
                        }
3678

3679 3680 3681 3682 3683
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3684

3685 3686
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3687
                     }
3688
                  }
3689

3690 3691 3692 3693 3694 3695
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3696
                     {
3697
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3698
                            == png_ptr->trans_color.gray)
3699
                        {
3700 3701 3702
                           unsigned int tmp = *sp & (0xf0f >> (4 - shift));
                           tmp |= png_ptr->background.gray << shift;
                           *sp = (png_byte)(tmp & 0xff);
3703
                        }
3704

3705 3706 3707 3708 3709
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3710

3711 3712
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3713 3714 3715 3716
                     }
                  }
                  break;
               }
3717

G
Guy Schalnat 已提交
3718 3719
               case 8:
               {
3720
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3721
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3722
                  {
3723 3724
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3725
                     {
3726 3727
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3728

G
Guy Schalnat 已提交
3729 3730 3731 3732 3733
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3734
#endif
G
Guy Schalnat 已提交
3735
                  {
3736 3737
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3738
                     {
3739 3740
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3741 3742 3743 3744
                     }
                  }
                  break;
               }
3745

G
Guy Schalnat 已提交
3746 3747
               case 16:
               {
3748
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3749
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3750
                  {
3751 3752
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3753 3754 3755
                     {
                        png_uint_16 v;

3756
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3757

3758
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3759
                        {
3760
                           /* Background is already in screen gamma */
3761 3762 3763 3764
                           *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray
                                & 0xff);
G
Guy Schalnat 已提交
3765
                        }
3766

G
Guy Schalnat 已提交
3767 3768
                        else
                        {
A
Andreas Dilger 已提交
3769
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3770
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3771
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3772
                        }
G
Guy Schalnat 已提交
3773
                     }
G
Guy Schalnat 已提交
3774 3775
                  }
                  else
G
Guy Schalnat 已提交
3776
#endif
G
Guy Schalnat 已提交
3777
                  {
3778 3779
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3780 3781 3782
                     {
                        png_uint_16 v;

3783
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3784

3785
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3786
                        {
3787 3788 3789 3790
                           *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray
                                & 0xff);
G
Guy Schalnat 已提交
3791 3792 3793 3794 3795
                        }
                     }
                  }
                  break;
               }
3796 3797 3798

               default:
                  break;
G
Guy Schalnat 已提交
3799 3800 3801
            }
            break;
         }
3802

G
Guy Schalnat 已提交
3803 3804 3805 3806
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3807
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3808
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3809
               {
3810 3811
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3812
                  {
3813 3814 3815
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3816
                     {
3817 3818 3819
                        *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 已提交
3820
                     }
3821

G
Guy Schalnat 已提交
3822 3823 3824 3825 3826 3827 3828 3829 3830
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3831
#endif
G
Guy Schalnat 已提交
3832
               {
3833 3834
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3835
                  {
3836 3837 3838
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3839
                     {
3840 3841 3842
                        *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 已提交
3843 3844 3845 3846
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3847
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3848
            {
3849
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3850
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3851
               {
3852 3853
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3854
                  {
3855
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3856

3857 3858
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3859

3860 3861
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3862

3863 3864 3865
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3866
                     {
3867
                        /* Background is already in screen gamma */
3868 3869
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3870 3871 3872 3873 3874 3875
                        *(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);
3876
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3877
                     }
3878

G
Guy Schalnat 已提交
3879 3880
                     else
                     {
3881
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3882
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3883
                        *(sp + 1) = (png_byte)(v & 0xff);
3884

A
Andreas Dilger 已提交
3885
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3886 3887
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3888

A
Andreas Dilger 已提交
3889
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3890 3891
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3892 3893 3894
                     }
                  }
               }
3895

G
Guy Schalnat 已提交
3896
               else
G
Guy Schalnat 已提交
3897
#endif
G
Guy Schalnat 已提交
3898
               {
3899 3900
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3901
                  {
3902
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3903

3904 3905
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3906

3907 3908
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3909

3910 3911 3912
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3913
                     {
3914 3915
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3916 3917 3918 3919 3920 3921
                        *(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);
3922
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3923 3924 3925 3926 3927 3928
                     }
                  }
               }
            }
            break;
         }
3929

G
Guy Schalnat 已提交
3930
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3931
         {
A
Andreas Dilger 已提交
3932
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3933
            {
3934
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3935 3936 3937
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3938
                  sp = row;
3939
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3940
                  {
3941
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3942

A
Andreas Dilger 已提交
3943
                     if (a == 0xff)
3944
                        *sp = gamma_table[*sp];
3945

A
Andreas Dilger 已提交
3946 3947
                     else if (a == 0)
                     {
3948
                        /* Background is already in screen gamma */
3949
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3950
                     }
3951

A
Andreas Dilger 已提交
3952 3953 3954
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3955

A
Andreas Dilger 已提交
3956
                        v = gamma_to_1[*sp];
3957
                        png_composite(w, v, a, png_ptr->background_1.gray);
3958 3959 3960
                        if (!optimize)
                           w = gamma_from_1[w];
                        *sp = w;
G
Guy Schalnat 已提交
3961 3962
                     }
                  }
A
Andreas Dilger 已提交
3963 3964
               }
               else
G
Guy Schalnat 已提交
3965
#endif
A
Andreas Dilger 已提交
3966
               {
3967
                  sp = row;
3968
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3969
                  {
3970
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3971

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

3975
                     else if (a < 0xff)
3976
                        png_composite(*sp, *sp, a, png_ptr->background.gray);
G
Guy Schalnat 已提交
3977 3978
                  }
               }
A
Andreas Dilger 已提交
3979 3980 3981
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3982
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3983 3984 3985
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3986
                  sp = row;
3987
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3988
                  {
3989 3990
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
A
Andreas Dilger 已提交
3991 3992

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3993
                     {
A
Andreas Dilger 已提交
3994
                        png_uint_16 v;
G
Guy Schalnat 已提交
3995

A
Andreas Dilger 已提交
3996
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3997 3998
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3999
                     }
4000

A
Andreas Dilger 已提交
4001 4002
                     else if (a == 0)
                     {
4003
                        /* Background is already in screen gamma */
4004 4005
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
4006
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
4007
                     }
4008

A
Andreas Dilger 已提交
4009 4010 4011
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
4012

A
Andreas Dilger 已提交
4013
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
4014
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
4015 4016 4017 4018 4019 4020
                        if (optimize)
                           w = v;
                        else
                           w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
4021 4022
                     }
                  }
A
Andreas Dilger 已提交
4023 4024
               }
               else
G
Guy Schalnat 已提交
4025
#endif
A
Andreas Dilger 已提交
4026
               {
4027
                  sp = row;
4028
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
4029
                  {
4030 4031
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
4032

4033
                     if (a == 0)
A
Andreas Dilger 已提交
4034
                     {
4035 4036
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
                                & 0xff);
4037
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
4038
                     }
4039

4040
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
4041 4042
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
4043

4044
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
4045
                        png_composite_16(v, g, a, png_ptr->background.gray);
4046 4047
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4048 4049 4050 4051 4052 4053
                     }
                  }
               }
            }
            break;
         }
4054

G
Guy Schalnat 已提交
4055 4056 4057 4058
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4059
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4060 4061
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
4062
               {
4063
                  sp = row;
4064
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
4065
                  {
4066
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
4067 4068 4069

                     if (a == 0xff)
                     {
4070 4071 4072
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
4073
                     }
4074

G
Guy Schalnat 已提交
4075 4076
                     else if (a == 0)
                     {
4077
                        /* Background is already in screen gamma */
4078 4079 4080
                        *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 已提交
4081
                     }
4082

G
Guy Schalnat 已提交
4083 4084
                     else
                     {
A
Andreas Dilger 已提交
4085
                        png_byte v, w;
G
Guy Schalnat 已提交
4086 4087

                        v = gamma_to_1[*sp];
4088
                        png_composite(w, v, a, png_ptr->background_1.red);
4089 4090
                        if (!optimize) w = gamma_from_1[w];
                        *sp = w;
4091

G
Guy Schalnat 已提交
4092
                        v = gamma_to_1[*(sp + 1)];
4093
                        png_composite(w, v, a, png_ptr->background_1.green);
4094 4095
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 1) = w;
4096

G
Guy Schalnat 已提交
4097
                        v = gamma_to_1[*(sp + 2)];
4098
                        png_composite(w, v, a, png_ptr->background_1.blue);
4099 4100
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
4101 4102 4103 4104
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
4105
#endif
G
Guy Schalnat 已提交
4106
               {
4107
                  sp = row;
4108
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
4109
                  {
4110
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
4111

4112
                     if (a == 0)
G
Guy Schalnat 已提交
4113
                     {
4114 4115 4116
                        *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 已提交
4117
                     }
4118

4119
                     else if (a < 0xff)
G
Guy Schalnat 已提交
4120
                     {
4121
                        png_composite(*sp, *sp, a, png_ptr->background.red);
4122

4123
                        png_composite(*(sp + 1), *(sp + 1), a,
4124
                            png_ptr->background.green);
4125

4126
                        png_composite(*(sp + 2), *(sp + 2), a,
4127
                            png_ptr->background.blue);
G
Guy Schalnat 已提交
4128 4129 4130 4131
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
4132
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4133
            {
4134
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4135 4136
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
4137
               {
4138
                  sp = row;
4139
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
4140
                  {
4141 4142
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
4143

G
Guy Schalnat 已提交
4144 4145 4146 4147
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
4148
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
4149 4150
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4151

A
Andreas Dilger 已提交
4152
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
4153 4154
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4155

A
Andreas Dilger 已提交
4156
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
4157 4158
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4159
                     }
4160

G
Guy Schalnat 已提交
4161 4162
                     else if (a == 0)
                     {
4163
                        /* Background is already in screen gamma */
4164 4165
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
4166 4167 4168 4169 4170 4171
                        *(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);
4172
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
4173
                     }
4174

G
Guy Schalnat 已提交
4175 4176
                     else
                     {
4177
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
4178 4179

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
4180
                        png_composite_16(w, v, a, png_ptr->background_1.red);
4181
                        if (!optimize)
4182 4183
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
                                8];
4184 4185
                        *sp = (png_byte)((w >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(w & 0xff);
4186

A
Andreas Dilger 已提交
4187
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
4188
                        png_composite_16(w, v, a, png_ptr->background_1.green);
4189
                        if (!optimize)
4190 4191
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
                                8];
4192

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

A
Andreas Dilger 已提交
4196
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
4197
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
4198
                        if (!optimize)
4199 4200
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
                                8];
4201

4202 4203
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
4204 4205 4206
                     }
                  }
               }
4207

G
Guy Schalnat 已提交
4208
               else
G
Guy Schalnat 已提交
4209
#endif
G
Guy Schalnat 已提交
4210
               {
4211
                  sp = row;
4212
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
4213
                  {
4214
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
4215
                         << 8) + (png_uint_16)(*(sp + 7)));
4216

4217
                     if (a == 0)
G
Guy Schalnat 已提交
4218
                     {
4219 4220
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
4221 4222 4223 4224 4225 4226
                        *(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);
4227
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
4228
                     }
4229

4230
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
4231
                     {
4232
                        png_uint_16 v;
A
Andreas Dilger 已提交
4233

4234 4235 4236 4237 4238
                        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 已提交
4239

4240
                        png_composite_16(v, r, a, png_ptr->background.red);
4241 4242
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4243

4244
                        png_composite_16(v, g, a, png_ptr->background.green);
4245 4246
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4247

4248
                        png_composite_16(v, b, a, png_ptr->background.blue);
4249 4250
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4251 4252 4253 4254 4255 4256
                     }
                  }
               }
            }
            break;
         }
4257 4258 4259

         default:
            break;
G
Guy Schalnat 已提交
4260 4261 4262
      }
   }
}
4263
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
G
Guy Schalnat 已提交
4264

4265
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4266
/* Gamma correct the image, avoiding the alpha channel.  Make sure
4267
 * you do this after you deal with the transparency issue on grayscale
4268
 * or RGB images. If your bit depth is 8, use gamma_table, if it
4269 4270 4271
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
4272
void /* PRIVATE */
4273
png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
G
Guy Schalnat 已提交
4274
{
4275 4276 4277 4278
   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 已提交
4279
   png_bytep sp;
G
Guy Schalnat 已提交
4280
   png_uint_32 i;
4281
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4282

4283
   png_debug(1, "in png_do_gamma");
4284

4285
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
4286
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
4287 4288 4289 4290 4291 4292 4293
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
4294 4295
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4296 4297 4298 4299 4300 4301 4302 4303 4304
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4305

A
Andreas Dilger 已提交
4306
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4307
            {
4308 4309
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4310 4311 4312
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
4313
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4314 4315 4316
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4317

A
Andreas Dilger 已提交
4318
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4319 4320
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4321
                  sp += 2;
4322

A
Andreas Dilger 已提交
4323
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4324 4325 4326 4327 4328 4329 4330
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
4331

G
Guy Schalnat 已提交
4332 4333 4334 4335
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4336 4337
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4338
               {
G
Guy Schalnat 已提交
4339 4340
                  *sp = gamma_table[*sp];
                  sp++;
4341

G
Guy Schalnat 已提交
4342 4343
                  *sp = gamma_table[*sp];
                  sp++;
4344

G
Guy Schalnat 已提交
4345 4346
                  *sp = gamma_table[*sp];
                  sp++;
4347

G
Guy Schalnat 已提交
4348 4349 4350
                  sp++;
               }
            }
4351

A
Andreas Dilger 已提交
4352
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4353
            {
4354 4355
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4356
               {
4357
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4358 4359
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4360
                  sp += 2;
4361

A
Andreas Dilger 已提交
4362
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4363 4364 4365
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4366

A
Andreas Dilger 已提交
4367
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4368 4369 4370 4371 4372
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4373 4374
            break;
         }
4375

G
Guy Schalnat 已提交
4376 4377 4378 4379
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4380 4381
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4382 4383
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4384
                  sp += 2;
G
Guy Schalnat 已提交
4385 4386
               }
            }
4387

A
Andreas Dilger 已提交
4388
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4389
            {
4390 4391
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4392
               {
4393
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4394 4395
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4396 4397 4398 4399 4400
                  sp += 4;
               }
            }
            break;
         }
4401

G
Guy Schalnat 已提交
4402 4403
         case PNG_COLOR_TYPE_GRAY:
         {
4404 4405
            if (row_info->bit_depth == 2)
            {
4406 4407
               sp = row;
               for (i = 0; i < row_width; i += 4)
4408 4409 4410 4411 4412 4413
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4414
                  *sp = (png_byte)(
4415 4416 4417 4418
                      ((((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) ));
4419 4420 4421
                  sp++;
               }
            }
4422

A
Andreas Dilger 已提交
4423
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4424
            {
4425 4426
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4427 4428 4429 4430
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4431
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4432
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4433 4434 4435
                  sp++;
               }
            }
4436

A
Andreas Dilger 已提交
4437 4438
            else if (row_info->bit_depth == 8)
            {
4439 4440
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4441 4442 4443 4444 4445
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4446

G
Guy Schalnat 已提交
4447 4448
            else if (row_info->bit_depth == 16)
            {
4449 4450
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4451
               {
4452
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4453 4454
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4455 4456 4457 4458 4459
                  sp += 2;
               }
            }
            break;
         }
4460 4461 4462

         default:
            break;
G
Guy Schalnat 已提交
4463 4464 4465
      }
   }
}
G
Guy Schalnat 已提交
4466
#endif
G
Guy Schalnat 已提交
4467

4468 4469 4470 4471 4472 4473
#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.
 */
void /* PRIVATE */
4474
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534
{
   png_uint_32 row_width = row_info->width;

   png_debug(1, "in png_do_encode_alpha");

   if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
   {
      if (row_info->bit_depth == 8)
      {
         PNG_CONST png_bytep table = png_ptr->gamma_from_1;

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

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

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

            return;
         }
      }

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

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

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

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

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

            return;
         }
      }
   }

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

4535
#ifdef PNG_READ_EXPAND_SUPPORTED
4536
/* Expands a palette row to an RGB or RGBA row depending
4537 4538
 * upon whether you supply trans and num_trans.
 */
4539
void /* PRIVATE */
G
Guy Schalnat 已提交
4540
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4541
   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
4542
{
G
Guy Schalnat 已提交
4543
   int shift, value;
G
Guy Schalnat 已提交
4544
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4545
   png_uint_32 i;
4546
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4547

4548
   png_debug(1, "in png_do_expand_palette");
4549

4550
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4551 4552 4553 4554 4555 4556 4557
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4558 4559
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4560
               shift = 7 - (int)((row_width + 7) & 0x07);
4561
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4562
               {
4563
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4564
                     *dp = 1;
4565

G
Guy Schalnat 已提交
4566 4567
                  else
                     *dp = 0;
4568

G
Guy Schalnat 已提交
4569 4570 4571 4572 4573
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4574

G
Guy Schalnat 已提交
4575 4576 4577 4578 4579 4580 4581
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4582

G
Guy Schalnat 已提交
4583 4584
            case 2:
            {
4585 4586
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4587
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4588
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4589
               {
4590
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4591
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4592 4593 4594 4595 4596
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4597

G
Guy Schalnat 已提交
4598 4599 4600 4601 4602 4603 4604
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4605

G
Guy Schalnat 已提交
4606 4607
            case 4:
            {
4608 4609
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4610
               shift = (int)((row_width & 0x01) << 2);
4611
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4612
               {
4613
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4614
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4615 4616 4617 4618 4619
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4620

G
Guy Schalnat 已提交
4621 4622 4623 4624 4625 4626 4627
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4628 4629 4630

            default:
               break;
G
Guy Schalnat 已提交
4631 4632 4633
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4634
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4635
      }
4636

4637
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4638 4639
      {
         {
4640
            if (num_trans > 0)
G
Guy Schalnat 已提交
4641
            {
4642 4643
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
4644

4645
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4646
               {
A
Andreas Dilger 已提交
4647
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4648
                     *dp-- = 0xff;
4649

G
Guy Schalnat 已提交
4650
                  else
4651
                     *dp-- = trans_alpha[*sp];
4652

G
Guy Schalnat 已提交
4653 4654 4655 4656 4657 4658 4659
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4660
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4661 4662 4663
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4664

G
Guy Schalnat 已提交
4665 4666
            else
            {
4667 4668
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4669

4670
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4671 4672 4673 4674 4675 4676
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4677

G
Guy Schalnat 已提交
4678 4679
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4680
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4681 4682 4683 4684 4685 4686 4687 4688
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4689 4690
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4691
 */
4692
void /* PRIVATE */
G
Guy Schalnat 已提交
4693
png_do_expand(png_row_infop row_info, png_bytep row,
4694
    png_const_color_16p trans_color)
G
Guy Schalnat 已提交
4695
{
G
Guy Schalnat 已提交
4696
   int shift, value;
G
Guy Schalnat 已提交
4697
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4698
   png_uint_32 i;
4699
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4700

4701
   png_debug(1, "in png_do_expand");
4702

G
Guy Schalnat 已提交
4703
   {
A
Andreas Dilger 已提交
4704
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4705
      {
4706
         unsigned int gray = trans_color ? trans_color->gray : 0;
A
Andreas Dilger 已提交
4707 4708

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4709
         {
A
Andreas Dilger 已提交
4710
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4711
            {
A
Andreas Dilger 已提交
4712
               case 1:
G
Guy Schalnat 已提交
4713
               {
4714
                  gray = (gray & 0x01) * 0xff;
4715 4716
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4717
                  shift = 7 - (int)((row_width + 7) & 0x07);
4718
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4719
                  {
4720
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4721
                        *dp = 0xff;
4722

A
Andreas Dilger 已提交
4723 4724
                     else
                        *dp = 0;
4725

A
Andreas Dilger 已提交
4726 4727 4728 4729 4730
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4731

A
Andreas Dilger 已提交
4732 4733
                     else
                        shift++;
G
Guy Schalnat 已提交
4734

A
Andreas Dilger 已提交
4735 4736 4737
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4738
               }
4739

A
Andreas Dilger 已提交
4740
               case 2:
G
Guy Schalnat 已提交
4741
               {
4742
                  gray = (gray & 0x03) * 0x55;
4743 4744
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
4745
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4746
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4747
                  {
4748
                     value = (*sp >> shift) & 0x03;
A
Andreas Dilger 已提交
4749 4750 4751 4752 4753 4754 4755
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
4756

A
Andreas Dilger 已提交
4757 4758
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4759

A
Andreas Dilger 已提交
4760 4761 4762
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4763
               }
4764

A
Andreas Dilger 已提交
4765
               case 4:
G
Guy Schalnat 已提交
4766
               {
4767
                  gray = (gray & 0x0f) * 0x11;
4768 4769
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4770
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4771
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4772
                  {
4773
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
4774 4775 4776 4777 4778 4779
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4780

A
Andreas Dilger 已提交
4781 4782
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4783

A
Andreas Dilger 已提交
4784 4785 4786
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4787
               }
4788 4789 4790

               default:
                  break;
G
Guy Schalnat 已提交
4791
            }
4792

A
Andreas Dilger 已提交
4793 4794
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4795
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4796
         }
A
Andreas Dilger 已提交
4797

4798
         if (trans_color != NULL)
G
Guy Schalnat 已提交
4799
         {
A
Andreas Dilger 已提交
4800
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4801
            {
4802
               gray = gray & 0xff;
4803 4804
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
4805

4806
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4807
               {
A
Andreas Dilger 已提交
4808 4809
                  if (*sp == gray)
                     *dp-- = 0;
4810

A
Andreas Dilger 已提交
4811 4812
                  else
                     *dp-- = 0xff;
4813

A
Andreas Dilger 已提交
4814
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4815
               }
A
Andreas Dilger 已提交
4816
            }
4817

A
Andreas Dilger 已提交
4818 4819
            else if (row_info->bit_depth == 16)
            {
4820 4821
               unsigned int gray_high = (gray >> 8) & 0xff;
               unsigned int gray_low = gray & 0xff;
A
Andreas Dilger 已提交
4822 4823
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4824
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4825
               {
4826
                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
A
Andreas Dilger 已提交
4827 4828 4829 4830
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4831

A
Andreas Dilger 已提交
4832 4833 4834 4835 4836
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4837

A
Andreas Dilger 已提交
4838 4839
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4840 4841
               }
            }
4842

A
Andreas Dilger 已提交
4843 4844 4845
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4846 4847
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
4848 4849
         }
      }
4850
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
G
Guy Schalnat 已提交
4851 4852 4853
      {
         if (row_info->bit_depth == 8)
         {
4854 4855 4856
            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 已提交
4857
            sp = row + (png_size_t)row_info->rowbytes - 1;
4858 4859
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4860
            {
4861
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
4862
                  *dp-- = 0;
4863

G
Guy Schalnat 已提交
4864 4865
               else
                  *dp-- = 0xff;
4866

G
Guy Schalnat 已提交
4867 4868 4869 4870 4871 4872 4873
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
4874 4875 4876 4877 4878 4879
            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 已提交
4880
            sp = row + row_info->rowbytes - 1;
4881 4882
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4883
            {
4884
               if (*(sp - 5) == red_high &&
4885 4886 4887 4888 4889
                   *(sp - 4) == red_low &&
                   *(sp - 3) == green_high &&
                   *(sp - 2) == green_low &&
                   *(sp - 1) == blue_high &&
                   *(sp    ) == blue_low)
G
Guy Schalnat 已提交
4890 4891 4892 4893
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4894

G
Guy Schalnat 已提交
4895 4896 4897 4898 4899
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4900

G
Guy Schalnat 已提交
4901 4902 4903 4904
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4905
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4906 4907 4908 4909 4910
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
4911
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4912
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4913 4914 4915
      }
   }
}
G
Guy Schalnat 已提交
4916
#endif
G
Guy Schalnat 已提交
4917

4918
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4919
/* If the bit depth is 8 and the color type is not a palette type expand the
4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948
 * whole row to 16 bits.  Has no effect otherwise.
 */
void /* PRIVATE */
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

4949
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4950
void /* PRIVATE */
4951
png_do_quantize(png_row_infop row_info, png_bytep row,
4952
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
G
Guy Schalnat 已提交
4953
{
G
Guy Schalnat 已提交
4954
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4955
   png_uint_32 i;
4956
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4957

4958
   png_debug(1, "in png_do_quantize");
4959

4960
   if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4961
   {
4962
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
G
Guy Schalnat 已提交
4963 4964 4965 4966
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4967
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4968 4969 4970 4971 4972
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

4973 4974 4975 4976 4977 4978 4979
            /* 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);
             */
4980 4981 4982 4983 4984 4985 4986 4987
            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));
G
Guy Schalnat 已提交
4988 4989 4990

            *dp++ = palette_lookup[p];
         }
4991

G
Guy Schalnat 已提交
4992 4993 4994
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4995
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4996
      }
4997

G
Guy Schalnat 已提交
4998
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4999
         palette_lookup != NULL)
G
Guy Schalnat 已提交
5000 5001 5002 5003
      {
         int r, g, b, p;
         sp = row;
         dp = row;
5004
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
5005 5006 5007 5008 5009 5010
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

5011 5012 5013 5014 5015 5016 5017 5018
            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));
G
Guy Schalnat 已提交
5019 5020 5021

            *dp++ = palette_lookup[p];
         }
5022

G
Guy Schalnat 已提交
5023 5024 5025
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
5026
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
5027
      }
5028

G
Guy Schalnat 已提交
5029
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
5030
         quantize_lookup)
G
Guy Schalnat 已提交
5031
      {
G
Guy Schalnat 已提交
5032
         sp = row;
5033

5034
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
5035
         {
5036
            *sp = quantize_lookup[*sp];
G
Guy Schalnat 已提交
5037 5038 5039 5040
         }
      }
   }
}
5041
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
5042
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
G
Guy Schalnat 已提交
5043

5044
#ifdef PNG_MNG_FEATURES_SUPPORTED
5045
/* Undoes intrapixel differencing  */
5046 5047 5048
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
5049
   png_debug(1, "in png_do_read_intrapixel");
5050

5051 5052 5053 5054 5055
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
5056

5057 5058 5059 5060 5061 5062 5063
      if (row_info->bit_depth == 8)
      {
         png_bytep rp;
         png_uint_32 i;

         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
            bytes_per_pixel = 3;
5064

5065 5066
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
5067

5068 5069 5070 5071 5072
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
5073 5074
            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
5075 5076 5077 5078 5079 5080 5081 5082 5083
         }
      }
      else if (row_info->bit_depth == 16)
      {
         png_bytep rp;
         png_uint_32 i;

         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
            bytes_per_pixel = 6;
5084

5085 5086
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
5087

5088 5089 5090 5091 5092
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
5093 5094 5095
            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
5096 5097
            png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
            png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
5098
            *(rp    ) = (png_byte)((red >> 8) & 0xff);
5099 5100 5101
            *(rp + 1) = (png_byte)(red & 0xff);
            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
            *(rp + 5) = (png_byte)(blue & 0xff);
5102 5103 5104 5105 5106
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
5107
#endif /* PNG_READ_SUPPORTED */