pngrtran.c 160.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.4 [(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
/* Scale 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
   png_ptr->transformations |= PNG_16_TO_8;
146
#ifdef PNG_READ_CHOP_16_TO_8_SUPPORTED
147
   png_ptr->transformations &= ~PNG_CHOP_16_TO_8;
148
#endif
149 150
}

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

   if (png_ptr == NULL)
      return;

   png_ptr->transformations |= PNG_CHOP_16_TO_8;
   png_ptr->transformations &= ~PNG_16_TO_8;
G
Guy Schalnat 已提交
163
}
G
Guy Schalnat 已提交
164
#endif
165
#endif /* PNG_READ_16_TO_8_SUPPORTED */
G
Guy Schalnat 已提交
166

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

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

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

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
#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 */

242 243 244 245 246 247 248 249 250 251 252 253 254
#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;

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

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

266
   /* The default file gamma is the inverse of the output gamma; the output
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
    * 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;

330
   /* Finally, if pre-multiplying, set the background fields to achieve the
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
    * 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)
{
356 357
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
      output_gamma));
358 359 360 361
}
#  endif
#endif

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

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

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

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

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

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

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

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

         int i;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

         num_new_palette = num_palette;

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

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

                  if (d <= max_d)
                  {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

G
[devel]  
Glenn Randers-Pehrson 已提交
768 769 770 771 772 773
#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");
774

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

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

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

   if (scrn_gamma <= 0)
797
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
798 799 800 801 802 803
#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 已提交
804 805
   png_ptr->gamma = file_gamma;
   png_ptr->screen_gamma = scrn_gamma;
G
Guy Schalnat 已提交
806
}
G
[devel]  
Glenn Randers-Pehrson 已提交
807 808 809 810 811

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

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

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

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

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

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

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

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

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

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

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

879 880


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

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

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

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

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

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

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

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

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

944 945 946
      case 2:
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
         break;
947

948 949
      case 3:
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
950 951 952
         break;

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

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

972 973
         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
974 975 976 977 978

         png_ptr->rgb_to_gray_red_coeff   = red_int;
         png_ptr->rgb_to_gray_green_coeff = green_int;
         png_ptr->rgb_to_gray_blue_coeff  =
          (png_uint_16)(32768 - red_int - green_int);
979
      }
980

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

987 988 989 990 991 992 993 994 995 996 997 998 999
         /* Use the defaults, from the cHRM chunk if set, else the built in Rec
          * 709 values (which correspond to sRGB, so we don't have to worry
          * about the sRGB chunk!)
          */
         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
            png_ptr->rgb_to_gray_green_coeff == 0 &&
            png_ptr->rgb_to_gray_blue_coeff == 0)
         {
            png_ptr->rgb_to_gray_red_coeff   = 6968;  /* .212671 * 32768 + .5 */
            png_ptr->rgb_to_gray_green_coeff = 23434; /* .715160 * 32768 + .5 */
            png_ptr->rgb_to_gray_blue_coeff  = 2366;
         }
      }
1000
   }
A
Andreas Dilger 已提交
1001
}
1002 1003 1004 1005 1006 1007 1008 1009

#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 已提交
1010
   double green)
1011 1012 1013 1014
{
   if (png_ptr == NULL)
      return;

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

A
Andreas Dilger 已提交
1021 1022
#endif

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

1031 1032
   if (png_ptr == NULL)
      return;
1033

1034
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1035 1036
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1037
#endif
1038 1039 1040
}
#endif

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

/*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 已提交
1074
{
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
   /* 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;
1085

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
   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 已提交
1113

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

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

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

1181 1182 1183 1184 1185 1186 1187 1188 1189
#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.
    */
1190
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
1191 1192 1193
       (png_ptr->transformations & PNG_EXPAND) &&
       !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
       /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
1194 1195
   {
      {
1196
         /* Expand background and tRNS chunks */
G
Guy Schalnat 已提交
1197 1198 1199
         switch (png_ptr->bit_depth)
         {
            case 1:
G
Guy Schalnat 已提交
1200
               png_ptr->background.gray *= (png_uint_16)0xff;
1201
               png_ptr->background.red = png_ptr->background.green
1202
                   =  png_ptr->background.blue = png_ptr->background.gray;
1203 1204
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
1205 1206
                 png_ptr->trans_color.gray *= (png_uint_16)0xff;
                 png_ptr->trans_color.red = png_ptr->trans_color.green
1207
                     = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
1208
               }
G
Guy Schalnat 已提交
1209
               break;
1210

G
Guy Schalnat 已提交
1211
            case 2:
G
Guy Schalnat 已提交
1212
               png_ptr->background.gray *= (png_uint_16)0x55;
1213
               png_ptr->background.red = png_ptr->background.green
1214
                   = png_ptr->background.blue = png_ptr->background.gray;
1215 1216
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
1217 1218 1219
                  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;
1220
               }
G
Guy Schalnat 已提交
1221
               break;
1222

G
Guy Schalnat 已提交
1223
            case 4:
G
Guy Schalnat 已提交
1224
               png_ptr->background.gray *= (png_uint_16)0x11;
1225
               png_ptr->background.red = png_ptr->background.green
1226
                   = png_ptr->background.blue = png_ptr->background.gray;
1227 1228
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
1229 1230 1231
                  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;
1232
               }
G
Guy Schalnat 已提交
1233
               break;
1234

1235 1236
            default:

G
Guy Schalnat 已提交
1237
            case 8:
1238

G
Guy Schalnat 已提交
1239
            case 16:
1240
               png_ptr->background.red = png_ptr->background.green
1241
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1242 1243 1244
               break;
         }
      }
1245 1246 1247
   } /* background expand and (therefore) no alpha association. */
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
}
1248

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

1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
      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 已提交
1286
      }
1287 1288 1289

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

1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
   /* 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
1333
    *  9) PNG_16_TO_8 or PNG_CHOP_16_TO_8 (strip16/chop16)
1334
    * 10) PNG_QUANTIZE (converts to palette)
1335
    * 11) PNG_EXPAND_16
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
    * 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;

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

1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
#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.
    *
1396
    * TODO: this code needs to be revised to avoid the complexity and
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
    * 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)
1411
   {
1412 1413 1414 1415 1416 1417
      /* 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)
1418
      {
1419 1420 1421 1422 1423 1424
         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;
         }
1425
      }
1426
   }
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
#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);
1442

1443 1444 1445
   else
      png_init_rgb_transformations(png_ptr);

1446 1447 1448 1449 1450 1451 1452 1453 1454
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
   defined(PNG_READ_EXPAND_16_SUPPORTED)
   if ((png_ptr->transformations & PNG_EXPAND_16) &&
      (png_ptr->transformations & PNG_COMPOSE) &&
      !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
      png_ptr->bit_depth != 16)
   {
      /* TODO: fix this.  Because the expand_16 operation is after the compose
       * handling the background color must be 8, not 16, bits deep, but the
1455
       * application will supply a 16-bit value so reduce it here.
1456 1457 1458
       *
       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
       * present, so that case is ok (until do_expand_16 is moved.)
1459 1460 1461
       *
       * NOTE: this discards the low 16 bits of the user supplied background
       * color, but until expand_16 works properly there is no choice!
1462
       */
1463 1464 1465 1466 1467
#     define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
      CHOP(png_ptr->background.red);
      CHOP(png_ptr->background.green);
      CHOP(png_ptr->background.blue);
      CHOP(png_ptr->background.gray);
1468 1469
#     undef CHOP
   }
1470
#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
1471

1472 1473 1474 1475
   /* 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
1476
    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
    * 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.
    *
1495
    * In 1.5.4 this is addressed below by an additional check on the individual
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505
    * 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)
1506
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1507
            || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
1508 1509 1510
               && png_gamma_significant(png_ptr->background_gamma))
#  endif
      )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
1511 1512
         && png_gamma_significant(png_ptr->screen_gamma))
      )
G
Guy Schalnat 已提交
1513
   {
1514
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1515

1516
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1517
      if (png_ptr->transformations & PNG_COMPOSE)
G
Guy Schalnat 已提交
1518
      {
1519
         if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1520
         {
1521 1522 1523
            /* 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 已提交
1524
            png_color back, back_1;
1525 1526 1527
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
1528 1529
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
G
[devel]  
Glenn Randers-Pehrson 已提交
1530

A
Andreas Dilger 已提交
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
               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 已提交
1541
               png_fixed_point g, gs;
A
Andreas Dilger 已提交
1542

1543 1544 1545 1546
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
G
[devel]  
Glenn Randers-Pehrson 已提交
1547
                     gs = PNG_FP_1;
1548
                     break;
1549

1550
                  case PNG_BACKGROUND_GAMMA_FILE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1551 1552
                     g = png_reciprocal(png_ptr->gamma);
                     gs = png_reciprocal2(png_ptr->gamma,
1553
                        png_ptr->screen_gamma);
1554
                     break;
1555

1556
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1557 1558
                     g = png_reciprocal(png_ptr->background_gamma);
                     gs = png_reciprocal2(png_ptr->background_gamma,
1559
                        png_ptr->screen_gamma);
1560 1561
                     break;
                  default:
G
[devel]  
Glenn Randers-Pehrson 已提交
1562 1563
                     g = PNG_FP_1;    /* back_1 */
                     gs = PNG_FP_1;   /* back */
1564
                     break;
1565
               }
A
Andreas Dilger 已提交
1566

1567
               if (png_gamma_significant(gs))
1568 1569 1570 1571 1572 1573 1574 1575 1576 1577
               {
                  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 已提交
1578
               {
1579
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
1580
                  back.green = (png_byte)png_ptr->background.green;
1581
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
1582
               }
1583

1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
               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 已提交
1594 1595
               else
               {
1596 1597 1598
                  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 已提交
1599 1600
               }
            }
1601

