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

A
Andreas Dilger 已提交
2
/* pngrtran.c - transforms the data in a row for PNG readers
3
 *
4
 * Last changed in libpng 1.6.0 [(PENDING RELEASE)]
5
 * Copyright (c) 1998-2011 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 26
png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
{
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;
   }
}

G
[devel]  
Glenn Randers-Pehrson 已提交
91
#ifdef PNG_READ_BACKGROUND_SUPPORTED
92
/* Handle alpha and tRNS via a background color */
G
[devel]  
Glenn Randers-Pehrson 已提交
93 94
void PNGFAPI
png_set_background_fixed(png_structp png_ptr,
95
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
96
    int need_expand, png_fixed_point background_gamma)
G
Guy Schalnat 已提交
97
{
G
[devel]  
Glenn Randers-Pehrson 已提交
98
   png_debug(1, "in png_set_background_fixed");
99

100 101
   if (png_ptr == NULL)
      return;
102

A
Andreas Dilger 已提交
103 104 105 106 107 108
   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
   {
      png_warning(png_ptr, "Application must supply a known background gamma");
      return;
   }

109 110 111 112
   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;

113 114
   png_memcpy(&(png_ptr->background), background_color,
      png_sizeof(png_color_16));
G
[devel]  
Glenn Randers-Pehrson 已提交
115
   png_ptr->background_gamma = background_gamma;
G
Guy Schalnat 已提交
116
   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
117 118 119 120
   if (need_expand)
      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
   else
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
G
Guy Schalnat 已提交
121
}
G
[devel]  
Glenn Randers-Pehrson 已提交
122 123 124 125

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
png_set_background(png_structp png_ptr,
126
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
127 128 129 130 131 132 133
    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 已提交
134

135 136 137 138 139
/* 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
140
void PNGAPI
141
png_set_scale_16(png_structp png_ptr)
G
Guy Schalnat 已提交
142
{
143
   png_debug(1, "in png_set_scale_16");
144

145 146
   if (png_ptr == NULL)
      return;
147

148
   png_ptr->transformations |= PNG_SCALE_16_TO_8;
149
}
150
#endif
151

152
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
153 154
/* Chop 16-bit depth files to 8-bit depth */
void PNGAPI
155
png_set_strip_16(png_structp png_ptr)
156
{
157
   png_debug(1, "in png_set_strip_16");
158 159 160 161

   if (png_ptr == NULL)
      return;

162
   png_ptr->transformations |= PNG_16_TO_8;
G
Guy Schalnat 已提交
163
}
164
#endif
G
Guy Schalnat 已提交
165

166
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
167
void PNGAPI
A
Andreas Dilger 已提交
168 169
png_set_strip_alpha(png_structp png_ptr)
{
170
   png_debug(1, "in png_set_strip_alpha");
171

172 173
   if (png_ptr == NULL)
      return;
174

175
   png_ptr->transformations |= PNG_STRIP_ALPHA;
A
Andreas Dilger 已提交
176 177 178
}
#endif

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
static png_fixed_point
translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
   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;
#     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
convert_gamma_value(png_structp png_ptr, double output_gamma)
{
   /* 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 */

241 242 243 244 245 246 247 248 249 250 251 252 253
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
void PNGFAPI
png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
   png_fixed_point output_gamma)
{
   int compose = 0;
   png_fixed_point file_gamma;

   png_debug(1, "in png_set_alpha_mode");

   if (png_ptr == NULL)
      return;

254
   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
255

256
   /* Validate the value to ensure it is in a reasonable range. The value
257 258 259 260 261
    * 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.
    */
262
   if (output_gamma < 70000 || output_gamma > 300000)
263
      png_error(png_ptr, "output gamma out of expected range");
264

265
   /* The default file gamma is the inverse of the output gamma; the output
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 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
    * 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.)
    */
   if (png_ptr->gamma == 0)
      png_ptr->gamma = file_gamma;

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

329
   /* Finally, if pre-multiplying, set the background fields to achieve the
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
    * desired result.
    */
   if (compose)
   {
      /* And obtain alpha pre-multiplication by composing on black: */
      png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
      png_ptr->background_gamma = png_ptr->gamma; /* just in case */
      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;
   }

   /* New API, make sure apps call the correct initializers: */
   png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
}

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
{
355 356
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
      output_gamma));
357 358 359 360
}
#  endif
#endif

361
#ifdef PNG_READ_QUANTIZE_SUPPORTED
362
/* Dither file to 8-bit.  Supply a palette, the current number
363 364 365
 * 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
366 367
 * modified to fit in the maximum number.  "full_quantize" indicates
 * whether we need a quantizing cube set up for RGB images, or if we
368 369
 * simply are reducing the number of colors in a paletted image.
 */
G
Guy Schalnat 已提交
370 371

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
372
{
373
   struct png_dsort_struct * next;
G
Guy Schalnat 已提交
374 375
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
376
} png_dsort;
377 378
typedef png_dsort *   png_dsortp;
typedef png_dsort * * png_dsortpp;
G
Guy Schalnat 已提交
379

380
void PNGAPI
381
png_set_quantize(png_structp png_ptr, png_colorp palette,
382
    int num_palette, int maximum_colors, png_const_uint_16p histogram,
383
    int full_quantize)
G
Guy Schalnat 已提交
384
{
385
   png_debug(1, "in png_set_quantize");
386

387 388
   if (png_ptr == NULL)
      return;
389

390
   png_ptr->transformations |= PNG_QUANTIZE;
G
Guy Schalnat 已提交
391

392
   if (!full_quantize)
G
Guy Schalnat 已提交
393 394 395
   {
      int i;

396
      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
397
          (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
398
      for (i = 0; i < num_palette; i++)
399
         png_ptr->quantize_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
400 401 402 403
   }

   if (num_palette > maximum_colors)
   {
A
Andreas Dilger 已提交
404
      if (histogram != NULL)
G
Guy Schalnat 已提交
405
      {
A
Andreas Dilger 已提交
406
         /* This is easy enough, just throw out the least used colors.
407 408
          * Perhaps not the best solution, but good enough.
          */
G
Guy Schalnat 已提交
409 410 411

         int i;

412
         /* Initialize an array to sort colors */
413
         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
414
             (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
415

416
         /* Initialize the quantize_sort array */
G
Guy Schalnat 已提交
417
         for (i = 0; i < num_palette; i++)
418
            png_ptr->quantize_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
419

A
Andreas Dilger 已提交
420
         /* Find the least used palette entries by starting a
421 422 423 424 425
          * 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 已提交
426 427 428

         for (i = num_palette - 1; i >= maximum_colors; i--)
         {
429
            int done; /* To stop early if the list is pre-sorted */
G
Guy Schalnat 已提交
430
            int j;
G
Guy Schalnat 已提交
431 432 433 434

            done = 1;
            for (j = 0; j < i; j++)
            {
435 436
               if (histogram[png_ptr->quantize_sort[j]]
                   < histogram[png_ptr->quantize_sort[j + 1]])
G
Guy Schalnat 已提交
437 438 439
               {
                  png_byte t;

440 441 442
                  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 已提交
443 444 445
                  done = 0;
               }
            }
446

G
Guy Schalnat 已提交
447 448 449 450
            if (done)
               break;
         }

451
         /* Swap the palette around, and set up a table, if necessary */
452
         if (full_quantize)
G
Guy Schalnat 已提交
453
         {
454
            int j = num_palette;
G
Guy Schalnat 已提交
455

456 457 458
            /* Put all the useful colors within the max, but don't
             * move the others.
             */
459
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
460
            {
461
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
462 463 464
               {
                  do
                     j--;
465
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
466

G
Guy Schalnat 已提交
467 468
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
469
            }
G
Guy Schalnat 已提交
470 471 472
         }
         else
         {
473
            int j = num_palette;
G
Guy Schalnat 已提交
474

475 476 477
            /* Move all the used colors inside the max limit, and
             * develop a translation table.
             */
478
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
479
            {
480
               /* Only move the colors we need to */
481
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
482 483 484 485 486
               {
                  png_color tmp_color;

                  do
                     j--;
487
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
488 489 490 491

                  tmp_color = palette[j];
                  palette[j] = palette[i];
                  palette[i] = tmp_color;
492
                  /* Indicate where the color went */
493 494
                  png_ptr->quantize_index[j] = (png_byte)i;
                  png_ptr->quantize_index[i] = (png_byte)j;
G
Guy Schalnat 已提交
495 496
               }
            }
A
Andreas Dilger 已提交
497

498
            /* Find closest color for those colors we are not using */
G
Guy Schalnat 已提交
499 500
            for (i = 0; i < num_palette; i++)
            {
501
               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
G
Guy Schalnat 已提交
502
               {
A
Andreas Dilger 已提交
503
                  int min_d, k, min_k, d_index;
G
Guy Schalnat 已提交
504

505
                  /* Find the closest color to one we threw out */
506
                  d_index = png_ptr->quantize_index[i];
A
Andreas Dilger 已提交
507 508
                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
                  for (k = 1, min_k = 0; k < maximum_colors; k++)
G
Guy Schalnat 已提交
509 510 511
                  {
                     int d;

A
Andreas Dilger 已提交
512
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
513 514 515 516

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
517
                        min_k = k;
G
Guy Schalnat 已提交
518 519
                     }
                  }
520
                  /* Point to closest color */
521
                  png_ptr->quantize_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
522 523 524
               }
            }
         }
525 526
         png_free(png_ptr, png_ptr->quantize_sort);
         png_ptr->quantize_sort = NULL;
G
Guy Schalnat 已提交
527 528 529
      }
      else
      {
A
Andreas Dilger 已提交
530
         /* This is much harder to do simply (and quickly).  Perhaps
531 532 533 534 535 536 537
          * 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 已提交
538 539 540
         int i;
         int max_d;
         int num_new_palette;
541
         png_dsortp t;
G
Guy Schalnat 已提交
542
         png_dsortpp hash;
543

544
         t = NULL;
G
Guy Schalnat 已提交
545

546
         /* Initialize palette index arrays */
547
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
548
             (png_uint_32)(num_palette * png_sizeof(png_byte)));
549
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
550
             (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
551

552
         /* Initialize the sort array */
G
Guy Schalnat 已提交
553 554
         for (i = 0; i < num_palette; i++)
         {
555 556
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
557 558
         }

559
         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
560
             png_sizeof(png_dsortp)));
G
Guy Schalnat 已提交
561 562 563

         num_new_palette = num_palette;

564 565 566 567 568 569 570 571
         /* 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 已提交
572 573
         max_d = 96;

G
Guy Schalnat 已提交
574
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
575 576 577 578 579 580 581 582 583
         {
            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 已提交
584
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
585 586 587 588

                  if (d <= max_d)
                  {

589
                     t = (png_dsortp)png_malloc_warn(png_ptr,
590
                         (png_uint_32)(png_sizeof(png_dsort)));
591

592 593
                     if (t == NULL)
                         break;
594

G
Guy Schalnat 已提交
595
                     t->next = hash[d];
G
Guy Schalnat 已提交
596 597
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
598 599 600
                     hash[d] = t;
                  }
               }
601 602
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
603 604
            }

605
            if (t != NULL)
G
Guy Schalnat 已提交
606 607
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
608
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
609
               {
G
Guy Schalnat 已提交
610
                  png_dsortp p;
G
Guy Schalnat 已提交
611 612 613

                  for (p = hash[i]; p; p = p->next)
                  {
614
                     if ((int)png_ptr->index_to_palette[p->left]
615 616 617
                         < num_new_palette &&
                         (int)png_ptr->index_to_palette[p->right]
                         < num_new_palette)
G
Guy Schalnat 已提交
618 619 620
                     {
                        int j, next_j;

621
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
622 623 624 625 626 627 628 629 630 631 632
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
633
                        palette[png_ptr->index_to_palette[j]]
634
                            = palette[num_new_palette];
635
                        if (!full_quantize)
G
Guy Schalnat 已提交
636 637 638 639 640
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
641
                              if (png_ptr->quantize_index[k] ==
642
                                  png_ptr->index_to_palette[j])
643
                                 png_ptr->quantize_index[k] =
644
                                     png_ptr->index_to_palette[next_j];
645

646
                              if ((int)png_ptr->quantize_index[k] ==
647
                                  num_new_palette)
648
                                 png_ptr->quantize_index[k] =
649
                                     png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
650 651 652
                           }
                        }

653
                        png_ptr->index_to_palette[png_ptr->palette_to_index
654
                            [num_new_palette]] = png_ptr->index_to_palette[j];
655

656
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
657
                            = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
658

659 660
                        png_ptr->index_to_palette[j] =
                            (png_byte)num_new_palette;
661

662 663
                        png_ptr->palette_to_index[num_new_palette] =
                            (png_byte)j;
G
Guy Schalnat 已提交
664 665 666 667 668 669 670 671 672 673 674
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

            for (i = 0; i < 769; i++)
            {
A
Andreas Dilger 已提交
675
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
676
               {
677
                  png_dsortp p = hash[i];
G
Guy Schalnat 已提交
678 679 680
                  while (p)
                  {
                     t = p->next;
A
Andreas Dilger 已提交
681
                     png_free(png_ptr, p);
G
Guy Schalnat 已提交
682 683 684 685 686 687 688
                     p = t;
                  }
               }
               hash[i] = 0;
            }
            max_d += 96;
         }
A
Andreas Dilger 已提交
689
         png_free(png_ptr, hash);
690 691
         png_free(png_ptr, png_ptr->palette_to_index);
         png_free(png_ptr, png_ptr->index_to_palette);
692 693
         png_ptr->palette_to_index = NULL;
         png_ptr->index_to_palette = NULL;
G
Guy Schalnat 已提交
694 695 696
      }
      num_palette = maximum_colors;
   }
A
Andreas Dilger 已提交
697
   if (png_ptr->palette == NULL)
G
Guy Schalnat 已提交
698
   {
G
Guy Schalnat 已提交
699 700
      png_ptr->palette = palette;
   }
G
Guy Schalnat 已提交
701
   png_ptr->num_palette = (png_uint_16)num_palette;
G
Guy Schalnat 已提交
702

703
   if (full_quantize)
G
Guy Schalnat 已提交
704 705
   {
      int i;
G
Guy Schalnat 已提交
706
      png_bytep distance;
707 708 709 710 711
      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);
712
      png_size_t num_entries = ((png_size_t)1 << total_bits);
G
Guy Schalnat 已提交
713

714
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
715
          (png_uint_32)(num_entries * png_sizeof(png_byte)));
716

717
      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
718
          png_sizeof(png_byte)));
719

720
      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
721 722 723

      for (i = 0; i < num_palette; i++)
      {
724
         int ir, ig, ib;
725 726 727
         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 已提交
728 729 730

         for (ir = 0; ir < num_red; ir++)
         {
731 732
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
733 734
            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
                PNG_QUANTIZE_GREEN_BITS));
G
Guy Schalnat 已提交
735 736

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
737
            {
738 739
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
740 741
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
742
               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
G
Guy Schalnat 已提交
743 744

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
745
               {
746
                  int d_index = index_g | ib;
747 748
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
749 750
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
751

752
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
753
                  {
A
Andreas Dilger 已提交
754 755
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
756 757
                  }
               }
758 759 760
            }
         }
      }
G
Guy Schalnat 已提交
761

A
Andreas Dilger 已提交
762
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
763 764
   }
}
765
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
766

G
[devel]  
Glenn Randers-Pehrson 已提交
767 768 769 770 771 772
#ifdef PNG_READ_GAMMA_SUPPORTED
void PNGFAPI
png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
   png_fixed_point file_gamma)
{
   png_debug(1, "in png_set_gamma_fixed");
773

774 775
   if (png_ptr == NULL)
      return;
776

777
   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
778 779 780
   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);

781
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
782 783 784
    * 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
785
    * was being used; however, png_set_background itself accepted and must still
786 787 788
    * 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
789 790
    * undocumented API feature) the following checks were only enabled in
    * libpng-1.6.0.
791 792
    */
   if (file_gamma <= 0)
793
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
794 795

   if (scrn_gamma <= 0)
796
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
797 798 799 800 801

   /* 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.
    */
G
[devel]  
Glenn Randers-Pehrson 已提交
802 803
   png_ptr->gamma = file_gamma;
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
804
}
G
[devel]  
Glenn Randers-Pehrson 已提交
805 806 807 808 809

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
{
810 811
   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 已提交
812 813 814
}
#  endif /* FLOATING_POINT_SUPPORTED */
#endif /* READ_GAMMA */
G
Guy Schalnat 已提交
815

816
#ifdef PNG_READ_EXPAND_SUPPORTED
817
/* Expand paletted images to RGB, expand grayscale images of
818
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
819 820
 * to alpha channels.
 */
821
void PNGAPI
G
Guy Schalnat 已提交
822
png_set_expand(png_structp png_ptr)
G
Guy Schalnat 已提交
823
{
824
   png_debug(1, "in png_set_expand");
825

826 827
   if (png_ptr == NULL)
      return;
828

829
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
830
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
G
Guy Schalnat 已提交
831
}
832 833 834 835 836 837 838 839 840 841 842 843 844

/* 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.
845
 *
846 847 848
 *  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().
849 850 851
 */

/* Expand paletted images to RGB. */
852
void PNGAPI
853 854
png_set_palette_to_rgb(png_structp png_ptr)
{
855
   png_debug(1, "in png_set_palette_to_rgb");
856

857 858
   if (png_ptr == NULL)
      return;
859

860
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
861
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
862 863 864 865 866 867
}

/* Expand grayscale images of less than 8-bit depth to 8 bits. */
void PNGAPI
png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
{
868
   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
869

870 871
   if (png_ptr == NULL)
      return;
872

873 874
   png_ptr->transformations |= PNG_EXPAND;
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
875 876
}

877 878


879
/* Expand tRNS chunks to alpha channels. */
880
void PNGAPI
881 882
png_set_tRNS_to_alpha(png_structp png_ptr)
{
883
   png_debug(1, "in png_set_tRNS_to_alpha");
884

885
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
886
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
887 888
}
#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
G
Guy Schalnat 已提交
889

890
#ifdef PNG_READ_EXPAND_16_SUPPORTED
891
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
892 893 894 895 896 897 898 899 900 901 902 903
 * it may not work correctly.)
 */
