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

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

19
#include "pngpriv.h"
20

21 22
#ifdef PNG_READ_SUPPORTED

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
png_set_background(png_structp png_ptr,
126
    png_const_color_16p background_color, int background_gamma_code,
G
[devel]  
Glenn Randers-Pehrson 已提交
127 128 129 130 131 132 133
    int need_expand, double background_gamma)
{
   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
}
#  endif  /* FLOATING_POINT */
#endif /* READ_BACKGROUND */
G
Guy Schalnat 已提交
134

135
#ifdef PNG_READ_16_TO_8_SUPPORTED
136
/* Strip 16 bit depth files to 8 bit depth */
137
void PNGAPI
G
Guy Schalnat 已提交
138
png_set_strip_16(png_structp png_ptr)
G
Guy Schalnat 已提交
139
{
140
   png_debug(1, "in png_set_strip_16");
141

142 143
   if (png_ptr == NULL)
      return;
144

G
Guy Schalnat 已提交
145 146
   png_ptr->transformations |= PNG_16_TO_8;
}
G
Guy Schalnat 已提交
147
#endif
G
Guy Schalnat 已提交
148

149
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
150
void PNGAPI
A
Andreas Dilger 已提交
151 152
png_set_strip_alpha(png_structp png_ptr)
{
153
   png_debug(1, "in png_set_strip_alpha");
154

155 156
   if (png_ptr == NULL)
      return;
157

158
   png_ptr->transformations |= PNG_STRIP_ALPHA;
A
Andreas Dilger 已提交
159 160 161
}
#endif

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 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
#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 */

224 225 226 227 228 229 230 231 232 233 234 235 236
#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;

237
   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
238

239
   /* Validate the value to ensure it is in a reasonable range. The value
240 241 242 243 244
    * 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.
    */
245
   if (output_gamma < 70000 || output_gamma > 300000)
246
      png_error(png_ptr, "output gamma out of expected range");
247

248
   /* The default file gamma is the inverse of the output gamma; the output
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 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
    * 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;

312
   /* Finally, if pre-multiplying, set the background fields to achieve the
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    * 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)
{
338 339
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
      output_gamma));
340 341 342 343
}
#  endif
#endif

344
#ifdef PNG_READ_QUANTIZE_SUPPORTED
A
Andreas Dilger 已提交
345
/* Dither file to 8 bit.  Supply a palette, the current number
346 347 348
 * 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
349 350
 * modified to fit in the maximum number.  "full_quantize" indicates
 * whether we need a quantizing cube set up for RGB images, or if we
351 352
 * simply are reducing the number of colors in a paletted image.
 */
G
Guy Schalnat 已提交
353 354

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
355
{
G
Guy Schalnat 已提交
356
   struct png_dsort_struct FAR * next;
G
Guy Schalnat 已提交
357 358
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
359 360 361
} png_dsort;
typedef png_dsort FAR *       png_dsortp;
typedef png_dsort FAR * FAR * png_dsortpp;
G
Guy Schalnat 已提交
362

363
void PNGAPI
364
png_set_quantize(png_structp png_ptr, png_colorp palette,
365
    int num_palette, int maximum_colors, png_const_uint_16p histogram,
366
    int full_quantize)
G
Guy Schalnat 已提交
367
{
368
   png_debug(1, "in png_set_quantize");
369

370 371
   if (png_ptr == NULL)
      return;
372

373
   png_ptr->transformations |= PNG_QUANTIZE;
G
Guy Schalnat 已提交
374

375
   if (!full_quantize)
G
Guy Schalnat 已提交
376 377 378
   {
      int i;

379
      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
380
          (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
381
      for (i = 0; i < num_palette; i++)
382
         png_ptr->quantize_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
383 384 385 386
   }

   if (num_palette > maximum_colors)
   {
A
Andreas Dilger 已提交
387
      if (histogram != NULL)
G
Guy Schalnat 已提交
388
      {
A
Andreas Dilger 已提交
389
         /* This is easy enough, just throw out the least used colors.
390 391
          * Perhaps not the best solution, but good enough.
          */
G
Guy Schalnat 已提交
392 393 394

         int i;

395
         /* Initialize an array to sort colors */
396
         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
397
             (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
398

399
         /* Initialize the quantize_sort array */
G
Guy Schalnat 已提交
400
         for (i = 0; i < num_palette; i++)
401
            png_ptr->quantize_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
402

A
Andreas Dilger 已提交
403
         /* Find the least used palette entries by starting a
404 405 406 407 408
          * 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 已提交
409 410 411

         for (i = num_palette - 1; i >= maximum_colors; i--)
         {
412
            int done; /* To stop early if the list is pre-sorted */
G
Guy Schalnat 已提交
413
            int j;
G
Guy Schalnat 已提交
414 415 416 417

            done = 1;
            for (j = 0; j < i; j++)
            {
418 419
               if (histogram[png_ptr->quantize_sort[j]]
                   < histogram[png_ptr->quantize_sort[j + 1]])
G
Guy Schalnat 已提交
420 421 422
               {
                  png_byte t;

423 424 425
                  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 已提交
426 427 428
                  done = 0;
               }
            }
429

G
Guy Schalnat 已提交
430 431 432 433
            if (done)
               break;
         }

434
         /* Swap the palette around, and set up a table, if necessary */
435
         if (full_quantize)
G
Guy Schalnat 已提交
436
         {
437
            int j = num_palette;
G
Guy Schalnat 已提交
438

439 440 441
            /* Put all the useful colors within the max, but don't
             * move the others.
             */
442
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
443
            {
444
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
445 446 447
               {
                  do
                     j--;
448
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
449

G
Guy Schalnat 已提交
450 451
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
452
            }
G
Guy Schalnat 已提交
453 454 455
         }
         else
         {
456
            int j = num_palette;
G
Guy Schalnat 已提交
457

458 459 460
            /* Move all the used colors inside the max limit, and
             * develop a translation table.
             */
461
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
462
            {
463
               /* Only move the colors we need to */
464
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
465 466 467 468 469
               {
                  png_color tmp_color;

                  do
                     j--;
470
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
471 472 473 474

                  tmp_color = palette[j];
                  palette[j] = palette[i];
                  palette[i] = tmp_color;
475
                  /* Indicate where the color went */
476 477
                  png_ptr->quantize_index[j] = (png_byte)i;
                  png_ptr->quantize_index[i] = (png_byte)j;
G
Guy Schalnat 已提交
478 479
               }
            }
A
Andreas Dilger 已提交
480

481
            /* Find closest color for those colors we are not using */
G
Guy Schalnat 已提交
482 483
            for (i = 0; i < num_palette; i++)
            {
484
               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
G
Guy Schalnat 已提交
485
               {
A
Andreas Dilger 已提交
486
                  int min_d, k, min_k, d_index;
G
Guy Schalnat 已提交
487

488
                  /* Find the closest color to one we threw out */
489
                  d_index = png_ptr->quantize_index[i];
A
Andreas Dilger 已提交
490 491
                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
                  for (k = 1, min_k = 0; k < maximum_colors; k++)
G
Guy Schalnat 已提交
492 493 494
                  {
                     int d;

A
Andreas Dilger 已提交
495
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
496 497 498 499

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
500
                        min_k = k;
G
Guy Schalnat 已提交
501 502
                     }
                  }
503
                  /* Point to closest color */
504
                  png_ptr->quantize_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
505 506 507
               }
            }
         }
508 509
         png_free(png_ptr, png_ptr->quantize_sort);
         png_ptr->quantize_sort = NULL;
G
Guy Schalnat 已提交
510 511 512
      }
      else
      {
A
Andreas Dilger 已提交
513
         /* This is much harder to do simply (and quickly).  Perhaps
514 515 516 517 518 519 520
          * 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 已提交
521 522 523
         int i;
         int max_d;
         int num_new_palette;
524
         png_dsortp t;
G
Guy Schalnat 已提交
525
         png_dsortpp hash;
526

527
         t = NULL;
G
Guy Schalnat 已提交
528

529
         /* Initialize palette index arrays */
530
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
531
             (png_uint_32)(num_palette * png_sizeof(png_byte)));
532
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
533
             (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
534

535
         /* Initialize the sort array */
G
Guy Schalnat 已提交
536 537
         for (i = 0; i < num_palette; i++)
         {
538 539
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
540 541
         }

542
         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
543
             png_sizeof(png_dsortp)));
G
Guy Schalnat 已提交
544 545 546

         num_new_palette = num_palette;

547 548 549 550 551 552 553 554
         /* 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 已提交
555 556
         max_d = 96;

G
Guy Schalnat 已提交
557
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
558 559 560 561 562 563 564 565 566
         {
            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 已提交
567
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
568 569 570 571

                  if (d <= max_d)
                  {

572
                     t = (png_dsortp)png_malloc_warn(png_ptr,
573
                         (png_uint_32)(png_sizeof(png_dsort)));
574

575 576
                     if (t == NULL)
                         break;
577

G
Guy Schalnat 已提交
578
                     t->next = hash[d];
G
Guy Schalnat 已提交
579 580
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
581 582 583
                     hash[d] = t;
                  }
               }
584 585
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
586 587
            }

588
            if (t != NULL)
G
Guy Schalnat 已提交
589 590
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
591
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
592
               {
G
Guy Schalnat 已提交
593
                  png_dsortp p;
G
Guy Schalnat 已提交
594 595 596

                  for (p = hash[i]; p; p = p->next)
                  {
597
                     if ((int)png_ptr->index_to_palette[p->left]
598 599 600
                         < num_new_palette &&
                         (int)png_ptr->index_to_palette[p->right]
                         < num_new_palette)
G
Guy Schalnat 已提交
601 602 603
                     {
                        int j, next_j;

604
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
605 606 607 608 609 610 611 612 613 614 615
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
616
                        palette[png_ptr->index_to_palette[j]]
617
                            = palette[num_new_palette];
618
                        if (!full_quantize)
G
Guy Schalnat 已提交
619 620 621 622 623
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
624
                              if (png_ptr->quantize_index[k] ==
625
                                  png_ptr->index_to_palette[j])
626
                                 png_ptr->quantize_index[k] =
627
                                     png_ptr->index_to_palette[next_j];
628

629
                              if ((int)png_ptr->quantize_index[k] ==
630
                                  num_new_palette)
631
                                 png_ptr->quantize_index[k] =
632
                                     png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
633 634 635
                           }
                        }

636
                        png_ptr->index_to_palette[png_ptr->palette_to_index
637
                            [num_new_palette]] = png_ptr->index_to_palette[j];
638

639
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
640
                            = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
641

642 643
                        png_ptr->index_to_palette[j] =
                            (png_byte)num_new_palette;
644

645 646
                        png_ptr->palette_to_index[num_new_palette] =
                            (png_byte)j;
G
Guy Schalnat 已提交
647 648 649 650 651 652 653 654 655 656 657
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

            for (i = 0; i < 769; i++)
            {
A
Andreas Dilger 已提交
658
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
659
               {
660
                  png_dsortp p = hash[i];
G
Guy Schalnat 已提交
661 662 663
                  while (p)
                  {
                     t = p->next;
A
Andreas Dilger 已提交
664
                     png_free(png_ptr, p);
G
Guy Schalnat 已提交
665 666 667 668 669 670 671
                     p = t;
                  }
               }
               hash[i] = 0;
            }
            max_d += 96;
         }
A
Andreas Dilger 已提交
672
         png_free(png_ptr, hash);
673 674
         png_free(png_ptr, png_ptr->palette_to_index);
         png_free(png_ptr, png_ptr->index_to_palette);
675 676
         png_ptr->palette_to_index = NULL;
         png_ptr->index_to_palette = NULL;
G
Guy Schalnat 已提交
677 678 679
      }
      num_palette = maximum_colors;
   }
A
Andreas Dilger 已提交
680
   if (png_ptr->palette == NULL)
G
Guy Schalnat 已提交
681
   {
G
Guy Schalnat 已提交
682 683
      png_ptr->palette = palette;
   }
G
Guy Schalnat 已提交
684
   png_ptr->num_palette = (png_uint_16)num_palette;
G
Guy Schalnat 已提交
685

686
   if (full_quantize)
G
Guy Schalnat 已提交
687 688
   {
      int i;
G
Guy Schalnat 已提交
689
      png_bytep distance;
690 691 692 693 694
      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);
695
      png_size_t num_entries = ((png_size_t)1 << total_bits);
G
Guy Schalnat 已提交
696

697
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
698
          (png_uint_32)(num_entries * png_sizeof(png_byte)));
699

700
      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
701
          png_sizeof(png_byte)));
702

703
      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
704 705 706

      for (i = 0; i < num_palette; i++)
      {
707
         int ir, ig, ib;
708 709 710
         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 已提交
711 712 713

         for (ir = 0; ir < num_red; ir++)
         {
714 715
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
716 717
            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
                PNG_QUANTIZE_GREEN_BITS));
G
Guy Schalnat 已提交
718 719

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
720
            {
721 722
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
723 724
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
725
               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
G
Guy Schalnat 已提交
726 727

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
728
               {
729
                  int d_index = index_g | ib;
730 731
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
732 733
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
734

735
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
736
                  {
A
Andreas Dilger 已提交
737 738
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
739 740
                  }
               }
741 742 743
            }
         }
      }
G
Guy Schalnat 已提交
744

A
Andreas Dilger 已提交
745
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
746 747
   }
}
748
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
749

G
[devel]  
Glenn Randers-Pehrson 已提交
750 751 752 753 754 755
#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");
756

757 758
   if (png_ptr == NULL)
      return;
759

760 761 762 763
   /* New in libpng-1.5.3 - reserve particular negative values as flags. */
   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);

764 765 766 767 768
#if PNG_LIBPNG_VER >= 10600
   /* Checking the gamma values for being >0 was added in 1.5.3 along with the
    * 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
769
    * was being used; however, png_set_background itself accepted and must still
770 771 772
    * 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
773
    * undocumented API feature) it will not be made until libpng-1.6.0.
774 775
    */
   if (file_gamma <= 0)
776
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
777 778

   if (scrn_gamma <= 0)
779
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
780 781 782 783 784 785
#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 已提交
786 787
   png_ptr->gamma = file_gamma;
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
788
}
G
[devel]  
Glenn Randers-Pehrson 已提交
789 790 791 792 793

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
{
794 795
   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 已提交
796 797 798
}
#  endif /* FLOATING_POINT_SUPPORTED */
#endif /* READ_GAMMA */
G
Guy Schalnat 已提交
799

