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

A
Andreas Dilger 已提交
2
/* pngrtran.c - transforms the data in a row for PNG readers
3
 *
4 5
 * Last changed in libpng 1.5.10 [(PENDING RELEASE)]
 * Copyright (c) 1998-2012 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
{
G
Guy Schalnat 已提交
373
   struct png_dsort_struct FAR * next;
G
Guy Schalnat 已提交
374 375
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
376 377 378
} png_dsort;
typedef png_dsort FAR *       png_dsortp;
typedef png_dsort FAR * FAR * 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
#if PNG_LIBPNG_VER >= 10600
782
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
783 784 785
    * 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
786
    * was being used; however, png_set_background itself accepted and must still
787 788 789
    * 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
790
    * undocumented API feature) it will not be made until 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 802
#endif

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

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

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

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

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

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

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

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

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

/* 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)
{
869
   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
870

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

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

878 879


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

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

891
#ifdef PNG_READ_EXPAND_16_SUPPORTED
892
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
893 894 895 896 897 898 899 900 901 902 903 904
 * 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;
905 906 907

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

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

917 918 919 920 921 922 923
   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 已提交
924
}
G
Guy Schalnat 已提交
925
#endif
G
Guy Schalnat 已提交
926

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

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

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

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

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

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

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

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

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

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

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

#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 已提交
1014
   double green)
1015 1016 1017 1018
{
   if (png_ptr == NULL)
      return;

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

A
Andreas Dilger 已提交
1025 1026
#endif

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

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

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

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

/*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 已提交
1078
{
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
   /* 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;
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 1116
   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 已提交
1117

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

1124 1125
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1126 1127
    */
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1128
       (png_ptr->transformations & PNG_EXPAND))
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 1161
      {
         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)
{
1162
   /* Added to libpng-1.5.4: check the color type to determine whether there
1163 1164 1165 1166 1167
    * 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;
1168

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

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

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

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

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

1221 1222
            default:

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

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

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

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

1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
      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 已提交
1281
      }
1282 1283 1284

      else if (png_ptr->screen_gamma != 0)
         /* The converse - assume the file matches the screen, note that this
1285
          * perhaps undesireable default can (from 1.5.4) be changed by calling
1286 1287 1288 1289 1290 1291 1292 1293 1294
          * 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,
1295
          * prior to 1.5.4
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
          */
         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 已提交
1312
   }
G
Guy Schalnat 已提交
1313
#endif
G
Guy Schalnat 已提交
1314

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

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

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

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

1439 1440 1441
   else
      png_init_rgb_transformations(png_ptr);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2090 2091
   /* 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
2092 2093 2094 2095 2096 2097 2098 2099
    * 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.
2100
       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
2101
       */
2102
      png_error(png_ptr, "Uninitialized row");
2103
   }
A
Andreas Dilger 已提交
2104

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2299 2300 2301 2302 2303 2304
#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
   /* Added at libpng-1.5.10 */
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
      png_do_check_palette_indexes(png_ptr, row_info);
#endif

2305
#ifdef PNG_READ_BGR_SUPPORTED
G
Guy Schalnat 已提交
2306
   if (png_ptr->transformations & PNG_BGR)
2307
      png_do_bgr(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2308 2309
#endif

2310
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2311
   if (png_ptr->transformations & PNG_PACKSWAP)
2312
      png_do_packswap(row_info, png_ptr->row_buf + 1);
A
Andreas Dilger 已提交
2313 2314
#endif

2315
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
2316
   if (png_ptr->transformations & PNG_FILLER)
2317
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
2318
          (png_uint_32)png_ptr->filler, png_ptr->flags);
A
Andreas Dilger 已提交
2319 2320
#endif

2321
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2322
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
2323
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
2324 2325
#endif

2326
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2327
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
2328
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
2329 2330
#endif

2331
#ifdef PNG_READ_16BIT_SUPPORTED
2332
#ifdef PNG_READ_SWAP_SUPPORTED
A
Andreas Dilger 已提交
2333
   if (png_ptr->transformations & PNG_SWAP_BYTES)
2334
      png_do_swap(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2335
#endif
2336
#endif
2337

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

2356
      if (png_ptr->user_transform_channels)
2357
         row_info->channels = png_ptr->user_transform_channels;
2358
#endif
2359 2360
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
          row_info->channels);
2361

2362
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
2363
   }
2364
#endif
G
Guy Schalnat 已提交
2365 2366
}

2367
#ifdef PNG_READ_PACK_SUPPORTED
2368 2369 2370 2371 2372 2373
/* 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.
 */