G
Guy Schalnat 已提交
1602 1603
            for (i = 0; i < num_palette; i++)
            {
1604 1605
               if (i < (int)png_ptr->num_trans &&
                   png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1606
               {
1607
                  if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1608 1609 1610
                  {
                     palette[i] = back;
                  }
1611
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
G
Guy Schalnat 已提交
1612
                  {
A
Andreas Dilger 已提交
1613
                     png_byte v, w;
G
Guy Schalnat 已提交
1614 1615

                     v = png_ptr->gamma_to_1[palette[i].red];
1616
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
1617 1618 1619
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
1620
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
G
Guy Schalnat 已提交
1621 1622 1623
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
1624
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
                     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];
               }
            }
1635 1636 1637

            /* Prevent the transformations being done again.
             *
1638
             * NOTE: this is highly dubious; it zaps the transformations in
1639 1640
             * place.  This seems inconsistent with the general treatment of the
             * transformations elsewhere.
1641
             */
1642 1643
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1644

1645
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1646
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1647
         {
1648 1649
            png_fixed_point g = PNG_FP_1;
            png_fixed_point gs = PNG_FP_1;
G
Guy Schalnat 已提交
1650 1651

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1652
            {
G
Guy Schalnat 已提交
1653
               case PNG_BACKGROUND_GAMMA_SCREEN:
G
[devel]  
Glenn Randers-Pehrson 已提交
1654 1655
                  g = png_ptr->screen_gamma;
                  /* gs = PNG_FP_1; */
G
Guy Schalnat 已提交
1656
                  break;
1657

G
Guy Schalnat 已提交
1658
               case PNG_BACKGROUND_GAMMA_FILE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1659 1660
                  g = png_reciprocal(png_ptr->gamma);
                  gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1661
                  break;
1662

G
Guy Schalnat 已提交
1663
               case PNG_BACKGROUND_GAMMA_UNIQUE:
G
[devel]  
Glenn Randers-Pehrson 已提交
1664 1665
                  g = png_reciprocal(png_ptr->background_gamma);
                  gs = png_reciprocal2(png_ptr->background_gamma,
1666
                      png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1667
                  break;
1668 1669

               default:
1670
                  png_error(png_ptr, "invalid background gamma type");
G
Guy Schalnat 已提交
1671 1672
            }

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

G
[devel]  
Glenn Randers-Pehrson 已提交
1676 1677
            png_ptr->background.gray = png_gamma_correct(png_ptr,
                png_ptr->background.gray, gs);
1678

1679 1680 1681
            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 已提交
1682
            {
1683
               /* RGB or RGBA with color background */
G
[devel]  
Glenn Randers-Pehrson 已提交
1684 1685
               png_ptr->background_1.red = png_gamma_correct(png_ptr,
                   png_ptr->background.red, g);
1686

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

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

G
[devel]  
Glenn Randers-Pehrson 已提交
1693 1694
               png_ptr->background.red = png_gamma_correct(png_ptr,
                   png_ptr->background.red, gs);
1695

G
[devel]  
Glenn Randers-Pehrson 已提交
1696 1697
               png_ptr->background.green = png_gamma_correct(png_ptr,
                   png_ptr->background.green, gs);
1698

G
[devel]  
Glenn Randers-Pehrson 已提交
1699 1700
               png_ptr->background.blue = png_gamma_correct(png_ptr,
                   png_ptr->background.blue, gs);
G
Guy Schalnat 已提交
1701
            }
1702

G
Guy Schalnat 已提交
1703 1704
            else
            {
1705 1706
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
1707
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1708

1709
               png_ptr->background.red = png_ptr->background.green
1710
                   = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1711
            }
1712 1713 1714
         } /* color_type != PNG_COLOR_TYPE_PALETTE */
      }/* png_ptr->transformations & PNG_BACKGROUND */

G
Guy Schalnat 已提交
1715
      else
1716
      /* Transformation does not include PNG_BACKGROUND */
1717
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1718
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1719
      {
1720 1721 1722
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1723

1724 1725 1726
         /*NOTE: there are other transformations that should probably be in here
          * too.
          */
G
Guy Schalnat 已提交
1727 1728 1729 1730 1731 1732
         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];
         }
1733

1734 1735
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
1736
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
G
Guy Schalnat 已提交
1737
   }
1738
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1739
   else
G
Guy Schalnat 已提交
1740
#endif
G
[devel]  
Glenn Randers-Pehrson 已提交
1741
#endif /* PNG_READ_GAMMA_SUPPORTED */
1742

1743
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1744 1745 1746
   /* 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 已提交
1747
   {
1748 1749
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
1750
      png_color back;
1751
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
1752 1753 1754 1755 1756

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

1757
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1758
      {
1759
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1760 1761 1762
         {
            palette[i] = back;
         }
1763

1764
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1765
         {
1766
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1767
            png_composite(palette[i].red, palette[i].red,
1768
                png_ptr->trans_alpha[i], back.red);
1769

A
Andreas Dilger 已提交
1770
            png_composite(palette[i].green, palette[i].green,
1771
                png_ptr->trans_alpha[i], back.green);
1772

A
Andreas Dilger 已提交
1773
            png_composite(palette[i].blue, palette[i].blue,
1774
                png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1775 1776
         }
      }
1777

1778
      png_ptr->transformations &= ~PNG_COMPOSE;
G
Guy Schalnat 已提交
1779
   }
1780
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
1781

1782
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
1783
   if ((png_ptr->transformations & PNG_SHIFT) &&
1784
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1785
   {
1786 1787 1788 1789 1790
      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 已提交
1791 1792 1793

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

G
Guy Schalnat 已提交
1795 1796
      if (sg < 0 || sg > 8)
         sg = 0;
1797

G
Guy Schalnat 已提交
1798 1799
      if (sb < 0 || sb > 8)
         sb = 0;
1800

1801
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1802 1803 1804 1805 1806 1807
      {
         png_ptr->palette[i].red >>= sr;
         png_ptr->palette[i].green >>= sg;
         png_ptr->palette[i].blue >>= sb;
      }
   }
1808
#endif  /* PNG_READ_SHIFT_SUPPORTED */
G
Guy Schalnat 已提交
1809 1810
}

A
Andreas Dilger 已提交
1811
/* Modify the info structure to reflect the transformations.  The
1812 1813 1814
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1815
void /* PRIVATE */
G
Guy Schalnat 已提交
1816
png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1817
{
1818
   png_debug(1, "in png_read_transform_info");
1819

1820
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
1821
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1822
   {
A
Andreas Dilger 已提交
1823 1824
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
1825
         /* This check must match what actually happens in
1826
          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1827 1828 1829
          * it is all opaque we must do the same (at present it does not.)
          */
         if (png_ptr->num_trans > 0)
A
Andreas Dilger 已提交
1830
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1831

A
Andreas Dilger 已提交
1832 1833
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1834

G
Guy Schalnat 已提交
1835
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1836 1837 1838 1839 1840
         info_ptr->num_trans = 0;
      }
      else
      {
         if (png_ptr->num_trans)
1841 1842
         {
            if (png_ptr->transformations & PNG_EXPAND_tRNS)
1843
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1844
         }
A
Andreas Dilger 已提交
1845 1846
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
1847

A
Andreas Dilger 已提交
1848 1849
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1850 1851 1852
   }
#endif

1853 1854 1855 1856 1857 1858
#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 已提交
1859 1860 1861
      info_ptr->background = png_ptr->background;
#endif

1862
#ifdef PNG_READ_GAMMA_SUPPORTED
1863
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1864 1865 1866 1867 1868
    * 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;
1869
#endif
1870

1871
#ifdef PNG_READ_16_TO_8_SUPPORTED
1872
#ifdef PNG_READ_16BIT_SUPPORTED
1873 1874
   if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_CHOP_16_TO_8)) &&
       (info_ptr->bit_depth == 16))
G
Guy Schalnat 已提交
1875
      info_ptr->bit_depth = 8;
1876 1877
#else
   /* Force chopping 16-bit input down to 8 */
1878 1879
   if (info_ptr->bit_depth == 16)
   {
1880 1881
      if (!(png_ptr->transformations & PNG_CHOP_16_TO_8))
        png_ptr->transformations |=PNG_16_TO_8;
1882 1883
      info_ptr->bit_depth = 8;
   }
1884
#endif
G
Guy Schalnat 已提交
1885 1886
#endif

1887
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1888 1889 1890 1891
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
#endif

1892
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1893 1894 1895 1896
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
#endif

1897 1898
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
1899 1900
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1901 1902
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
1903 1904 1905
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
1906
   }
G
Guy Schalnat 已提交
1907 1908
#endif

1909 1910 1911 1912 1913 1914 1915 1916
#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

1917
#ifdef PNG_READ_PACK_SUPPORTED
1918
   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
1919 1920 1921
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
1922
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1923
      info_ptr->channels = 1;
1924

G
Guy Schalnat 已提交
1925 1926
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
1927

G
Guy Schalnat 已提交
1928 1929
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
1930

1931
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1932
   if (png_ptr->transformations & PNG_STRIP_ALPHA)
1933
   {
A
Andreas Dilger 已提交
1934
      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1935 1936
      info_ptr->num_trans = 0;
   }
A
Andreas Dilger 已提交
1937 1938
#endif

1939 1940 1941
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

1942
#ifdef PNG_READ_FILLER_SUPPORTED
1943
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1944 1945 1946
   if ((png_ptr->transformations & PNG_FILLER) &&
       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1947
   {
1948
      info_ptr->channels++;
1949
      /* If adding a true alpha channel not just filler */
1950
      if (png_ptr->transformations & PNG_ADD_ALPHA)
1951
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1952
   }
A
Andreas Dilger 已提交
1953 1954
#endif

1955 1956
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1957
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
1958 1959
   {
      if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1960
         info_ptr->bit_depth = png_ptr->user_transform_depth;
1961

1962
      if (info_ptr->channels < png_ptr->user_transform_channels)
1963
         info_ptr->channels = png_ptr->user_transform_channels;
1964
   }
1965 1966
#endif

G
Guy Schalnat 已提交
1967
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1968
       info_ptr->bit_depth);
1969

1970
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1971