800
#ifdef PNG_READ_EXPAND_SUPPORTED
801
/* Expand paletted images to RGB, expand grayscale images of
802
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
803 804
 * to alpha channels.
 */
805
void PNGAPI
G
Guy Schalnat 已提交
806
png_set_expand(png_structp png_ptr)
G
Guy Schalnat 已提交
807
{
808
   png_debug(1, "in png_set_expand");
809

810 811
   if (png_ptr == NULL)
      return;
812

813
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
814
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
G
Guy Schalnat 已提交
815
}
816 817 818 819 820 821 822 823 824 825 826 827 828

/* 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.
829
 *
830 831 832
 *  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().
833 834 835
 */

/* Expand paletted images to RGB. */
836
void PNGAPI
837 838
png_set_palette_to_rgb(png_structp png_ptr)
{
839
   png_debug(1, "in png_set_palette_to_rgb");
840

841 842
   if (png_ptr == NULL)
      return;
843

844
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
845
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
846 847 848 849 850 851
}

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

854 855
   if (png_ptr == NULL)
      return;
856

857 858
   png_ptr->transformations |= PNG_EXPAND;
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
859 860
}

861 862


863
/* Expand tRNS chunks to alpha channels. */
864
void PNGAPI
865 866
png_set_tRNS_to_alpha(png_structp png_ptr)
{
867
   png_debug(1, "in png_set_tRNS_to_alpha");
868

869
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
870
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
871 872
}
#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
G
Guy Schalnat 已提交
873

874 875 876 877 878 879 880 881 882 883 884 885 886 887
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16 bit channels, expand the tRNS chunk too (because otherwise
 * 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;
888 889 890

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

894
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
895
void PNGAPI
G
Guy Schalnat 已提交
896
png_set_gray_to_rgb(png_structp png_ptr)
G
Guy Schalnat 已提交
897
{
898
   png_debug(1, "in png_set_gray_to_rgb");
899

900 901 902 903 904 905 906
   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 已提交
907
}
G
Guy Schalnat 已提交
908
#endif
G
Guy Schalnat 已提交
909

910
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
911
void PNGFAPI
912
png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
913
    png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
914
{
915
   png_debug(1, "in png_set_rgb_to_gray");
916

917 918
   if (png_ptr == NULL)
      return;
919

920 921
   switch(error_action)
   {
922 923 924
      case 1:
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
         break;
925

926 927 928
      case 2:
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
929

930 931
      case 3:
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
932 933 934
         break;

      default:
935 936
         png_error(png_ptr, "invalid error action to rgb_to_gray");
         break;
937 938
   }
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
939
#ifdef PNG_READ_EXPAND_SUPPORTED
940 941 942
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
943 944
      png_warning(png_ptr,
        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
945

946 947 948 949
      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
   }
#endif
   {
950
      png_uint_16 red_int, green_int;
951
      if (red < 0 || green < 0)
952
      {
953 954
         red_int   =  6968; /* .212671 * 32768 + .5 */
         green_int = 23434; /* .715160 * 32768 + .5 */
955
      }
956

957
      else if (red + green < 100000L)
958
      {
959 960
         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
961
      }
962

963
      else
964 965
      {
         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
966 967
         red_int   =  6968;
         green_int = 23434;
968
      }
969

970 971
      png_ptr->rgb_to_gray_red_coeff   = red_int;
      png_ptr->rgb_to_gray_green_coeff = green_int;
972
      png_ptr->rgb_to_gray_blue_coeff  =
973
          (png_uint_16)(32768 - red_int - green_int);
974
   }
A
Andreas Dilger 已提交
975
}
976 977 978 979 980 981 982 983

#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 已提交
984
   double green)
985 986 987 988
{
   if (png_ptr == NULL)
      return;

G
[devel]  
Glenn Randers-Pehrson 已提交
989 990 991
   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"));
992 993 994
}
#endif /* FLOATING POINT */

A
Andreas Dilger 已提交
995 996
#endif

997
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
998
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
999
void PNGAPI
1000
png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
1001
    read_user_transform_fn)
1002
{
1003
   png_debug(1, "in png_set_read_user_transform_fn");
1004

1005 1006
   if (png_ptr == NULL)
      return;
1007

1008
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1009 1010
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1011
#endif
1012 1013 1014
}
#endif

1015
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
#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 已提交
1037
/* Initialize everything needed for the read.  This includes modifying
1038 1039
 * the palette.
 */
1040 1041 1042 1043 1044 1045 1046 1047

/*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 已提交
1048
{
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
   /* 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;
1059

1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
   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 已提交
1087

G
Guy Schalnat 已提交
1088
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1089 1090 1091 1092
   /* 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.
    */
1093

1094 1095
   /* The following code cannot be entered in the alpha pre-multiplication case
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1096 1097
    */
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1098
       (png_ptr->transformations & PNG_EXPAND))
1099
   {
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
      {
         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)
{
   /* Added to libpng-1.5.3: check the color type to determine whether there
    * 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;
1138

1139 1140
   /* If no alpha we can optimize. */
   if (!input_has_alpha)
1141
   {
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
      /* 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);
1153 1154
   }

1155 1156 1157 1158 1159 1160 1161 1162 1163
#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.
    */
1164
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1165 1166 1167
       (png_ptr->transformations & PNG_EXPAND) &&
       !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
       /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
1168 1169
   {
      {
1170
         /* Expand background and tRNS chunks */
G
Guy Schalnat 已提交
1171 1172 1173
         switch (png_ptr->bit_depth)
         {
            case 1:
G
Guy Schalnat 已提交
1174
               png_ptr->background.gray *= (png_uint_16)0xff;
1175
               png_ptr->background.red = png_ptr->background.green
1176
                   =  png_ptr->background.blue = png_ptr->background.gray;
1177 1178
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
1179 1180
                 png_ptr->trans_color.gray *= (png_uint_16)0xff;
                 png_ptr->trans_color.red = png_ptr->trans_color.green
1181
                     = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
1182
               }
G
Guy Schalnat 已提交
1183
               break;
1184

G
Guy Schalnat 已提交
1185
            case 2:
G
Guy Schalnat 已提交
1186
               png_ptr->background.gray *= (png_uint_16)0x55;
1187
               png_ptr->background.red = png_ptr->background.green
1188
                   = png_ptr->background.blue = png_ptr->background.gray;
1189 1190
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
1191 1192 1193
                  png_ptr->trans_color.gray *= (png_uint_16)0x55;
                  png_ptr->trans_color.red = png_ptr->trans_color.green
                      = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
1194
               }
G
Guy Schalnat 已提交
1195
               break;
1196

G
Guy Schalnat 已提交
1197
            case 4:
G
Guy Schalnat 已提交
1198
               png_ptr->background.gray *= (png_uint_16)0x11;
1199
               png_ptr->background.red = png_ptr->background.green
1200
                   = png_ptr->background.blue = png_ptr->background.gray;
1201 1202
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
1203 1204 1205
                  png_ptr->trans_color.gray *= (png_uint_16)0x11;
                  png_ptr->trans_color.red = png_ptr->trans_color.green
                      = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
1206
               }
G
Guy Schalnat 已提交
1207
               break;
1208

1209 1210
            default:

G
Guy Schalnat 已提交
1211
            case 8:
1212

G
Guy Schalnat 已提交
1213
            case 16:
1214
               png_ptr->background.red = png_ptr->background.green
1215
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1216 1217 1218
               break;
         }
      }
1219 1220 1221
   } /* background expand and (therefore) no alpha association. */
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
}
1222

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
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
   /* Prior to 1.5.3 these tests were performed from png_set_gamma, 1.5.3 adds
    * png_set_alpha_mode and this is another source for a default file gamma so
    * the test needs to be performed later - here.  In addition prior to 1.5.3
    * 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;
1248

1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
      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 已提交
1260
      }
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290

      else if (png_ptr->screen_gamma != 0)
         /* The converse - assume the file matches the screen, note that this
          * perhaps undesireable default can (from 1.5.3) be changed by calling
          * 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,
          * prior to 1.5.3
          */
         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 已提交
1291
   }
G
Guy Schalnat 已提交
1292
#endif
G
Guy Schalnat 已提交
1293

1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
   /* 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
    *  9) PNG_16_TO_8 (strip16)
    * 10) PNG_QUANTIZE (converts to palette)
    * 11) PNG_EXPAND_16 [NOTE: temporarily moved to (3) for accuracy!]
    * 12) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
    * 13) PNG_INVERT_MONO
    * 14) PNG_SHIFT
    * 15) PNG_PACK
    * 16) PNG_BGR
    * 17) PNG_PACKSWAP
    * 18) PNG_FILLER (includes PNG_ADD_ALPHA)
    * 19) PNG_INVERT_ALPHA
    * 20) PNG_SWAP_ALPHA
    * 21) PNG_SWAP_BYTES
    * 22) PNG_USER_TRANSFORM [must be last]
    */
#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;

      /* Kill the tRNS chunk itself too.  Prior to 1.5.3 this did not happen
       * 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
       * get.)  This makes the behavior consistent from 1.5.3:
       */
      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 已提交
1355
#endif
1356

1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
#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.
    *
    * NOTE: this code needs to be revised to avoid the complexity and
    * 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
       * the file was greyscale the background value is gray.
       */
      if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   }

   else if (png_ptr->transformations & PNG_COMPOSE)