2374
void /* PRIVATE */
G
Guy Schalnat 已提交
2375
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2376
{
2377
   png_debug(1, "in png_do_unpack");
2378

A
Andreas Dilger 已提交
2379
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2380
   {
2381
      png_uint_32 i;
2382
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2383

G
Guy Schalnat 已提交
2384 2385 2386 2387
      switch (row_info->bit_depth)
      {
         case 1:
         {
2388 2389
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2390
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2391
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2392
            {
2393
               *dp = (png_byte)((*sp >> shift) & 0x01);
2394

G
Guy Schalnat 已提交
2395 2396 2397 2398
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2399
               }
2400

G
Guy Schalnat 已提交
2401 2402 2403 2404 2405 2406 2407
               else
                  shift++;

               dp--;
            }
            break;
         }
2408

G
Guy Schalnat 已提交
2409 2410 2411
         case 2:
         {

2412 2413
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2414
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2415
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2416
            {
2417
               *dp = (png_byte)((*sp >> shift) & 0x03);
2418

G
Guy Schalnat 已提交
2419 2420 2421 2422 2423
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2424

G
Guy Schalnat 已提交
2425 2426 2427 2428 2429 2430 2431
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2432

G
Guy Schalnat 已提交
2433 2434
         case 4:
         {
2435 2436
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2437
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2438
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2439
            {
2440
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2441

G
Guy Schalnat 已提交
2442 2443 2444 2445 2446
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2447

G
Guy Schalnat 已提交
2448 2449 2450 2451 2452 2453 2454
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2455 2456 2457

         default:
            break;
G
Guy Schalnat 已提交
2458 2459
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2460
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2461
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2462 2463
   }
}
G
Guy Schalnat 已提交
2464
#endif
G
Guy Schalnat 已提交
2465

2466
#ifdef PNG_READ_SHIFT_SUPPORTED
2467 2468 2469 2470 2471
/* 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.
 */
2472
void /* PRIVATE */
2473 2474
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2475
{
2476 2477
   int color_type;

2478
   png_debug(1, "in png_do_unshift");
2479

2480 2481 2482 2483
   /* 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 已提交
2484 2485
   {
      int shift[4];
2486
      int channels = 0;
2487
      int bit_depth = row_info->bit_depth;
G
Guy Schalnat 已提交
2488

2489
      if (color_type & PNG_COLOR_MASK_COLOR)
G
Guy Schalnat 已提交
2490
      {
2491 2492 2493
         shift[channels++] = bit_depth - sig_bits->red;
         shift[channels++] = bit_depth - sig_bits->green;
         shift[channels++] = bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2494
      }
2495

G
Guy Schalnat 已提交
2496 2497
      else
      {
2498
         shift[channels++] = bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2499
      }
2500

2501
      if (color_type & PNG_COLOR_MASK_ALPHA)
G
Guy Schalnat 已提交
2502
      {
2503
         shift[channels++] = bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2504
      }
G
Guy Schalnat 已提交
2505

G
Guy Schalnat 已提交
2506
      {
2507
         int c, have_shift;
2508

2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519
         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 已提交
2520

2521 2522 2523
         if (!have_shift)
            return;
      }
G
Guy Schalnat 已提交
2524

2525
      switch (bit_depth)
G
Guy Schalnat 已提交
2526
      {
2527
         default:
2528 2529
         /* Must be 1bpp gray: should not be here! */
            /* NOTREACHED */
2530
            break;
2531

G
Guy Schalnat 已提交
2532
         case 2:
2533 2534
         /* Must be 2bpp gray */
         /* assert(channels == 1 && shift[0] == 1) */
G
Guy Schalnat 已提交
2535
         {
2536 2537
            png_bytep bp = row;
            png_bytep bp_end = bp + row_info->rowbytes;
A
Andreas Dilger 已提交
2538

2539
            while (bp < bp_end)
G
Guy Schalnat 已提交
2540
            {
2541 2542
               int b = (*bp >> 1) & 0x55;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2543 2544 2545
            }
            break;
         }
2546

G
Guy Schalnat 已提交
2547
         case 4:
2548 2549
         /* Must be 4bpp gray */
         /* assert(channels == 1) */
G
Guy Schalnat 已提交
2550
         {
2551
            png_bytep bp = row;
2552 2553 2554 2555 2556
            png_bytep bp_end = bp + row_info->rowbytes;
            int gray_shift = shift[0];
            int mask =  0xf >> gray_shift;

            mask |= mask << 4;
2557

2558
            while (bp < bp_end)
G
Guy Schalnat 已提交
2559
            {
2560 2561
               int b = (*bp >> gray_shift) & mask;
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2562 2563 2564
            }
            break;
         }
2565

G
Guy Schalnat 已提交
2566
         case 8:
2567
         /* Single byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2568
         {
2569
            png_bytep bp = row;
2570 2571
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2572

2573
            while (bp < bp_end)
A
Andreas Dilger 已提交
2574
            {
2575
               int b = *bp >> shift[channel];
2576 2577
               if (++channel >= channels)
                  channel = 0;
2578
               *bp++ = (png_byte)b;
G
Guy Schalnat 已提交
2579 2580 2581
            }
            break;
         }
2582

2583
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2584
         case 16:
2585
         /* Double byte components, G, GA, RGB, RGBA */
G
Guy Schalnat 已提交
2586
         {
2587
            png_bytep bp = row;
2588 2589
            png_bytep bp_end = bp + row_info->rowbytes;
            int channel = 0;
G
Guy Schalnat 已提交
2590

2591
            while (bp < bp_end)
A
Andreas Dilger 已提交
2592
            {
2593 2594 2595 2596 2597
               int value = (bp[0] << 8) + bp[1];

               value >>= shift[channel];
               if (++channel >= channels)
                  channel = 0;
2598 2599
               *bp++ = (png_byte)(value >> 8);
               *bp++ = (png_byte)(value & 0xff);
G
Guy Schalnat 已提交
2600 2601 2602
            }
            break;
         }
2603
#endif
G
Guy Schalnat 已提交
2604 2605 2606
      }
   }
}
G
Guy Schalnat 已提交
2607
#endif
G
Guy Schalnat 已提交
2608

2609
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2610
/* Scale rows of bit depth 16 down to 8 accurately */
2611
void /* PRIVATE */
2612
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2613
{
2614
   png_debug(1, "in png_do_scale_16_to_8");
2615

A
Andreas Dilger 已提交
2616
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2617
   {
2618
      png_bytep sp = row; /* source */
2619
      png_bytep dp = row; /* destination */
2620
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2621

2622
      while (sp < ep)
G
Guy Schalnat 已提交
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 2648 2649 2650 2651 2652 2653 2654
         /* 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
          */
2655

2656
         png_int_32 tmp = *sp++; /* must be signed! */
2657
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2658
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2659
      }
2660

G
Guy Schalnat 已提交
2661
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2662
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2663
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2664 2665
   }
}
2666
#endif
2667

2668
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679
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 */
2680
      png_bytep dp = row; /* destination */
2681 2682 2683 2684
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
2685 2686
         *dp++ = *sp;
         sp += 2; /* skip low byte */
2687 2688 2689 2690 2691 2692 2693
      }

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