void PNGAPI
png_set_expand_16(png_structp png_ptr)
{
   png_debug(1, "in png_set_expand_16");

   if (png_ptr == NULL)
      return;

   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
904 905 906

   /* New API, make sure apps call the correct initializers: */
   png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
907 908 909
}
#endif

910
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
911
void PNGAPI
G
Guy Schalnat 已提交
912
png_set_gray_to_rgb(png_structp png_ptr)
G
Guy Schalnat 已提交
913
{
914
   png_debug(1, "in png_set_gray_to_rgb");
915

916 917 918 919 920 921 922
   if (png_ptr != NULL)
   {
      /* 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;
      png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   }
G
Guy Schalnat 已提交
923
}
G
Guy Schalnat 已提交
924
#endif
G
Guy Schalnat 已提交
925

926
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
927
void PNGFAPI
928
png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
929
    png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
930
{
931
   png_debug(1, "in png_set_rgb_to_gray");
932

933 934
   if (png_ptr == NULL)
      return;
935

936 937
   switch(error_action)
   {
938
      case PNG_ERROR_ACTION_NONE:
939 940
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
         break;
941

942
      case PNG_ERROR_ACTION_WARN:
943 944
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
945

946
      case PNG_ERROR_ACTION_ERROR:
947
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
948 949 950
         break;

      default:
951 952
         png_error(png_ptr, "invalid error action to rgb_to_gray");
         break;
953 954
   }
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
955
#ifdef PNG_READ_EXPAND_SUPPORTED
956 957 958
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
959 960
      png_warning(png_ptr,
        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
961

962 963 964 965
      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
   }
#endif
   {
966
      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
967
      {
968
         png_uint_16 red_int, green_int;
969

970 971 972 973 974
         /* 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.
          */
975 976
         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
977 978 979

         png_ptr->rgb_to_gray_red_coeff   = red_int;
         png_ptr->rgb_to_gray_green_coeff = green_int;
980
         png_ptr->rgb_to_gray_coefficients_set = 1;
981
      }
982

983
      else
984
      {
985 986 987
         if (red >= 0 && green >= 0)
            png_warning(png_ptr,
               "ignoring out of range rgb_to_gray coefficients");
988

989 990 991 992 993
         /* 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.
994 995
          */
         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
996
            png_ptr->rgb_to_gray_green_coeff == 0)
997
         {
998 999 1000
            png_ptr->rgb_to_gray_red_coeff   = 6968;
            png_ptr->rgb_to_gray_green_coeff = 23434;
            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1001 1002
         }
      }
1003
   }
A
Andreas Dilger 已提交
1004
}
1005 1006 1007 1008 1009 1010 1011 1012

#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
png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
G
[devel]  
Glenn Randers-Pehrson 已提交
1013
   double green)
1014 1015 1016 1017
{
   if (png_ptr == NULL)
      return;

G
[devel]  
Glenn Randers-Pehrson 已提交
1018 1019 1020
   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"));
1021 1022 1023
}
#endif /* FLOATING POINT */

A
Andreas Dilger 已提交
1024 1025
#endif

1026
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1027
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1028
void PNGAPI
1029
png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
1030
    read_user_transform_fn)
1031
{
1032
   png_debug(1, "in png_set_read_user_transform_fn");
1033

1034 1035
   if (png_ptr == NULL)
      return;
1036

1037
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1038 1039
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1040
#endif
1041 1042 1043
}
#endif

1044
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
#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 已提交
1066
/* Initialize everything needed for the read.  This includes modifying
1067 1068
 * the palette.
 */
1069 1070 1071 1072 1073 1074 1075 1076

/*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 */
png_init_palette_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
1077
{
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
   /* 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;
1088

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
   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)
         if (png_ptr->trans_alpha[i] == 255)
            continue;
         else if (png_ptr->trans_alpha[i] == 0)
            input_has_transparency = 1;
         else
            input_has_alpha = 1;
   }

   /* 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 已提交
1116

G
Guy Schalnat 已提交
1117
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1118 1119 1120 1121
   /* 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.
    */
1122

1123 1124
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1125 1126
    */
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1127
       (png_ptr->transformations & PNG_EXPAND))