1385
   {
1386 1387 1388 1389 1390 1391
      /* 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)
1392
      {
1393 1394 1395 1396 1397 1398
         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;
         }
1399
      }
1400
   }
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
#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);
1416

1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
   else
      png_init_rgb_transformations(png_ptr);

   /* 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
    * 1.5.3 betas simply to enable external critique and testing (i.e. to
    * 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.
    *
    * In 1.5.3 this is addressed below by an additional check on the individual
    * 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)
            || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
               && png_gamma_significant(png_ptr->background_gamma))))
      || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
         && png_gamma_significant(png_ptr->screen_gamma))
      )
G
Guy Schalnat 已提交
1459
   {
1460
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1461

1462
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1463
      if (png_ptr->transformations & PNG_COMPOSE)
G
Guy Schalnat 已提交
1464
      {
1465
         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1466
         {
1467 1468 1469
            /* 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 已提交
1470
            png_color back, back_1;
1471 1472 1473
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1474 1475
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1476

A
Andreas Dilger 已提交
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
               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 已提交
1487
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1488

1489 1490 1491 1492
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
G
[devel]  
Glenn Randers-Pehrson 已提交
1493
                     gs = PNG_FP_1;
1494
                     break;
1495

1496
                  case PNG_BACKGROUND_GAMMA_FILE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1497 1498
                     g = png_reciprocal(png_ptr->gamma);
                     gs = png_reciprocal2(png_ptr->gamma,
1499
                        png_ptr->screen_gamma);
1500
                     break;
1501

1502
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1503 1504
                     g = png_reciprocal(png_ptr->background_gamma);
                     gs = png_reciprocal2(png_ptr->background_gamma,
1505
                        png_ptr->screen_gamma);
1506 1507
                     break;
                  default:
G
[devel]  
Glenn Randers-Pehrson 已提交
1508 1509
                     g = PNG_FP_1;    /* back_1 */
                     gs = PNG_FP_1;   /* back */
1510
                     break;
1511
               }
A
Andreas Dilger 已提交
1512

1513
               if (png_gamma_significant(gs))
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
               {
                  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 已提交
1524
               {
1525
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1526
                  back.green = (png_byte)png_ptr->background.green;
1527
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1528
               }
1529

1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
               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 已提交
1540 1541
               else
               {
1542 1543 1544
                  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 已提交
1545 1546
               }
            }
1547

G
Guy Schalnat 已提交
1548 1549
            for (i = 0; i < num_palette; i++)
            {
1550 1551
               if (i < (int)png_ptr->num_trans &&
                   png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1552
               {
1553
                  if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1554 1555 1556
                  {
                     palette[i] = back;
                  }
1557
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
G
Guy Schalnat 已提交
1558
                  {
A
Andreas Dilger 已提交
1559
                     png_byte v, w;
G
Guy Schalnat 已提交
1560 1561

                     v = png_ptr->gamma_to_1[palette[i].red];
1562
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
1563 1564 1565
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
1566
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
G
Guy Schalnat 已提交
1567 1568 1569
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
1570
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
                     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];
               }
            }
1581 1582 1583

            /* Prevent the transformations being done again.
             *
1584
             * NOTE: this is highly dubious; it zaps the transformations in
1585 1586
             * place.  This seems inconsistent with the general treatment of the
             * transformations elsewhere.
1587
             */
1588 1589
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1590

1591
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1592
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1593
         {
1594 1595
            png_fixed_point g = PNG_FP_1;
            png_fixed_point gs = PNG_FP_1;
G
Guy Schalnat 已提交
1596 1597

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1598
            {
G
Guy Schalnat 已提交
1599
               case PNG_BACKGROUND_GAMMA_SCREEN:
G
[devel]  
Glenn Randers-Pehrson 已提交
1600 1601
                  g = png_ptr->screen_gamma;
                  /* gs = PNG_FP_1; */
G
Guy Schalnat 已提交
1602
                  break;
1603

G
Guy Schalnat 已提交
1604
               case PNG_BACKGROUND_GAMMA_FILE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1605 1606
                  g = png_reciprocal(png_ptr->gamma);
                  gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1607
                  break;
1608

G
Guy Schalnat 已提交
1609
               case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1610 1611
                  g = png_reciprocal(png_ptr->background_gamma);
                  gs = png_reciprocal2(png_ptr->background_gamma,
1612
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1613
                  break;
1614 1615

               default:
1616
                  png_error(png_ptr, "invalid background gamma type");
G
Guy Schalnat 已提交
1617 1618
            }

G
[devel]  
Glenn Randers-Pehrson 已提交
1619
            png_ptr->background_1.gray = png_gamma_correct(png_ptr,
1620
                png_ptr->background.gray, g);
1621

G
[devel]  
Glenn Randers-Pehrson 已提交
1622 1623
            png_ptr->background.gray = png_gamma_correct(png_ptr,
                png_ptr->background.gray, gs);
1624

1625 1626 1627
            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 已提交
1628
            {
1629
               /* RGB or RGBA with color background */
G
[devel]  
Glenn Randers-Pehrson 已提交
1630 1631
               png_ptr->background_1.red = png_gamma_correct(png_ptr,
                   png_ptr->background.red, g);
1632

G
[devel]  
Glenn Randers-Pehrson 已提交
1633 1634
               png_ptr->background_1.green = png_gamma_correct(png_ptr,
                   png_ptr->background.green, g);
1635

G
[devel]  
Glenn Randers-Pehrson 已提交
1636 1637
               png_ptr->background_1.blue = png_gamma_correct(png_ptr,
                   png_ptr->background.blue, g);
1638

G
[devel]  
Glenn Randers-Pehrson 已提交
1639 1640
               png_ptr->background.red = png_gamma_correct(png_ptr,
                   png_ptr->background.red, gs);
1641

G
[devel]  
Glenn Randers-Pehrson 已提交
1642 1643
               png_ptr->background.green = png_gamma_correct(png_ptr,
                   png_ptr->background.green, gs);
1644

G
[devel]  
Glenn Randers-Pehrson 已提交
1645 1646
               png_ptr->background.blue = png_gamma_correct(png_ptr,
                   png_ptr->background.blue, gs);
G
Guy Schalnat 已提交
1647
            }
1648

G
Guy Schalnat 已提交
1649 1650
            else
            {
1651 1652
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
1653
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1654

1655
               png_ptr->background.red = png_ptr->background.green
1656
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1657
            }
1658 1659 1660
         } /* color_type != PNG_COLOR_TYPE_PALETTE */
      }/* png_ptr->transformations & PNG_BACKGROUND */

G
Guy Schalnat 已提交
1661
      else
1662
      /* Transformation does not include PNG_BACKGROUND */
1663
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1664
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1665
      {
1666 1667 1668
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1669

1670 1671 1672
         /*NOTE: there are other transformations that should probably be in here
          * too.
          */
G
Guy Schalnat 已提交
1673 1674 1675 1676 1677 1678
         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];
         }
1679

1680 1681
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
1682
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
G
Guy Schalnat 已提交
1683
   }
1684
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1685
   else
G
Guy Schalnat 已提交
1686
#endif
G
[devel]  
Glenn Randers-Pehrson 已提交
1687
#endif /* PNG_READ_GAMMA_SUPPORTED */
1688

1689
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1690 1691 1692
   /* 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 已提交
1693
   {
1694 1695
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
1696
      png_color back;
1697
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
1698 1699 1700 1701 1702

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

1703
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1704
      {
1705
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1706 1707 1708
         {
            palette[i] = back;
         }
1709

1710
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1711
         {
1712
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1713
            png_composite(palette[i].red, palette[i].red,
1714
                png_ptr->trans_alpha[i], back.red);
1715

A
Andreas Dilger 已提交
1716
            png_composite(palette[i].green, palette[i].green,
1717
                png_ptr->trans_alpha[i], back.green);
1718

A
Andreas Dilger 已提交
1719
            png_composite(palette[i].blue, palette[i].blue,
1720
                png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1721 1722
         }
      }
1723

1724
      png_ptr->transformations &= ~PNG_COMPOSE;
G
Guy Schalnat 已提交
1725
   }
1726
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
1727

1728
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
1729
   if ((png_ptr->transformations & PNG_SHIFT) &&
1730
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1731
   {
1732 1733 1734 1735 1736
      png_uint_16 i;
      png_uint_16 istop = png_ptr->num_palette;
      int sr = 8 - png_ptr->sig_bit.red;
      int sg = 8 - png_ptr->sig_bit.green;
      int sb = 8 - png_ptr->sig_bit.blue;
G
Guy Schalnat 已提交
1737 1738 1739

      if (sr < 0 || sr > 8)
         sr = 0;
1740

G
Guy Schalnat 已提交
1741 1742
      if (sg < 0 || sg > 8)
         sg = 0;
1743

G
Guy Schalnat 已提交
1744 1745
      if (sb < 0 || sb > 8)
         sb = 0;
1746

1747
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1748 1749 1750 1751 1752 1753
      {
         png_ptr->palette[i].red >>= sr;
         png_ptr->palette[i].green >>= sg;
         png_ptr->palette[i].blue >>= sb;
      }
   }
1754
#endif  /* PNG_READ_SHIFT_SUPPORTED */
G
Guy Schalnat 已提交
1755 1756
}

A
Andreas Dilger 已提交
1757
/* Modify the info structure to reflect the transformations.  The
1758 1759 1760
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1761
void /* PRIVATE */
G
Guy Schalnat 已提交
1762
png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1763
{
1764
   png_debug(1, "in png_read_transform_info");
1765

1766
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
1767
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1768
   {
A
Andreas Dilger 已提交
1769 1770
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
1771
         if (png_ptr->num_trans &&
1772
             (png_ptr->transformations & PNG_EXPAND_tRNS))
A
Andreas Dilger 已提交
1773
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1774

A
Andreas Dilger 已提交
1775 1776
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1777

G
Guy Schalnat 已提交
1778
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1779 1780 1781 1782 1783
         info_ptr->num_trans = 0;
      }
      else
      {
         if (png_ptr->num_trans)
1784 1785
         {
            if (png_ptr->transformations & PNG_EXPAND_tRNS)
1786
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1787
         }
A
Andreas Dilger 已提交
1788 1789
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1790

A
Andreas Dilger 已提交
1791 1792
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1793 1794 1795
   }
#endif

1796 1797 1798 1799 1800 1801 1802 1803
#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

1804 1805 1806 1807 1808 1809
#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 已提交
1810 1811 1812
      info_ptr->background = png_ptr->background;
#endif

1813
#ifdef PNG_READ_GAMMA_SUPPORTED
1814 1815 1816 1817 1818 1819
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.3),
    * 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;
1820
#endif
1821

1822
#ifdef PNG_READ_16_TO_8_SUPPORTED
1823
#ifdef PNG_READ_16BIT_SUPPORTED
1824
   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
G
Guy Schalnat 已提交
1825
      info_ptr->bit_depth = 8;
1826 1827
#else
   /* Force chopping 16-bit input down to 8 */
1828 1829 1830 1831 1832
   if (info_ptr->bit_depth == 16)
   {
      png_ptr->transformations |=PNG_16_TO_8;
      info_ptr->bit_depth = 8;
   }
1833
#endif
G
Guy Schalnat 已提交
1834 1835
#endif

1836
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1837 1838 1839 1840
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
#endif

1841
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1842 1843 1844 1845
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
#endif

1846 1847
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
1848 1849
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1850 1851
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
1852 1853 1854
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
1855
   }
G
Guy Schalnat 已提交
1856 1857
#endif

1858
#ifdef PNG_READ_PACK_SUPPORTED
1859
   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
1860 1861 1862
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
1863
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1864
      info_ptr->channels = 1;
1865

G
Guy Schalnat 已提交
1866 1867
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
1868

G
Guy Schalnat 已提交
1869 1870
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
1871

1872
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1873
   if (png_ptr->transformations & PNG_STRIP_ALPHA)