2696
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2697
void /* PRIVATE */
A
Andreas Dilger 已提交
2698 2699
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2700
   png_debug(1, "in png_do_read_swap_alpha");
2701

A
Andreas Dilger 已提交
2702
   {
2703
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2704 2705 2706 2707 2708
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2709 2710
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2711 2712
            png_byte save;
            png_uint_32 i;
2713

2714
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2715 2716 2717 2718 2719 2720 2721 2722
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2723 2724

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2725 2726 2727
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2728 2729
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2730 2731
            png_byte save[2];
            png_uint_32 i;
2732

2733
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2747
#endif
A
Andreas Dilger 已提交
2748
      }
2749

A
Andreas Dilger 已提交
2750 2751 2752 2753 2754
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2755 2756
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2757 2758
            png_byte save;
            png_uint_32 i;
2759

2760
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2761 2762 2763 2764 2765 2766
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2767 2768

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2769 2770 2771
         /* This converts from GGAA to AAGG */
         else
         {
2772 2773
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2774 2775 2776
            png_byte save[2];
            png_uint_32 i;

2777
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2778 2779 2780 2781 2782 2783 2784 2785 2786
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2787
#endif
A
Andreas Dilger 已提交
2788
      }
G
Guy Schalnat 已提交
2789 2790
   }
}
G
Guy Schalnat 已提交
2791
#endif
G
Guy Schalnat 已提交
2792

2793
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2794
void /* PRIVATE */
2795 2796
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2797
   png_uint_32 row_width;
2798
   png_debug(1, "in png_do_read_invert_alpha");
2799

2800 2801
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2802
   {
2803
      if (row_info->bit_depth == 8)
2804 2805
      {
         /* This inverts the alpha channel in RGBA */
2806 2807 2808
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2809

2810 2811 2812
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
2813

2814 2815 2816 2817 2818
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2819
*/
2820 2821
            sp-=3;
            dp=sp;
2822
         }
2823
      }
2824 2825

#ifdef PNG_READ_16BIT_SUPPORTED
2826 2827 2828 2829 2830 2831
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2832

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

2862 2863 2864 2865
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = *(--sp);
2866
         }
2867
      }
2868 2869

#ifdef PNG_READ_16BIT_SUPPORTED
2870 2871
      else
      {
2872
         /* This inverts the alpha channel in GGAA */
2873 2874 2875
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2876

2877 2878 2879 2880
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2881
/*
2882 2883
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2884
*/
2885 2886
            sp-=2;
            dp=sp;
2887 2888
         }
      }
2889
#endif
2890 2891 2892 2893
   }
}
#endif

2894
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2895
/* Add filler channel if we have RGB color */
2896
void /* PRIVATE */
G
Guy Schalnat 已提交
2897
png_do_read_filler(png_row_infop row_info, png_bytep row,
2898
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2899
{
G
Guy Schalnat 已提交
2900
   png_uint_32 i;
2901 2902
   png_uint_32 row_width = row_info->width;

2903
#ifdef PNG_READ_16BIT_SUPPORTED
2904
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2905
#endif
2906
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
2907

2908
   png_debug(1, "in png_do_read_filler");
2909

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

2931 2932
         else
         {
2933
            /* This changes the data from G to XG */
2934 2935
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2936 2937 2938
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2939
               *(--dp) = lo_filler;
2940 2941 2942 2943 2944 2945
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2946

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

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

3010 3011
         else
         {
3012
            /* This changes the data from RGB to XRGB */
3013 3014
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
3015 3016 3017 3018 3019
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
3020
               *(--dp) = lo_filler;
3021 3022 3023 3024 3025 3026
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
3027

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

3054 3055
         else
         {
3056
            /* This changes the data from RRGGBB to XXRRGGBB */
3057 3058
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3059 3060 3061 3062 3063 3064 3065 3066 3067
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
3068
               *(--dp) = lo_filler;
3069
            }
3070

3071 3072
            row_info->channels = 4;
            row_info->pixel_depth = 64;
3073
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
3074
         }
G
Guy Schalnat 已提交
3075
      }
3076
#endif
3077
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
3078
}
G
Guy Schalnat 已提交
3079
#endif
G
Guy Schalnat 已提交
3080

3081
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
3082
/* Expand grayscale files to RGB, with or without alpha */
3083
void /* PRIVATE */
G
Guy Schalnat 已提交
3084
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
3085
{
G
Guy Schalnat 已提交
3086
   png_uint_32 i;
3087
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
3088

3089
   png_debug(1, "in png_do_gray_to_rgb");
3090

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

G
Guy Schalnat 已提交
3109 3110
         else
         {
3111
            /* This changes GG to RRGGBB */
3112 3113
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
3114
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3115 3116 3117 3118 3119
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
3120 3121
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3122 3123 3124
            }
         }
      }