1128
   {
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
      {
         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 */
png_init_rgb_transformations(png_structp png_ptr)
{
1161
   /* Added to libpng-1.5.4: check the color type to determine whether there
1162 1163 1164 1165 1166
    * 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;
1167

1168 1169
   /* If no alpha we can optimize. */
   if (!input_has_alpha)
1170
   {
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
      /* 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);
1182 1183
   }

1184 1185 1186 1187 1188 1189 1190 1191 1192
#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.
    */
1193
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1194 1195 1196
       (png_ptr->transformations & PNG_EXPAND) &&
       !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
       /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
1197 1198
   {
      {
1199
         /* Expand background and tRNS chunks */
1200 1201 1202
         int gray = png_ptr->background.gray;
         int trans_gray = png_ptr->trans_color.gray;

G
Guy Schalnat 已提交
1203 1204 1205
         switch (png_ptr->bit_depth)
         {
            case 1:
1206 1207
               gray *= 0xff;
               trans_gray *= 0xff;
G
Guy Schalnat 已提交
1208
               break;
1209

G
Guy Schalnat 已提交
1210
            case 2:
1211 1212
               gray *= 0x55;
               trans_gray *= 0x55;
G
Guy Schalnat 已提交
1213
               break;
1214

G
Guy Schalnat 已提交
1215
            case 4:
1216 1217
               gray *= 0x11;
               trans_gray *= 0x11;
G
Guy Schalnat 已提交
1218
               break;
1219

1220 1221
            default:

G
Guy Schalnat 已提交
1222
            case 8:
1223
               /* Already 8 bits, fall through */
1224

G
Guy Schalnat 已提交
1225
            case 16:
1226
               /* Already a full 16 bits */
G
Guy Schalnat 已提交
1227 1228
               break;
         }
1229 1230 1231 1232 1233 1234 1235 1236 1237

         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 已提交
1238
      }
1239 1240 1241
   } /* background expand and (therefore) no alpha association. */
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
}
1242

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
void /* PRIVATE */
png_init_read_transformations(png_structp png_ptr)
{
   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
1257
   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1258
    * png_set_alpha_mode and this is another source for a default file gamma so
1259
    * the test needs to be performed later - here.  In addition prior to 1.5.4
1260 1261 1262 1263 1264 1265 1266 1267
    * 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;
1268

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
      if (png_ptr->gamma != 0) /* has been set */
      {
         if (png_ptr->screen_gamma != 0) /* screen set too */
            gamma_correction = png_gamma_threshold(png_ptr->gamma,
               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.
             */
            png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma);
G
Guy Schalnat 已提交
1280
      }
1281 1282 1283

      else if (png_ptr->screen_gamma != 0)
         /* The converse - assume the file matches the screen, note that this
1284
          * perhaps undesireable default can (from 1.5.4) be changed by calling
1285 1286 1287 1288 1289 1290 1291 1292 1293
          * png_set_alpha_mode (even if the alpha handling mode isn't required
          * or isn't changed from the default.)
          */
         png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma);

      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,
1294
          * prior to 1.5.4
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
          */
         png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1;

      /* 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 已提交
1311
   }
G
Guy Schalnat 已提交
1312
#endif
G
Guy Schalnat 已提交
1313

1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
   /* 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
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341
    *  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]
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
    */
#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;

1356
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1357 1358 1359 1360
       * 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
1361
       * get.)  This makes the behavior consistent from 1.5.4:
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
       */
      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 已提交
1376
#endif
1377

1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
   defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   /* 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.
    *
1391
    * TODO: this code needs to be revised to avoid the complexity and
1392 1393 1394 1395 1396 1397 1398
    * 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
1399
       * the file was grayscale the background value is gray.
1400 1401 1402 1403 1404 1405
       */
      if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

   else if (png_ptr->transformations & PNG_COMPOSE)
1406
   {
1407 1408 1409 1410 1411 1412
      /* 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)
1413
      {
1414 1415 1416 1417 1418 1419
         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;
         }
1420
      }
1421
   }
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */

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

1438 1439 1440
   else
      png_init_rgb_transformations(png_ptr);

1441 1442 1443 1444 1445 1446 1447 1448 1449
#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
1450
       * application will supply a 16-bit value so reduce it here.
1451 1452 1453
       *
       * 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.)
1454 1455 1456
       *
       * NOTE: this discards the low 16 bits of the user supplied background
       * color, but until expand_16 works properly there is no choice!
1457
       */
1458 1459 1460 1461 1462
#     define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
      CHOP(png_ptr->background.red);
      CHOP(png_ptr->background.green);
      CHOP(png_ptr->background.blue);
      CHOP(png_ptr->background.gray);
1463 1464
#     undef CHOP
   }
1465
#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
1466

1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
#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

1489 1490 1491 1492
   /* 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
1493
    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
    * 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.
    *
1512
    * In 1.5.4 this is addressed below by an additional check on the individual
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
    * 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)
         && (png_gamma_significant(png_ptr->gamma) ||
            png_gamma_significant(png_ptr->screen_gamma)))
      || ((png_ptr->transformations & PNG_COMPOSE)
         && (png_gamma_significant(png_ptr->gamma)
            || png_gamma_significant(png_ptr->screen_gamma)
1523
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1524
            || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
1525 1526 1527
               && png_gamma_significant(png_ptr->background_gamma))
#  endif
      )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
1528 1529
         && png_gamma_significant(png_ptr->screen_gamma))
      )
G
Guy Schalnat 已提交
1530
   {
1531
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1532

1533
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1534
      if (png_ptr->transformations & PNG_COMPOSE)
G
Guy Schalnat 已提交
1535
      {
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
         /* 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");

1546
         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1547
         {
1548 1549 1550
            /* 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 已提交
1551
            png_color back, back_1;
1552 1553 1554
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1555 1556
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1557

A
Andreas Dilger 已提交
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
               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 已提交
1568
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1569

1570 1571 1572 1573
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
G
[devel]  
Glenn Randers-Pehrson 已提交
1574
                     gs = PNG_FP_1;
1575
                     break;
1576

1577
                  case PNG_BACKGROUND_GAMMA_FILE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1578 1579
                     g = png_reciprocal(png_ptr->gamma);
                     gs = png_reciprocal2(png_ptr->gamma,
1580
                        png_ptr->screen_gamma);
1581
                     break;
1582

1583
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1584 1585
                     g = png_reciprocal(png_ptr->background_gamma);
                     gs = png_reciprocal2(png_ptr->background_gamma,
1586
                        png_ptr->screen_gamma);
1587 1588
                     break;
                  default:
G
[devel]  
Glenn Randers-Pehrson 已提交
1589 1590
                     g = PNG_FP_1;    /* back_1 */
                     gs = PNG_FP_1;   /* back */
1591
                     break;
1592
               }
A
Andreas Dilger 已提交
1593

1594
               if (png_gamma_significant(gs))
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604
               {
                  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 已提交
1605
               {
1606
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1607
                  back.green = (png_byte)png_ptr->background.green;
1608
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1609
               }
1610

1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
               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 已提交
1621 1622
               else
               {
1623 1624 1625
                  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 已提交
1626 1627
               }
            }
1628

G
Guy Schalnat 已提交
1629 1630
            for (i = 0; i < num_palette; i++)
            {
1631 1632
               if (i < (int)png_ptr->num_trans &&
                   png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1633
               {
1634
                  if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1635 1636 1637
                  {
                     palette[i] = back;
                  }
1638
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
G
Guy Schalnat 已提交
1639
                  {
A
Andreas Dilger 已提交
1640
                     png_byte v, w;
G
Guy Schalnat 已提交
1641 1642

                     v = png_ptr->gamma_to_1[palette[i].red];
1643
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
1644 1645 1646
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
1647
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
G
Guy Schalnat 已提交
1648 1649 1650
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
1651
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
                     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];
               }
            }
1662 1663 1664

            /* Prevent the transformations being done again.
             *
1665
             * NOTE: this is highly dubious; it removes the transformations in
1666 1667
             * place.  This seems inconsistent with the general treatment of the
             * transformations elsewhere.
1668
             */
1669 1670
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1671

1672
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1673
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1674
         {
1675 1676 1677
            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 已提交
1678 1679

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1680
            {
G
Guy Schalnat 已提交
1681
               case PNG_BACKGROUND_GAMMA_SCREEN:
G
[devel]  
Glenn Randers-Pehrson 已提交
1682 1683
                  g = png_ptr->screen_gamma;
                  /* gs = PNG_FP_1; */
G
Guy Schalnat 已提交
1684
                  break;
1685

G
Guy Schalnat 已提交
1686
               case PNG_BACKGROUND_GAMMA_FILE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1687 1688
                  g = png_reciprocal(png_ptr->gamma);
                  gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1689
                  break;
1690

G
Guy Schalnat 已提交
1691
               case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1692 1693
                  g = png_reciprocal(png_ptr->background_gamma);
                  gs = png_reciprocal2(png_ptr->background_gamma,
1694
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1695
                  break;
1696 1697

               default:
1698
                  png_error(png_ptr, "invalid background gamma type");
G
Guy Schalnat 已提交
1699 1700
            }

1701 1702
            g_sig = png_gamma_significant(g);
            gs_sig = png_gamma_significant(gs);
1703

1704 1705 1706 1707 1708 1709 1710
            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);
1711

1712 1713 1714
            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 已提交
1715
            {
1716
               /* RGB or RGBA with color background */
1717 1718 1719 1720
               if (g_sig)
               {
                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, g);
1721

1722 1723
                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, g);
1724

1725 1726 1727
                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, g);
               }
1728

1729 1730 1731 1732
               if (gs_sig)
               {
                  png_ptr->background.red = png_gamma_correct(png_ptr,
                      png_ptr->background.red, gs);
1733

1734 1735
                  png_ptr->background.green = png_gamma_correct(png_ptr,
                      png_ptr->background.green, gs);
1736

1737 1738 1739
                  png_ptr->background.blue = png_gamma_correct(png_ptr,
                      png_ptr->background.blue, gs);
               }
G
Guy Schalnat 已提交
1740
            }
1741

G
Guy Schalnat 已提交
1742 1743
            else
            {
1744 1745
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
1746
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1747

1748
               png_ptr->background.red = png_ptr->background.green
1749
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1750
            }
1751 1752 1753

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

G
Guy Schalnat 已提交
1757
      else
1758
      /* Transformation does not include PNG_BACKGROUND */
1759
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1760 1761 1762 1763 1764 1765 1766
      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 已提交
1767
      {
1768 1769 1770
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1771

1772 1773 1774
         /*NOTE: there are other transformations that should probably be in here
          * too.
          */
G
Guy Schalnat 已提交
1775 1776 1777 1778 1779 1780
         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];
         }
1781

1782 1783
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
1784
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
G
Guy Schalnat 已提交
1785
   }
1786
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1787
   else
G
Guy Schalnat 已提交
1788
#endif
G
[devel]  
Glenn Randers-Pehrson 已提交
1789
#endif /* PNG_READ_GAMMA_SUPPORTED */
1790

1791
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1792 1793 1794
   /* 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 已提交
1795
   {
1796 1797
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
1798
      png_color back;
1799
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
1800 1801 1802 1803 1804

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

1805
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1806
      {
1807
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1808 1809 1810
         {
            palette[i] = back;
         }
1811

1812
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1813
         {
1814
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1815
            png_composite(palette[i].red, palette[i].red,
1816
                png_ptr->trans_alpha[i], back.red);
1817

A
Andreas Dilger 已提交
1818
            png_composite(palette[i].green, palette[i].green,
1819
                png_ptr->trans_alpha[i], back.green);
1820

A
Andreas Dilger 已提交
1821
            png_composite(palette[i].blue, palette[i].blue,
1822
                png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1823 1824
         }
      }
1825

1826
      png_ptr->transformations &= ~PNG_COMPOSE;
G
Guy Schalnat 已提交
1827
   }
1828
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
1829

1830
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
1831
   if ((png_ptr->transformations & PNG_SHIFT) &&
1832
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1833
   {
1834 1835 1836
      int i;
      int istop = png_ptr->num_palette;
      int shift = 8 - png_ptr->sig_bit.red;
G
Guy Schalnat 已提交
1837

1838 1839 1840 1841 1842 1843 1844
      /* 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;
1845

1846 1847 1848
         component >>= shift;
         png_ptr->palette[i].red = (png_byte)component;
      }
1849

1850 1851 1852 1853
      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;
1854

1855 1856 1857 1858 1859 1860
         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 已提交
1861
      {
1862 1863 1864 1865
         int component = png_ptr->palette[i].blue;

         component >>= shift;
         png_ptr->palette[i].blue = (png_byte)component;
G
Guy Schalnat 已提交
1866 1867
      }
   }
1868
#endif  /* PNG_READ_SHIFT_SUPPORTED */
G
Guy Schalnat 已提交
1869 1870
}