1972
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
1973 1974 1975 1976 1977 1978 1979
    * check in png_rowbytes that the user buffer won't get overwritten.  Note
    * that the field is not always set - if png_read_update_info isn't called
    * the application has to either not do any transforms or get the calculation
    * right itself.
    */
   png_ptr->info_rowbytes = info_ptr->rowbytes;

1980
#ifndef PNG_READ_EXPAND_SUPPORTED
1981
   if (png_ptr)
1982 1983
      return;
#endif
G
Guy Schalnat 已提交
1984 1985
}

1986 1987 1988 1989
/* 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.
 */
1990
void /* PRIVATE */
G
Guy Schalnat 已提交
1991
png_do_read_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
1992
{
1993
   png_debug(1, "in png_do_read_transformations");
1994

A
Andreas Dilger 已提交
1995
   if (png_ptr->row_buf == NULL)
G
Guy Schalnat 已提交
1996
   {
1997
      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
1998 1999 2000
       * error is incredibly rare and incredibly easy to debug without this
       * information.
       */
2001
      png_error(png_ptr, "NULL row buffer");
G
Guy Schalnat 已提交
2002
   }
2003

2004 2005
   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
2006 2007 2008 2009 2010 2011 2012 2013
    * 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.
2014
       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
2015
       */
2016
      png_error(png_ptr, "Uninitialized row");
2017
   }
A
Andreas Dilger 已提交
2018

2019
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
2020
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
2021
   {
A
Andreas Dilger 已提交
2022 2023 2024
      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
2025
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
A
Andreas Dilger 已提交
2026
      }
2027

2028
      else
A
Andreas Dilger 已提交
2029
      {
2030 2031
         if (png_ptr->num_trans &&
             (png_ptr->transformations & PNG_EXPAND_tRNS))
A
Andreas Dilger 已提交
2032
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
2033
                &(png_ptr->trans_color));
2034

2035
         else
A
Andreas Dilger 已提交
2036
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
2037
                NULL);
A
Andreas Dilger 已提交
2038
      }
G
Guy Schalnat 已提交
2039
   }
G
Guy Schalnat 已提交
2040 2041
#endif

2042
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2043
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
2044
      !(png_ptr->transformations & PNG_COMPOSE) &&
2045 2046 2047
      (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,
2048
         0 /* at_start == false, because SWAP_ALPHA happens later */);
A
Andreas Dilger 已提交
2049 2050
#endif

2051
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2052 2053 2054
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
   {
      int rgb_error =
2055 2056 2057
          png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
              png_ptr->row_buf + 1);

2058
      if (rgb_error)
2059 2060
      {
         png_ptr->rgb_to_gray_status=1;
2061
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
2062
             PNG_RGB_TO_GRAY_WARN)
2063
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
2064

2065 2066
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_ERR)
2067 2068 2069 2070 2071
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

2072
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
2073
 *
2074 2075 2076 2077
 *   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.
2078
 *
2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100
 *   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.
2101 2102
 */

2103
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2104 2105 2106
   /* If gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons
    */
2107
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
2108
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
2109 2110 2111
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2112 2113 2114 2115
#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 已提交
2116 2117
#endif

2118
#ifdef PNG_READ_GAMMA_SUPPORTED
G
Guy Schalnat 已提交
2119
   if ((png_ptr->transformations & PNG_GAMMA) &&
2120 2121 2122
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
       !((png_ptr->transformations & PNG_COMPOSE) &&
2123 2124
       ((png_ptr->num_trans != 0) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
2125
#endif
2126
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
2127
      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
G
Guy Schalnat 已提交
2128 2129
#endif

2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
#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

2145 2146
#ifdef PNG_READ_16_TO_8_SUPPORTED
   if (png_ptr->transformations & PNG_16_TO_8)
2147
      png_do_scale_16_to_8(&(png_ptr->row_info), png_ptr->row_buf + 1);
2148
#  ifdef PNG_READ_CHOP_16_TO_8_SUPPORTED
2149
   else if (png_ptr->transformations & PNG_CHOP_16_TO_8)
2150
      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
2151
#  endif
2152 2153
#endif

2154 2155
#ifdef PNG_READ_QUANTIZE_SUPPORTED
   if (png_ptr->transformations & PNG_QUANTIZE)
G
Guy Schalnat 已提交
2156
   {
2157
      png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1,
2158
          png_ptr->palette_lookup, png_ptr->quantize_index);
2159

2160
      if (png_ptr->row_info.rowbytes == 0)
2161
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
A
Andreas Dilger 已提交
2162
   }
2163
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
G
Guy Schalnat 已提交
2164

2165 2166 2167 2168 2169 2170 2171 2172 2173
#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
2174 2175

#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2176
   /*NOTE: moved here in 1.5.4 (from much later in this list.) */
2177 2178 2179 2180
   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
2181

2182
#ifdef PNG_READ_INVERT_SUPPORTED
G
Guy Schalnat 已提交
2183
   if (png_ptr->transformations & PNG_INVERT_MONO)
G
Guy Schalnat 已提交
2184
      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2185 2186
#endif

2187
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
2188 2189
   if (png_ptr->transformations & PNG_SHIFT)
      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
2190
          &(png_ptr->shift));
G
Guy Schalnat 已提交
2191 2192
#endif

2193
#ifdef PNG_READ_PACK_SUPPORTED
G
Guy Schalnat 已提交
2194
   if (png_ptr->transformations & PNG_PACK)
G
Guy Schalnat 已提交
2195
      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2196 2197
#endif

2198
#ifdef PNG_READ_BGR_SUPPORTED
G
Guy Schalnat 已提交
2199 2200
   if (png_ptr->transformations & PNG_BGR)
      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2201 2202
#endif

2203
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2204 2205 2206 2207
   if (png_ptr->transformations & PNG_PACKSWAP)
      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2208
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
2209 2210
   if (png_ptr->transformations & PNG_FILLER)
      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
2211
          (png_uint_32)png_ptr->filler, png_ptr->flags);
A
Andreas Dilger 已提交
2212 2213
#endif

2214
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2215 2216 2217 2218
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2219
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2220 2221 2222 2223
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

2224
#ifdef PNG_READ_16BIT_SUPPORTED
2225
#ifdef PNG_READ_SWAP_SUPPORTED
A
Andreas Dilger 已提交
2226 2227
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
2228
#endif
2229
#endif
2230

2231
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
2232
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
2233
    {
2234
      if (png_ptr->read_user_transform_fn != NULL)
2235
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
2236 2237 2238
             (png_ptr,                    /* png_ptr */
             &(png_ptr->row_info),     /* row_info: */
                /*  png_uint_32 width;       width of row */
2239
                /*  png_size_t rowbytes;     number of bytes in row */
2240 2241 2242 2243 2244
                /*  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 */
2245
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
2246
      if (png_ptr->user_transform_depth)
2247
         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
2248

2249
      if (png_ptr->user_transform_channels)
2250
         png_ptr->row_info.channels = png_ptr->user_transform_channels;
2251
#endif
2252
      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
2253
          png_ptr->row_info.channels);
2254

2255
      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
2256
          png_ptr->row_info.width);
2257
   }
2258
#endif
G
Guy Schalnat 已提交
2259 2260
}

2261
#ifdef PNG_READ_PACK_SUPPORTED
2262 2263 2264 2265 2266 2267
/* 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.
 */
2268
void /* PRIVATE */
G
Guy Schalnat 已提交
2269
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2270
{
2271
   png_debug(1, "in png_do_unpack");
2272

A
Andreas Dilger 已提交
2273
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
2274
   {
2275
      png_uint_32 i;
2276
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
2277

G
Guy Schalnat 已提交
2278 2279 2280 2281
      switch (row_info->bit_depth)
      {
         case 1:
         {
2282 2283
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
2284
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
2285
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2286
            {
2287
               *dp = (png_byte)((*sp >> shift) & 0x01);
2288

G
Guy Schalnat 已提交
2289 2290 2291 2292
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
2293
               }
2294

G
Guy Schalnat 已提交
2295 2296 2297 2298 2299 2300 2301
               else
                  shift++;

               dp--;
            }
            break;
         }
2302

G
Guy Schalnat 已提交
2303 2304 2305
         case 2:
         {

2306 2307
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
2308
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
2309
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2310
            {
2311
               *dp = (png_byte)((*sp >> shift) & 0x03);
2312

G
Guy Schalnat 已提交
2313 2314 2315 2316 2317
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
2318

G
Guy Schalnat 已提交
2319 2320 2321 2322 2323 2324 2325
               else
                  shift += 2;

               dp--;
            }
            break;
         }
2326

G
Guy Schalnat 已提交
2327 2328
         case 4:
         {
2329 2330
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
2331
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
2332
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2333
            {
2334
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2335

G
Guy Schalnat 已提交
2336 2337 2338 2339 2340
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
2341

G
Guy Schalnat 已提交
2342 2343 2344 2345 2346 2347 2348
               else
                  shift = 4;

               dp--;
            }
            break;
         }
2349 2350 2351

         default:
            break;
G
Guy Schalnat 已提交
2352 2353
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2354
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2355
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
2356 2357
   }
}
G
Guy Schalnat 已提交
2358
#endif
G
Guy Schalnat 已提交
2359

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

A
Andreas Dilger 已提交
2372 2373
   if (
       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2374 2375
   {
      int shift[4];
2376 2377 2378
      int channels = 0;
      int c;
      png_uint_16 value = 0;
2379
      png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2380 2381 2382

      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
G
Guy Schalnat 已提交
2383 2384 2385
         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 已提交
2386
      }
2387

G
Guy Schalnat 已提交
2388 2389
      else
      {
G
Guy Schalnat 已提交
2390
         shift[channels++] = row_info->bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
2391
      }
2392

G
Guy Schalnat 已提交
2393 2394
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
G
Guy Schalnat 已提交
2395
         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
2396
      }
G
Guy Schalnat 已提交
2397

A
Andreas Dilger 已提交
2398
      for (c = 0; c < channels; c++)