3125

G
Guy Schalnat 已提交
3126 3127 3128 3129
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
3130
            /* This changes GA to RGBA */
3131 3132
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3133
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3134 3135 3136 3137
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
3138
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3139 3140
            }
         }
3141

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

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

{
   int rgb_error = 0;

3228
   png_debug(1, "in png_do_rgb_to_gray");
3229

3230
   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
3231
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
3232
   {
3233 3234 3235 3236 3237 3238
      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;
3239

3240
      if (row_info->bit_depth == 8)
3241 3242
      {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254
         /* 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++)
3255
            {
3256 3257 3258
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3259

3260
               if (red != green || red != blue)
3261
               {
3262 3263 3264
                  red = png_ptr->gamma_to_1[red];
                  green = png_ptr->gamma_to_1[green];
                  blue = png_ptr->gamma_to_1[blue];
3265

3266 3267 3268
                  rgb_error |= 1;
                  *(dp++) = png_ptr->gamma_from_1[
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3269
               }
3270

3271 3272 3273 3274 3275 3276 3277
               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];
3278

3279
                  *(dp++) = red;
3280
               }
3281 3282 3283

               if (have_alpha)
                  *(dp++) = *(sp++);
3284 3285
            }
         }
3286 3287
         else
#endif
3288
         {
3289 3290 3291
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3292

3293
            for (i = 0; i < row_width; i++)
3294
            {
3295 3296 3297
               png_byte red   = *(sp++);
               png_byte green = *(sp++);
               png_byte blue  = *(sp++);
3298

3299 3300 3301 3302 3303 3304 3305 3306
               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);
               }
3307

3308 3309
               else
                  *(dp++) = red;
3310

3311 3312
               if (have_alpha)
                  *(dp++) = *(sp++);
3313 3314 3315
            }
         }
      }
3316 3317

      else /* RGB bit_depth == 16 */
3318 3319
      {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
3320 3321 3322 3323 3324 3325 3326
         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++)
3327
            {
3328
               png_uint_16 red, green, blue, w;
3329

3330 3331 3332
               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;
3333

3334 3335 3336 3337 3338
               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];
3339

3340 3341
                  else
                     w = red;
3342
               }
3343 3344

               else
3345
               {
3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366
                  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++);
3367 3368 3369
               }
            }
         }
3370 3371
         else
#endif
3372
         {
3373 3374 3375
            png_bytep sp = row;
            png_bytep dp = row;
            png_uint_32 i;
3376

3377 3378 3379
            for (i = 0; i < row_width; i++)
            {
               png_uint_16 red, green, blue, gray16;
3380

3381 3382 3383
               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;
3384

3385 3386
               if (red != green || red != blue)
                  rgb_error |= 1;
3387

3388
               /* From 1.5.5 in the 16 bit case do the accurate conversion even
3389 3390 3391 3392 3393 3394 3395
                * 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);
3396

3397
               if (have_alpha)
3398
               {
3399
                  *(dp++) = *(sp++);
3400 3401 3402 3403 3404
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3405

3406
      row_info->channels = (png_byte)(row_info->channels - 2);
3407 3408
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
3409
      row_info->pixel_depth = (png_byte)(row_info->channels *
3410
          row_info->bit_depth);
3411
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3412 3413 3414 3415
   }
   return rgb_error;
}
#endif
3416
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
3417

3418
#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
3419 3420 3421
/* 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
3422
 * of code.  This API is not used internally.
3423
 */
3424
void PNGAPI
G
Guy Schalnat 已提交
3425
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
3426 3427 3428 3429 3430 3431
{
   int num_palette;
   int color_inc;
   int i;
   int v;

3432
   png_debug(1, "in png_do_build_grayscale_palette");
3433

A
Andreas Dilger 已提交
3434
   if (palette == NULL)
G
Guy Schalnat 已提交
3435 3436 3437 3438 3439 3440 3441 3442
      return;

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

G
Guy Schalnat 已提交
3444 3445 3446 3447
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
3448

G
Guy Schalnat 已提交
3449 3450 3451 3452
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
3453

G
Guy Schalnat 已提交
3454 3455 3456 3457
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
3458

G
Guy Schalnat 已提交
3459
      default:
G
Guy Schalnat 已提交
3460
         num_palette = 0;
G
Guy Schalnat 已提交
3461
         color_inc = 0;
G
Guy Schalnat 已提交
3462 3463 3464 3465 3466
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
3467 3468 3469
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
3470 3471
   }
}
3472
#endif
G
Guy Schalnat 已提交
3473 3474


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

3495
   png_bytep sp;
G
Guy Schalnat 已提交
3496
   png_uint_32 i;
3497
   png_uint_32 row_width = row_info->width;
3498
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
G
Guy Schalnat 已提交
3499
   int shift;
G
Guy Schalnat 已提交
3500

3501
   png_debug(1, "in png_do_compose");
3502

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

G
Guy Schalnat 已提交
3523 3524 3525 3526 3527
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
3528

G
Guy Schalnat 已提交
3529 3530 3531 3532 3533
                     else
                        shift--;
                  }
                  break;
               }