A
Andreas Dilger 已提交
1871
/* Modify the info structure to reflect the transformations.  The
1872 1873 1874
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1875
void /* PRIVATE */
G
Guy Schalnat 已提交
1876
png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1877
{
1878
   png_debug(1, "in png_read_transform_info");
1879

1880
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
1881
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1882
   {
A
Andreas Dilger 已提交
1883 1884
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
1885
         /* This check must match what actually happens in
1886
          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1887 1888 1889
          * it is all opaque we must do the same (at present it does not.)
          */
         if (png_ptr->num_trans > 0)
A
Andreas Dilger 已提交
1890
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1891

A
Andreas Dilger 已提交
1892 1893
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1894

G
Guy Schalnat 已提交
1895
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1896 1897 1898 1899 1900
         info_ptr->num_trans = 0;
      }
      else
      {
         if (png_ptr->num_trans)
1901 1902
         {
            if (png_ptr->transformations & PNG_EXPAND_tRNS)
1903
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1904
         }
A
Andreas Dilger 已提交
1905 1906
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1907

A
Andreas Dilger 已提交
1908 1909
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1910 1911 1912
   }
#endif

1913 1914 1915 1916 1917 1918
#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 已提交
1919 1920 1921
      info_ptr->background = png_ptr->background;
#endif

1922
#ifdef PNG_READ_GAMMA_SUPPORTED
1923
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1924 1925 1926 1927 1928
    * 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.
    */
   info_ptr->gamma = png_ptr->gamma;
1929
#endif
1930

1931 1932
   if (info_ptr->bit_depth == 16)
   {
1933
#  ifdef PNG_READ_16BIT_SUPPORTED
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943
#     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

1944
#  else
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
      /* 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
1957

1958
#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
1959 1960 1961 1962 1963 1964
            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
1965
#    endif
1966
#endif /* !READ_16BIT_SUPPORTED */
1967
   }
G
Guy Schalnat 已提交
1968

1969
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1970
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1971 1972
      info_ptr->color_type = (png_byte)(info_ptr->color_type |
         PNG_COLOR_MASK_COLOR);
1973 1974
#endif

1975
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1976
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1977 1978
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_COLOR);
1979 1980
#endif

1981 1982
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
1983 1984
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1985 1986
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
1987 1988 1989
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
1990
   }
G
Guy Schalnat 已提交
1991 1992
#endif

1993 1994 1995 1996 1997 1998 1999 2000
#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

2001
#ifdef PNG_READ_PACK_SUPPORTED
2002
   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
2003 2004 2005
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
2006
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2007
      info_ptr->channels = 1;
2008

G
Guy Schalnat 已提交
2009 2010
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
2011

G
Guy Schalnat 已提交
2012 2013
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
2014

2015
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2016
   if (png_ptr->transformations & PNG_STRIP_ALPHA)
2017
   {
2018 2019
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
         ~PNG_COLOR_MASK_ALPHA);
2020 2021
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
2022 2023
#endif

2024 2025 2026
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

2027
#ifdef PNG_READ_FILLER_SUPPORTED
2028
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
2029 2030 2031
   if ((png_ptr->transformations & PNG_FILLER) &&
       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
2032
   {
2033
      info_ptr->channels++;
2034
      /* If adding a true alpha channel not just filler */
2035
      if (png_ptr->transformations & PNG_ADD_ALPHA)
2036
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2037
   }
A
Andreas Dilger 已提交
2038 2039
#endif

2040 2041
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2042
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2043 2044
   {
      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
2045
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2046

2047
      if (info_ptr->channels < png_ptr->user_transform_channels)
2048
         info_ptr->channels = png_ptr->user_transform_channels;
2049
   }
2050 2051
#endif

G
Guy Schalnat 已提交
2052
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2053
       info_ptr->bit_depth);
2054

2055
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2056

2057
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2058 2059 2060 2061 2062 2063 2064
    * 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;

2065
#ifndef PNG_READ_EXPAND_SUPPORTED
2066
   if (png_ptr)
2067 2068
      return;
#endif
G
Guy Schalnat 已提交
2069 2070
}

2071 2072 2073 2074
/* 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.
 */
2075
void /* PRIVATE */
2076
png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
G
Guy Schalnat 已提交
2077
{
2078
   png_debug(1, "in png_do_read_transformations");
2079

A
Andreas Dilger 已提交
2080
   if (png_ptr->row_buf == NULL)
G
Guy Schalnat 已提交
2081
   {
2082
      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
2083 2084 2085
       * error is incredibly rare and incredibly easy to debug without this
       * information.
       */
2086
      png_error(png_ptr, "NULL row buffer");
G
Guy Schalnat 已提交
2087
   }
2088

2089 2090
   /* 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
2091 2092 2093 2094 2095 2096 2097 2098
    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.5 the new flag is set only for
    * selected new APIs to ensure that there is no API change.
    */
   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.
2099
       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
2100
       */
2101
      png_error(png_ptr, "Uninitialized row");
2102
   }
A
Andreas Dilger 已提交
2103

2104
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
2105
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
2106
   {
2107
      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
A
Andreas Dilger 已提交
2108
      {
2109
         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
2110
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
A
Andreas Dilger 已提交
2111
      }
2112

2113
      else
A
Andreas Dilger 已提交
2114
      {
2115 2116
         if (png_ptr->num_trans &&
             (png_ptr->transformations & PNG_EXPAND_tRNS))
2117
            png_do_expand(row_info, png_ptr->row_buf + 1,
2118
                &(png_ptr->trans_color));
2119

2120
         else
2121
            png_do_expand(row_info, png_ptr->row_buf + 1,
2122
                NULL);
A
Andreas Dilger 已提交
2123
      }
G
Guy Schalnat 已提交
2124
   }
G
Guy Schalnat 已提交
2125 2126
#endif

2127
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2128
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
2129
      !(png_ptr->transformations & PNG_COMPOSE) &&
2130 2131 2132
      (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,
2133
         0 /* at_start == false, because SWAP_ALPHA happens later */);
A
Andreas Dilger 已提交
2134 2135
#endif

2136
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2137 2138 2139
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
   {
      int rgb_error =
2140
          png_do_rgb_to_gray(png_ptr, row_info,
2141 2142
              png_ptr->row_buf + 1);

2143
      if (rgb_error)
2144 2145
      {
         png_ptr->rgb_to_gray_status=1;
2146
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
2147
             PNG_RGB_TO_GRAY_WARN)
2148
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
2149

2150 2151
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_ERR)
2152 2153 2154 2155 2156
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

2157
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
2158
 *
2159 2160 2161 2162
 *   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.
2163
 *
2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185
 *   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.
2186 2187
 */

2188
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2189 2190 2191
   /* If gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons
    */
2192
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
2193
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
2194
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
2195 2196
#endif

2197 2198 2199
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
   if (png_ptr->transformations & PNG_COMPOSE)
2200
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2201 2202
#endif