G
Guy Schalnat 已提交
2399
      {
A
Andreas Dilger 已提交
2400 2401
         if (shift[c] <= 0)
            shift[c] = 0;
2402

G
Guy Schalnat 已提交
2403 2404 2405
         else
            value = 1;
      }
G
Guy Schalnat 已提交
2406

G
Guy Schalnat 已提交
2407 2408
      if (!value)
         return;
G
Guy Schalnat 已提交
2409

G
Guy Schalnat 已提交
2410
      switch (row_info->bit_depth)
G
Guy Schalnat 已提交
2411
      {
2412
         default:
2413
            break;
2414

G
Guy Schalnat 已提交
2415 2416
         case 2:
         {
A
Andreas Dilger 已提交
2417
            png_bytep bp;
2418 2419
            png_size_t i;
            png_size_t istop = row_info->rowbytes;
A
Andreas Dilger 已提交
2420

2421
            for (bp = row, i = 0; i < istop; i++)
G
Guy Schalnat 已提交
2422 2423
            {
               *bp >>= 1;
2424
               *bp++ &= 0x55;
G
Guy Schalnat 已提交
2425 2426 2427
            }
            break;
         }
2428

G
Guy Schalnat 已提交
2429 2430
         case 4:
         {
2431
            png_bytep bp = row;
2432 2433
            png_size_t i;
            png_size_t istop = row_info->rowbytes;
2434
            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
2435
                (png_byte)((int)0xf >> shift[0]));
2436

2437
            for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
2438 2439
            {
               *bp >>= shift[0];
2440
               *bp++ &= mask;
G
Guy Schalnat 已提交
2441 2442 2443
            }
            break;
         }
2444

G
Guy Schalnat 已提交
2445 2446
         case 8:
         {
2447
            png_bytep bp = row;
2448
            png_uint_32 i;
2449
            png_uint_32 istop = row_width * channels;
G
Guy Schalnat 已提交
2450

2451
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
2452
            {
2453
               *bp++ >>= shift[i%channels];
G
Guy Schalnat 已提交
2454 2455 2456
            }
            break;
         }
2457

2458
#ifdef PNG_READ_16BIT_SUPPORTED
G
Guy Schalnat 已提交
2459 2460
         case 16:
         {
2461 2462 2463
            png_bytep bp = row;
            png_uint_32 i;
            png_uint_32 istop = channels * row_width;
G
Guy Schalnat 已提交
2464

2465
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
2466
            {
2467 2468 2469 2470
               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 已提交
2471 2472 2473
            }
            break;
         }
2474
#endif
G
Guy Schalnat 已提交
2475 2476 2477
      }
   }
}
G
Guy Schalnat 已提交
2478
#endif
G
Guy Schalnat 已提交
2479

2480
#ifdef PNG_READ_16_TO_8_SUPPORTED
2481
/* Scale rows of bit depth 16 down to 8 accurately */
2482
void /* PRIVATE */
2483
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2484
{
2485
   png_debug(1, "in png_do_scale_16_to_8");
2486

A
Andreas Dilger 已提交
2487
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2488
   {
2489 2490 2491
      png_bytep sp = row; /* source */
      png_bytep dp = row; /* destinaton */
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
A
Andreas Dilger 已提交
2492

2493
      while (sp < ep)
G
Guy Schalnat 已提交
2494
      {
2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525
         /* The input is an array of 16 bit components, these must be scaled to
          * 8 bits each.  For a 16 bit value V the required value (from the PNG
          * specification) is:
          *
          *    (V * 255) / 65535
          *
          * This reduces to round(V / 257), or floor((V + 128.5)/257)
          *
          * Represent V as the two byte value vhi.vlo.  Make a guess that the
          * result is the top byte of V, vhi, then the correction to this value
          * is:
          *
          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
          *          = floor(((vlo-vhi) + 128.5) / 257)
          *
          * This can be approximated using integer arithmetic (and a signed
          * shift):
          *
          *    error = (vlo-vhi+128) >> 8;
          *
          * The approximate differs from the exact answer only when (vlo-vhi) is
          * 128; it then gives a correction of +1 when the exact correction is
          * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit
          * input values) is:
          *
          *    error = (vlo-vhi+128)*65535 >> 24;
          *
          * An alternative arithmetic calculation which also gives no errors is:
          *
          *    (V * 255 + 32895) >> 16
          */
2526

2527
         png_int_32 tmp = *sp++; /* must be signed! */
2528
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2529
         *dp++ = (png_byte)tmp;
G
Guy Schalnat 已提交
2530
      }
2531

G
Guy Schalnat 已提交
2532
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
2533
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2534
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
2535 2536
   }
}
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563

void /* PRIVATE */
/* Simply discard the low byte.  This was the default behavior prior
 * to libpng-1.5.4.
 */
png_do_chop(png_row_infop row_info, png_bytep row)
{
   png_debug(1, "in png_do_chop");

   if (row_info->bit_depth == 16)
   {
      png_bytep sp = row; /* source */
      png_bytep dp = row; /* destinaton */
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */

      while (sp < ep)
      {
         *dp++ = *sp++;
         sp++;
      }

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

2565
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2566
void /* PRIVATE */
A
Andreas Dilger 已提交
2567 2568
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
2569
   png_debug(1, "in png_do_read_swap_alpha");
2570

A
Andreas Dilger 已提交
2571
   {
2572
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2573 2574 2575 2576 2577
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
2578 2579
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2580 2581
            png_byte save;
            png_uint_32 i;
2582

2583
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2584 2585 2586 2587 2588 2589 2590 2591
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2592 2593

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2594 2595 2596
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
2597 2598
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2599 2600
            png_byte save[2];
            png_uint_32 i;
2601

2602
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2616
#endif
A
Andreas Dilger 已提交
2617
      }
2618

A
Andreas Dilger 已提交
2619 2620 2621 2622 2623
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
2624 2625
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2626 2627
            png_byte save;
            png_uint_32 i;
2628

2629
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2630 2631 2632 2633 2634 2635
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
2636 2637

#ifdef PNG_READ_16BIT_SUPPORTED
A
Andreas Dilger 已提交
2638 2639 2640
         /* This converts from GGAA to AAGG */
         else
         {
2641 2642
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
2643 2644 2645
            png_byte save[2];
            png_uint_32 i;

2646
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
2647 2648 2649 2650 2651 2652 2653 2654 2655
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
2656
#endif
A
Andreas Dilger 已提交
2657
      }
G
Guy Schalnat 已提交
2658 2659
   }
}
G
Guy Schalnat 已提交
2660
#endif
G
Guy Schalnat 已提交
2661

2662
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2663
void /* PRIVATE */
2664 2665
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
2666
   png_uint_32 row_width;
2667
   png_debug(1, "in png_do_read_invert_alpha");
2668

2669 2670
   row_width = row_info->width;
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2671
   {
2672
      if (row_info->bit_depth == 8)
2673 2674
      {
         /* This inverts the alpha channel in RGBA */
2675 2676 2677
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2678

2679 2680 2681
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
2682

2683 2684 2685 2686 2687
/*          This does nothing:
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            We can replace it with:
2688
*/
2689 2690
            sp-=3;
            dp=sp;
2691
         }
2692
      }
2693 2694

#ifdef PNG_READ_16BIT_SUPPORTED
2695 2696 2697 2698 2699 2700
      /* This inverts the alpha channel in RRGGBBAA */
      else
      {
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2701

2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714
         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:
2715
*/
2716 2717
            sp-=6;
            dp=sp;
2718 2719
         }
      }
2720
#endif
2721 2722 2723 2724
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   {
      if (row_info->bit_depth == 8)
2725
      {
2726
         /* This inverts the alpha channel in GA */
2727 2728 2729
         png_bytep sp = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2730

2731 2732 2733 2734
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = *(--sp);
2735
         }
2736
      }
2737 2738

#ifdef PNG_READ_16BIT_SUPPORTED
2739 2740
      else
      {
2741
         /* This inverts the alpha channel in GGAA */
2742 2743 2744
         png_bytep sp  = row + row_info->rowbytes;
         png_bytep dp = sp;
         png_uint_32 i;
2745

2746 2747 2748 2749
         for (i = 0; i < row_width; i++)
         {
            *(--dp) = (png_byte)(255 - *(--sp));
            *(--dp) = (png_byte)(255 - *(--sp));
2750
/*
2751 2752
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
2753
*/
2754 2755
            sp-=2;
            dp=sp;
2756 2757
         }
      }
2758
#endif
2759 2760 2761 2762
   }
}
#endif