3534

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

3551 3552
                        else
                        {
3553
                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
3554
                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
3555
                               (p << 4) | (p << 6)] >> 6) & 0x03);
3556 3557 3558
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3559

3560 3561 3562 3563 3564
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3565

3566 3567
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3568
                     }
3569
                  }
3570

3571 3572 3573 3574 3575 3576
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3577
                     {
3578
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3579
                            == png_ptr->trans_color.gray)
3580 3581
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3582
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3583
                        }
3584

3585 3586 3587 3588 3589
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3590

3591 3592
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3593 3594 3595 3596
                     }
                  }
                  break;
               }
3597

G
Guy Schalnat 已提交
3598 3599
               case 4:
               {
3600
#ifdef PNG_READ_GAMMA_SUPPORTED
3601
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3602
                  {
3603 3604 3605
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3606
                     {
3607
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3608
                            == png_ptr->trans_color.gray)
3609 3610
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3611
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3612
                        }
3613

3614 3615
                        else
                        {
3616
                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
3617
                           png_byte g = (png_byte)((gamma_table[p |
3618
                               (p << 4)] >> 4) & 0x0f);
3619 3620 3621
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3622

3623 3624 3625 3626 3627
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3628

3629 3630
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3631
                     }
3632
                  }
3633

3634 3635 3636 3637 3638 3639
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3640
                     {
3641
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3642
                            == png_ptr->trans_color.gray)
3643 3644
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3645
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3646
                        }
3647

3648 3649 3650 3651 3652
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3653

3654 3655
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3656 3657 3658 3659
                     }
                  }
                  break;
               }
3660

G
Guy Schalnat 已提交
3661 3662
               case 8:
               {
3663
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3664
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3665
                  {
3666 3667
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3668
                     {
3669 3670
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3671

G
Guy Schalnat 已提交
3672 3673 3674 3675 3676
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3677
#endif
G
Guy Schalnat 已提交
3678
                  {
3679 3680
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3681
                     {
3682 3683
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3684 3685 3686 3687
                     }
                  }
                  break;
               }
3688

G
Guy Schalnat 已提交
3689 3690
               case 16:
               {
3691
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3692
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3693
                  {
3694 3695
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3696 3697 3698
                     {
                        png_uint_16 v;

3699
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3700

3701
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3702
                        {
3703
                           /* Background is already in screen gamma */
3704 3705
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3706
                        }
3707

G
Guy Schalnat 已提交
3708 3709
                        else
                        {
A
Andreas Dilger 已提交
3710
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3711
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3712
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3713
                        }
G
Guy Schalnat 已提交
3714
                     }
G
Guy Schalnat 已提交
3715 3716
                  }
                  else
G
Guy Schalnat 已提交
3717
#endif
G
Guy Schalnat 已提交
3718
                  {
3719 3720
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3721 3722 3723
                     {
                        png_uint_16 v;

3724
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3725

3726
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3727
                        {
3728 3729
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3730 3731 3732 3733 3734
                        }
                     }
                  }
                  break;
               }
3735 3736 3737

               default:
                  break;
G
Guy Schalnat 已提交
3738 3739 3740
            }
            break;
         }
3741

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

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

3796 3797
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3798

3799 3800
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3801

3802 3803 3804
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3805
                     {
3806
                        /* Background is already in screen gamma */
3807 3808 3809 3810 3811 3812
                        *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 已提交
3813
                     }
3814

G
Guy Schalnat 已提交
3815 3816
                     else
                     {
3817
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3818
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3819
                        *(sp + 1) = (png_byte)(v & 0xff);
3820

A
Andreas Dilger 已提交
3821
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3822 3823
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3824

A
Andreas Dilger 已提交
3825
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3826 3827
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3828 3829 3830
                     }
                  }
               }
3831

G
Guy Schalnat 已提交
3832
               else
G
Guy Schalnat 已提交
3833
#endif
G
Guy Schalnat 已提交
3834
               {
3835 3836
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3837
                  {
3838
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3839

3840 3841
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3842

3843 3844
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3845

3846 3847 3848
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3849
                     {
3850 3851 3852 3853 3854 3855
                        *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 已提交
3856 3857 3858 3859 3860 3861
                     }
                  }
               }
            }
            break;
         }
3862

G
Guy Schalnat 已提交
3863
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3864
         {
A
Andreas Dilger 已提交
3865
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3866
            {
3867
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3868 3869 3870
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3871
                  sp = row;
3872
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3873
                  {
3874
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3875

A
Andreas Dilger 已提交
3876
                     if (a == 0xff)
3877
                        *sp = gamma_table[*sp];
3878

A
Andreas Dilger 已提交
3879 3880
                     else if (a == 0)
                     {
3881
                        /* Background is already in screen gamma */
3882
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3883
                     }
3884

A
Andreas Dilger 已提交
3885 3886 3887
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3888

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

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

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

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3926
                     {
A
Andreas Dilger 已提交
3927
                        png_uint_16 v;
G
Guy Schalnat 已提交
3928

A
Andreas Dilger 已提交
3929
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3930 3931
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3932
                     }
3933

A
Andreas Dilger 已提交
3934 3935
                     else if (a == 0)
                     {
3936
                        /* Background is already in screen gamma */
3937 3938
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3939
                     }
3940

A
Andreas Dilger 已提交
3941 3942 3943
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3944

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

3965
                     if (a == 0)
A
Andreas Dilger 已提交
3966
                     {
3967 3968
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3969
                     }
3970

3971
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3972 3973
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3974

3975
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3976
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3977 3978
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3979 3980 3981 3982 3983 3984
                     }
                  }
               }
            }
            break;
         }