2203
#ifdef PNG_READ_GAMMA_SUPPORTED
G
Guy Schalnat 已提交
2204
   if ((png_ptr->transformations & PNG_GAMMA) &&
2205 2206 2207 2208
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
      /* Because RGB_TO_GRAY does the gamma transform. */
      !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
#endif
2209 2210
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
2211 2212 2213
      /* Because PNG_COMPOSE does the gamma transform if there is something to
       * do (if there is an alpha channel or transparency.)
       */
2214
       !((png_ptr->transformations & PNG_COMPOSE) &&
2215 2216
       ((png_ptr->num_trans != 0) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
2217
#endif
2218 2219 2220
      /* Because png_init_read_transformations transforms the palette, unless
       * RGB_TO_GRAY will do the transform.
       */
2221
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
2222
      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2223 2224
#endif

2225 2226 2227
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
      (png_ptr->transformations & PNG_COMPOSE) &&
2228 2229 2230
      (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,
2231 2232 2233 2234 2235
         0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif

#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
2236 2237
      (row_info->color_type & PNG_COLOR_MASK_ALPHA))
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
2238 2239
#endif

2240
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2241
   if (png_ptr->transformations & PNG_SCALE_16_TO_8)
2242
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
2243
#endif
2244

2245
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2246 2247 2248 2249
   /* 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.
    */
2250
   if (png_ptr->transformations & PNG_16_TO_8)
2251
      png_do_chop(row_info, png_ptr->row_buf + 1);
2252 2253
#endif

2254 2255
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
2256
   {
2257
      png_do_quantize(row_info, png_ptr->row_buf + 1,
2258
          png_ptr->palette_lookup, png_ptr->quantize_index);
2259

2260
      if (row_info->rowbytes == 0)
2261
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
A
Andreas Dilger 已提交
2262
   }
2263
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
2264

2265 2266 2267 2268 2269 2270 2271
#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)
2272
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
2273
#endif
2274 2275

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2276
   /*NOTE: moved here in 1.5.4 (from much later in this list.) */
2277 2278
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
2279
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
2280
#endif
2281

2282
#ifdef PNG_READ_INVERT_SUPPORTED
G
Guy Schalnat 已提交
2283
   if (png_ptr->transformations & PNG_INVERT_MONO)
2284
      png_do_invert(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2285 2286
#endif

2287
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
2288
   if (png_ptr->transformations & PNG_SHIFT)
2289
      png_do_unshift(row_info, png_ptr->row_buf + 1,
2290
          &(png_ptr->shift));
G
Guy Schalnat 已提交
2291 2292
#endif

2293
#ifdef PNG_READ_PACK_SUPPORTED
G
Guy Schalnat 已提交
2294
   if (png_ptr->transformations & PNG_PACK)
2295
      png_do_unpack(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2296 2297
#endif

2298
#ifdef PNG_READ_BGR_SUPPORTED
G
Guy Schalnat 已提交
2299
   if (png_ptr->transformations & PNG_BGR)
2300
      png_do_bgr(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2301 2302
#endif

2303
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2304
   if (png_ptr->transformations & PNG_PACKSWAP)
2305
      png_do_packswap(row_info, png_ptr->row_buf + 1);
A
Andreas Dilger 已提交
2306 2307
#endif

2308
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
2309
   if (png_ptr->transformations & PNG_FILLER)
2310
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
2311
          (png_uint_32)png_ptr->filler, png_ptr->flags);
A
Andreas Dilger 已提交
2312 2313
#endif

2314
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2315
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
2316
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
2317 2318
#endif

2319
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2320
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
2321
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
2322 2323
#endif

2324
#ifdef PNG_READ_16BIT_SUPPORTED
2325
#ifdef PNG_READ_SWAP_SUPPORTED
A
Andreas Dilger 已提交
2326
   if (png_ptr->transformations & PNG_SWAP_BYTES)
2327
      png_do_swap(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2328
#endif
2329
#endif
2330

2331
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
2332
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2333
    {
2334
      if (png_ptr->read_user_transform_fn != NULL)
2335
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
2336 2337
             (png_ptr,     /* png_ptr */
             row_info,     /* row_info: */
2338
                /*  png_uint_32 width;       width of row */
2339
                /*  png_size_t rowbytes;     number of bytes in row */
2340 2341 2342 2343 2344
                /*  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 */
2345
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
2346
      if (png_ptr->user_transform_depth)
2347
         row_info->bit_depth = png_ptr->user_transform_depth;
2348

2349
      if (png_ptr->user_transform_channels)
2350
         row_info->channels = png_ptr->user_transform_channels;
2351
#endif
2352 2353
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
2354

2355
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
2356
   }
2357
#endif
G
Guy Schalnat 已提交
2358 2359
}

2360
#ifdef PNG_READ_PACK_SUPPORTED
2361 2362 2363 2364 2365 2366
/* 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.
 */
2367
void /* PRIVATE */
G
Guy Schalnat 已提交
2368
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2369
{
2370
   png_debug(1, "in png_do_unpack");
2371

A
Andreas Dilger 已提交
2372
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2373
   {
2374
      png_uint_32 i;
2375
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2376

G
Guy Schalnat 已提交
2377 2378 2379 2380
      switch (row_info->bit_depth)
      {
         case 1:
         {
2381 2382
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2383
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2384
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2385
            {
2386
               *dp = (png_byte)((*sp >> shift) & 0x01);
2387

G
Guy Schalnat 已提交
2388 2389 2390 2391
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2392
               }
2393

G
Guy Schalnat 已提交
2394 2395 2396 2397 2398 2399 2400
               else
                  shift++;

               dp--;
            }
            break;
         }
2401

G
Guy Schalnat 已提交
2402 2403 2404
         case 2:
         {

2405 2406
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2407
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2408
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2409
            {
2410
               *dp = (png_byte)((*sp >> shift) & 0x03);
2411

G
Guy Schalnat 已提交
2412 2413 2414 2415 2416
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2417

G
Guy Schalnat 已提交
2418 2419 2420 2421 2422 2423 2424
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2425

G
Guy Schalnat 已提交
2426 2427
         case 4:
         {
2428 2429
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2430
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2431
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2432
            {
2433
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2434

G
Guy Schalnat 已提交
2435 2436 2437 2438 2439
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2440

G
Guy Schalnat 已提交
2441 2442 2443 2444 2445 2446 2447
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2448 2449 2450

         default:
            break;
G
Guy Schalnat 已提交
2451 2452
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2453
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2454
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2455 2456
   }
}
G
Guy Schalnat 已提交
2457
#endif
G
Guy Schalnat 已提交
2458

2459
#ifdef PNG_READ_SHIFT_SUPPORTED
2460 2461 2462 2463 2464
/* 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.
 */
2465
void /* PRIVATE */
2466 2467
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2468
{
2469 2470
   int color_type;

2471
   png_debug(1, "in png_do_unshift");
2472

2473 2474 2475 2476
   /* 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 已提交
2477 2478
   {
      int shift[4];
2479
      int channels = 0;
2480
      int bit_depth = row_info->bit_depth;
G
Guy Schalnat 已提交
2481

2482
      if (color_type & PNG_COLOR_MASK_COLOR)
G
Guy Schalnat 已提交
2483
      {
2484 2485 2486
         shift[channels++] = bit_depth - sig_bits->red;
         shift[channels++] = bit_depth - sig_bits->green;
         shift[channels++] = bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2487
      }
2488

G
Guy Schalnat 已提交
2489 2490
      else
      {
2491
         shift[channels++] = bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2492
      }
2493

2494
      if (color_type & PNG_COLOR_MASK_ALPHA)
G
Guy Schalnat 已提交
2495
      {
2496
         shift[channels++] = bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2497
      }
G
Guy Schalnat 已提交
2498

G
Guy Schalnat 已提交
2499
      {
2500
         int c, have_shift;
2501

2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
         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 已提交
2513

2514 2515 2516
         if (!have_shift)
            return;
      }
G
Guy Schalnat 已提交
2517

2518
      switch (bit_depth)
G
Guy Schalnat 已提交
2519
      {
2520
         default:
2521 2522
         /* Must be 1bpp gray: should not be here! */
            /* NOTREACHED */
2523
            break;
2524

G
Guy Schalnat 已提交
2525
         case 2:
2526 2527
         /* Must be 2bpp gray */
         /* assert(channels == 1 && shift[0] == 1) */
G
Guy Schalnat 已提交
2528
         {
2529 2530
            png_bytep bp = row;
            png_bytep bp_end = bp + row_info->rowbytes;
A
Andreas Dilger 已提交
2531

2532
            while (bp < bp_end)
G
Guy Schalnat 已提交
2533
            {
2534 2535
               int b = (*bp >> 1) & 0x55;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2536 2537 2538
            }
            break;
         }
2539

G
Guy Schalnat 已提交
2540
         case 4:
2541 2542
         /* Must be 4bpp gray */
         /* assert(channels == 1) */
G
Guy Schalnat 已提交
2543
         {
2544
            png_bytep bp = row;
2545 2546 2547 2548 2549
            png_bytep bp_end = bp + row_info->rowbytes;
            int gray_shift = shift[0];
            int mask =  0xf >> gray_shift;

            mask |= mask << 4;
2550

2551
            while (bp < bp_end)
G
Guy Schalnat 已提交
2552
            {
2553 2554
               int b = (*bp >> gray_shift) & mask;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2555 2556 2557
            }
            break;
         }
2558

G
Guy Schalnat 已提交
2559
         case 8:
2560
         /* Single byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2561
         {
2562
            png_bytep bp = row;
2563 2564
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2565

2566
            while (bp < bp_end)
A
Andreas Dilger 已提交
2567
            {
2568
               int b = *bp >> shift[channel];
2569 2570
               if (++channel >= channels)
                  channel = 0;
2571
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2572 2573 2574
            }
            break;
         }
2575

2576
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2577
         case 16:
2578
         /* Double byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2579
         {
2580
            png_bytep bp = row;
2581 2582
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2583

2584
            while (bp < bp_end)
A
Andreas Dilger 已提交
2585
            {
2586 2587 2588 2589 2590
               int value = (bp[0] << 8) + bp[1];

               value >>= shift[channel];
               if (++channel >= channels)
                  channel = 0;
2591 2592
               *bp++ = (png_byte)(value >> 8);
               *bp++ = (png_byte)(value & 0xff);
G
Guy Schalnat 已提交
2593 2594 2595
            }
            break;
         }
2596
#endif
G
Guy Schalnat 已提交
2597 2598 2599
      }
   }
}
G
Guy Schalnat 已提交
2600
#endif
G
Guy Schalnat 已提交
2601

2602
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2603
/* Scale rows of bit depth 16 down to 8 accurately */
2604
void /* PRIVATE */
2605
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2606
{
2607
   png_debug(1, "in png_do_scale_16_to_8");
2608

A
Andreas Dilger 已提交
2609
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2610
   {
2611
      png_bytep sp = row; /* source */
2612
      png_bytep dp = row; /* destination */
2613
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2614

2615
      while (sp < ep)
G
Guy Schalnat 已提交
2616
      {
2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647
         /* 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
          */
2648

2649
         png_int_32 tmp = *sp++; /* must be signed! */
2650
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2651
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2652
      }
2653

G
Guy Schalnat 已提交
2654
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2655
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2656
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2657 2658
   }
}
2659
#endif
2660

2661
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
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 */
2673
      png_bytep dp = row; /* destination */
2674 2675 2676 2677
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
2678 2679
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2680 2681 2682 2683 2684 2685 2686
      }

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

2689
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2690
void /* PRIVATE */
A
Andreas Dilger 已提交
2691 2692
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2693
   png_debug(1, "in png_do_read_swap_alpha");
2694

A
Andreas Dilger 已提交
2695
   {
2696
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2697 2698 2699 2700 2701
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2702 2703
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2704 2705
            png_byte save;
            png_uint_32 i;
2706

2707
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2708 2709 2710 2711 2712 2713 2714 2715
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2716 2717

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2718 2719 2720
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2721 2722
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2723 2724
            png_byte save[2];
            png_uint_32 i;
2725

2726
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2740
#endif
A
Andreas Dilger 已提交
2741
      }
2742

A
Andreas Dilger 已提交
2743 2744 2745 2746 2747
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2748 2749
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2750 2751
            png_byte save;
            png_uint_32 i;
2752

2753
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2754 2755 2756 2757 2758 2759
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2760 2761

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2762 2763 2764
         /* This converts from GGAA to AAGG */
         else
         {
2765 2766
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2767 2768 2769
            png_byte save[2];
            png_uint_32 i;

2770
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2771 2772 2773 2774 2775 2776 2777 2778 2779
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2780
#endif
A
Andreas Dilger 已提交
2781
      }
G
Guy Schalnat 已提交
2782 2783
   }
}
G
Guy Schalnat 已提交
2784
#endif
G
Guy Schalnat 已提交
2785

2786
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2787
void /* PRIVATE */
2788 2789
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2790
   png_uint_32 row_width;
2791
   png_debug(1, "in png_do_read_invert_alpha");
2792

2793 2794
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2795
   {
2796
      if (row_info->bit_depth == 8)
2797 2798
      {
         /* This inverts the alpha channel in RGBA */
2799 2800 2801
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2802

2803 2804 2805
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
2806

2807 2808 2809 2810 2811
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2812
*/
2813 2814
            sp-=3;
            dp=sp;
2815
         }
2816
      }
2817 2818

#ifdef PNG_READ_16BIT_SUPPORTED
2819 2820 2821 2822 2823 2824
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2825

2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838
         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:
2839
*/
2840 2841
            sp-=6;
            dp=sp;
2842 2843
         }
      }
2844
#endif
2845 2846 2847 2848
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2849
      {
2850
         /* This inverts the alpha channel in GA */
2851 2852 2853
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2854

2855 2856 2857 2858
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = *(--sp);
2859
         }
2860
      }
2861 2862

#ifdef PNG_READ_16BIT_SUPPORTED
2863 2864
      else
      {
2865
         /* This inverts the alpha channel in GGAA */
2866 2867 2868
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2869

2870 2871 2872 2873
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2874
/*
2875 2876
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2877
*/
2878 2879
            sp-=2;
            dp=sp;
2880 2881
         }
      }
2882
#endif
2883 2884 2885 2886
   }
}
#endif

2887
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2888
/* Add filler channel if we have RGB color */
2889
void /* PRIVATE */
G
Guy Schalnat 已提交
2890
png_do_read_filler(png_row_infop row_info, png_bytep row,
2891
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2892
{
G
Guy Schalnat 已提交
2893
   png_uint_32 i;
2894 2895
   png_uint_32 row_width = row_info->width;

2896
#ifdef PNG_READ_16BIT_SUPPORTED
2897
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2898
#endif
2899
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
2900

2901
   png_debug(1, "in png_do_read_filler");
2902

A
Andreas Dilger 已提交
2903
   if (
2904
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2905
   {
2906
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2907
      {
2908
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2909
         {
2910
            /* This changes the data from G to GX */
2911 2912
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
2913 2914
            for (i = 1; i < row_width; i++)
            {
2915
               *(--dp) = lo_filler;
2916 2917
               *(--dp) = *(--sp);
            }
2918
            *(--dp) = lo_filler;
2919 2920 2921 2922
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
2923

2924 2925
         else
         {
2926
            /* This changes the data from G to XG */
2927 2928
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2929 2930 2931
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2932
               *(--dp) = lo_filler;
2933 2934 2935 2936 2937 2938
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2939

2940
#ifdef PNG_READ_16BIT_SUPPORTED
2941
      else if (row_info->bit_depth == 16)
2942 2943 2944
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2945
            /* This changes the data from GG to GGXX */
2946 2947
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2948 2949 2950
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2951
               *(--dp) = lo_filler;
2952 2953 2954
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2955 2956
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2957 2958
            row_info->channels = 2;
            row_info->pixel_depth = 32;
2959
            row_info->rowbytes = row_width * 4;
2960
         }
2961

2962 2963
         else
         {
2964
            /* This changes the data from GG to XXGG */
2965 2966
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2967 2968 2969 2970 2971
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2972
               *(--dp) = lo_filler;
2973 2974
            }
            row_info->channels = 2;
2975 2976
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
2977
         }
G
Guy Schalnat 已提交
2978
      }
2979
#endif
2980 2981 2982
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
2983
      if (row_info->bit_depth == 8)
2984 2985 2986
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2987
            /* This changes the data from RGB to RGBX */
2988 2989
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
2990 2991
            for (i = 1; i < row_width; i++)
            {
2992
               *(--dp) = lo_filler;
2993 2994 2995 2996
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2997
            *(--dp) = lo_filler;
2998 2999 3000 3001
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
3002

3003 3004
         else
         {
3005
            /* This changes the data from RGB to XRGB */
3006 3007
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
3008 3009 3010 3011 3012
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
3013
               *(--dp) = lo_filler;
3014 3015 3016 3017 3018 3019
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
3020

3021
#ifdef PNG_READ_16BIT_SUPPORTED
3022
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
3023
      {
3024
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
3025
         {
3026
            /* This changes the data from RRGGBB to RRGGBBXX */
3027 3028
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3029 3030 3031
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
3032
               *(--dp) = lo_filler;
3033 3034 3035 3036 3037 3038 3039
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
3040 3041
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
3042 3043
            row_info->channels = 4;
            row_info->pixel_depth = 64;
3044
            row_info->rowbytes = row_width * 8;
3045
         }
3046

3047 3048
         else
         {
3049
            /* This changes the data from RRGGBB to XXRRGGBB */
3050 3051
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3052 3053 3054 3055 3056 3057 3058 3059 3060
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
3061
               *(--dp) = lo_filler;
3062
            }
3063

3064 3065
            row_info->channels = 4;
            row_info->pixel_depth = 64;
3066
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
3067
         }
G
Guy Schalnat 已提交
3068
      }
3069
#endif
3070
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
3071
}
G
Guy Schalnat 已提交
3072
#endif
G
Guy Schalnat 已提交
3073

3074
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
3075
/* Expand grayscale files to RGB, with or without alpha */
3076
void /* PRIVATE */
G
Guy Schalnat 已提交
3077
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
3078
{
G
Guy Schalnat 已提交
3079
   png_uint_32 i;
3080
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3081

3082
   png_debug(1, "in png_do_gray_to_rgb");
3083

A
Andreas Dilger 已提交
3084
   if (row_info->bit_depth >= 8 &&
3085
       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
G
Guy Schalnat 已提交
3086 3087 3088 3089 3090
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
3091
            /* This changes G to RGB */
3092 3093
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3094
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3095 3096 3097
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
3098
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3099 3100
            }
         }
3101

G
Guy Schalnat 已提交
3102 3103
         else
         {
3104
            /* This changes GG to RRGGBB */
3105 3106
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
3107
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3108 3109 3110 3111 3112
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
3113 3114
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3115 3116 3117
            }
         }
      }
3118

G
Guy Schalnat 已提交
3119 3120 3121 3122
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
3123
            /* This changes GA to RGBA */
3124 3125
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3126
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3127 3128 3129 3130
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
3131
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3132 3133
            }
         }
3134

G
Guy Schalnat 已提交
3135 3136
         else
         {
3137
            /* This changes GGAA to RRGGBBAA */
3138 3139
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
3140
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3141 3142 3143 3144 3145 3146 3147
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
3148 3149
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3150 3151 3152
            }
         }
      }