1874
   {
A
Andreas Dilger 已提交
1875
      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1876 1877
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
1878 1879
#endif

1880 1881 1882
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

1883
#ifdef PNG_READ_FILLER_SUPPORTED
1884
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1885 1886 1887
   if ((png_ptr->transformations & PNG_FILLER) &&
       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1888
   {
1889
      info_ptr->channels++;
1890
      /* If adding a true alpha channel not just filler */
1891
      if (png_ptr->transformations & PNG_ADD_ALPHA)
1892
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1893
   }
A
Andreas Dilger 已提交
1894 1895
#endif

1896 1897
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1898
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
1899 1900
   {
      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1901
         info_ptr->bit_depth = png_ptr->user_transform_depth;
1902

1903
      if (info_ptr->channels < png_ptr->user_transform_channels)
1904
         info_ptr->channels = png_ptr->user_transform_channels;
1905
   }
1906 1907
#endif

G
Guy Schalnat 已提交
1908
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1909
       info_ptr->bit_depth);
1910

1911
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1912

1913
#ifndef PNG_READ_EXPAND_SUPPORTED
1914
   if (png_ptr)
1915 1916
      return;
#endif
G
Guy Schalnat 已提交
1917 1918
}

1919 1920 1921 1922
/* 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.
 */
1923
void /* PRIVATE */
G
Guy Schalnat 已提交
1924
png_do_read_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
1925
{
1926
   png_debug(1, "in png_do_read_transformations");
1927

A
Andreas Dilger 已提交
1928
   if (png_ptr->row_buf == NULL)
G
Guy Schalnat 已提交
1929
   {
1930 1931 1932 1933
      /* Prior to 1.5.3 this output row/pass where the NULL pointer is, but this
       * error is incredibly rare and incredibly easy to debug without this
       * information.
       */
1934
      png_error(png_ptr, "NULL row buffer");
G
Guy Schalnat 已提交
1935
   }
1936

1937
   /* The following is debugging; prior to 1.5.3 the code was never compiled in;
1938 1939 1940 1941 1942 1943 1944 1945 1946 1947
    * in 1.5.3 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
    * 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.
       * This check added to libpng-1.2.19 (but not enabled until 1.5.3).
1948
       */
1949
      png_error(png_ptr, "Uninitialized row");
1950
   }
A
Andreas Dilger 已提交
1951

1952
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
1953
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1954
   {
A
Andreas Dilger 已提交
1955 1956 1957
      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1958
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
A
Andreas Dilger 已提交
1959
      }
1960

1961
      else
A
Andreas Dilger 已提交
1962
      {
1963 1964
         if (png_ptr->num_trans &&
             (png_ptr->transformations & PNG_EXPAND_tRNS))
A
Andreas Dilger 已提交
1965
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1966
                &(png_ptr->trans_color));
1967

1968
         else
A
Andreas Dilger 已提交
1969
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1970
                NULL);
A
Andreas Dilger 已提交
1971
      }
G
Guy Schalnat 已提交
1972
   }
G
Guy Schalnat 已提交
1973 1974
#endif

1975
   /* TODO: Delay the 'expand 16' step until later for efficiency, so that the
1976 1977
    * intermediate steps work with 8 bit data.
    */
1978 1979 1980 1981 1982 1983 1984 1985 1986
#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)
      png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1);
#endif
1987

1988
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1989
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
1990
      !(png_ptr->transformations & PNG_COMPOSE) &&
1991 1992 1993
      (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
      png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
      png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
1994
         0 /* at_start == false, because SWAP_ALPHA happens later */);
A
Andreas Dilger 已提交
1995 1996
#endif

1997
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1998 1999 2000
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
   {
      int rgb_error =
2001 2002 2003
          png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
              png_ptr->row_buf + 1);

2004
      if (rgb_error)
2005 2006
      {
         png_ptr->rgb_to_gray_status=1;
2007
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
2008
             PNG_RGB_TO_GRAY_WARN)
2009
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
2010

2011 2012
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_ERR)
2013 2014 2015 2016 2017
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

2018
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
2019
 *
2020 2021 2022 2023
 *   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.
2024
 *
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046
 *   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.
2047 2048
 */

2049
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2050 2051 2052
   /* If gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons
    */
2053
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
2054
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
2055 2056 2057
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2058 2059 2060 2061
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
   if (png_ptr->transformations & PNG_COMPOSE)
      png_do_compose(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2062 2063
#endif

2064
#ifdef PNG_READ_GAMMA_SUPPORTED
G
Guy Schalnat 已提交
2065
   if ((png_ptr->transformations & PNG_GAMMA) &&
2066 2067 2068
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
       !((png_ptr->transformations & PNG_COMPOSE) &&
2069 2070
       ((png_ptr->num_trans != 0) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
2071
#endif
2072
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
2073
      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2074 2075
#endif

2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
      (png_ptr->transformations & PNG_COMPOSE) &&
      (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
      png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
      png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
         0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif

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

2091 2092 2093 2094 2095
#ifdef PNG_READ_16_TO_8_SUPPORTED
   if (png_ptr->transformations & PNG_16_TO_8)
      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2096 2097
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
2098
   {
2099
      png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1,
2100
          png_ptr->palette_lookup, png_ptr->quantize_index);
2101

2102
      if (png_ptr->row_info.rowbytes == 0)
2103
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
A
Andreas Dilger 已提交
2104
   }
2105
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
2106

2107 2108 2109 2110 2111
#if 0
   /* This is where this code *should* be for efficiency, but that requires all
    * the inaccurate calculations above to output 16 bit values if expand_16 is
    * set!
    */
2112 2113 2114 2115 2116 2117 2118 2119 2120
#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)
      png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1);
#endif
2121 2122 2123 2124 2125 2126 2127 2128
#endif /*commented out*/

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /*NOTE: moved here in 1.5.3 (from much later in this list.) */
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
2129

2130
#ifdef PNG_READ_INVERT_SUPPORTED
G
Guy Schalnat 已提交
2131
   if (png_ptr->transformations & PNG_INVERT_MONO)
G
Guy Schalnat 已提交
2132
      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2133 2134
#endif

2135
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
2136 2137
   if (png_ptr->transformations & PNG_SHIFT)
      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
2138
          &(png_ptr->shift));
G
Guy Schalnat 已提交
2139 2140
#endif

2141
#ifdef PNG_READ_PACK_SUPPORTED
G
Guy Schalnat 已提交
2142
   if (png_ptr->transformations & PNG_PACK)
G
Guy Schalnat 已提交
2143
      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2144 2145
#endif

2146
#ifdef PNG_READ_BGR_SUPPORTED
G
Guy Schalnat 已提交
2147 2148
   if (png_ptr->transformations & PNG_BGR)
      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2149 2150
#endif

2151
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2152 2153 2154 2155
   if (png_ptr->transformations & PNG_PACKSWAP)
      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2156
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
2157 2158
   if (png_ptr->transformations & PNG_FILLER)
      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
2159
          (png_uint_32)png_ptr->filler, png_ptr->flags);
A
Andreas Dilger 已提交
2160 2161
#endif

2162
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2163 2164 2165 2166
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2167
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2168 2169 2170 2171
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2172
#ifdef PNG_READ_16BIT_SUPPORTED
2173
#ifdef PNG_READ_SWAP_SUPPORTED
A
Andreas Dilger 已提交
2174 2175
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2176
#endif
2177
#endif
2178

2179
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
2180
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2181
    {
2182
      if (png_ptr->read_user_transform_fn != NULL)
2183
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
2184 2185 2186
             (png_ptr,                    /* png_ptr */
             &(png_ptr->row_info),     /* row_info: */
                /*  png_uint_32 width;       width of row */
2187
                /*  png_size_t rowbytes;     number of bytes in row */
2188 2189 2190 2191 2192
                /*  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 */
2193
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
2194
      if (png_ptr->user_transform_depth)
2195
         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
2196

2197
      if (png_ptr->user_transform_channels)
2198
         png_ptr->row_info.channels = png_ptr->user_transform_channels;
2199
#endif
2200
      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
2201
          png_ptr->row_info.channels);
2202

2203
      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
2204
          png_ptr->row_info.width);
2205
   }
2206
#endif
G
Guy Schalnat 已提交
2207 2208
}

2209
#ifdef PNG_READ_PACK_SUPPORTED
2210 2211 2212 2213 2214 2215
/* 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.
 */