2763
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2764
/* Add filler channel if we have RGB color */
2765
void /* PRIVATE */
G
Guy Schalnat 已提交
2766
png_do_read_filler(png_row_infop row_info, png_bytep row,
2767
    png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2768
{
G
Guy Schalnat 已提交
2769
   png_uint_32 i;
2770 2771
   png_uint_32 row_width = row_info->width;

2772
#ifdef PNG_READ_16BIT_SUPPORTED
2773
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2774
#endif
2775
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
2776

2777
   png_debug(1, "in png_do_read_filler");
2778

A
Andreas Dilger 已提交
2779
   if (
2780
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2781
   {
2782
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2783
      {
2784
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2785
         {
2786
            /* This changes the data from G to GX */
2787 2788
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
2789 2790
            for (i = 1; i < row_width; i++)
            {
2791
               *(--dp) = lo_filler;
2792 2793
               *(--dp) = *(--sp);
            }
2794
            *(--dp) = lo_filler;
2795 2796 2797 2798
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
2799

2800 2801
         else
         {
2802
            /* This changes the data from G to XG */
2803 2804
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2805 2806 2807
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2808
               *(--dp) = lo_filler;
2809 2810 2811 2812 2813 2814
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2815

2816
#ifdef PNG_READ_16BIT_SUPPORTED
2817
      else if (row_info->bit_depth == 16)
2818 2819 2820
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2821
            /* This changes the data from GG to GGXX */
2822 2823
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2824 2825 2826
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2827
               *(--dp) = lo_filler;
2828 2829 2830
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2831 2832
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2833 2834
            row_info->channels = 2;
            row_info->pixel_depth = 32;
2835
            row_info->rowbytes = row_width * 4;
2836
         }
2837

2838 2839
         else
         {
2840
            /* This changes the data from GG to XXGG */
2841 2842
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2843 2844 2845 2846 2847
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2848
               *(--dp) = lo_filler;
2849 2850
            }
            row_info->channels = 2;
2851 2852
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
2853
         }
G
Guy Schalnat 已提交
2854
      }
2855
#endif
2856 2857 2858
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
2859
      if (row_info->bit_depth == 8)
2860 2861 2862
      {
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2863
            /* This changes the data from RGB to RGBX */
2864 2865
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
2866 2867
            for (i = 1; i < row_width; i++)
            {
2868
               *(--dp) = lo_filler;
2869 2870 2871 2872
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2873
            *(--dp) = lo_filler;
2874 2875 2876 2877
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
2878

2879 2880
         else
         {
2881
            /* This changes the data from RGB to XRGB */
2882 2883
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
2884 2885 2886 2887 2888
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2889
               *(--dp) = lo_filler;
2890 2891 2892 2893 2894 2895
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
2896

2897
#ifdef PNG_READ_16BIT_SUPPORTED
2898
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2899
      {
2900
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2901
         {
2902
            /* This changes the data from RRGGBB to RRGGBBXX */
2903 2904
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2905 2906 2907
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2908
               *(--dp) = lo_filler;
2909 2910 2911 2912 2913 2914 2915
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2916 2917
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2918 2919
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2920
            row_info->rowbytes = row_width * 8;
2921
         }
2922

2923 2924
         else
         {
2925
            /* This changes the data from RRGGBB to XXRRGGBB */
2926 2927
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2928 2929 2930 2931 2932 2933 2934 2935 2936
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2937
               *(--dp) = lo_filler;
2938
            }
2939

2940 2941
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2942
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2943
         }
G
Guy Schalnat 已提交
2944
      }
2945
#endif
2946
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2947
}
G
Guy Schalnat 已提交
2948
#endif
G
Guy Schalnat 已提交
2949

2950
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2951
/* Expand grayscale files to RGB, with or without alpha */
2952
void /* PRIVATE */
G
Guy Schalnat 已提交
2953
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2954
{
G
Guy Schalnat 已提交
2955
   png_uint_32 i;
2956
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2957

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

A
Andreas Dilger 已提交
2960
   if (row_info->bit_depth >= 8 &&
2961
       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
G
Guy Schalnat 已提交
2962 2963 2964 2965 2966
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
2967
            /* This changes G to RGB */
2968 2969
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2970
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2971 2972 2973
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
2974
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2975 2976
            }
         }
2977

G
Guy Schalnat 已提交
2978 2979
         else
         {
2980
            /* This changes GG to RRGGBB */
2981 2982
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2983
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2984 2985 2986 2987 2988
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2989 2990
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2991 2992 2993
            }
         }
      }
2994

G
Guy Schalnat 已提交
2995 2996 2997 2998
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
2999
            /* This changes GA to RGBA */
3000 3001
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
3002
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3003 3004 3005 3006
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
3007
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3008 3009
            }
         }
3010

G
Guy Schalnat 已提交
3011 3012
         else
         {
3013
            /* This changes GGAA to RRGGBBAA */
3014 3015
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
3016
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3017 3018 3019 3020 3021 3022 3023
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
3024 3025
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
3026 3027 3028
            }
         }
      }
G
Guy Schalnat 已提交
3029
      row_info->channels += (png_byte)2;
G
Guy Schalnat 已提交
3030
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
G
Guy Schalnat 已提交
3031
      row_info->pixel_depth = (png_byte)(row_info->channels *
3032
          row_info->bit_depth);
3033
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3034 3035
   }
}
G
Guy Schalnat 已提交
3036
#endif
G
Guy Schalnat 已提交
3037

3038
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
3039
/* Reduce RGB files to grayscale, with or without alpha
3040
 * using the equation given in Poynton's ColorFAQ at
3041
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
3042
 * New link:
3043
 * <http://www.poynton.com/notes/colour_and_gamma/>
3044
 * Charles Poynton poynton at poynton.com
3045 3046 3047 3048
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
 *  We approximate this with
3049
 *
3050
 *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
3051 3052 3053
 *
 *  which can be expressed with integers as
 *
3054
 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
3055 3056 3057 3058 3059
 *
 *  The calculation is to be done in a linear colorspace.
 *
 *  Other integer coefficents can be used via png_set_rgb_to_gray().
 */
3060
int /* PRIVATE */
3061 3062 3063 3064 3065 3066 3067 3068
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;

3069
   png_debug(1, "in png_do_rgb_to_gray");
3070

3071
   if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
3072
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
3073
   {
3074 3075 3076
      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;
3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092

      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++)];
3093

3094
                  if (red != green || red != blue)
3095 3096 3097
                  {
                     rgb_error |= 1;
                     *(dp++) = png_ptr->gamma_from_1[
3098
                         (rc*red + gc*green + bc*blue)>>15];
3099
                  }
3100

3101
                  else
3102
                     *(dp++) = *(sp - 1);
3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114
               }
            }
            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++);
3115

3116
                  if (red != green || red != blue)
3117 3118
                  {
                     rgb_error |= 1;
3119
                     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3120
                  }
3121

3122
                  else
3123
                     *(dp++) = *(sp - 1);
3124 3125 3126
               }
            }
         }
3127

3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139
         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;

3140 3141 3142
                  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;
3143

3144
                  if (red == green && red == blue)
3145
                     w = red;
3146

3147 3148
                  else
                  {
3149 3150
                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff)
                         >> png_ptr->gamma_shift][red>>8];
3151 3152
                     png_uint_16 green_1 =
                         png_ptr->gamma_16_to_1[(green&0xff) >>
3153
                         png_ptr->gamma_shift][green>>8];
3154 3155
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff)
                         >> png_ptr->gamma_shift][blue>>8];
3156
                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
3157
                         + bc*blue_1)>>15);
3158 3159 3160 3161
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
                     rgb_error |= 1;
                  }
3162

3163 3164
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, gray16;

3176 3177 3178
                  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;
3179

3180
                  if (red != green || red != blue)
3181
                     rgb_error |= 1;
3182

3183
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
3184 3185
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203
               }
            }
         }
      }
      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++)];
3204

3205
                  if (red != green || red != blue)
3206
                     rgb_error |= 1;
3207

3208
                  *(dp++) =  png_ptr->gamma_from_1
3209
                      [(rc*red + gc*green + bc*blue)>>15];
3210

3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223
                  *(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++);
3224
                  if (red != green || red != blue)
3225
                     rgb_error |= 1;
3226

3227
                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243
                  *(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;

3244 3245 3246
                  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;
3247

3248
                  if (red == green && red == blue)
3249
                     w = red;
3250

3251 3252 3253
                  else
                  {
                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
3254
                         png_ptr->gamma_shift][red>>8];
3255

3256 3257 3258
                     png_uint_16 green_1 =
                         png_ptr->gamma_16_to_1[(green&0xff) >>
                         png_ptr->gamma_shift][green>>8];
3259

3260
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
3261
                         png_ptr->gamma_shift][blue>>8];
3262

3263
                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
3264
                         + gc * green_1 + bc * blue_1)>>15);
3265

3266 3267
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
3268

3269 3270
                     rgb_error |= 1;
                  }
3271

3272 3273
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285
                  *(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;
3286 3287 3288
                  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;
3289

3290
                  if (red != green || red != blue)
3291
                     rgb_error |= 1;
3292

3293
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
3294 3295
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
3296 3297 3298 3299 3300 3301
                  *(dp++) = *(sp++);  /* alpha */
                  *(dp++) = *(sp++);
               }
            }
         }
      }
3302 3303 3304
      row_info->channels -= 2;
      row_info->color_type = (png_byte)(row_info->color_type &
          ~PNG_COLOR_MASK_COLOR);
3305
      row_info->pixel_depth = (png_byte)(row_info->channels *
3306
          row_info->bit_depth);
3307
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3308 3309 3310 3311
   }
   return rgb_error;
}
#endif
3312
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
3313

3314
#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
3315 3316 3317
/* 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
3318
 * of code.  This API is not used internally.
3319
 */
3320
void PNGAPI
G
Guy Schalnat 已提交
3321
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
3322 3323 3324 3325 3326 3327
{
   int num_palette;
   int color_inc;
   int i;
   int v;

3328
   png_debug(1, "in png_do_build_grayscale_palette");
3329

A
Andreas Dilger 已提交
3330
   if (palette == NULL)
G
Guy Schalnat 已提交
3331 3332 3333 3334 3335 3336 3337 3338
      return;

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

G
Guy Schalnat 已提交
3340 3341 3342 3343
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
3344

G
Guy Schalnat 已提交
3345 3346 3347 3348
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
3349

G
Guy Schalnat 已提交
3350 3351 3352 3353
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
3354

G
Guy Schalnat 已提交
3355
      default:
G
Guy Schalnat 已提交
3356
         num_palette = 0;
G
Guy Schalnat 已提交
3357
         color_inc = 0;
G
Guy Schalnat 已提交
3358 3359 3360 3361 3362
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
3363 3364 3365
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
3366 3367
   }
}
3368
#endif
G
Guy Schalnat 已提交
3369 3370


3371
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
3372
#ifdef PNG_READ_BACKGROUND_SUPPORTED
A
Andreas Dilger 已提交
3373
/* Replace any alpha or transparency with the supplied background color.
3374 3375 3376
 * "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.
 */