3153
      row_info->channels = (png_byte)(row_info->channels + 2);
G
Guy Schalnat 已提交
3154
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
G
Guy Schalnat 已提交
3155
      row_info->pixel_depth = (png_byte)(row_info->channels *
3156
          row_info->bit_depth);
3157
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3158 3159
   }
}
G
Guy Schalnat 已提交
3160
#endif
G
Guy Schalnat 已提交
3161

3162
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
3163
/* Reduce RGB files to grayscale, with or without alpha
3164 3165 3166 3167 3168
 * 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 )
3169
 * Charles Poynton poynton at poynton.com
3170 3171 3172
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
3173
 *  which can be expressed with integers as
3174
 *
3175 3176 3177 3178 3179 3180 3181
 *     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
3182 3183 3184
 *
 *  which can be expressed with integers as
 *
3185 3186
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
 *
3187 3188 3189 3190 3191
 *  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:
3192
 *
3193
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
3194
 *
3195 3196 3197 3198 3199
 *  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
3200
 *
3201 3202 3203
 *  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.
3204
 *
3205 3206 3207 3208
 *  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.
3209
 *
3210 3211 3212 3213
 *  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.
3214
 */
3215
int /* PRIVATE */
3216 3217 3218 3219 3220
png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)

{
   int rgb_error = 0;

3221
   png_debug(1, "in png_do_rgb_to_gray");
3222

3223
   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
3224
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
3225
   {
3226 3227 3228 3229 3230 3231
      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;
3232

3233
      if (row_info->bit_depth == 8)
3234 3235
      {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247
         /* 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++)
3248
            {
3249 3250 3251
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3252

3253
               if (red != green || red != blue)
3254
               {
3255 3256 3257
                  red = png_ptr->gamma_to_1[red];
                  green = png_ptr->gamma_to_1[green];
                  blue = png_ptr->gamma_to_1[blue];
3258

3259 3260 3261
                  rgb_error |= 1;
                  *(dp++) = png_ptr->gamma_from_1[
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3262
               }
3263

3264 3265 3266 3267 3268 3269 3270
               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];
3271

3272
                  *(dp++) = red;
3273
               }
3274 3275 3276

               if (have_alpha)
                  *(dp++) = *(sp++);
3277 3278
            }
         }
3279 3280
         else
#endif
3281
         {
3282 3283 3284
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3285

3286
            for (i = 0; i < row_width; i++)
3287
            {
3288 3289 3290
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3291

3292 3293 3294 3295 3296 3297 3298 3299
               if (red != green || red != blue)
               {
                  rgb_error |= 1;
                  /*NOTE: this is the historical approach which simply
                   * truncates the results.
                   */
                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
               }
3300

3301 3302
               else
                  *(dp++) = red;
3303

3304 3305
               if (have_alpha)
                  *(dp++) = *(sp++);
3306 3307 3308
            }
         }
      }
3309 3310

      else /* RGB bit_depth == 16 */
3311 3312
      {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
3313 3314 3315 3316 3317 3318 3319
         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++)
3320
            {
3321
               png_uint_16 red, green, blue, w;
3322

3323 3324 3325
               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;
3326

3327 3328 3329 3330 3331
               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];
3332

3333 3334
                  else
                     w = red;
3335
               }
3336 3337

               else
3338
               {
3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359
                  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++);
3360 3361 3362
               }
            }
         }
3363 3364
         else
#endif
3365
         {
3366 3367 3368
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3369

3370 3371 3372
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3373

3374 3375 3376
               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;
3377

3378 3379
               if (red != green || red != blue)
                  rgb_error |= 1;
3380

3381
               /* From 1.5.5 in the 16 bit case do the accurate conversion even
3382 3383 3384 3385 3386 3387 3388
                * 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);
3389

3390
               if (have_alpha)
3391
               {
3392
                  *(dp++) = *(sp++);
3393 3394 3395 3396 3397
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3398

3399
      row_info->channels = (png_byte)(row_info->channels - 2);
3400 3401
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
3402
      row_info->pixel_depth = (png_byte)(row_info->channels *
3403
          row_info->bit_depth);
3404
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3405 3406 3407 3408
   }
   return rgb_error;
}
#endif
3409
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
3410

3411
#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
3412 3413 3414
/* 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
3415
 * of code.  This API is not used internally.
3416
 */
3417
void PNGAPI
G
Guy Schalnat 已提交
3418
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
3419 3420 3421 3422 3423 3424
{
   int num_palette;
   int color_inc;
   int i;
   int v;

3425
   png_debug(1, "in png_do_build_grayscale_palette");
3426

A
Andreas Dilger 已提交
3427
   if (palette == NULL)
G
Guy Schalnat 已提交
3428 3429 3430 3431 3432 3433 3434 3435
      return;

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

G
Guy Schalnat 已提交
3437 3438 3439 3440
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
3441

G
Guy Schalnat 已提交
3442 3443 3444 3445
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
3446

G
Guy Schalnat 已提交
3447 3448 3449 3450
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
3451

G
Guy Schalnat 已提交
3452
      default:
G
Guy Schalnat 已提交
3453
         num_palette = 0;
G
Guy Schalnat 已提交
3454
         color_inc = 0;
G
Guy Schalnat 已提交
3455 3456 3457 3458 3459
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
3460 3461 3462
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
3463 3464
   }
}
3465
#endif
G
Guy Schalnat 已提交
3466 3467


3468
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
3469 3470
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
A
Andreas Dilger 已提交
3471
/* Replace any alpha or transparency with the supplied background color.
3472 3473 3474
 * "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.
 */
3475
void /* PRIVATE */
3476
png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
3477
{
3478
#ifdef PNG_READ_GAMMA_SUPPORTED
3479 3480 3481 3482 3483 3484 3485
   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;
3486
#endif
3487

3488
   png_bytep sp;
G
Guy Schalnat 已提交
3489
   png_uint_32 i;
3490
   png_uint_32 row_width = row_info->width;
3491
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
G
Guy Schalnat 已提交
3492
   int shift;
G
Guy Schalnat 已提交
3493

3494
   png_debug(1, "in png_do_compose");
3495

G
Guy Schalnat 已提交
3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
3507
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3508
                  {
3509
                     if ((png_uint_16)((*sp >> shift) & 0x01)
3510
                        == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3511
                     {
G
Guy Schalnat 已提交
3512
                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
3513
                        *sp |= (png_byte)(png_ptr->background.gray << shift);
G
Guy Schalnat 已提交
3514
                     }
3515

G
Guy Schalnat 已提交
3516 3517 3518 3519 3520
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
3521

G
Guy Schalnat 已提交
3522 3523 3524 3525 3526
                     else
                        shift--;
                  }
                  break;
               }
3527

G
Guy Schalnat 已提交
3528 3529
               case 2:
               {
3530
#ifdef PNG_READ_GAMMA_SUPPORTED
3531
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3532
                  {
3533 3534 3535
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3536
                     {
3537
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3538
                            == png_ptr->trans_color.gray)
3539 3540
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3541
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3542
                        }
3543

3544 3545
                        else
                        {
3546
                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
3547
                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
3548
                               (p << 4) | (p << 6)] >> 6) & 0x03);
3549 3550 3551
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3552

3553 3554 3555 3556 3557
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3558

3559 3560
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3561
                     }
3562
                  }
3563

3564 3565 3566 3567 3568 3569
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3570
                     {
3571
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3572
                            == png_ptr->trans_color.gray)
3573 3574
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3575
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3576
                        }
3577

3578 3579 3580 3581 3582
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3583

3584 3585
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3586 3587 3588 3589
                     }
                  }
                  break;
               }
3590

G
Guy Schalnat 已提交
3591 3592
               case 4:
               {
3593
#ifdef PNG_READ_GAMMA_SUPPORTED
3594
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3595
                  {
3596 3597 3598
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3599
                     {
3600
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3601
                            == png_ptr->trans_color.gray)
3602 3603
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3604
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3605
                        }
3606

3607 3608
                        else
                        {
3609
                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
3610
                           png_byte g = (png_byte)((gamma_table[p |
3611
                               (p << 4)] >> 4) & 0x0f);
3612 3613 3614
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3615

3616 3617 3618 3619 3620
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3621

3622 3623
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3624
                     }
3625
                  }
3626

3627 3628 3629 3630 3631 3632
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3633
                     {
3634
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3635
                            == png_ptr->trans_color.gray)
3636 3637
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3638
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3639
                        }
3640

3641 3642 3643 3644 3645
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3646

3647 3648
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3649 3650 3651 3652
                     }
                  }
                  break;
               }
3653

G
Guy Schalnat 已提交
3654 3655
               case 8:
               {
3656
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3657
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3658
                  {
3659 3660
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3661
                     {
3662 3663
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3664

G
Guy Schalnat 已提交
3665 3666 3667 3668 3669
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3670
#endif
G
Guy Schalnat 已提交
3671
                  {
3672 3673
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3674
                     {
3675 3676
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3677 3678 3679 3680
                     }
                  }
                  break;
               }
3681

G
Guy Schalnat 已提交
3682 3683
               case 16:
               {
3684
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3685
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3686
                  {
3687 3688
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3689 3690 3691
                     {
                        png_uint_16 v;

3692
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3693

3694
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3695
                        {
3696
                           /* Background is already in screen gamma */
3697 3698
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3699
                        }
3700

G
Guy Schalnat 已提交
3701 3702
                        else
                        {
A
Andreas Dilger 已提交
3703
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3704
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3705
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3706
                        }
G
Guy Schalnat 已提交
3707
                     }
G
Guy Schalnat 已提交
3708 3709
                  }
                  else
G
Guy Schalnat 已提交
3710
#endif
G
Guy Schalnat 已提交
3711
                  {
3712 3713
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3714 3715 3716
                     {
                        png_uint_16 v;

3717
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3718

3719
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3720
                        {
3721 3722
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3723 3724 3725 3726 3727
                        }
                     }
                  }
                  break;
               }
3728 3729 3730

               default:
                  break;
G
Guy Schalnat 已提交
3731 3732 3733
            }
            break;
         }