2216
void /* PRIVATE */
G
Guy Schalnat 已提交
2217
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2218
{
2219
   png_debug(1, "in png_do_unpack");
2220

A
Andreas Dilger 已提交
2221
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2222
   {
2223
      png_uint_32 i;
2224
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2225

G
Guy Schalnat 已提交
2226 2227 2228 2229
      switch (row_info->bit_depth)
      {
         case 1:
         {
2230 2231
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2232
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2233
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2234
            {
2235
               *dp = (png_byte)((*sp >> shift) & 0x01);
2236

G
Guy Schalnat 已提交
2237 2238 2239 2240
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2241
               }
2242

G
Guy Schalnat 已提交
2243 2244 2245 2246 2247 2248 2249
               else
                  shift++;

               dp--;
            }
            break;
         }
2250

G
Guy Schalnat 已提交
2251 2252 2253
         case 2:
         {

2254 2255
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2256
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2257
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2258
            {
2259
               *dp = (png_byte)((*sp >> shift) & 0x03);
2260

G
Guy Schalnat 已提交
2261 2262 2263 2264 2265
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2266

G
Guy Schalnat 已提交
2267 2268 2269 2270 2271 2272 2273
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2274

G
Guy Schalnat 已提交
2275 2276
         case 4:
         {
2277 2278
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2279
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2280
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2281
            {
2282
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2283

G
Guy Schalnat 已提交
2284 2285 2286 2287 2288
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2289

G
Guy Schalnat 已提交
2290 2291 2292 2293 2294 2295 2296
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2297 2298 2299

         default:
            break;
G
Guy Schalnat 已提交
2300 2301
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2302
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2303
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2304 2305
   }
}
G
Guy Schalnat 已提交
2306
#endif
G
Guy Schalnat 已提交
2307

2308
#ifdef PNG_READ_SHIFT_SUPPORTED
2309 2310 2311 2312 2313
/* 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.
 */
2314
void /* PRIVATE */
2315 2316
png_do_unshift(png_row_infop row_info, png_bytep row,
    png_const_color_8p sig_bits)
G
Guy Schalnat 已提交
2317
{
2318
   png_debug(1, "in png_do_unshift");
2319

A
Andreas Dilger 已提交
2320 2321
   if (
       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2322 2323
   {
      int shift[4];
2324 2325 2326
      int channels = 0;
      int c;
      png_uint_16 value = 0;
2327
      png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2328 2329 2330

      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
G
Guy Schalnat 已提交
2331 2332 2333
         shift[channels++] = row_info->bit_depth - sig_bits->red;
         shift[channels++] = row_info->bit_depth - sig_bits->green;
         shift[channels++] = row_info->bit_depth - sig_bits->blue;
G
Guy Schalnat 已提交
2334
      }
2335

G
Guy Schalnat 已提交
2336 2337
      else
      {
G
Guy Schalnat 已提交
2338
         shift[channels++] = row_info->bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2339
      }
2340

G
Guy Schalnat 已提交
2341 2342
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
G
Guy Schalnat 已提交
2343
         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2344
      }
G
Guy Schalnat 已提交
2345

A
Andreas Dilger 已提交
2346
      for (c = 0; c < channels; c++)
G
Guy Schalnat 已提交
2347
      {
A
Andreas Dilger 已提交
2348 2349
         if (shift[c] <= 0)
            shift[c] = 0;
2350

G
Guy Schalnat 已提交
2351 2352 2353
         else
            value = 1;
      }
G
Guy Schalnat 已提交
2354

G
Guy Schalnat 已提交
2355 2356
      if (!value)
         return;
G
Guy Schalnat 已提交
2357

G
Guy Schalnat 已提交
2358
      switch (row_info->bit_depth)
G
Guy Schalnat 已提交
2359
      {
2360
         default:
2361
            break;
2362

G
Guy Schalnat 已提交
2363 2364
         case 2:
         {
A
Andreas Dilger 已提交
2365
            png_bytep bp;
2366 2367
            png_size_t i;
            png_size_t istop = row_info->rowbytes;
A
Andreas Dilger 已提交
2368

2369
            for (bp = row, i = 0; i < istop; i++)
G
Guy Schalnat 已提交
2370 2371
            {
               *bp >>= 1;
2372
               *bp++ &= 0x55;
G
Guy Schalnat 已提交
2373 2374 2375
            }
            break;
         }
2376

G
Guy Schalnat 已提交
2377 2378
         case 4:
         {
2379
            png_bytep bp = row;
2380 2381
            png_size_t i;
            png_size_t istop = row_info->rowbytes;
2382
            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
2383
                (png_byte)((int)0xf >> shift[0]));
2384

2385
            for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
2386 2387
            {
               *bp >>= shift[0];
2388
               *bp++ &= mask;
G
Guy Schalnat 已提交
2389 2390 2391
            }
            break;
         }
2392

G
Guy Schalnat 已提交
2393 2394
         case 8:
         {
2395
            png_bytep bp = row;
2396
            png_uint_32 i;
2397
            png_uint_32 istop = row_width * channels;
G
Guy Schalnat 已提交
2398

2399
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
2400
            {
2401
               *bp++ >>= shift[i%channels];
G
Guy Schalnat 已提交
2402 2403 2404
            }
            break;
         }
2405

2406
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2407 2408
         case 16:
         {
2409 2410 2411
            png_bytep bp = row;
            png_uint_32 i;
            png_uint_32 istop = channels * row_width;
G
Guy Schalnat 已提交
2412

2413
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
2414
            {
2415 2416 2417 2418
               value = (png_uint_16)((*bp << 8) + *(bp + 1));
               value >>= shift[i%channels];
               *bp++ = (png_byte)(value >> 8);
               *bp++ = (png_byte)(value & 0xff);
G
Guy Schalnat 已提交
2419 2420 2421
            }
            break;
         }
2422
#endif
G
Guy Schalnat 已提交
2423 2424 2425
      }
   }
}
G
Guy Schalnat 已提交
2426
#endif
G
Guy Schalnat 已提交
2427

2428
#ifdef PNG_READ_16_TO_8_SUPPORTED
2429
/* Chop rows of bit depth 16 down to 8 */
2430
void /* PRIVATE */
G
Guy Schalnat 已提交
2431
png_do_chop(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2432
{
2433
   png_debug(1, "in png_do_chop");
2434

A
Andreas Dilger 已提交
2435
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2436
   {
2437 2438 2439 2440
      png_bytep sp = row;
      png_bytep dp = row;
      png_uint_32 i;
      png_uint_32 istop = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2441

2442
      for (i = 0; i<istop; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
2443
      {
2444
#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
2445 2446 2447 2448 2449
      /* This does a more accurate scaling of the 16-bit color
       * value, rather than a simple low-byte truncation.
       *
       * What the ideal calculation should be:
       *   *dp = (((((png_uint_32)(*sp) << 8) |
2450 2451
       *          (png_uint_32)(*(sp + 1))) * 255 + 127)
       *          / (png_uint_32)65535L;
2452 2453 2454
       *
       * GRR: no, I think this is what it really should be:
       *   *dp = (((((png_uint_32)(*sp) << 8) |
2455 2456
       *           (png_uint_32)(*(sp + 1))) + 128L)
       *           / (png_uint_32)257L;
2457 2458
       *
       * GRR: here's the exact calculation with shifts:
2459 2460
       *   temp = (((png_uint_32)(*sp) << 8) |
       *           (png_uint_32)(*(sp + 1))) + 128L;
2461 2462 2463 2464 2465 2466 2467 2468
       *   *dp = (temp - (temp >> 8)) >> 8;
       *
       * Approximate calculation with shift/add instead of multiply/divide:
       *   *dp = ((((png_uint_32)(*sp) << 8) |
       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
       *
       * What we actually do to avoid extra shifting and conversion:
       */
2469

A
Andreas Dilger 已提交
2470 2471
         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
#else
2472
       /* Simply discard the low order byte */
G
Guy Schalnat 已提交
2473
         *dp = *sp;
A
Andreas Dilger 已提交
2474
#endif
G
Guy Schalnat 已提交
2475 2476
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2477
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2478
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2479 2480 2481 2482
   }
}
#endif

2483
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2484
void /* PRIVATE */
A
Andreas Dilger 已提交
2485 2486
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2487
   png_debug(1, "in png_do_read_swap_alpha");
2488

A
Andreas Dilger 已提交
2489
   {
2490
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2491 2492 2493 2494 2495
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2496 2497
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2498 2499
            png_byte save;
            png_uint_32 i;
2500

2501
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2502 2503 2504 2505 2506 2507 2508 2509
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2510 2511

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2512 2513 2514
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2515 2516
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2517 2518
            png_byte save[2];
            png_uint_32 i;
2519

2520
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2534
#endif
A
Andreas Dilger 已提交
2535
      }
2536

A
Andreas Dilger 已提交
2537 2538 2539 2540 2541
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2542 2543
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2544 2545
            png_byte save;
            png_uint_32 i;
2546

2547
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2548 2549 2550 2551 2552 2553
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2554 2555

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2556 2557 2558
         /* This converts from GGAA to AAGG */
         else
         {
2559 2560
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2561 2562 2563
            png_byte save[2];
            png_uint_32 i;

2564
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2565 2566 2567 2568 2569 2570 2571 2572 2573
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2574
#endif
A
Andreas Dilger 已提交
2575
      }
G
Guy Schalnat 已提交
2576 2577
   }
}
G
Guy Schalnat 已提交
2578
#endif
G
Guy Schalnat 已提交
2579

2580
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2581
void /* PRIVATE */
2582 2583
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2584
   png_uint_32 row_width;
2585
   png_debug(1, "in png_do_read_invert_alpha");
2586

2587 2588
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2589
   {
2590
      if (row_info->bit_depth == 8)
2591 2592
      {
         /* This inverts the alpha channel in RGBA */
2593 2594 2595
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2596

2597 2598 2599
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
2600

2601 2602 2603 2604 2605
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2606
*/
2607 2608
            sp-=3;
            dp=sp;
2609
         }
2610
      }
2611 2612

#ifdef PNG_READ_16BIT_SUPPORTED
2613 2614 2615 2616 2617 2618
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2619

2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632
         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:
2633
*/
2634 2635
            sp-=6;
            dp=sp;
2636 2637
         }
      }
2638
#endif
2639 2640 2641 2642
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2643
      {
2644
         /* This inverts the alpha channel in GA */
2645 2646 2647
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2648

2649 2650 2651 2652
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = *(--sp);
2653
         }
2654
      }
2655 2656

#ifdef PNG_READ_16BIT_SUPPORTED
2657 2658
      else
      {
2659
         /* This inverts the alpha channel in GGAA */
2660 2661 2662
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2663

2664 2665 2666 2667
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2668
/*
2669 2670
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2671
*/
2672 2673
            sp-=2;
            dp=sp;
2674 2675
         }
      }
2676
#endif
2677 2678 2679 2680
   }
}
#endif

2681
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2682
/* Add filler channel if we have RGB color */
2683
void /* PRIVATE */
G
Guy Schalnat 已提交
2684
png_do_read_filler(png_row_infop row_info, png_bytep row,
2685
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2686
{
G
Guy Schalnat 已提交
2687
   png_uint_32 i;
2688 2689
   png_uint_32 row_width = row_info->width;

2690
#ifdef PNG_READ_16BIT_SUPPORTED
2691
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2692
#endif
2693
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
2694

2695
   png_debug(1, "in png_do_read_filler");
2696

A
Andreas Dilger 已提交
2697
   if (
2698
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2699
   {
2700
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2701
      {
2702
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2703
         {
2704
            /* This changes the data from G to GX */
2705 2706
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
2707 2708
            for (i = 1; i < row_width; i++)
            {
2709
               *(--dp) = lo_filler;
2710 2711
               *(--dp) = *(--sp);
            }
2712
            *(--dp) = lo_filler;
2713 2714 2715 2716
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
2717

2718 2719
         else
         {
2720
            /* This changes the data from G to XG */
2721 2722
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2723 2724 2725
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2726
               *(--dp) = lo_filler;
2727 2728 2729 2730 2731 2732
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2733

2734
#ifdef PNG_READ_16BIT_SUPPORTED
2735
      else if (row_info->bit_depth == 16)
2736 2737 2738
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2739
            /* This changes the data from GG to GGXX */
2740 2741
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2742 2743 2744
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2745
               *(--dp) = lo_filler;
2746 2747 2748
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2749 2750
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2751 2752
            row_info->channels = 2;
            row_info->pixel_depth = 32;
2753
            row_info->rowbytes = row_width * 4;
2754
         }
2755

2756 2757
         else
         {
2758
            /* This changes the data from GG to XXGG */
2759 2760
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2761 2762 2763 2764 2765
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2766
               *(--dp) = lo_filler;
2767 2768
            }
            row_info->channels = 2;
2769 2770
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
2771
         }
G
Guy Schalnat 已提交
2772
      }
2773
#endif
2774 2775 2776
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
2777
      if (row_info->bit_depth == 8)
2778 2779 2780
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2781
            /* This changes the data from RGB to RGBX */
2782 2783
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
2784 2785
            for (i = 1; i < row_width; i++)
            {
2786
               *(--dp) = lo_filler;
2787 2788 2789 2790
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2791
            *(--dp) = lo_filler;
2792 2793 2794 2795
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
2796

2797 2798
         else
         {
2799
            /* This changes the data from RGB to XRGB */
2800 2801
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
2802 2803 2804 2805 2806
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2807
               *(--dp) = lo_filler;
2808 2809 2810 2811 2812 2813
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
2814

2815
#ifdef PNG_READ_16BIT_SUPPORTED
2816
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2817
      {
2818
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2819
         {
2820
            /* This changes the data from RRGGBB to RRGGBBXX */
2821 2822
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2823 2824 2825
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2826
               *(--dp) = lo_filler;
2827 2828 2829 2830 2831 2832 2833
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2834 2835
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2836 2837
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2838
            row_info->rowbytes = row_width * 8;
2839
         }
2840

2841 2842
         else
         {
2843
            /* This changes the data from RRGGBB to XXRRGGBB */
2844 2845
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2846 2847 2848 2849 2850 2851 2852 2853 2854
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2855
               *(--dp) = lo_filler;
2856
            }
2857

2858 2859
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2860
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2861
         }
G
Guy Schalnat 已提交
2862
      }
2863
#endif
2864
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2865
}
G
Guy Schalnat 已提交
2866
#endif
G
Guy Schalnat 已提交
2867

2868
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2869
/* Expand grayscale files to RGB, with or without alpha */
2870
void /* PRIVATE */
G
Guy Schalnat 已提交
2871
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2872
{
G
Guy Schalnat 已提交
2873
   png_uint_32 i;
2874
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2875

2876
   png_debug(1, "in png_do_gray_to_rgb");
2877

A
Andreas Dilger 已提交
2878
   if (row_info->bit_depth >= 8 &&
2879
       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
G
Guy Schalnat 已提交
2880 2881 2882 2883 2884
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
2885
            /* This changes G to RGB */
2886 2887
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2888
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2889 2890 2891
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
2892
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2893 2894
            }
         }
2895

G
Guy Schalnat 已提交
2896 2897
         else
         {
2898
            /* This changes GG to RRGGBB */
2899 2900
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2901
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2902 2903 2904 2905 2906
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2907 2908
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2909 2910 2911
            }
         }
      }
2912

G
Guy Schalnat 已提交
2913 2914 2915 2916
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
2917
            /* This changes GA to RGBA */
2918 2919
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2920
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2921 2922 2923 2924
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
2925
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2926 2927
            }
         }
2928