3377
void /* PRIVATE */
3378
png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
3379
{
3380
#ifdef PNG_READ_GAMMA_SUPPORTED
3381 3382 3383 3384 3385 3386 3387
   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;
3388
#endif
3389

3390
   png_bytep sp;
G
Guy Schalnat 已提交
3391
   png_uint_32 i;
3392
   png_uint_32 row_width = row_info->width;
3393
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
G
Guy Schalnat 已提交
3394
   int shift;
G
Guy Schalnat 已提交
3395

3396
   png_debug(1, "in png_do_compose");
3397

G
Guy Schalnat 已提交
3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
3409
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3410
                  {
3411
                     if ((png_uint_16)((*sp >> shift) & 0x01)
3412
                        == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3413
                     {
G
Guy Schalnat 已提交
3414
                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
3415
                        *sp |= (png_byte)(png_ptr->background.gray << shift);
G
Guy Schalnat 已提交
3416
                     }
3417

G
Guy Schalnat 已提交
3418 3419 3420 3421 3422
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
3423

G
Guy Schalnat 已提交
3424 3425 3426 3427 3428
                     else
                        shift--;
                  }
                  break;
               }
3429

G
Guy Schalnat 已提交
3430 3431
               case 2:
               {
3432
#ifdef PNG_READ_GAMMA_SUPPORTED
3433
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3434
                  {
3435 3436 3437
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3438
                     {
3439
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3440
                            == png_ptr->trans_color.gray)
3441 3442
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3443
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3444
                        }
3445

3446 3447
                        else
                        {
3448
                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
3449
                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
3450
                               (p << 4) | (p << 6)] >> 6) & 0x03);
3451 3452 3453
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3454

3455 3456 3457 3458 3459
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3460

3461 3462
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3463
                     }
3464
                  }
3465

3466 3467 3468 3469 3470 3471
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3472
                     {
3473
                        if ((png_uint_16)((*sp >> shift) & 0x03)
3474
                            == png_ptr->trans_color.gray)
3475 3476
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3477
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3478
                        }
3479

3480 3481 3482 3483 3484
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
3485

3486 3487
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
3488 3489 3490 3491
                     }
                  }
                  break;
               }
3492

G
Guy Schalnat 已提交
3493 3494
               case 4:
               {
3495
#ifdef PNG_READ_GAMMA_SUPPORTED
3496
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3497
                  {
3498 3499 3500
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3501
                     {
3502
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3503
                            == png_ptr->trans_color.gray)
3504 3505
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3506
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3507
                        }
3508

3509 3510
                        else
                        {
3511
                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
3512
                           png_byte g = (png_byte)((gamma_table[p |
3513
                               (p << 4)] >> 4) & 0x0f);
3514 3515 3516
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
3517

3518 3519 3520 3521 3522
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3523

3524 3525
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3526
                     }
3527
                  }
3528

3529 3530 3531 3532 3533 3534
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3535
                     {
3536
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
3537
                            == png_ptr->trans_color.gray)
3538 3539
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3540
                           *sp |= (png_byte)(png_ptr->background.gray << shift);
3541
                        }
3542

3543 3544 3545 3546 3547
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
3548

3549 3550
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
3551 3552 3553 3554
                     }
                  }
                  break;
               }
3555

G
Guy Schalnat 已提交
3556 3557
               case 8:
               {
3558
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3559
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
3560
                  {
3561 3562
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3563
                     {
3564 3565
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
3566

G
Guy Schalnat 已提交
3567 3568 3569 3570 3571
                        else
                           *sp = gamma_table[*sp];
                     }
                  }
                  else
G
Guy Schalnat 已提交
3572
#endif
G
Guy Schalnat 已提交
3573
                  {
3574 3575
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3576
                     {
3577 3578
                        if (*sp == png_ptr->trans_color.gray)
                           *sp = (png_byte)png_ptr->background.gray;
G
Guy Schalnat 已提交
3579 3580 3581 3582
                     }
                  }
                  break;
               }
3583

G
Guy Schalnat 已提交
3584 3585
               case 16:
               {
3586
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3587
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3588
                  {
3589 3590
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3591 3592 3593
                     {
                        png_uint_16 v;

3594
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3595

3596
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3597
                        {
3598
                           /* Background is already in screen gamma */
3599 3600
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3601
                        }
3602

G
Guy Schalnat 已提交
3603 3604
                        else
                        {
A
Andreas Dilger 已提交
3605
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3606
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3607
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3608
                        }
G
Guy Schalnat 已提交
3609
                     }
G
Guy Schalnat 已提交
3610 3611
                  }
                  else
G
Guy Schalnat 已提交
3612
#endif
G
Guy Schalnat 已提交
3613
                  {
3614 3615
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3616 3617 3618
                     {
                        png_uint_16 v;

3619
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3620

3621
                        if (v == png_ptr->trans_color.gray)
G
Guy Schalnat 已提交
3622
                        {
3623 3624
                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
G
Guy Schalnat 已提交
3625 3626 3627 3628 3629
                        }
                     }
                  }
                  break;
               }
3630 3631 3632

               default:
                  break;
G
Guy Schalnat 已提交
3633 3634 3635
            }
            break;
         }
3636

G
Guy Schalnat 已提交
3637 3638 3639 3640
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3641
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3642
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
3643
               {
3644 3645
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3646
                  {
3647 3648 3649
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3650
                     {
3651 3652 3653
                        *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 已提交
3654
                     }
3655

G
Guy Schalnat 已提交
3656 3657 3658 3659 3660 3661 3662 3663 3664
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3665
#endif
G
Guy Schalnat 已提交
3666
               {
3667 3668
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
3669
                  {
3670 3671 3672
                     if (*sp == png_ptr->trans_color.red &&
                         *(sp + 1) == png_ptr->trans_color.green &&
                         *(sp + 2) == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3673
                     {
3674 3675 3676
                        *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 已提交
3677 3678 3679 3680
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3681
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3682
            {
3683
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3684
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
3685
               {
3686 3687
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3688
                  {
3689
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3690

3691 3692
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3693

3694 3695
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
3696

3697 3698 3699
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3700
                     {
3701
                        /* Background is already in screen gamma */
3702 3703 3704 3705 3706 3707
                        *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 已提交
3708
                     }
3709

G
Guy Schalnat 已提交
3710 3711
                     else
                     {
3712
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3713
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
3714
                        *(sp + 1) = (png_byte)(v & 0xff);
3715

A
Andreas Dilger 已提交
3716
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3717 3718
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3719

A
Andreas Dilger 已提交
3720
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3721 3722
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3723 3724 3725
                     }
                  }
               }
3726

G
Guy Schalnat 已提交
3727
               else
G
Guy Schalnat 已提交
3728
#endif
G
Guy Schalnat 已提交
3729
               {
3730 3731
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
3732
                  {
3733
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3734

3735 3736
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3737

3738 3739
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
                         + *(sp + 5));
G
Guy Schalnat 已提交
3740

3741 3742 3743
                     if (r == png_ptr->trans_color.red &&
                         g == png_ptr->trans_color.green &&
                         b == png_ptr->trans_color.blue)
G
Guy Schalnat 已提交
3744
                     {
3745 3746 3747 3748 3749 3750
                        *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 已提交
3751 3752 3753 3754 3755 3756
                     }
                  }
               }
            }
            break;
         }
3757

G
Guy Schalnat 已提交
3758
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3759
         {
A
Andreas Dilger 已提交
3760
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3761
            {
3762
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3763 3764 3765
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3766
                  sp = row;
3767
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3768
                  {
3769
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3770

A
Andreas Dilger 已提交
3771
                     if (a == 0xff)
3772
                        *sp = gamma_table[*sp];
3773

A
Andreas Dilger 已提交
3774 3775
                     else if (a == 0)
                     {
3776
                        /* Background is already in screen gamma */
3777
                        *sp = (png_byte)png_ptr->background.gray;
A
Andreas Dilger 已提交
3778
                     }
3779

A
Andreas Dilger 已提交
3780 3781 3782
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3783

A
Andreas Dilger 已提交
3784
                        v = gamma_to_1[*sp];
3785
                        png_composite(w, v, a, png_ptr->background_1.gray);
3786 3787 3788
                        if (!optimize)
                           w = gamma_from_1[w];
                        *sp = w;
G
Guy Schalnat 已提交
3789 3790
                     }
                  }
A
Andreas Dilger 已提交
3791 3792
               }
               else
G
Guy Schalnat 已提交
3793
#endif
A
Andreas Dilger 已提交
3794
               {
3795
                  sp = row;
3796
                  for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
3797
                  {
3798
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3799

3800 3801
                     if (a == 0)
                        *sp = (png_byte)png_ptr->background.gray;
3802

3803 3804
                     else if (a < 0xff)
                        png_composite(*sp, *sp, a, png_ptr->background_1.gray);
G
Guy Schalnat 已提交
3805 3806
                  }
               }
A
Andreas Dilger 已提交
3807 3808 3809
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3810
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3811 3812 3813
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3814
                  sp = row;
3815
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3816
                  {
3817 3818
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
A
Andreas Dilger 已提交
3819 3820

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3821
                     {
A
Andreas Dilger 已提交
3822
                        png_uint_16 v;
G
Guy Schalnat 已提交
3823

A
Andreas Dilger 已提交
3824
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3825 3826
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3827
                     }
3828

A
Andreas Dilger 已提交
3829 3830
                     else if (a == 0)
                     {
3831
                        /* Background is already in screen gamma */
3832 3833
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3834
                     }
3835

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

A
Andreas Dilger 已提交
3840
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3841
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3842 3843 3844 3845 3846 3847
                        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 已提交
3848 3849
                     }
                  }
A
Andreas Dilger 已提交
3850 3851
               }
               else
G
Guy Schalnat 已提交
3852
#endif
A
Andreas Dilger 已提交
3853
               {
3854
                  sp = row;
3855
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3856
                  {
3857 3858
                     png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                         + *(sp + 3));
3859

3860
                     if (a == 0)
A
Andreas Dilger 已提交
3861
                     {
3862 3863
                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
A
Andreas Dilger 已提交
3864
                     }
3865

3866
                     else if (a < 0xffff)
A
Andreas Dilger 已提交
3867 3868
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3869

3870
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3871
                        png_composite_16(v, g, a, png_ptr->background_1.gray);
3872 3873
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3874 3875 3876 3877 3878 3879
                     }
                  }
               }
            }
            break;
         }
3880