3734

G
Guy Schalnat 已提交
3735 3736 3737 3738
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3739
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3740
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3741
               {
3742 3743
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3744
                  {
3745 3746 3747
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3748
                     {
3749 3750 3751
                        *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 已提交
3752
                     }
3753

G
Guy Schalnat 已提交
3754 3755 3756 3757 3758 3759 3760 3761 3762
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3763
#endif
G
Guy Schalnat 已提交
3764
               {
3765 3766
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3767
                  {
3768 3769 3770
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3771
                     {
3772 3773 3774
                        *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 已提交
3775 3776 3777 3778
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3779
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3780
            {
3781
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3782
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3783
               {
3784 3785
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3786
                  {
3787
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3788

3789 3790
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3791

3792 3793
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3794

3795 3796 3797
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3798
                     {
3799
                        /* Background is already in screen gamma */
3800 3801 3802 3803 3804 3805
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3806
                     }
3807

G
Guy Schalnat 已提交
3808 3809
                     else
                     {
3810
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3811
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3812
                        *(sp + 1) = (png_byte)(v & 0xff);
3813

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

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

G
Guy Schalnat 已提交
3825
               else
G
Guy Schalnat 已提交
3826
#endif
G
Guy Schalnat 已提交
3827
               {
3828 3829
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3830
                  {
3831
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3832

3833 3834
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3835

3836 3837
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3838

3839 3840 3841
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3842
                     {
3843 3844 3845 3846 3847 3848
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
3849 3850 3851 3852 3853 3854
                     }
                  }
               }
            }
            break;
         }
3855

G
Guy Schalnat 已提交
3856
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3857
         {
A
Andreas Dilger 已提交
3858
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3859
            {
3860
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3861 3862 3863
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3864
                  sp = row;
3865
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3866
                  {
3867
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3868

A
Andreas Dilger 已提交
3869
                     if (a == 0xff)
3870
                        *sp = gamma_table[*sp];
3871

A
Andreas Dilger 已提交
3872 3873
                     else if (a == 0)
                     {
3874
                        /* Background is already in screen gamma */
3875
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3876
                     }
3877

A
Andreas Dilger 已提交
3878 3879 3880
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3881

A
Andreas Dilger 已提交
3882
                        v = gamma_to_1[*sp];
3883
                        png_composite(w, v, a, png_ptr->background_1.gray);
3884 3885 3886
                        if (!optimize)
                           w = gamma_from_1[w];
                        *sp = w;
G
Guy Schalnat 已提交
3887 3888
                     }
                  }
A
Andreas Dilger 已提交
3889 3890
               }
               else
G
Guy Schalnat 已提交
3891
#endif
A
Andreas Dilger 已提交
3892
               {
3893
                  sp = row;
3894
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3895
                  {
3896
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3897

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

3901 3902
                     else if (a < 0xff)
                        png_composite(*sp, *sp, a, png_ptr->background_1.gray);
G
Guy Schalnat 已提交
3903 3904
                  }
               }
A
Andreas Dilger 已提交
3905 3906 3907
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3908
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3909 3910 3911
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3912
                  sp = row;
3913
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3914
                  {
3915 3916
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
A
Andreas Dilger 已提交
3917 3918

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3919
                     {
A
Andreas Dilger 已提交
3920
                        png_uint_16 v;
G
Guy Schalnat 已提交
3921

A
Andreas Dilger 已提交
3922
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3923 3924
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3925
                     }
3926

A
Andreas Dilger 已提交
3927 3928
                     else if (a == 0)
                     {
3929
                        /* Background is already in screen gamma */
3930 3931
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3932
                     }
3933

A
Andreas Dilger 已提交
3934 3935 3936
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3937

A
Andreas Dilger 已提交
3938
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3939
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3940 3941 3942 3943 3944 3945
                        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 已提交
3946 3947
                     }
                  }
A
Andreas Dilger 已提交
3948 3949
               }
               else
G
Guy Schalnat 已提交
3950
#endif
A
Andreas Dilger 已提交
3951
               {
3952
                  sp = row;
3953
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3954
                  {
3955 3956
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3957

3958
                     if (a == 0)
A
Andreas Dilger 已提交
3959
                     {
3960 3961
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3962
                     }
3963

3964
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3965 3966
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3967

3968
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3969
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3970 3971
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3972 3973 3974 3975 3976 3977
                     }
                  }
               }
            }
            break;
         }
3978

G
Guy Schalnat 已提交
3979 3980 3981 3982
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3983
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3984 3985
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3986
               {
3987
                  sp = row;
3988
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3989
                  {
3990
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3991 3992 3993

                     if (a == 0xff)
                     {
3994 3995 3996
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
3997
                     }
3998

G
Guy Schalnat 已提交
3999 4000
                     else if (a == 0)
                     {
4001
                        /* Background is already in screen gamma */
4002 4003 4004
                        *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 已提交
4005
                     }
4006

G
Guy Schalnat 已提交
4007 4008
                     else
                     {
A
Andreas Dilger 已提交
4009
                        png_byte v, w;
G
Guy Schalnat 已提交
4010 4011

                        v = gamma_to_1[*sp];
4012
                        png_composite(w, v, a, png_ptr->background_1.red);
4013 4014
                        if (!optimize) w = gamma_from_1[w];
                        *sp = w;
4015

G
Guy Schalnat 已提交
4016
                        v = gamma_to_1[*(sp + 1)];
4017
                        png_composite(w, v, a, png_ptr->background_1.green);
4018 4019
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 1) = w;
4020

G
Guy Schalnat 已提交
4021
                        v = gamma_to_1[*(sp + 2)];
4022
                        png_composite(w, v, a, png_ptr->background_1.blue);
4023 4024
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
4025 4026 4027 4028
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
4029
#endif
G
Guy Schalnat 已提交
4030
               {
4031
                  sp = row;
4032
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
4033
                  {
4034
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
4035

4036
                     if (a == 0)
G
Guy Schalnat 已提交
4037
                     {
4038 4039 4040
                        *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 已提交
4041
                     }
4042

4043
                     else if (a < 0xff)
G
Guy Schalnat 已提交
4044
                     {
4045
                        png_composite(*sp, *sp, a, png_ptr->background.red);
4046

4047
                        png_composite(*(sp + 1), *(sp + 1), a,
4048
                            png_ptr->background.green);
4049

4050
                        png_composite(*(sp + 2), *(sp + 2), a,
4051
                            png_ptr->background.blue);
G
Guy Schalnat 已提交
4052 4053 4054 4055
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
4056
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4057
            {
4058
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4059 4060
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
4061
               {
4062
                  sp = row;
4063
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
4064
                  {
4065 4066
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
4067

G
Guy Schalnat 已提交
4068 4069 4070 4071
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
4072
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
4073 4074
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4075

A
Andreas Dilger 已提交
4076
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
4077 4078
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4079

A
Andreas Dilger 已提交
4080
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
4081 4082
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4083
                     }
4084

G
Guy Schalnat 已提交
4085 4086
                     else if (a == 0)
                     {
4087
                        /* Background is already in screen gamma */
4088 4089 4090 4091 4092 4093
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
4094
                     }
4095

G
Guy Schalnat 已提交
4096 4097
                     else
                     {
4098
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
4099 4100

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

A
Andreas Dilger 已提交
4107
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
4108
                        png_composite_16(w, v, a, png_ptr->background_1.green);
4109 4110
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4111

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

A
Andreas Dilger 已提交
4115
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
4116
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
4117 4118
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4119

4120 4121
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
4122 4123 4124
                     }
                  }
               }
4125

G
Guy Schalnat 已提交
4126
               else
G
Guy Schalnat 已提交
4127
#endif
G
Guy Schalnat 已提交
4128
               {
4129
                  sp = row;
4130
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
4131
                  {
4132
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
4133
                         << 8) + (png_uint_16)(*(sp + 7)));
4134

4135
                     if (a == 0)
G
Guy Schalnat 已提交
4136
                     {
4137 4138 4139 4140 4141 4142
                        *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
G
Guy Schalnat 已提交
4143
                     }
4144

4145
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
4146
                     {
4147
                        png_uint_16 v;
A
Andreas Dilger 已提交
4148

4149 4150 4151 4152 4153
                        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 已提交
4154

4155
                        png_composite_16(v, r, a, png_ptr->background.red);
4156 4157
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4158

4159
                        png_composite_16(v, g, a, png_ptr->background.green);
4160 4161
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4162

4163
                        png_composite_16(v, b, a, png_ptr->background.blue);
4164 4165
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4166 4167 4168 4169 4170 4171
                     }
                  }
               }
            }
            break;
         }
4172 4173 4174

         default:
            break;
G
Guy Schalnat 已提交
4175 4176 4177
      }
   }
}
4178
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
G
Guy Schalnat 已提交
4179

4180
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4181
/* Gamma correct the image, avoiding the alpha channel.  Make sure
4182
 * you do this after you deal with the transparency issue on grayscale
4183
 * or RGB images. If your bit depth is 8, use gamma_table, if it
4184 4185 4186
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
4187
void /* PRIVATE */
4188
png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
G
Guy Schalnat 已提交
4189
{
4190 4191 4192 4193
   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 已提交
4194
   png_bytep sp;
G
Guy Schalnat 已提交
4195
   png_uint_32 i;
4196
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4197

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

4200
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
4201
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
4202 4203 4204 4205 4206 4207 4208
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
4209 4210
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4211 4212 4213 4214 4215 4216 4217 4218 4219
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4220

A
Andreas Dilger 已提交
4221
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4222
            {
4223 4224
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4225 4226 4227
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
4228
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4229 4230 4231
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4232

A
Andreas Dilger 已提交
4233
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4234 4235
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4236
                  sp += 2;
4237

A
Andreas Dilger 已提交
4238
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4239 4240 4241 4242 4243 4244 4245
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
4246

G
Guy Schalnat 已提交
4247 4248 4249 4250
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4251 4252
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4253
               {
G
Guy Schalnat 已提交
4254 4255
                  *sp = gamma_table[*sp];
                  sp++;
4256

G
Guy Schalnat 已提交
4257 4258
                  *sp = gamma_table[*sp];
                  sp++;
4259

G
Guy Schalnat 已提交
4260 4261
                  *sp = gamma_table[*sp];
                  sp++;
4262

G
Guy Schalnat 已提交
4263 4264 4265
                  sp++;
               }
            }
4266

A
Andreas Dilger 已提交
4267
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4268
            {
4269 4270
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4271
               {
4272
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4273 4274
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4275
                  sp += 2;
4276

A
Andreas Dilger 已提交
4277
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4278 4279 4280
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4281

A
Andreas Dilger 已提交
4282
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4283 4284 4285 4286 4287
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4288 4289
            break;
         }
4290

G
Guy Schalnat 已提交
4291 4292 4293 4294
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4295 4296
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4297 4298
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4299
                  sp += 2;
G
Guy Schalnat 已提交
4300 4301
               }
            }
4302

A
Andreas Dilger 已提交
4303
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4304
            {
4305 4306
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4307
               {
4308
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4309 4310
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4311 4312 4313 4314 4315
                  sp += 4;
               }
            }
            break;
         }
4316