3985

G
Guy Schalnat 已提交
3986 3987 3988 3989
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3990
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3991 3992
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3993
               {
3994
                  sp = row;
3995
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3996
                  {
3997
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3998 3999 4000

                     if (a == 0xff)
                     {
4001 4002 4003
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
4004
                     }
4005

G
Guy Schalnat 已提交
4006 4007
                     else if (a == 0)
                     {
4008
                        /* Background is already in screen gamma */
4009 4010 4011
                        *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 已提交
4012
                     }
4013

G
Guy Schalnat 已提交
4014 4015
                     else
                     {
A
Andreas Dilger 已提交
4016
                        png_byte v, w;
G
Guy Schalnat 已提交
4017 4018

                        v = gamma_to_1[*sp];
4019
                        png_composite(w, v, a, png_ptr->background_1.red);
4020 4021
                        if (!optimize) w = gamma_from_1[w];
                        *sp = w;
4022

G
Guy Schalnat 已提交
4023
                        v = gamma_to_1[*(sp + 1)];
4024
                        png_composite(w, v, a, png_ptr->background_1.green);
4025 4026
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 1) = w;
4027

G
Guy Schalnat 已提交
4028
                        v = gamma_to_1[*(sp + 2)];
4029
                        png_composite(w, v, a, png_ptr->background_1.blue);
4030 4031
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
4032 4033 4034 4035
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
4036
#endif
G
Guy Schalnat 已提交
4037
               {
4038
                  sp = row;
4039
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
4040
                  {
4041
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
4042

4043
                     if (a == 0)
G
Guy Schalnat 已提交
4044
                     {
4045 4046 4047
                        *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 已提交
4048
                     }
4049

4050
                     else if (a < 0xff)
G
Guy Schalnat 已提交
4051
                     {
4052
                        png_composite(*sp, *sp, a, png_ptr->background.red);
4053

4054
                        png_composite(*(sp + 1), *(sp + 1), a,
4055
                            png_ptr->background.green);
4056

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

G
Guy Schalnat 已提交
4075 4076 4077 4078
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
4079
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
4080 4081
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4082

A
Andreas Dilger 已提交
4083
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
4084 4085
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4086

A
Andreas Dilger 已提交
4087
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
4088 4089
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4090
                     }
4091

G
Guy Schalnat 已提交
4092 4093
                     else if (a == 0)
                     {
4094
                        /* Background is already in screen gamma */
4095 4096 4097 4098 4099 4100
                        *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 已提交
4101
                     }
4102

G
Guy Schalnat 已提交
4103 4104
                     else
                     {
4105
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
4106 4107

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
4108
                        png_composite_16(w, v, a, png_ptr->background_1.red);
4109 4110 4111 4112
                        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);
4113

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

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

A
Andreas Dilger 已提交
4122
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
4123
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
4124 4125
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4126

4127 4128
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
4129 4130 4131
                     }
                  }
               }
4132

G
Guy Schalnat 已提交
4133
               else
G
Guy Schalnat 已提交
4134
#endif
G
Guy Schalnat 已提交
4135
               {
4136
                  sp = row;
4137
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
4138
                  {
4139
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
4140
                         << 8) + (png_uint_16)(*(sp + 7)));
4141

4142
                     if (a == 0)
G
Guy Schalnat 已提交
4143
                     {
4144 4145 4146 4147 4148 4149
                        *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 已提交
4150
                     }
4151

4152
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
4153
                     {
4154
                        png_uint_16 v;
A
Andreas Dilger 已提交
4155

4156 4157 4158 4159 4160
                        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 已提交
4161

4162
                        png_composite_16(v, r, a, png_ptr->background.red);
4163 4164
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4165

4166
                        png_composite_16(v, g, a, png_ptr->background.green);
4167 4168
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4169

4170
                        png_composite_16(v, b, a, png_ptr->background.blue);
4171 4172
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4173 4174 4175 4176 4177 4178
                     }
                  }
               }
            }
            break;
         }
4179 4180 4181

         default:
            break;
G
Guy Schalnat 已提交
4182 4183 4184
      }
   }
}
4185
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
G
Guy Schalnat 已提交
4186

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

4205
   png_debug(1, "in png_do_gamma");
4206

4207
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
4208
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
4209 4210 4211 4212 4213 4214 4215
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
4216 4217
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4218 4219 4220 4221 4222 4223 4224 4225 4226
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4227