G
Guy Schalnat 已提交
2929 2930
         else
         {
2931
            /* This changes GGAA to RRGGBBAA */
2932 2933
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2934
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2935 2936 2937 2938 2939 2940 2941
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2942 2943
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2944 2945 2946
            }
         }
      }
G
Guy Schalnat 已提交
2947
      row_info->channels += (png_byte)2;
G
Guy Schalnat 已提交
2948
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
G
Guy Schalnat 已提交
2949
      row_info->pixel_depth = (png_byte)(row_info->channels *
2950
          row_info->bit_depth);
2951
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
2952 2953
   }
}
G
Guy Schalnat 已提交
2954
#endif
G
Guy Schalnat 已提交
2955

2956
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2957
/* Reduce RGB files to grayscale, with or without alpha
2958
 * using the equation given in Poynton's ColorFAQ at
2959
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
2960
 * New link:
2961
 * <http://www.poynton.com/notes/colour_and_gamma/>
2962
 * Charles Poynton poynton at poynton.com
2963 2964 2965 2966
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
 *  We approximate this with
2967
 *
2968
 *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
2969 2970 2971
 *
 *  which can be expressed with integers as
 *
2972
 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2973 2974 2975 2976 2977
 *
 *  The calculation is to be done in a linear colorspace.
 *
 *  Other integer coefficents can be used via png_set_rgb_to_gray().
 */
2978
int /* PRIVATE */
2979 2980 2981 2982 2983 2984 2985 2986
png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)

{
   png_uint_32 i;

   png_uint_32 row_width = row_info->width;
   int rgb_error = 0;

2987
   png_debug(1, "in png_do_rgb_to_gray");
2988

2989
   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
2990
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
2991
   {
2992 2993 2994
      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
      png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010

      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
      {
         if (row_info->bit_depth == 8)
         {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
            {
               png_bytep sp = row;
               png_bytep dp = row;

               for (i = 0; i < row_width; i++)
               {
                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
3011

3012
                  if (red != green || red != blue)
3013 3014 3015
                  {
                     rgb_error |= 1;
                     *(dp++) = png_ptr->gamma_from_1[
3016
                         (rc*red + gc*green + bc*blue)>>15];
3017
                  }
3018

3019
                  else
3020
                     *(dp++) = *(sp - 1);
3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_byte red   = *(sp++);
                  png_byte green = *(sp++);
                  png_byte blue  = *(sp++);
3033

3034
                  if (red != green || red != blue)
3035 3036
                  {
                     rgb_error |= 1;
3037
                     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3038
                  }
3039

3040
                  else
3041
                     *(dp++) = *(sp - 1);
3042 3043 3044
               }
            }
         }
3045

3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057
         else /* RGB bit_depth == 16 */
         {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
            if (png_ptr->gamma_16_to_1 != NULL &&
                png_ptr->gamma_16_from_1 != NULL)
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, w;

3058 3059 3060
                  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;
3061

3062
                  if (red == green && red == blue)
3063
                     w = red;
3064

3065 3066
                  else
                  {
3067 3068
                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
                         >> png_ptr->gamma_shift][red>>8];
3069 3070
                     png_uint_16 green_1 =
                         png_ptr->gamma_16_to_1[(green&0xff) >>
3071
                         png_ptr->gamma_shift][green>>8];
3072 3073
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
                         >> png_ptr->gamma_shift][blue>>8];
3074
                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
3075
                         + bc*blue_1)>>15);
3076 3077 3078 3079
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
                     rgb_error |= 1;
                  }
3080

3081 3082
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, gray16;

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

3098
                  if (red != green || red != blue)
3099
                     rgb_error |= 1;
3100

3101
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
3102 3103
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121
               }
            }
         }
      }
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
3122

3123
                  if (red != green || red != blue)
3124
                     rgb_error |= 1;
3125

3126
                  *(dp++) =  png_ptr->gamma_from_1
3127
                      [(rc*red + gc*green + bc*blue)>>15];
3128

3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141
                  *(dp++) = *(sp++);  /* alpha */
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_byte red   = *(sp++);
                  png_byte green = *(sp++);
                  png_byte blue  = *(sp++);
3142
                  if (red != green || red != blue)
3143
                     rgb_error |= 1;
3144

3145
                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161
                  *(dp++) = *(sp++);  /* alpha */
               }
            }
         }
         else /* RGBA bit_depth == 16 */
         {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
            if (png_ptr->gamma_16_to_1 != NULL &&
                png_ptr->gamma_16_from_1 != NULL)
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, w;

3162 3163 3164
                  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;
3165

3166
                  if (red == green && red == blue)
3167
                     w = red;
3168

3169 3170 3171
                  else
                  {
                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
3172
                         png_ptr->gamma_shift][red>>8];
3173

3174 3175 3176
                     png_uint_16 green_1 =
                         png_ptr->gamma_16_to_1[(green&0xff) >>
                         png_ptr->gamma_shift][green>>8];
3177

3178
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
3179
                         png_ptr->gamma_shift][blue>>8];
3180

3181
                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
3182
                         + gc * green_1 + bc * blue_1)>>15);
3183

3184 3185
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
3186

3187 3188
                     rgb_error |= 1;
                  }
3189

3190 3191
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203
                  *(dp++) = *(sp++);  /* alpha */
                  *(dp++) = *(sp++);
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, gray16;
3204 3205 3206
                  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;
3207

3208
                  if (red != green || red != blue)
3209
                     rgb_error |= 1;
3210

3211
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
3212 3213
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
3214 3215 3216 3217 3218 3219
                  *(dp++) = *(sp++);  /* alpha */
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3220 3221 3222
      row_info->channels -= 2;
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
3223
      row_info->pixel_depth = (png_byte)(row_info->channels *
3224
          row_info->bit_depth);
3225
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3226 3227 3228 3229
   }
   return rgb_error;
}
#endif
3230
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
3231

3232
#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
3233 3234 3235
/* 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
3236
 * of code.  This API is not used internally.
3237
 */
3238
void PNGAPI
G
Guy Schalnat 已提交
3239
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
3240 3241 3242 3243 3244 3245
{
   int num_palette;
   int color_inc;
   int i;
   int v;

3246
   png_debug(1, "in png_do_build_grayscale_palette");
3247

A
Andreas Dilger 已提交
3248
   if (palette == NULL)
G
Guy Schalnat 已提交
3249 3250 3251 3252 3253 3254 3255 3256
      return;

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

G
Guy Schalnat 已提交
3258 3259 3260 3261
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
3262

G
Guy Schalnat 已提交
3263 3264 3265 3266
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
3267

G
Guy Schalnat 已提交
3268 3269 3270 3271
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
3272

G
Guy Schalnat 已提交
3273
      default:
G
Guy Schalnat 已提交
3274
         num_palette = 0;
G
Guy Schalnat 已提交
3275
         color_inc = 0;
G
Guy Schalnat 已提交
3276 3277 3278 3279 3280
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
3281 3282 3283
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
3284 3285
   }
}
3286
#endif
G
Guy Schalnat 已提交
3287 3288


3289
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
3290
#ifdef PNG_READ_BACKGROUND_SUPPORTED
A
Andreas Dilger 已提交
3291
/* Replace any alpha or transparency with the supplied background color.
3292 3293 3294
 * "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.
 */
3295
void /* PRIVATE */
3296
png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
3297
{
3298
#ifdef PNG_READ_GAMMA_SUPPORTED
3299 3300 3301 3302 3303 3304 3305
   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;
3306
#endif
3307

3308
   png_bytep sp;
G
Guy Schalnat 已提交
3309
   png_uint_32 i;
3310
   png_uint_32 row_width = row_info->width;
3311
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
G
Guy Schalnat 已提交
3312
   int shift;
G
Guy Schalnat 已提交
3313

3314
   png_debug(1, "in png_do_compose");
3315

G
Guy Schalnat 已提交
3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
3327
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3328
                  {
3329
                     if ((png_uint_16)((*sp >> shift) & 0x01)
3330
                        == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3331
                     {
G
Guy Schalnat 已提交
3332
                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
3333
                        *sp |= (png_byte)(png_ptr->background.gray << shift);
G
Guy Schalnat 已提交
3334
                     }
3335

G
Guy Schalnat 已提交
3336 3337 3338 3339 3340
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
3341

G
Guy Schalnat 已提交
3342 3343 3344 3345 3346
                     else
                        shift--;
                  }
                  break;
               }
3347

G
Guy Schalnat 已提交
3348 3349
               case 2:
               {
3350
#ifdef PNG_READ_GAMMA_SUPPORTED
3351
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3352
                  {
3353 3354 3355
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3356
                     {
3357
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3358
                            == png_ptr->trans_color.gray)
3359 3360
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3361
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3362
                        }
3363

3364 3365
                        else
                        {
3366
                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
3367
                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
3368
                               (p << 4) | (p << 6)] >> 6) & 0x03);
3369 3370 3371
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3372

3373 3374 3375 3376 3377
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3378

3379 3380
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3381
                     }
3382
                  }
3383

3384 3385 3386 3387 3388 3389
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3390
                     {
3391
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3392
                            == png_ptr->trans_color.gray)
3393 3394
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3395
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3396
                        }
3397

3398 3399 3400 3401 3402
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3403

3404 3405
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3406 3407 3408 3409
                     }
                  }
                  break;
               }
3410

G
Guy Schalnat 已提交
3411 3412
               case 4:
               {
3413
#ifdef PNG_READ_GAMMA_SUPPORTED
3414
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3415
                  {
3416 3417 3418
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3419
                     {
3420
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3421
                            == png_ptr->trans_color.gray)
3422 3423
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3424
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3425
                        }
3426

3427 3428
                        else
                        {
3429
                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
3430
                           png_byte g = (png_byte)((gamma_table[p |
3431
                               (p << 4)] >> 4) & 0x0f);
3432 3433 3434
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3435

3436 3437 3438 3439 3440
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3441

3442 3443
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3444
                     }
3445
                  }
3446

3447 3448 3449 3450 3451 3452
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3453
                     {
3454
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3455
                            == png_ptr->trans_color.gray)
3456 3457
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3458
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3459
                        }
3460

3461 3462 3463 3464 3465
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3466

3467 3468
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3469 3470 3471 3472
                     }
                  }
                  break;
               }
3473

G
Guy Schalnat 已提交
3474 3475
               case 8:
               {
3476
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3477
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3478
                  {
3479 3480
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3481
                     {
3482 3483
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3484

G
Guy Schalnat 已提交
3485 3486 3487 3488 3489
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3490
#endif
G
Guy Schalnat 已提交
3491
                  {
3492 3493
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3494
                     {
3495 3496
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3497 3498 3499 3500
                     }
                  }
                  break;
               }
3501

G
Guy Schalnat 已提交
3502 3503
               case 16:
               {
3504
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3505
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3506
                  {
3507 3508
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3509 3510 3511
                     {
                        png_uint_16 v;

3512
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3513

3514
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3515
                        {
3516
                           /* Background is already in screen gamma */
3517 3518
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3519
                        }
3520

G
Guy Schalnat 已提交
3521 3522
                        else
                        {
A
Andreas Dilger 已提交
3523
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3524
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3525
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3526
                        }
G
Guy Schalnat 已提交
3527
                     }
G
Guy Schalnat 已提交
3528 3529
                  }
                  else
G
Guy Schalnat 已提交
3530
#endif
G
Guy Schalnat 已提交
3531
                  {
3532 3533
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3534 3535 3536
                     {
                        png_uint_16 v;

3537
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3538

3539
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3540
                        {
3541 3542
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3543 3544 3545 3546 3547
                        }
                     }
                  }
                  break;
               }
3548 3549 3550

               default:
                  break;
G
Guy Schalnat 已提交
3551 3552 3553
            }
            break;
         }
3554