G
Guy Schalnat 已提交
3881 3882 3883 3884
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3885
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3886 3887
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3888
               {
3889
                  sp = row;
3890
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3891
                  {
3892
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3893 3894 3895

                     if (a == 0xff)
                     {
3896 3897 3898
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
G
Guy Schalnat 已提交
3899
                     }
3900

G
Guy Schalnat 已提交
3901 3902
                     else if (a == 0)
                     {
3903
                        /* Background is already in screen gamma */
3904 3905 3906
                        *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 已提交
3907
                     }
3908

G
Guy Schalnat 已提交
3909 3910
                     else
                     {
A
Andreas Dilger 已提交
3911
                        png_byte v, w;
G
Guy Schalnat 已提交
3912 3913

                        v = gamma_to_1[*sp];
3914
                        png_composite(w, v, a, png_ptr->background_1.red);
3915 3916
                        if (!optimize) w = gamma_from_1[w];
                        *sp = w;
3917

G
Guy Schalnat 已提交
3918
                        v = gamma_to_1[*(sp + 1)];
3919
                        png_composite(w, v, a, png_ptr->background_1.green);
3920 3921
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 1) = w;
3922

G
Guy Schalnat 已提交
3923
                        v = gamma_to_1[*(sp + 2)];
3924
                        png_composite(w, v, a, png_ptr->background_1.blue);
3925 3926
                        if (!optimize) w = gamma_from_1[w];
                        *(sp + 2) = w;
G
Guy Schalnat 已提交
3927 3928 3929 3930
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3931
#endif
G
Guy Schalnat 已提交
3932
               {
3933
                  sp = row;
3934
                  for (i = 0; i < row_width; i++, sp += 4)
G
Guy Schalnat 已提交
3935
                  {
3936
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3937

3938
                     if (a == 0)
G
Guy Schalnat 已提交
3939
                     {
3940 3941 3942
                        *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 已提交
3943
                     }
3944

3945
                     else if (a < 0xff)
G
Guy Schalnat 已提交
3946
                     {
3947
                        png_composite(*sp, *sp, a, png_ptr->background.red);
3948

3949
                        png_composite(*(sp + 1), *(sp + 1), a,
3950
                            png_ptr->background.green);
3951

3952
                        png_composite(*(sp + 2), *(sp + 2), a,
3953
                            png_ptr->background.blue);
G
Guy Schalnat 已提交
3954 3955 3956 3957
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3958
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3959
            {
3960
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3961 3962
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
3963
               {
3964
                  sp = row;
3965
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
3966
                  {
3967 3968
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
3969

G
Guy Schalnat 已提交
3970 3971 3972 3973
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3974
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3975 3976
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
3977

A
Andreas Dilger 已提交
3978
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3979 3980
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
3981

A
Andreas Dilger 已提交
3982
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3983 3984
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3985
                     }
3986

G
Guy Schalnat 已提交
3987 3988
                     else if (a == 0)
                     {
3989
                        /* Background is already in screen gamma */
3990 3991 3992 3993 3994 3995
                        *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 已提交
3996
                     }
3997

G
Guy Schalnat 已提交
3998 3999
                     else
                     {
4000
                        png_uint_16 v, w;
A
Andreas Dilger 已提交
4001 4002

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
4003
                        png_composite_16(w, v, a, png_ptr->background_1.red);
4004 4005 4006 4007
                        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);
4008

A
Andreas Dilger 已提交
4009
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
4010
                        png_composite_16(w, v, a, png_ptr->background_1.green);
4011 4012
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4013

4014 4015
                        *(sp + 2) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(w & 0xff);
4016

A
Andreas Dilger 已提交
4017
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
4018
                        png_composite_16(w, v, a, png_ptr->background_1.blue);
4019 4020
                        if (!optimize)
                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4021

4022 4023
                        *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
4024 4025 4026
                     }
                  }
               }
4027

G
Guy Schalnat 已提交
4028
               else
G
Guy Schalnat 已提交
4029
#endif
G
Guy Schalnat 已提交
4030
               {
4031
                  sp = row;
4032
                  for (i = 0; i < row_width; i++, sp += 8)
G
Guy Schalnat 已提交
4033
                  {
4034
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
4035
                         << 8) + (png_uint_16)(*(sp + 7)));
4036

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

4047
                     else if (a < 0xffff)
G
Guy Schalnat 已提交
4048
                     {
4049
                        png_uint_16 v;
A
Andreas Dilger 已提交
4050

4051 4052 4053 4054 4055
                        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 已提交
4056

4057
                        png_composite_16(v, r, a, png_ptr->background.red);
4058 4059
                        *sp = (png_byte)((v >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(v & 0xff);
4060

4061
                        png_composite_16(v, g, a, png_ptr->background.green);
4062 4063
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
4064

4065
                        png_composite_16(v, b, a, png_ptr->background.blue);
4066 4067
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4068 4069 4070 4071 4072 4073
                     }
                  }
               }
            }
            break;
         }
4074 4075 4076

         default:
            break;
G
Guy Schalnat 已提交
4077 4078 4079
      }
   }
}
G
Guy Schalnat 已提交
4080
#endif
G
Guy Schalnat 已提交
4081

4082
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
4083
/* Gamma correct the image, avoiding the alpha channel.  Make sure
4084
 * you do this after you deal with the transparency issue on grayscale
4085
 * or RGB images. If your bit depth is 8, use gamma_table, if it
4086 4087 4088
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
4089
void /* PRIVATE */
4090
png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
G
Guy Schalnat 已提交
4091
{
4092 4093 4094 4095
   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 已提交
4096
   png_bytep sp;
G
Guy Schalnat 已提交
4097
   png_uint_32 i;
4098
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4099

4100
   png_debug(1, "in png_do_gamma");
4101

4102
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
4103
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
4104 4105 4106 4107 4108 4109 4110
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
4111 4112
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4113 4114 4115 4116 4117 4118 4119 4120 4121
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
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 4129
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
4130
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4131 4132 4133
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4134

A
Andreas Dilger 已提交
4135
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4136 4137
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4138
                  sp += 2;
4139

A
Andreas Dilger 已提交
4140
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4141 4142 4143 4144 4145 4146 4147
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
4148

G
Guy Schalnat 已提交
4149 4150 4151 4152
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4153 4154
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4155
               {
G
Guy Schalnat 已提交
4156 4157
                  *sp = gamma_table[*sp];
                  sp++;
4158

G
Guy Schalnat 已提交
4159 4160
                  *sp = gamma_table[*sp];
                  sp++;
4161

G
Guy Schalnat 已提交
4162 4163
                  *sp = gamma_table[*sp];
                  sp++;
4164

G
Guy Schalnat 已提交
4165 4166 4167
                  sp++;
               }
            }
4168

A
Andreas Dilger 已提交
4169
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4170
            {
4171 4172
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4173
               {
4174
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4175 4176
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4177
                  sp += 2;
4178

A
Andreas Dilger 已提交
4179
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4180 4181 4182
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
4183

A
Andreas Dilger 已提交
4184
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4185 4186 4187 4188 4189
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
4190 4191
            break;
         }
4192

G
Guy Schalnat 已提交
4193 4194 4195 4196
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
4197 4198
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4199 4200
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
4201
                  sp += 2;
G
Guy Schalnat 已提交
4202 4203
               }
            }
4204

A
Andreas Dilger 已提交
4205
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
4206
            {
4207 4208
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4209
               {
4210
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
4211 4212
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
4213 4214 4215 4216 4217
                  sp += 4;
               }
            }
            break;
         }
4218

G
Guy Schalnat 已提交
4219 4220
         case PNG_COLOR_TYPE_GRAY:
         {
4221 4222
            if (row_info->bit_depth == 2)
            {
4223 4224
               sp = row;
               for (i = 0; i < row_width; i += 4)
4225 4226 4227 4228 4229 4230
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

4231
                  *sp = (png_byte)(
4232 4233 4234 4235
                      ((((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) ));
4236 4237 4238
                  sp++;
               }
            }
4239

A
Andreas Dilger 已提交
4240
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
4241
            {
4242 4243
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
4244 4245 4246 4247
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

4248
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4249
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
4250 4251 4252
                  sp++;
               }
            }
4253

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

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

         default:
            break;
G
Guy Schalnat 已提交
4280 4281 4282
      }
   }
}
G
Guy Schalnat 已提交
4283
#endif
G
Guy Schalnat 已提交
4284

4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351
#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

4352
#ifdef PNG_READ_EXPAND_SUPPORTED
4353
/* Expands a palette row to an RGB or RGBA row depending
4354 4355
 * upon whether you supply trans and num_trans.
 */
4356
void /* PRIVATE */
G
Guy Schalnat 已提交
4357
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4358
   png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
4359
{
G
Guy Schalnat 已提交
4360
   int shift, value;
G
Guy Schalnat 已提交
4361
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4362
   png_uint_32 i;
4363
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4364

4365
   png_debug(1, "in png_do_expand_palette");
4366

4367
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
4368 4369 4370 4371 4372 4373 4374
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
4375 4376
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
4377
               shift = 7 - (int)((row_width + 7) & 0x07);
4378
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4379
               {
4380
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
4381
                     *dp = 1;
4382

G
Guy Schalnat 已提交
4383 4384
                  else
                     *dp = 0;
4385

G
Guy Schalnat 已提交
4386 4387 4388 4389 4390
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
4391

G
Guy Schalnat 已提交
4392 4393 4394 4395 4396 4397 4398
                  else
                     shift++;

                  dp--;
               }
               break;
            }
4399