A
Andreas Dilger 已提交
4228
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4229
            {
4230 4231
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4232 4233 4234
               {
                  png_uint_16 v;

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

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

A
Andreas Dilger 已提交
4245
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4246 4247 4248 4249 4250 4251 4252
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
4253

G
Guy Schalnat 已提交
4254 4255 4256 4257
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4258 4259
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4260
               {
G
Guy Schalnat 已提交
4261 4262
                  *sp = gamma_table[*sp];
                  sp++;
4263

G
Guy Schalnat 已提交
4264 4265
                  *sp = gamma_table[*sp];
                  sp++;
4266

G
Guy Schalnat 已提交
4267 4268
                  *sp = gamma_table[*sp];
                  sp++;
4269

G
Guy Schalnat 已提交
4270 4271 4272
                  sp++;
               }
            }
4273

A
Andreas Dilger 已提交
4274
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4275
            {
4276 4277
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4278
               {
4279
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4280 4281
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4282
                  sp += 2;
4283

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

A
Andreas Dilger 已提交
4289
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4290 4291 4292 4293 4294
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4295 4296
            break;
         }
4297

G
Guy Schalnat 已提交
4298 4299 4300 4301
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4302 4303
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4304 4305
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4306
                  sp += 2;
G
Guy Schalnat 已提交
4307 4308
               }
            }
4309

A
Andreas Dilger 已提交
4310
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4311
            {
4312 4313
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4314
               {
4315
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4316 4317
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4318 4319 4320 4321 4322
                  sp += 4;
               }
            }
            break;
         }
4323

G
Guy Schalnat 已提交
4324 4325
         case PNG_COLOR_TYPE_GRAY:
         {
4326 4327
            if (row_info->bit_depth == 2)
            {
4328 4329
               sp = row;
               for (i = 0; i < row_width; i += 4)
4330 4331 4332 4333 4334 4335
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4336
                  *sp = (png_byte)(
4337 4338 4339 4340
                      ((((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) ));
4341 4342 4343
                  sp++;
               }
            }
4344

A
Andreas Dilger 已提交
4345
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4346
            {
4347 4348
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4349 4350 4351 4352
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4353
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4354
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4355 4356 4357
                  sp++;
               }
            }
4358

A
Andreas Dilger 已提交
4359 4360
            else if (row_info->bit_depth == 8)
            {
4361 4362
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4363 4364 4365 4366 4367
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4368

G
Guy Schalnat 已提交
4369 4370
            else if (row_info->bit_depth == 16)
            {
4371 4372
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4373
               {
4374
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4375 4376
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4377 4378 4379 4380 4381
                  sp += 2;
               }
            }
            break;
         }
4382 4383 4384

         default:
            break;
G
Guy Schalnat 已提交
4385 4386 4387
      }
   }
}
G
Guy Schalnat 已提交
4388
#endif
G
Guy Schalnat 已提交
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 4450 4451 4452 4453 4454 4455 4456
#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

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

4470
   png_debug(1, "in png_do_expand_palette");
4471

4472
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4473 4474 4475 4476 4477 4478 4479
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4480 4481
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4482
               shift = 7 - (int)((row_width + 7) & 0x07);