G
Guy Schalnat 已提交
3555 3556 3557 3558
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3559
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3560
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3561
               {
3562 3563
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3564
                  {
3565 3566 3567
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3568
                     {
3569 3570 3571
                        *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 已提交
3572
                     }
3573

G
Guy Schalnat 已提交
3574 3575 3576 3577 3578 3579 3580 3581 3582
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3583
#endif
G
Guy Schalnat 已提交
3584
               {
3585 3586
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3587
                  {
3588 3589 3590
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3591
                     {
3592 3593 3594
                        *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 已提交
3595 3596 3597 3598
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3599
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3600
            {
3601
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3602
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3603
               {
3604 3605
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3606
                  {
3607
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3608

3609 3610
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3611

3612 3613
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3614

3615 3616 3617
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3618
                     {
3619
                        /* Background is already in screen gamma */
3620 3621 3622 3623 3624 3625
                        *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 已提交
3626
                     }
3627

G
Guy Schalnat 已提交
3628 3629
                     else
                     {
3630
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3631
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3632
                        *(sp + 1) = (png_byte)(v & 0xff);
3633

A
Andreas Dilger 已提交
3634
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3635 3636
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3637

A
Andreas Dilger 已提交
3638
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3639 3640
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3641 3642 3643
                     }
                  }
               }
3644

G
Guy Schalnat 已提交
3645
               else
G
Guy Schalnat 已提交
3646
#endif
G
Guy Schalnat 已提交
3647
               {
3648 3649
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3650
                  {
3651
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3652

3653 3654
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3655

3656 3657
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3658

3659 3660 3661
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3662
                     {
3663 3664 3665 3666 3667 3668
                        *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 已提交
3669 3670 3671 3672 3673 3674
                     }
                  }
               }
            }
            break;
         }
3675

G
Guy Schalnat 已提交
3676
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3677
         {
A
Andreas Dilger 已提交
3678
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3679
            {
3680
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3681 3682 3683
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3684
                  sp = row;
3685
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3686
                  {
3687
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3688

A
Andreas Dilger 已提交
3689
                     if (a == 0xff)
3690
                        *sp = gamma_table[*sp];
3691

A
Andreas Dilger 已提交
3692 3693
                     else if (a == 0)
                     {
3694
                        /* Background is already in screen gamma */
3695
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3696
                     }
3697

A
Andreas Dilger 已提交
3698 3699 3700
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3701

A
Andreas Dilger 已提交
3702
                        v = gamma_to_1[*sp];
3703
                        png_composite(w, v, a, png_ptr->background_1.gray);
3704 3705 3706
                        if (!optimize)
                           w = gamma_from_1[w];
                        *sp = w;
G
Guy Schalnat 已提交
3707 3708
                     }
                  }
A
Andreas Dilger 已提交
3709 3710
               }
               else
G
Guy Schalnat 已提交
3711
#endif
A
Andreas Dilger 已提交
3712
               {
3713
                  sp = row;
3714
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3715
                  {
3716
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3717

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

3721 3722
                     else if (a < 0xff)
                        png_composite(*sp, *sp, a, png_ptr->background_1.gray);
G
Guy Schalnat 已提交
3723 3724
                  }
               }
A
Andreas Dilger 已提交
3725 3726 3727
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3728
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3729 3730 3731
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3732
                  sp = row;
3733
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3734
                  {
3735 3736
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
A
Andreas Dilger 已提交
3737 3738

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3739
                     {
A
Andreas Dilger 已提交
3740
                        png_uint_16 v;
G
Guy Schalnat 已提交
3741

A
Andreas Dilger 已提交
3742
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3743 3744
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3745
                     }
3746

A
Andreas Dilger 已提交
3747 3748
                     else if (a == 0)
                     {
3749
                        /* Background is already in screen gamma */
3750 3751
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3752
                     }
3753

A
Andreas Dilger 已提交
3754 3755 3756
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3757

A
Andreas Dilger 已提交
3758
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3759
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3760 3761 3762 3763 3764 3765
                        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 已提交
3766 3767
                     }
                  }
A
Andreas Dilger 已提交
3768 3769
               }
               else
G
Guy Schalnat 已提交
3770
#endif
A
Andreas Dilger 已提交
3771
               {
3772
                  sp = row;
3773
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3774
                  {
3775 3776
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3777

3778
                     if (a == 0)
A
Andreas Dilger 已提交
3779
                     {
3780 3781
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3782
                     }
3783

3784
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3785 3786
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3787

3788
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3789
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3790 3791
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3792 3793 3794 3795 3796 3797
                     }
                  }
               }
            }
            break;
         }
3798

G
Guy Schalnat 已提交
3799 3800 3801 3802
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3803
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3804 3805
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3806
               {
3807
                  sp = row;
3808
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3809
                  {
3810
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3811 3812 3813

                     if (a == 0xff)
                     {
3814 3815 3816
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
3817
                     }
3818

G
Guy Schalnat 已提交
3819 3820
                     else if (a == 0)
                     {
3821
                        /* Background is already in screen gamma */
3822 3823 3824
                        *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 已提交
3825
                     }
3826

G
Guy Schalnat 已提交
3827 3828
                     else
                     {
A
Andreas Dilger 已提交
3829
                        png_byte v, w;
G
Guy Schalnat 已提交
3830 3831

                        v = gamma_to_1[*sp];
3832
                        png_composite(w, v, a, png_ptr->background_1.red);
3833 3834
                        if (!optimize) w = gamma_from_1[w];
                        *sp = w;
3835

G
Guy Schalnat 已提交
3836
                        v = gamma_to_1[*(sp + 1)];
3837
                        png_composite(w, v, a, png_ptr->background_1.green);
3838 3839
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 1) = w;
3840

G
Guy Schalnat 已提交
3841
                        v = gamma_to_1[*(sp + 2)];
3842
                        png_composite(w, v, a, png_ptr->background_1.blue);
3843 3844
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
3845 3846 3847 3848
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3849
#endif
G
Guy Schalnat 已提交
3850
               {
3851
                  sp = row;
3852
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3853
                  {
3854
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3855

3856
                     if (a == 0)
G
Guy Schalnat 已提交
3857
                     {
3858 3859 3860
                        *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 已提交
3861
                     }
3862

3863
                     else if (a < 0xff)
G
Guy Schalnat 已提交
3864
                     {
3865
                        png_composite(*sp, *sp, a, png_ptr->background.red);
3866

3867
                        png_composite(*(sp + 1), *(sp + 1), a,
3868
                            png_ptr->background.green);
3869

3870
                        png_composite(*(sp + 2), *(sp + 2), a,
3871
                            png_ptr->background.blue);
G
Guy Schalnat 已提交
3872 3873 3874 3875
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3876
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3877
            {
3878
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3879 3880
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
3881
               {
3882
                  sp = row;
3883
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3884
                  {
3885 3886
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
3887

G
Guy Schalnat 已提交
3888 3889 3890 3891
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3892
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3893 3894
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3895

A
Andreas Dilger 已提交
3896
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3897 3898
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3899

A
Andreas Dilger 已提交
3900
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3901 3902
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3903
                     }
3904

G
Guy Schalnat 已提交
3905 3906
                     else if (a == 0)
                     {
3907
                        /* Background is already in screen gamma */
3908 3909 3910 3911 3912 3913
                        *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 已提交
3914
                     }
3915

G
Guy Schalnat 已提交
3916 3917
                     else
                     {
3918
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
3919 3920

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3921
                        png_composite_16(w, v, a, png_ptr->background_1.red);
3922 3923 3924 3925
                        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);
3926

A
Andreas Dilger 已提交
3927
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3928
                        png_composite_16(w, v, a, png_ptr->background_1.green);
3929 3930
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3931

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

A
Andreas Dilger 已提交
3935
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3936
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
3937 3938
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3939

3940 3941
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3942 3943 3944
                     }
                  }
               }
3945

G
Guy Schalnat 已提交
3946
               else
G
Guy Schalnat 已提交
3947
#endif
G
Guy Schalnat 已提交
3948
               {
3949
                  sp = row;
3950
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3951
                  {
3952
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3953
                         << 8) + (png_uint_16)(*(sp + 7)));
3954

3955
                     if (a == 0)
G
Guy Schalnat 已提交
3956
                     {
3957 3958 3959 3960 3961 3962
                        *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 已提交
3963
                     }
3964

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

3969 3970 3971 3972 3973
                        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 已提交
3974

3975
                        png_composite_16(v, r, a, png_ptr->background.red);
3976 3977
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3978

3979
                        png_composite_16(v, g, a, png_ptr->background.green);
3980 3981
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3982

3983
                        png_composite_16(v, b, a, png_ptr->background.blue);
3984 3985
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3986 3987 3988 3989 3990 3991
                     }
                  }
               }
            }
            break;
         }
3992 3993 3994

         default:
            break;
G
Guy Schalnat 已提交
3995 3996 3997
      }
   }
}
G
Guy Schalnat 已提交
3998
#endif
G
Guy Schalnat 已提交
3999

4000
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4001
/* Gamma correct the image, avoiding the alpha channel.  Make sure
4002
 * you do this after you deal with the transparency issue on grayscale
4003
 * or RGB images. If your bit depth is 8, use gamma_table, if it
4004 4005 4006
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
4007
void /* PRIVATE */
4008
png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
G
Guy Schalnat 已提交
4009
{
4010 4011 4012 4013
   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 已提交
4014
   png_bytep sp;
G
Guy Schalnat 已提交
4015
   png_uint_32 i;
4016
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4017

4018
   png_debug(1, "in png_do_gamma");
4019

4020
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
4021
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
4022 4023 4024 4025 4026 4027 4028
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
4029 4030
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4031 4032 4033 4034 4035 4036 4037 4038 4039
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4040

A
Andreas Dilger 已提交
4041
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4042
            {
4043 4044
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4045 4046 4047
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
4048
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4049 4050 4051
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4052

A
Andreas Dilger 已提交
4053
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4054 4055
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4056
                  sp += 2;
4057

A
Andreas Dilger 已提交
4058
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4059 4060 4061 4062 4063 4064 4065
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
4066

G
Guy Schalnat 已提交
4067 4068 4069 4070
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4071 4072
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4073
               {
G
Guy Schalnat 已提交
4074 4075
                  *sp = gamma_table[*sp];
                  sp++;
4076

G
Guy Schalnat 已提交
4077 4078
                  *sp = gamma_table[*sp];
                  sp++;
4079

G
Guy Schalnat 已提交
4080 4081
                  *sp = gamma_table[*sp];
                  sp++;
4082

G
Guy Schalnat 已提交
4083 4084 4085
                  sp++;
               }
            }
4086

A
Andreas Dilger 已提交
4087
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4088
            {
4089 4090
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4091
               {
4092
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4093 4094
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4095
                  sp += 2;
4096

A
Andreas Dilger 已提交
4097
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4098 4099 4100
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4101

A
Andreas Dilger 已提交
4102
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4103 4104 4105 4106 4107
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4108 4109
            break;
         }
4110

G
Guy Schalnat 已提交
4111 4112 4113 4114
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4115 4116
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4117 4118
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4119
                  sp += 2;
G
Guy Schalnat 已提交
4120 4121
               }
            }
4122

A
Andreas Dilger 已提交
4123
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4124
            {
4125 4126
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4127
               {
4128
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4129 4130
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4131 4132 4133 4134 4135
                  sp += 4;
               }
            }
            break;
         }
4136

G
Guy Schalnat 已提交
4137 4138
         case PNG_COLOR_TYPE_GRAY:
         {
4139 4140
            if (row_info->bit_depth == 2)
            {
4141 4142
               sp = row;
               for (i = 0; i < row_width; i += 4)
4143 4144 4145 4146 4147 4148
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4149
                  *sp = (png_byte)(
4150 4151 4152 4153
                      ((((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) ));
4154 4155 4156
                  sp++;
               }
            }
4157

A
Andreas Dilger 已提交
4158
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4159
            {
4160 4161
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4162 4163 4164 4165
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4166
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4167
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4168 4169 4170
                  sp++;
               }
            }
4171

A
Andreas Dilger 已提交
4172 4173
            else if (row_info->bit_depth == 8)
            {
4174 4175
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4176 4177 4178 4179 4180
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
4181

G
Guy Schalnat 已提交
4182 4183
            else if (row_info->bit_depth == 16)
            {
4184 4185
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4186
               {
4187
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4188 4189
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4190 4191 4192 4193 4194
                  sp += 2;
               }
            }
            break;
         }
4195 4196 4197

         default:
            break;
G
Guy Schalnat 已提交
4198 4199 4200
      }
   }
}
G
Guy Schalnat 已提交
4201
#endif
G
Guy Schalnat 已提交
4202