G
Guy Schalnat 已提交
4400 4401
            case 2:
            {
4402 4403
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
4404
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4405
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4406
               {
4407
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
4408
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4409 4410 4411 4412 4413
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
4414

G
Guy Schalnat 已提交
4415 4416 4417 4418 4419 4420 4421
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
4422

G
Guy Schalnat 已提交
4423 4424
            case 4:
            {
4425 4426
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
4427
               shift = (int)((row_width & 0x01) << 2);
4428
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4429
               {
4430
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
4431
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
4432 4433 4434 4435 4436
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
4437

G
Guy Schalnat 已提交
4438 4439 4440 4441 4442 4443 4444
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
4445 4446 4447

            default:
               break;
G
Guy Schalnat 已提交
4448 4449 4450
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
4451
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4452
      }
4453

4454
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4455 4456
      {
         {
4457
            if (num_trans > 0)
G
Guy Schalnat 已提交
4458
            {
4459 4460
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
4461

4462
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4463
               {
A
Andreas Dilger 已提交
4464
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
4465
                     *dp-- = 0xff;
4466

G
Guy Schalnat 已提交
4467
                  else
4468
                     *dp-- = trans_alpha[*sp];
4469

G
Guy Schalnat 已提交
4470 4471 4472 4473 4474 4475 4476
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
4477
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
4478 4479 4480
               row_info->color_type = 6;
               row_info->channels = 4;
            }
4481

G
Guy Schalnat 已提交
4482 4483
            else
            {
4484 4485
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
4486

4487
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4488 4489 4490 4491 4492 4493
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
4494

G
Guy Schalnat 已提交
4495 4496
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
4497
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
4498 4499 4500 4501 4502 4503 4504 4505
               row_info->color_type = 2;
               row_info->channels = 3;
            }
         }
      }
   }
}

4506 4507
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
4508
 */
4509
void /* PRIVATE */
G
Guy Schalnat 已提交
4510
png_do_expand(png_row_infop row_info, png_bytep row,
4511
    png_const_color_16p trans_color)
G
Guy Schalnat 已提交
4512
{
G
Guy Schalnat 已提交
4513
   int shift, value;
G
Guy Schalnat 已提交
4514
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4515
   png_uint_32 i;
4516
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4517

4518
   png_debug(1, "in png_do_expand");
4519

G
Guy Schalnat 已提交
4520
   {
A
Andreas Dilger 已提交
4521
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
4522
      {
4523
         png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
A
Andreas Dilger 已提交
4524 4525

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
4526
         {
A
Andreas Dilger 已提交
4527
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
4528
            {
A
Andreas Dilger 已提交
4529
               case 1:
G
Guy Schalnat 已提交
4530
               {
4531
                  gray = (png_uint_16)((gray & 0x01) * 0xff);
4532 4533
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
4534
                  shift = 7 - (int)((row_width + 7) & 0x07);
4535
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4536
                  {
4537
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
4538
                        *dp = 0xff;
4539

A
Andreas Dilger 已提交
4540 4541
                     else
                        *dp = 0;
4542

A
Andreas Dilger 已提交
4543 4544 4545 4546 4547
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
4548

A
Andreas Dilger 已提交
4549 4550
                     else
                        shift++;
G
Guy Schalnat 已提交
4551

A
Andreas Dilger 已提交
4552 4553 4554
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4555
               }
4556

A
Andreas Dilger 已提交
4557
               case 2:
G
Guy Schalnat 已提交
4558
               {
4559
                  gray = (png_uint_16)((gray & 0x03) * 0x55);
4560 4561
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
4562
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4563
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4564
                  {
4565
                     value = (*sp >> shift) & 0x03;
A
Andreas Dilger 已提交
4566 4567 4568 4569 4570 4571 4572
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
4573

A
Andreas Dilger 已提交
4574 4575
                     else
                        shift += 2;
G
Guy Schalnat 已提交
4576

A
Andreas Dilger 已提交
4577 4578 4579
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4580
               }
4581

A
Andreas Dilger 已提交
4582
               case 4:
G
Guy Schalnat 已提交
4583
               {
4584
                  gray = (png_uint_16)((gray & 0x0f) * 0x11);
4585 4586
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
4587
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4588
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4589
                  {
4590
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
4591 4592 4593 4594 4595 4596
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
4597

A
Andreas Dilger 已提交
4598 4599
                     else
                        shift = 4;
G
Guy Schalnat 已提交
4600

A
Andreas Dilger 已提交
4601 4602 4603
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
4604
               }
4605 4606 4607

               default:
                  break;
G
Guy Schalnat 已提交
4608
            }
4609

A
Andreas Dilger 已提交
4610 4611
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
4612
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
4613
         }
A
Andreas Dilger 已提交
4614

4615
         if (trans_color != NULL)
G
Guy Schalnat 已提交
4616
         {
A
Andreas Dilger 已提交
4617
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4618
            {
4619
               gray = gray & 0xff;
4620 4621
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
4622

4623
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4624
               {
A
Andreas Dilger 已提交
4625 4626
                  if (*sp == gray)
                     *dp-- = 0;
4627

A
Andreas Dilger 已提交
4628 4629
                  else
                     *dp-- = 0xff;
4630

A
Andreas Dilger 已提交
4631
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4632
               }
A
Andreas Dilger 已提交
4633
            }
4634

A
Andreas Dilger 已提交
4635 4636
            else if (row_info->bit_depth == 16)
            {
4637 4638
               png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
               png_byte gray_low = (png_byte)(gray & 0xff);
A
Andreas Dilger 已提交
4639 4640
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
4641
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4642
               {
4643
                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
A
Andreas Dilger 已提交
4644 4645 4646 4647
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
4648

A
Andreas Dilger 已提交
4649 4650 4651 4652 4653
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
4654

A
Andreas Dilger 已提交
4655 4656
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
4657 4658
               }
            }
4659

A
Andreas Dilger 已提交
4660 4661 4662
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4663 4664
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
4665 4666
         }
      }
4667
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
G
Guy Schalnat 已提交
4668 4669 4670
      {
         if (row_info->bit_depth == 8)
         {
4671 4672 4673
            png_byte red = (png_byte)(trans_color->red & 0xff);
            png_byte green = (png_byte)(trans_color->green & 0xff);
            png_byte blue = (png_byte)(trans_color->blue & 0xff);
G
Guy Schalnat 已提交
4674
            sp = row + (png_size_t)row_info->rowbytes - 1;
4675 4676
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4677
            {
4678
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
4679
                  *dp-- = 0;
4680

G
Guy Schalnat 已提交
4681 4682
               else
                  *dp-- = 0xff;
4683

G
Guy Schalnat 已提交
4684 4685 4686 4687 4688 4689 4690
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
4691 4692 4693 4694 4695 4696
            png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
            png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
            png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
            png_byte red_low = (png_byte)(trans_color->red & 0xff);
            png_byte green_low = (png_byte)(trans_color->green & 0xff);
            png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
A
Andreas Dilger 已提交
4697
            sp = row + row_info->rowbytes - 1;
4698 4699
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4700
            {
4701
               if (*(sp - 5) == red_high &&
4702 4703 4704 4705 4706
                   *(sp - 4) == red_low &&
                   *(sp - 3) == green_high &&
                   *(sp - 2) == green_low &&
                   *(sp - 1) == blue_high &&
                   *(sp    ) == blue_low)
G
Guy Schalnat 已提交
4707 4708 4709 4710
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
4711

G
Guy Schalnat 已提交
4712 4713 4714 4715 4716
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
4717

G
Guy Schalnat 已提交
4718 4719 4720 4721
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4722
               *dp-- = *sp--;
G
Guy Schalnat 已提交
4723 4724 4725 4726 4727
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
4728
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4729
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4730 4731 4732
      }
   }
}
G
Guy Schalnat 已提交
4733
#endif
G
Guy Schalnat 已提交
4734

4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765
#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

4766
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4767
void /* PRIVATE */
4768
png_do_quantize(png_row_infop row_info, png_bytep row,
4769
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
G
Guy Schalnat 已提交
4770
{
G
Guy Schalnat 已提交
4771
   png_bytep sp, dp;
G
Guy Schalnat 已提交
4772
   png_uint_32 i;
4773
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
4774

4775
   png_debug(1, "in png_do_quantize");
4776

4777
   if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
4778
   {
4779
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
G
Guy Schalnat 已提交
4780 4781 4782 4783
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4784
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4785 4786 4787 4788 4789
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

4790 4791 4792 4793 4794 4795 4796
            /* 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);
             */
4797 4798 4799 4800 4801 4802 4803 4804
            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 已提交
4805 4806 4807

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

G
Guy Schalnat 已提交
4809 4810 4811
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4812
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4813
      }
4814

G
Guy Schalnat 已提交
4815
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4816
         palette_lookup != NULL)
G
Guy Schalnat 已提交
4817 4818 4819 4820
      {
         int r, g, b, p;
         sp = row;
         dp = row;
4821
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
4822 4823 4824 4825 4826 4827
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

4828 4829 4830 4831 4832 4833 4834 4835
            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 已提交
4836 4837 4838

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

G
Guy Schalnat 已提交
4840 4841 4842
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
4843
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
4844
      }
4845

G
Guy Schalnat 已提交
4846
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4847
         quantize_lookup)
G
Guy Schalnat 已提交
4848
      {
G
Guy Schalnat 已提交
4849
         sp = row;
4850

4851
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
4852
         {
4853
            *sp = quantize_lookup[*sp];
G
Guy Schalnat 已提交
4854 4855 4856 4857
         }
      }
   }
}
4858
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
4859
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
G
Guy Schalnat 已提交
4860

4861
#ifdef PNG_MNG_FEATURES_SUPPORTED
4862
/* Undoes intrapixel differencing  */
4863 4864 4865
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
4866
   png_debug(1, "in png_do_read_intrapixel");
4867

4868 4869 4870 4871 4872
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
4873

4874 4875 4876 4877 4878 4879 4880
      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;
4881

4882 4883
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
4884

4885 4886 4887 4888 4889
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4890 4891
            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
4892 4893 4894 4895 4896 4897 4898 4899 4900
         }
      }
      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;
4901

4902 4903
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
4904

4905 4906 4907 4908 4909
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4910 4911 4912 4913 4914
            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);
4915
            *(rp    ) = (png_byte)((red >> 8) & 0xff);
4916 4917 4918
            *(rp + 1) = (png_byte)(red & 0xff);
            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
            *(rp + 5) = (png_byte)(blue & 0xff);
4919 4920 4921 4922 4923
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
4924
#endif /* PNG_READ_SUPPORTED */