4483
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4484
               {
4485
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4486
                     *dp = 1;
4487

G
Guy Schalnat 已提交
4488 4489
                  else
                     *dp = 0;
4490

G
Guy Schalnat 已提交
4491 4492 4493 4494 4495
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4496

G
Guy Schalnat 已提交
4497 4498 4499 4500 4501 4502 4503
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4504

G
Guy Schalnat 已提交
4505 4506
            case 2:
            {
4507 4508
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4509
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4510
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4511
               {
4512
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4513
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4514 4515 4516 4517 4518
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4519

G
Guy Schalnat 已提交
4520 4521 4522 4523 4524 4525 4526
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4527

G
Guy Schalnat 已提交
4528 4529
            case 4:
            {
4530 4531
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4532
               shift = (int)((row_width & 0x01) << 2);
4533
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4534
               {
4535
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4536
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4537 4538 4539 4540 4541
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4542

G
Guy Schalnat 已提交
4543 4544 4545 4546 4547 4548 4549
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4550 4551 4552

            default:
               break;
G
Guy Schalnat 已提交
4553 4554 4555
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4556
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4557
      }
4558

4559
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4560 4561
      {
         {
4562
            if (num_trans > 0)
G
Guy Schalnat 已提交
4563
            {
4564 4565
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
4566

4567
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4568
               {
A
Andreas Dilger 已提交
4569
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4570
                     *dp-- = 0xff;
4571

G
Guy Schalnat 已提交
4572
                  else
4573
                     *dp-- = trans_alpha[*sp];
4574

G
Guy Schalnat 已提交
4575 4576 4577 4578 4579 4580 4581
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4582
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4583 4584 4585
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4586

G
Guy Schalnat 已提交
4587 4588
            else
            {
4589 4590
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4591

4592
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4593 4594 4595 4596 4597 4598
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4599

G
Guy Schalnat 已提交
4600 4601
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4602
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4603 4604 4605 4606 4607 4608 4609 4610
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

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

4623
   png_debug(1, "in png_do_expand");
4624

G
Guy Schalnat 已提交
4625
   {
A
Andreas Dilger 已提交
4626
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4627
      {
4628
         png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
A
Andreas Dilger 已提交
4629 4630

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4631
         {
A
Andreas Dilger 已提交
4632
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4633
            {
A
Andreas Dilger 已提交
4634
               case 1:
G
Guy Schalnat 已提交
4635
               {
4636
                  gray = (png_uint_16)((gray & 0x01) * 0xff);
4637 4638
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4639
                  shift = 7 - (int)((row_width + 7) & 0x07);
4640
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4641
                  {
4642
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4643
                        *dp = 0xff;
4644

A
Andreas Dilger 已提交
4645 4646
                     else
                        *dp = 0;
4647

A
Andreas Dilger 已提交
4648 4649 4650 4651 4652
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4653

A
Andreas Dilger 已提交
4654 4655
                     else
                        shift++;
G
Guy Schalnat 已提交
4656

A
Andreas Dilger 已提交
4657 4658 4659
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4660
               }
4661

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

A
Andreas Dilger 已提交
4679 4680
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4681

A
Andreas Dilger 已提交
4682 4683 4684
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4685
               }
4686

A
Andreas Dilger 已提交
4687
               case 4:
G
Guy Schalnat 已提交
4688
               {
4689
                  gray = (png_uint_16)((gray & 0x0f) * 0x11);
4690 4691
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4692
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4693
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4694
                  {
4695
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
4696 4697 4698 4699 4700 4701
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4702

A
Andreas Dilger 已提交
4703 4704
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4705

A
Andreas Dilger 已提交
4706 4707 4708
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4709
               }
4710 4711 4712

               default:
                  break;
G
Guy Schalnat 已提交
4713
            }
4714

A
Andreas Dilger 已提交
4715 4716
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4717
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4718
         }
A
Andreas Dilger 已提交
4719

4720
         if (trans_color != NULL)
G
Guy Schalnat 已提交
4721
         {
A
Andreas Dilger 已提交
4722
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4723
            {
4724
               gray = gray & 0xff;
4725 4726
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
4727

4728
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4729
               {
A
Andreas Dilger 已提交
4730 4731
                  if (*sp == gray)
                     *dp-- = 0;
4732

A
Andreas Dilger 已提交
4733 4734
                  else
                     *dp-- = 0xff;
4735

A
Andreas Dilger 已提交
4736
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4737
               }
A
Andreas Dilger 已提交
4738
            }
4739

A
Andreas Dilger 已提交
4740 4741
            else if (row_info->bit_depth == 16)
            {
4742 4743
               png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
               png_byte gray_low = (png_byte)(gray & 0xff);
A
Andreas Dilger 已提交
4744 4745
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4746
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4747
               {
4748
                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
A
Andreas Dilger 已提交
4749 4750 4751 4752
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4753

A
Andreas Dilger 已提交
4754 4755 4756 4757 4758
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4759

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

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

G
Guy Schalnat 已提交
4786 4787
               else
                  *dp-- = 0xff;
4788

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

G
Guy Schalnat 已提交
4817 4818 4819 4820 4821
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4822

G
Guy Schalnat 已提交
4823 4824 4825 4826
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4827
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4828 4829 4830 4831 4832
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
4833
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4834
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4835 4836 4837
      }
   }
}
G
Guy Schalnat 已提交
4838
#endif
G
Guy Schalnat 已提交
4839

4840
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4841
/* If the bit depth is 8 and the color type is not a palette type expand the
4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
 * 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

4871
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4872
void /* PRIVATE */
4873
png_do_quantize(png_row_infop row_info, png_bytep row,
4874
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
G
Guy Schalnat 已提交
4875
{
G
Guy Schalnat 已提交
4876
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4877
   png_uint_32 i;
4878
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4879

4880
   png_debug(1, "in png_do_quantize");
4881

4882
   if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4883
   {
4884
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
G
Guy Schalnat 已提交
4885 4886 4887 4888
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4889
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4890 4891 4892 4893 4894
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

4895 4896 4897 4898 4899 4900 4901
            /* 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);
             */
4902 4903 4904 4905 4906 4907 4908 4909
            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 已提交
4910 4911 4912

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

G
Guy Schalnat 已提交
4914 4915 4916
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4917
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4918
      }
4919

G
Guy Schalnat 已提交
4920
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4921
         palette_lookup != NULL)
G
Guy Schalnat 已提交
4922 4923 4924 4925
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4926
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4927 4928 4929 4930 4931 4932
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

4933 4934 4935 4936 4937 4938 4939 4940
            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 已提交
4941 4942 4943

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

G
Guy Schalnat 已提交
4945 4946 4947
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4948
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4949
      }
4950

G
Guy Schalnat 已提交
4951
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4952
         quantize_lookup)
G
Guy Schalnat 已提交
4953
      {
G
Guy Schalnat 已提交
4954
         sp = row;
4955

4956
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
4957
         {
4958
            *sp = quantize_lookup[*sp];
G
Guy Schalnat 已提交
4959 4960 4961 4962
         }
      }
   }
}
4963
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
4964
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
G
Guy Schalnat 已提交
4965

4966
#ifdef PNG_MNG_FEATURES_SUPPORTED
4967
/* Undoes intrapixel differencing  */
4968 4969 4970
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
4971
   png_debug(1, "in png_do_read_intrapixel");
4972

4973 4974 4975 4976 4977
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
4978

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

4987 4988
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
4989

4990 4991 4992 4993 4994
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4995 4996
            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
4997 4998 4999 5000 5001 5002 5003 5004 5005
         }
      }
      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;
5006

5007 5008
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
5009

5010 5011 5012 5013 5014
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
5015 5016 5017
            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);
5018 5019
            png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
            png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
5020
            *(rp    ) = (png_byte)((red >> 8) & 0xff);
5021 5022 5023
            *(rp + 1) = (png_byte)(red & 0xff);
            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
            *(rp + 5) = (png_byte)(blue & 0xff);
5024 5025 5026 5027 5028
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
5029
#endif /* PNG_READ_SUPPORTED */