4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269
#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

4270
#ifdef PNG_READ_EXPAND_SUPPORTED
4271
/* Expands a palette row to an RGB or RGBA row depending
4272 4273
 * upon whether you supply trans and num_trans.
 */
4274
void /* PRIVATE */
G
Guy Schalnat 已提交
4275
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4276
   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
4277
{
G
Guy Schalnat 已提交
4278
   int shift, value;
G
Guy Schalnat 已提交
4279
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4280
   png_uint_32 i;
4281
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4282

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

4285
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4286 4287 4288 4289 4290 4291 4292
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4293 4294
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4295
               shift = 7 - (int)((row_width + 7) & 0x07);
4296
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4297
               {
4298
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4299
                     *dp = 1;
4300

G
Guy Schalnat 已提交
4301 4302
                  else
                     *dp = 0;
4303

G
Guy Schalnat 已提交
4304 4305 4306 4307 4308
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4309

G
Guy Schalnat 已提交
4310 4311 4312 4313 4314 4315 4316
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4317

G
Guy Schalnat 已提交
4318 4319
            case 2:
            {
4320 4321
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4322
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4323
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4324
               {
4325
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4326
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4327 4328 4329 4330 4331
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4332

G
Guy Schalnat 已提交
4333 4334 4335 4336 4337 4338 4339
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4340

G
Guy Schalnat 已提交
4341 4342
            case 4:
            {
4343 4344
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4345
               shift = (int)((row_width & 0x01) << 2);
4346
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4347
               {
4348
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4349
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4350 4351 4352 4353 4354
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4355

G
Guy Schalnat 已提交
4356 4357 4358 4359 4360 4361 4362
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4363 4364 4365

            default:
               break;
G
Guy Schalnat 已提交
4366 4367 4368
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4369
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4370
      }
4371

4372
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4373 4374
      {
         {
4375
            if (trans_alpha != NULL)
G
Guy Schalnat 已提交
4376
            {
4377 4378
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
4379

4380
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4381
               {
A
Andreas Dilger 已提交
4382
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4383
                     *dp-- = 0xff;
4384

G
Guy Schalnat 已提交
4385
                  else
4386
                     *dp-- = trans_alpha[*sp];
4387

G
Guy Schalnat 已提交
4388 4389 4390 4391 4392 4393 4394
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4395
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4396 4397 4398
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4399

G
Guy Schalnat 已提交
4400 4401
            else
            {
4402 4403
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4404

4405
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4406 4407 4408 4409 4410 4411
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4412

G
Guy Schalnat 已提交
4413 4414
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4415
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4416 4417 4418 4419 4420 4421 4422 4423
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4424 4425
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4426
 */
4427
void /* PRIVATE */
G
Guy Schalnat 已提交
4428
png_do_expand(png_row_infop row_info, png_bytep row,
4429
    png_const_color_16p trans_value)
G
Guy Schalnat 已提交
4430
{
G
Guy Schalnat 已提交
4431
   int shift, value;
G
Guy Schalnat 已提交
4432
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4433
   png_uint_32 i;
4434
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4435

4436
   png_debug(1, "in png_do_expand");
4437

G
Guy Schalnat 已提交
4438
   {
A
Andreas Dilger 已提交
4439
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4440
      {
4441
         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
A
Andreas Dilger 已提交
4442 4443

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4444
         {
A
Andreas Dilger 已提交
4445
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4446
            {
A
Andreas Dilger 已提交
4447
               case 1:
G
Guy Schalnat 已提交
4448
               {
4449
                  gray = (png_uint_16)((gray & 0x01) * 0xff);
4450 4451
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4452
                  shift = 7 - (int)((row_width + 7) & 0x07);
4453
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4454
                  {
4455
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4456
                        *dp = 0xff;
4457

A
Andreas Dilger 已提交
4458 4459
                     else
                        *dp = 0;
4460

A
Andreas Dilger 已提交
4461 4462 4463 4464 4465
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4466

A
Andreas Dilger 已提交
4467 4468
                     else
                        shift++;
G
Guy Schalnat 已提交
4469

A
Andreas Dilger 已提交
4470 4471 4472
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4473
               }
4474

A
Andreas Dilger 已提交
4475
               case 2:
G
Guy Schalnat 已提交
4476
               {
4477
                  gray = (png_uint_16)((gray & 0x03) * 0x55);
4478 4479
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
4480
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4481
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4482
                  {
4483
                     value = (*sp >> shift) & 0x03;
A
Andreas Dilger 已提交
4484 4485 4486 4487 4488 4489 4490
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
4491

A
Andreas Dilger 已提交
4492 4493
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4494

A
Andreas Dilger 已提交
4495 4496 4497
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4498
               }
4499

A
Andreas Dilger 已提交
4500
               case 4:
G
Guy Schalnat 已提交
4501
               {
4502
                  gray = (png_uint_16)((gray & 0x0f) * 0x11);
4503 4504
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4505
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4506
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4507
                  {
4508
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
4509 4510 4511 4512 4513 4514
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4515

A
Andreas Dilger 已提交
4516 4517
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4518

A
Andreas Dilger 已提交
4519 4520 4521
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4522
               }
4523 4524 4525

               default:
                  break;
G
Guy Schalnat 已提交
4526
            }
4527

A
Andreas Dilger 已提交
4528 4529
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4530
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4531
         }
A
Andreas Dilger 已提交
4532

A
Andreas Dilger 已提交
4533
         if (trans_value != NULL)
G
Guy Schalnat 已提交
4534
         {
A
Andreas Dilger 已提交
4535
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4536
            {
4537
               gray = gray & 0xff;
4538 4539
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
4540

4541
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4542
               {
A
Andreas Dilger 已提交
4543 4544
                  if (*sp == gray)
                     *dp-- = 0;
4545

A
Andreas Dilger 已提交
4546 4547
                  else
                     *dp-- = 0xff;
4548

A
Andreas Dilger 已提交
4549
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4550
               }
A
Andreas Dilger 已提交
4551
            }
4552

A
Andreas Dilger 已提交
4553 4554
            else if (row_info->bit_depth == 16)
            {
4555 4556
               png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
               png_byte gray_low = (png_byte)(gray & 0xff);
A
Andreas Dilger 已提交
4557 4558
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4559
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4560
               {
4561
                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
A
Andreas Dilger 已提交
4562 4563 4564 4565
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4566

A
Andreas Dilger 已提交
4567 4568 4569 4570 4571
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4572

A
Andreas Dilger 已提交
4573 4574
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4575 4576
               }
            }
4577

A
Andreas Dilger 已提交
4578 4579 4580
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4581 4582
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
4583 4584 4585 4586 4587 4588
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
      {
         if (row_info->bit_depth == 8)
         {
4589 4590 4591
            png_byte red = (png_byte)(trans_value->red & 0xff);
            png_byte green = (png_byte)(trans_value->green & 0xff);
            png_byte blue = (png_byte)(trans_value->blue & 0xff);
G
Guy Schalnat 已提交
4592
            sp = row + (png_size_t)row_info->rowbytes - 1;
4593 4594
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4595
            {
4596
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
4597
                  *dp-- = 0;
4598

G
Guy Schalnat 已提交
4599 4600
               else
                  *dp-- = 0xff;
4601

G
Guy Schalnat 已提交
4602 4603 4604 4605 4606 4607 4608
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
4609 4610 4611 4612 4613 4614
            png_byte red_high = (png_byte)((trans_value->red >> 8) & 0xff);
            png_byte green_high = (png_byte)((trans_value->green >> 8) & 0xff);
            png_byte blue_high = (png_byte)((trans_value->blue >> 8) & 0xff);
            png_byte red_low = (png_byte)(trans_value->red & 0xff);
            png_byte green_low = (png_byte)(trans_value->green & 0xff);
            png_byte blue_low = (png_byte)(trans_value->blue & 0xff);
A
Andreas Dilger 已提交
4615
            sp = row + row_info->rowbytes - 1;
4616 4617
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4618
            {
4619
               if (*(sp - 5) == red_high &&
4620 4621 4622 4623 4624
                   *(sp - 4) == red_low &&
                   *(sp - 3) == green_high &&
                   *(sp - 2) == green_low &&
                   *(sp - 1) == blue_high &&
                   *(sp    ) == blue_low)
G
Guy Schalnat 已提交
4625 4626 4627 4628
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4629

G
Guy Schalnat 已提交
4630 4631 4632 4633 4634
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4635

G
Guy Schalnat 已提交
4636 4637 4638 4639
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4640
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4641 4642 4643 4644 4645
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
4646
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4647
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4648 4649 4650
      }
   }
}
G
Guy Schalnat 已提交
4651
#endif
G
Guy Schalnat 已提交
4652

4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* If the bit depth is 8 and the colour type is not a palette type expand the
 * 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

4684
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4685
void /* PRIVATE */
4686
png_do_quantize(png_row_infop row_info, png_bytep row,
4687
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
G
Guy Schalnat 已提交
4688
{
G
Guy Schalnat 已提交
4689
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4690
   png_uint_32 i;
4691
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4692

4693
   png_debug(1, "in png_do_quantize");
4694

4695
   if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4696
   {
4697
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
G
Guy Schalnat 已提交
4698 4699 4700 4701
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4702
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4703 4704 4705 4706 4707
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

4708 4709 4710 4711 4712 4713 4714
            /* 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);
             */
4715 4716 4717 4718 4719 4720 4721 4722
            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 已提交
4723 4724 4725

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

G
Guy Schalnat 已提交
4727 4728 4729
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4730
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4731
      }
4732

G
Guy Schalnat 已提交
4733
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4734
         palette_lookup != NULL)
G
Guy Schalnat 已提交
4735 4736 4737 4738
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4739
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4740 4741 4742 4743 4744 4745
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

4746 4747 4748 4749 4750 4751 4752 4753
            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 已提交
4754 4755 4756

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

G
Guy Schalnat 已提交
4758 4759 4760
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4761
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4762
      }
4763

G
Guy Schalnat 已提交
4764
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4765
         quantize_lookup)
G
Guy Schalnat 已提交
4766
      {
G
Guy Schalnat 已提交
4767
         sp = row;
4768

4769
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
4770
         {
4771
            *sp = quantize_lookup[*sp];
G
Guy Schalnat 已提交
4772 4773 4774 4775
         }
      }
   }
}
4776
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
4777
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
G
Guy Schalnat 已提交
4778

4779
#ifdef PNG_MNG_FEATURES_SUPPORTED
4780
/* Undoes intrapixel differencing  */
4781 4782 4783
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
4784
   png_debug(1, "in png_do_read_intrapixel");
4785

4786 4787 4788 4789 4790
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
4791

4792 4793 4794 4795 4796 4797 4798
      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;
4799

4800 4801
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
4802

4803 4804 4805 4806 4807
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4808 4809
            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
4810 4811 4812 4813 4814 4815 4816 4817 4818
         }
      }
      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;
4819

4820 4821
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
4822

4823 4824 4825 4826 4827
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4828 4829 4830 4831 4832
            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);
            png_uint_32 red  = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
            png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
4833
            *(rp    ) = (png_byte)((red >> 8) & 0xff);
4834 4835 4836
            *(rp + 1) = (png_byte)(red & 0xff);
            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
            *(rp + 5) = (png_byte)(blue & 0xff);
4837 4838 4839 4840 4841
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
4842
#endif /* PNG_READ_SUPPORTED */