G
Guy Schalnat 已提交
4317 4318
         case PNG_COLOR_TYPE_GRAY:
         {
4319 4320
            if (row_info->bit_depth == 2)
            {
4321 4322
               sp = row;
               for (i = 0; i < row_width; i += 4)
4323 4324 4325 4326 4327 4328
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4329
                  *sp = (png_byte)(
4330 4331 4332 4333
                      ((((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) ));
4334 4335 4336
                  sp++;
               }
            }
4337

A
Andreas Dilger 已提交
4338
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4339
            {
4340 4341
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4342 4343 4344 4345
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4346
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4347
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4348 4349 4350
                  sp++;
               }
            }
4351

A
Andreas Dilger 已提交
4352 4353
            else if (row_info->bit_depth == 8)
            {
4354 4355
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4356 4357 4358 4359 4360
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4361

G
Guy Schalnat 已提交
4362 4363
            else if (row_info->bit_depth == 16)
            {
4364 4365
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4366
               {
4367
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4368 4369
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4370 4371 4372 4373 4374
                  sp += 2;
               }
            }
            break;
         }
4375 4376 4377

         default:
            break;
G
Guy Schalnat 已提交
4378 4379 4380
      }
   }
}
G
Guy Schalnat 已提交
4381
#endif
G
Guy Schalnat 已提交
4382

4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449
#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 */
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
   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

4450
#ifdef PNG_READ_EXPAND_SUPPORTED
4451
/* Expands a palette row to an RGB or RGBA row depending
4452 4453
 * upon whether you supply trans and num_trans.
 */
4454
void /* PRIVATE */
G
Guy Schalnat 已提交
4455
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4456
   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
4457
{
G
Guy Schalnat 已提交
4458
   int shift, value;
G
Guy Schalnat 已提交
4459
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4460
   png_uint_32 i;
4461
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4462

4463
   png_debug(1, "in png_do_expand_palette");
4464

4465
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4466 4467 4468 4469 4470 4471 4472
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4473 4474
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4475
               shift = 7 - (int)((row_width + 7) & 0x07);
4476
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4477
               {
4478
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4479
                     *dp = 1;
4480

G
Guy Schalnat 已提交
4481 4482
                  else
                     *dp = 0;
4483

G
Guy Schalnat 已提交
4484 4485 4486 4487 4488
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4489

G
Guy Schalnat 已提交
4490 4491 4492 4493 4494 4495 4496
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4497

G
Guy Schalnat 已提交
4498 4499
            case 2:
            {
4500 4501
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4502
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4503
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4504
               {
4505
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4506
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4507 4508 4509 4510 4511
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4512

G
Guy Schalnat 已提交
4513 4514 4515 4516 4517 4518 4519
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4520

G
Guy Schalnat 已提交
4521 4522
            case 4:
            {
4523 4524
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4525
               shift = (int)((row_width & 0x01) << 2);
4526
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4527
               {
4528
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4529
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4530 4531 4532 4533 4534
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4535

G
Guy Schalnat 已提交
4536 4537 4538 4539 4540 4541 4542
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4543 4544 4545

            default:
               break;
G
Guy Schalnat 已提交
4546 4547 4548
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4549
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4550
      }
4551

4552
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4553 4554
      {
         {
4555
            if (num_trans > 0)
G
Guy Schalnat 已提交
4556
            {
4557 4558
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
4559

4560
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4561
               {
A
Andreas Dilger 已提交
4562
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4563
                     *dp-- = 0xff;
4564

G
Guy Schalnat 已提交
4565
                  else
4566
                     *dp-- = trans_alpha[*sp];
4567

G
Guy Schalnat 已提交
4568 4569 4570 4571 4572 4573 4574
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4575
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4576 4577 4578
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4579

G
Guy Schalnat 已提交
4580 4581
            else
            {
4582 4583
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4584

4585
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4586 4587 4588 4589 4590 4591
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4592

G
Guy Schalnat 已提交
4593 4594
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4595
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4596 4597 4598 4599 4600 4601 4602 4603
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4604 4605
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4606
 */
4607
void /* PRIVATE */
G
Guy Schalnat 已提交
4608
png_do_expand(png_row_infop row_info, png_bytep row,
4609
    png_const_color_16p trans_color)
G
Guy Schalnat 已提交
4610
{
G
Guy Schalnat 已提交
4611
   int shift, value;
G
Guy Schalnat 已提交
4612
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4613
   png_uint_32 i;
4614
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4615

4616
   png_debug(1, "in png_do_expand");
4617

G
Guy Schalnat 已提交
4618
   {
A
Andreas Dilger 已提交
4619
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4620
      {
4621
         png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
A
Andreas Dilger 已提交
4622 4623

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4624
         {
A
Andreas Dilger 已提交
4625
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4626
            {
A
Andreas Dilger 已提交
4627
               case 1:
G
Guy Schalnat 已提交
4628
               {
4629
                  gray = (png_uint_16)((gray & 0x01) * 0xff);
4630 4631
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4632
                  shift = 7 - (int)((row_width + 7) & 0x07);
4633
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4634
                  {
4635
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4636
                        *dp = 0xff;
4637

A
Andreas Dilger 已提交
4638 4639
                     else
                        *dp = 0;
4640

A
Andreas Dilger 已提交
4641 4642 4643 4644 4645
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4646

A
Andreas Dilger 已提交
4647 4648
                     else
                        shift++;
G
Guy Schalnat 已提交
4649

A
Andreas Dilger 已提交
4650 4651 4652
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4653
               }
4654

A
Andreas Dilger 已提交
4655
               case 2:
G
Guy Schalnat 已提交
4656
               {
4657
                  gray = (png_uint_16)((gray & 0x03) * 0x55);
4658 4659
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
4660
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4661
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4662
                  {
4663
                     value = (*sp >> shift) & 0x03;
A
Andreas Dilger 已提交
4664 4665 4666 4667 4668 4669 4670
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
4671

A
Andreas Dilger 已提交
4672 4673
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4674

A
Andreas Dilger 已提交
4675 4676 4677
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4678
               }
4679

A
Andreas Dilger 已提交
4680
               case 4:
G
Guy Schalnat 已提交
4681
               {
4682
                  gray = (png_uint_16)((gray & 0x0f) * 0x11);
4683 4684
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4685
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4686
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4687
                  {
4688
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
4689 4690 4691 4692 4693 4694
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4695

A
Andreas Dilger 已提交
4696 4697
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4698

A
Andreas Dilger 已提交
4699 4700 4701
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4702
               }
4703 4704 4705

               default:
                  break;
G
Guy Schalnat 已提交
4706
            }
4707

A
Andreas Dilger 已提交
4708 4709
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4710
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4711
         }
A
Andreas Dilger 已提交
4712

4713
         if (trans_color != NULL)
G
Guy Schalnat 已提交
4714
         {
A
Andreas Dilger 已提交
4715
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4716
            {
4717
               gray = gray & 0xff;
4718 4719
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
4720

4721
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4722
               {
A
Andreas Dilger 已提交
4723 4724
                  if (*sp == gray)
                     *dp-- = 0;
4725

A
Andreas Dilger 已提交
4726 4727
                  else
                     *dp-- = 0xff;
4728

A
Andreas Dilger 已提交
4729
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4730
               }
A
Andreas Dilger 已提交
4731
            }
4732

A
Andreas Dilger 已提交
4733 4734
            else if (row_info->bit_depth == 16)
            {
4735 4736
               png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
               png_byte gray_low = (png_byte)(gray & 0xff);
A
Andreas Dilger 已提交
4737 4738
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4739
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4740
               {
4741
                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
A
Andreas Dilger 已提交
4742 4743 4744 4745
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4746

A
Andreas Dilger 已提交
4747 4748 4749 4750 4751
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4752

A
Andreas Dilger 已提交
4753 4754
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4755 4756
               }
            }
4757

A
Andreas Dilger 已提交
4758 4759 4760
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4761 4762
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
4763 4764
         }
      }
4765
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
G
Guy Schalnat 已提交
4766 4767 4768
      {
         if (row_info->bit_depth == 8)
         {
4769 4770 4771
            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 已提交
4772
            sp = row + (png_size_t)row_info->rowbytes - 1;
4773 4774
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4775
            {
4776
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
4777
                  *dp-- = 0;
4778

G
Guy Schalnat 已提交
4779 4780
               else
                  *dp-- = 0xff;
4781

G
Guy Schalnat 已提交
4782 4783 4784 4785 4786 4787 4788
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
4789 4790 4791 4792 4793 4794
            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 已提交
4795
            sp = row + row_info->rowbytes - 1;
4796 4797
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4798
            {
4799
               if (*(sp - 5) == red_high &&
4800 4801 4802 4803 4804
                   *(sp - 4) == red_low &&
                   *(sp - 3) == green_high &&
                   *(sp - 2) == green_low &&
                   *(sp - 1) == blue_high &&
                   *(sp    ) == blue_low)
G
Guy Schalnat 已提交
4805 4806 4807 4808
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4809

G
Guy Schalnat 已提交
4810 4811 4812 4813 4814
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4815

G
Guy Schalnat 已提交
4816 4817 4818 4819
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4820
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4821 4822 4823 4824 4825
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
4826
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4827
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4828 4829 4830
      }
   }
}
G
Guy Schalnat 已提交
4831
#endif
G
Guy Schalnat 已提交
4832

4833
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4834
/* If the bit depth is 8 and the color type is not a palette type expand the
4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863
 * 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

4864
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4865
void /* PRIVATE */
4866
png_do_quantize(png_row_infop row_info, png_bytep row,
4867
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
G
Guy Schalnat 已提交
4868
{
G
Guy Schalnat 已提交
4869
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4870
   png_uint_32 i;
4871
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4872

4873
   png_debug(1, "in png_do_quantize");
4874

4875
   if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4876
   {
4877
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
G
Guy Schalnat 已提交
4878 4879 4880 4881
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4882
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4883 4884 4885 4886 4887
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

4888 4889 4890 4891 4892 4893 4894
            /* 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);
             */
4895 4896 4897 4898 4899 4900 4901 4902
            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 已提交
4903 4904 4905

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

G
Guy Schalnat 已提交
4907 4908 4909
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4910
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4911
      }
4912

G
Guy Schalnat 已提交
4913
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4914
         palette_lookup != NULL)
G
Guy Schalnat 已提交
4915 4916 4917 4918
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4919
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4920 4921 4922 4923 4924 4925
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

4926 4927 4928 4929 4930 4931 4932 4933
            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 已提交
4934 4935 4936

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

G
Guy Schalnat 已提交
4938 4939 4940
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4941
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4942
      }
4943

G
Guy Schalnat 已提交
4944
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4945
         quantize_lookup)
G
Guy Schalnat 已提交
4946
      {
G
Guy Schalnat 已提交
4947
         sp = row;
4948

4949
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
4950
         {
4951
            *sp = quantize_lookup[*sp];
G
Guy Schalnat 已提交
4952 4953 4954 4955
         }
      }
   }
}
4956
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
4957
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
G
Guy Schalnat 已提交
4958

4959
#ifdef PNG_MNG_FEATURES_SUPPORTED
4960
/* Undoes intrapixel differencing  */
4961 4962 4963
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
4964
   png_debug(1, "in png_do_read_intrapixel");
4965

4966 4967 4968 4969 4970
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
4971

4972 4973 4974 4975 4976 4977 4978
      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;
4979

4980 4981
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
4982

4983 4984 4985 4986 4987
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4988 4989
            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
4990 4991 4992 4993 4994 4995 4996 4997 4998
         }
      }
      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;
4999

5000 5001
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
5002

5003 5004 5005 5006 5007
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
5008 5009 5010
            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);
5011 5012
            png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
            png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
5013
            *(rp    ) = (png_byte)((red >> 8) & 0xff);
5014 5015 5016
            *(rp + 1) = (png_byte)(red & 0xff);
            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
            *(rp + 5) = (png_byte)(blue & 0xff);
5017 5018 5019 5020 5021
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
5022
#endif /* PNG_READ_SUPPORTED */