You need to sign in or sign up before continuing.
pngrtran.c 139.7 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.4.0 [September 23, 2009]
5
 * Copyright (c) 1998-2009 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 "png.h"
20
#ifdef PNG_READ_SUPPORTED
21
#include "pngpriv.h"
22

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;
   }
}

91 92
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
    defined(PNG_FLOATING_POINT_SUPPORTED)
93
/* Handle alpha and tRNS via a background color */
94
void PNGAPI
G
Guy Schalnat 已提交
95 96
png_set_background(png_structp png_ptr,
   png_color_16p background_color, int background_gamma_code,
G
Guy Schalnat 已提交
97
   int need_expand, double background_gamma)
G
Guy Schalnat 已提交
98
{
99
   png_debug(1, "in png_set_background");
100
 
101 102
   if (png_ptr == NULL)
      return;
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;
   }

G
Guy Schalnat 已提交
109
   png_ptr->transformations |= PNG_BACKGROUND;
110 111
   png_memcpy(&(png_ptr->background), background_color,
      png_sizeof(png_color_16));
G
Guy Schalnat 已提交
112
   png_ptr->background_gamma = (float)background_gamma;
G
Guy Schalnat 已提交
113
   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
G
Guy Schalnat 已提交
114
   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
G
Guy Schalnat 已提交
115
}
G
Guy Schalnat 已提交
116
#endif
G
Guy Schalnat 已提交
117

118
#ifdef PNG_READ_16_TO_8_SUPPORTED
119
/* Strip 16 bit depth files to 8 bit depth */
120
void PNGAPI
G
Guy Schalnat 已提交
121
png_set_strip_16(png_structp png_ptr)
G
Guy Schalnat 已提交
122
{
123
   png_debug(1, "in png_set_strip_16");
124

125 126
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
127 128
   png_ptr->transformations |= PNG_16_TO_8;
}
G
Guy Schalnat 已提交
129
#endif
G
Guy Schalnat 已提交
130

131
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
132
void PNGAPI
A
Andreas Dilger 已提交
133 134
png_set_strip_alpha(png_structp png_ptr)
{
135
   png_debug(1, "in png_set_strip_alpha");
136

137 138
   if (png_ptr == NULL)
      return;
139
   png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
A
Andreas Dilger 已提交
140 141 142
}
#endif

143
#ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
144 145 146
void PNGAPI
png_set_premultiply_alpha(png_structp png_ptr)
{
147
   png_debug(1, "in png_set_premultiply_alpha");
148

149 150
   if(png_ptr == NULL)
      return;
151 152 153 154 155 156 157 158
   png_ptr->transformations |=
     (PNG_PREMULTIPLY_ALPHA | PNG_EXPAND_tRNS);
   png_ptr->transformations |=
     PNG_EXPAND;  /* This shouldn't be necessary */
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
#endif

159
#ifdef PNG_READ_DITHER_SUPPORTED
A
Andreas Dilger 已提交
160
/* Dither file to 8 bit.  Supply a palette, the current number
161 162 163 164 165 166 167
 * 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
 * modified to fit in the maximum number.  "full_dither" indicates
 * whether we need a dithering cube set up for RGB images, or if we
 * simply are reducing the number of colors in a paletted image.
 */
G
Guy Schalnat 已提交
168 169

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
170
{
G
Guy Schalnat 已提交
171
   struct png_dsort_struct FAR * next;
G
Guy Schalnat 已提交
172 173
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
174 175 176
} png_dsort;
typedef png_dsort FAR *       png_dsortp;
typedef png_dsort FAR * FAR * png_dsortpp;
G
Guy Schalnat 已提交
177

178
void PNGAPI
G
Guy Schalnat 已提交
179 180
png_set_dither(png_structp png_ptr, png_colorp palette,
   int num_palette, int maximum_colors, png_uint_16p histogram,
G
Guy Schalnat 已提交
181 182
   int full_dither)
{
183
   png_debug(1, "in png_set_dither");
184

185 186
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
187 188
   png_ptr->transformations |= PNG_DITHER;

G
Guy Schalnat 已提交
189
   if (!full_dither)
G
Guy Schalnat 已提交
190 191 192
   {
      int i;

A
Andreas Dilger 已提交
193
      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
194
         (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
195
      for (i = 0; i < num_palette; i++)
G
Guy Schalnat 已提交
196
         png_ptr->dither_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
197 198 199 200
   }

   if (num_palette > maximum_colors)
   {
A
Andreas Dilger 已提交
201
      if (histogram != NULL)
G
Guy Schalnat 已提交
202
      {
A
Andreas Dilger 已提交
203
         /* This is easy enough, just throw out the least used colors.
204 205
          * Perhaps not the best solution, but good enough.
          */
G
Guy Schalnat 已提交
206 207 208

         int i;

209
         /* Initialize an array to sort colors */
210
         png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
211
            (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
212

213
         /* Initialize the dither_sort array */
G
Guy Schalnat 已提交
214
         for (i = 0; i < num_palette; i++)
215
            png_ptr->dither_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
216

A
Andreas Dilger 已提交
217
         /* Find the least used palette entries by starting a
218 219 220 221 222
          * 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 已提交
223 224 225

         for (i = num_palette - 1; i >= maximum_colors; i--)
         {
226
            int done; /* To stop early if the list is pre-sorted */
G
Guy Schalnat 已提交
227
            int j;
G
Guy Schalnat 已提交
228 229 230 231

            done = 1;
            for (j = 0; j < i; j++)
            {
232 233
               if (histogram[png_ptr->dither_sort[j]]
                   < histogram[png_ptr->dither_sort[j + 1]])
G
Guy Schalnat 已提交
234 235 236
               {
                  png_byte t;

237 238 239
                  t = png_ptr->dither_sort[j];
                  png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
                  png_ptr->dither_sort[j + 1] = t;
G
Guy Schalnat 已提交
240 241 242 243 244 245 246
                  done = 0;
               }
            }
            if (done)
               break;
         }

247
         /* Swap the palette around, and set up a table, if necessary */
G
Guy Schalnat 已提交
248 249
         if (full_dither)
         {
250
            int j = num_palette;
G
Guy Schalnat 已提交
251

252 253 254
            /* Put all the useful colors within the max, but don't
             * move the others.
             */
255
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
256
            {
257
               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
258 259 260
               {
                  do
                     j--;
261
                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
262 263
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
264
            }
G
Guy Schalnat 已提交
265 266 267
         }
         else
         {
268
            int j = num_palette;
G
Guy Schalnat 已提交
269

270 271 272
            /* Move all the used colors inside the max limit, and
             * develop a translation table.
             */
273
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
274
            {
275
               /* Only move the colors we need to */
276
               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
277 278 279 280 281
               {
                  png_color tmp_color;

                  do
                     j--;
282
                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
283 284 285 286

                  tmp_color = palette[j];
                  palette[j] = palette[i];
                  palette[i] = tmp_color;
287
                  /* Indicate where the color went */
G
Guy Schalnat 已提交
288 289
                  png_ptr->dither_index[j] = (png_byte)i;
                  png_ptr->dither_index[i] = (png_byte)j;
G
Guy Schalnat 已提交
290 291
               }
            }
A
Andreas Dilger 已提交
292

293
            /* Find closest color for those colors we are not using */
G
Guy Schalnat 已提交
294 295
            for (i = 0; i < num_palette; i++)
            {
296
               if ((int)png_ptr->dither_index[i] >= maximum_colors)
G
Guy Schalnat 已提交
297
               {
A
Andreas Dilger 已提交
298
                  int min_d, k, min_k, d_index;
G
Guy Schalnat 已提交
299

300
                  /* Find the closest color to one we threw out */
A
Andreas Dilger 已提交
301 302 303
                  d_index = png_ptr->dither_index[i];
                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
                  for (k = 1, min_k = 0; k < maximum_colors; k++)
G
Guy Schalnat 已提交
304 305 306
                  {
                     int d;

A
Andreas Dilger 已提交
307
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
308 309 310 311

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
312
                        min_k = k;
G
Guy Schalnat 已提交
313 314
                     }
                  }
315
                  /* Point to closest color */
A
Andreas Dilger 已提交
316
                  png_ptr->dither_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
317 318 319
               }
            }
         }
320
         png_free(png_ptr, png_ptr->dither_sort);
321
         png_ptr->dither_sort = NULL;
G
Guy Schalnat 已提交
322 323 324
      }
      else
      {
A
Andreas Dilger 已提交
325
         /* This is much harder to do simply (and quickly).  Perhaps
326 327 328 329 330 331 332
          * 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 已提交
333 334 335
         int i;
         int max_d;
         int num_new_palette;
336
         png_dsortp t;
G
Guy Schalnat 已提交
337
         png_dsortpp hash;
338

339
         t = NULL;
G
Guy Schalnat 已提交
340

341
         /* Initialize palette index arrays */
342
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
343
            (png_uint_32)(num_palette * png_sizeof(png_byte)));
344
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
345
            (png_uint_32)(num_palette * png_sizeof(png_byte)));
G
Guy Schalnat 已提交
346

347
         /* Initialize the sort array */
G
Guy Schalnat 已提交
348 349
         for (i = 0; i < num_palette; i++)
         {
350 351
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
352 353
         }

354
         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
355
            png_sizeof(png_dsortp)));
G
Guy Schalnat 已提交
356 357 358

         num_new_palette = num_palette;

359 360 361 362 363 364 365 366
         /* 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 已提交
367 368
         max_d = 96;

G
Guy Schalnat 已提交
369
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
370 371 372 373 374 375 376 377 378
         {
            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 已提交
379
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
380 381 382 383

                  if (d <= max_d)
                  {

384
                     t = (png_dsortp)png_malloc_warn(png_ptr,
385
                         (png_uint_32)(png_sizeof(png_dsort)));
386 387
                     if (t == NULL)
                         break;
G
Guy Schalnat 已提交
388
                     t->next = hash[d];
G
Guy Schalnat 已提交
389 390
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
391 392 393
                     hash[d] = t;
                  }
               }
394 395
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
396 397
            }

398
            if (t != NULL)
G
Guy Schalnat 已提交
399 400
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
401
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
402
               {
G
Guy Schalnat 已提交
403
                  png_dsortp p;
G
Guy Schalnat 已提交
404 405 406

                  for (p = hash[i]; p; p = p->next)
                  {
407 408 409 410
                     if ((int)png_ptr->index_to_palette[p->left]
                        < num_new_palette &&
                        (int)png_ptr->index_to_palette[p->right]
                        < num_new_palette)
G
Guy Schalnat 已提交
411 412 413
                     {
                        int j, next_j;

414
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
415 416 417 418 419 420 421 422 423 424 425
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
426 427
                        palette[png_ptr->index_to_palette[j]]
                          = palette[num_new_palette];
G
Guy Schalnat 已提交
428 429 430 431 432 433 434
                        if (!full_dither)
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
                              if (png_ptr->dither_index[k] ==
435
                                 png_ptr->index_to_palette[j])
G
Guy Schalnat 已提交
436
                                 png_ptr->dither_index[k] =
437
                                    png_ptr->index_to_palette[next_j];
438
                              if ((int)png_ptr->dither_index[k] ==
G
Guy Schalnat 已提交
439 440
                                 num_new_palette)
                                 png_ptr->dither_index[k] =
441
                                    png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
442 443 444
                           }
                        }

445 446 447 448
                        png_ptr->index_to_palette[png_ptr->palette_to_index
                           [num_new_palette]] = png_ptr->index_to_palette[j];
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
                           = png_ptr->palette_to_index[num_new_palette];
G
Guy Schalnat 已提交
449

450 451
                        png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
                        png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
G
Guy Schalnat 已提交
452 453 454 455 456 457 458 459 460 461 462
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

            for (i = 0; i < 769; i++)
            {
A
Andreas Dilger 已提交
463
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
464
               {
465
                  png_dsortp p = hash[i];
G
Guy Schalnat 已提交
466 467 468
                  while (p)
                  {
                     t = p->next;
A
Andreas Dilger 已提交
469
                     png_free(png_ptr, p);
G
Guy Schalnat 已提交
470 471 472 473 474 475 476
                     p = t;
                  }
               }
               hash[i] = 0;
            }
            max_d += 96;
         }
A
Andreas Dilger 已提交
477
         png_free(png_ptr, hash);
478 479
         png_free(png_ptr, png_ptr->palette_to_index);
         png_free(png_ptr, png_ptr->index_to_palette);
480 481
         png_ptr->palette_to_index = NULL;
         png_ptr->index_to_palette = NULL;
G
Guy Schalnat 已提交
482 483 484
      }
      num_palette = maximum_colors;
   }
A
Andreas Dilger 已提交
485
   if (png_ptr->palette == NULL)
G
Guy Schalnat 已提交
486
   {
G
Guy Schalnat 已提交
487 488
      png_ptr->palette = palette;
   }
G
Guy Schalnat 已提交
489
   png_ptr->num_palette = (png_uint_16)num_palette;
G
Guy Schalnat 已提交
490 491 492 493

   if (full_dither)
   {
      int i;
G
Guy Schalnat 已提交
494
      png_bytep distance;
495
      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
G
Guy Schalnat 已提交
496
         PNG_DITHER_BLUE_BITS;
497 498 499 500
      int num_red = (1 << PNG_DITHER_RED_BITS);
      int num_green = (1 << PNG_DITHER_GREEN_BITS);
      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
      png_size_t num_entries = ((png_size_t)1 << total_bits);
G
Guy Schalnat 已提交
501

502
      png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr,
503
         (png_uint_32)(num_entries * png_sizeof(png_byte)));
504

505 506 507
      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
         png_sizeof(png_byte)));
      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
508 509 510

      for (i = 0; i < num_palette; i++)
      {
511 512 513 514
         int ir, ig, ib;
         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
G
Guy Schalnat 已提交
515 516 517

         for (ir = 0; ir < num_red; ir++)
         {
518 519
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
520
            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
G
Guy Schalnat 已提交
521 522

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
523
            {
524 525
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
526 527 528
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
G
Guy Schalnat 已提交
529 530

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
531
               {
532
                  int d_index = index_g | ib;
533 534
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
535 536
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
537

538
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
539
                  {
A
Andreas Dilger 已提交
540 541
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
542 543
                  }
               }
544 545 546
            }
         }
      }
G
Guy Schalnat 已提交
547

A
Andreas Dilger 已提交
548
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
549 550
   }
}
G
Guy Schalnat 已提交
551
#endif
G
Guy Schalnat 已提交
552

553
#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
A
Andreas Dilger 已提交
554
/* Transform the image from the file_gamma to the screen_gamma.  We
555 556 557
 * 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.
558 559 560 561
 *
 * We will turn off gamma transformation later if no semitransparent entries
 * are present in the tRNS array for palette images.  We can't do it here
 * because we don't necessarily have the tRNS chunk yet.
562
 */
563
void PNGAPI
564
png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
G
Guy Schalnat 已提交
565
{
566
   png_debug(1, "in png_set_gamma");
567

568 569
   if (png_ptr == NULL)
      return;
570

571 572 573 574
   if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
     png_ptr->transformations |= PNG_GAMMA;
G
Guy Schalnat 已提交
575
   png_ptr->gamma = (float)file_gamma;
576
   png_ptr->screen_gamma = (float)scrn_gamma;
G
Guy Schalnat 已提交
577
}
G
Guy Schalnat 已提交
578
#endif
G
Guy Schalnat 已提交
579

580
#ifdef PNG_READ_EXPAND_SUPPORTED
581
/* Expand paletted images to RGB, expand grayscale images of
582
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
583 584
 * to alpha channels.
 */
585
void PNGAPI
G
Guy Schalnat 已提交
586
png_set_expand(png_structp png_ptr)
G
Guy Schalnat 已提交
587
{
588
   png_debug(1, "in png_set_expand");
589

590 591
   if (png_ptr == NULL)
      return;
592

593
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
594
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
G
Guy Schalnat 已提交
595
}
596 597 598 599 600 601 602 603 604 605 606 607 608

/* 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.
609 610 611
 *
 *  GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
 *  to expand only the sample depth but not to expand the tRNS to alpha.
612 613 614
 */

/* Expand paletted images to RGB. */
615
void PNGAPI
616 617
png_set_palette_to_rgb(png_structp png_ptr)
{
618
   png_debug(1, "in png_set_palette_to_rgb");
619

620 621
   if (png_ptr == NULL)
      return;
622

623
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
624
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
625 626 627 628 629 630
}

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

633 634
   if (png_ptr == NULL)
      return;
635

636 637
   png_ptr->transformations |= PNG_EXPAND;
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
638 639
}

640 641


642
/* Expand tRNS chunks to alpha channels. */
643
void PNGAPI
644 645
png_set_tRNS_to_alpha(png_structp png_ptr)
{
646
   png_debug(1, "in png_set_tRNS_to_alpha");
647

648
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
649
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
650 651
}
#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
G
Guy Schalnat 已提交
652

653
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
654
void PNGAPI
G
Guy Schalnat 已提交
655
png_set_gray_to_rgb(png_structp png_ptr)
G
Guy Schalnat 已提交
656
{
657
   png_debug(1, "in png_set_gray_to_rgb");
658

G
Guy Schalnat 已提交
659
   png_ptr->transformations |= PNG_GRAY_TO_RGB;
660
   png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
G
Guy Schalnat 已提交
661
}
G
Guy Schalnat 已提交
662
#endif
G
Guy Schalnat 已提交
663

664 665
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
666 667
/* 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.
668
 */
669

670
void PNGAPI
671
png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
672 673
   double green)
{
674 675 676 677 678
   int red_fixed = (int)((float)red*100000.0 + 0.5);
   int green_fixed = (int)((float)green*100000.0 + 0.5);
   if (png_ptr == NULL)
      return;
   png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
679 680 681
}
#endif

682
void PNGAPI
683 684
png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
   png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
685
{
686
   png_debug(1, "in png_set_rgb_to_gray");
687

688 689
   if (png_ptr == NULL)
      return;
690

691 692 693 694
   switch(error_action)
   {
      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
              break;
695

696 697
      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
              break;
698

699 700 701
      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
   }
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
702
#ifdef PNG_READ_EXPAND_SUPPORTED
703 704 705
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
706 707
      png_warning(png_ptr,
        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
708 709 710 711
      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
   }
#endif
   {
712
      png_uint_16 red_int, green_int;
713
      if (red < 0 || green < 0)
714
      {
715 716
         red_int   =  6968; /* .212671 * 32768 + .5 */
         green_int = 23434; /* .715160 * 32768 + .5 */
717
      }
718
      else if (red + green < 100000L)
719
      {
720 721
         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
722 723
      }
      else
724 725
      {
         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
726 727
         red_int   =  6968;
         green_int = 23434;
728
      }
729 730
      png_ptr->rgb_to_gray_red_coeff   = red_int;
      png_ptr->rgb_to_gray_green_coeff = green_int;
731
      png_ptr->rgb_to_gray_blue_coeff  =
732
         (png_uint_16)(32768 - red_int - green_int);
733
   }
A
Andreas Dilger 已提交
734 735 736
}
#endif

737
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
738
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
739
void PNGAPI
740 741 742
png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
   read_user_transform_fn)
{
743
   png_debug(1, "in png_set_read_user_transform_fn");
744

745 746
   if (png_ptr == NULL)
      return;
747

748
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
749 750
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
751
#endif
752 753 754
}
#endif

A
Andreas Dilger 已提交
755
/* Initialize everything needed for the read.  This includes modifying
756 757
 * the palette.
 */
758
void /* PRIVATE */
G
Guy Schalnat 已提交
759
png_init_read_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
760
{
761
   png_debug(1, "in png_init_read_transformations");
762

763 764 765 766
  {
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
 || defined(PNG_READ_GAMMA_SUPPORTED)
   int color_type = png_ptr->color_type;
767
#endif
G
Guy Schalnat 已提交
768

G
Guy Schalnat 已提交
769
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
770

771
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
772
   /* Detect gray background and attempt to enable optimization
773 774 775
    * for gray --> RGB case
    *
    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
    * 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.
    */
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
       !(color_type & PNG_COLOR_MASK_COLOR))
   {
          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
   } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
              !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
              (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
              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;
   }
#endif

797 798
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
       (png_ptr->transformations & PNG_EXPAND))
G
Guy Schalnat 已提交
799
   {
800
      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
801
      {
802
         /* Expand background and tRNS chunks */
G
Guy Schalnat 已提交
803 804 805
         switch (png_ptr->bit_depth)
         {
            case 1:
G
Guy Schalnat 已提交
806
               png_ptr->background.gray *= (png_uint_16)0xff;
807 808
               png_ptr->background.red = png_ptr->background.green
                 =  png_ptr->background.blue = png_ptr->background.gray;
809 810
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
811 812 813
                 png_ptr->trans_color.gray *= (png_uint_16)0xff;
                 png_ptr->trans_color.red = png_ptr->trans_color.green
                   = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
814
               }
G
Guy Schalnat 已提交
815
               break;
816

G
Guy Schalnat 已提交
817
            case 2:
G
Guy Schalnat 已提交
818
               png_ptr->background.gray *= (png_uint_16)0x55;
819 820
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
821 822
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
823 824 825
                 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;
826
               }
G
Guy Schalnat 已提交
827
               break;
828

G
Guy Schalnat 已提交
829
            case 4:
G
Guy Schalnat 已提交
830
               png_ptr->background.gray *= (png_uint_16)0x11;
831 832
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
833 834
               if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
               {
835 836 837
                 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;
838
               }
G
Guy Schalnat 已提交
839
               break;
840

G
Guy Schalnat 已提交
841
            case 8:
842

G
Guy Schalnat 已提交
843
            case 16:
844 845
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
846 847 848
               break;
         }
      }
G
Guy Schalnat 已提交
849
      else if (color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
850
      {
G
Guy Schalnat 已提交
851
         png_ptr->background.red   =
G
Guy Schalnat 已提交
852 853 854
            png_ptr->palette[png_ptr->background.index].red;
         png_ptr->background.green =
            png_ptr->palette[png_ptr->background.index].green;
G
Guy Schalnat 已提交
855
         png_ptr->background.blue  =
G
Guy Schalnat 已提交
856
            png_ptr->palette[png_ptr->background.index].blue;
857

858
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
859 860
        if (png_ptr->transformations & PNG_INVERT_ALPHA)
        {
861
#ifdef PNG_READ_EXPAND_SUPPORTED
862
           if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
863 864
#endif
           {
865 866 867
           /* Invert the alpha channel (in tRNS) unless the pixels are
            * going to be expanded, in which case leave it for later
            */
868
              int i, istop;
869 870
              istop=(int)png_ptr->num_trans;
              for (i=0; i<istop; i++)
871
                 png_ptr->trans_alpha[i] = (png_byte)(255 - png_ptr->trans_alpha[i]);
872 873 874 875
           }
        }
#endif

G
Guy Schalnat 已提交
876 877
      }
   }
G
Guy Schalnat 已提交
878
#endif
G
Guy Schalnat 已提交
879

880
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
G
Guy Schalnat 已提交
881
   png_ptr->background_1 = png_ptr->background;
G
Guy Schalnat 已提交
882
#endif
883
#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
884 885 886 887 888

   if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
       && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
         < PNG_GAMMA_THRESHOLD))
   {
889
    int i, k;
890 891 892
    k=0;
    for (i=0; i<png_ptr->num_trans; i++)
    {
893
      if (png_ptr->trans_alpha[i] != 0 && png_ptr->trans_alpha[i] != 0xff)
894
        k=1; /* Partial transparency is present */
895 896
    }
    if (k == 0)
897
      png_ptr->transformations &= ~PNG_GAMMA;
898 899
   }

900 901
   if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
        png_ptr->gamma != 0.0)
G
Guy Schalnat 已提交
902 903
   {
      png_build_gamma_table(png_ptr);
904
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
905
      if (png_ptr->transformations & PNG_BACKGROUND)
G
Guy Schalnat 已提交
906
      {
G
Guy Schalnat 已提交
907 908
         if (color_type == PNG_COLOR_TYPE_PALETTE)
         {
909
           /* Could skip if no transparency */
G
Guy Schalnat 已提交
910
            png_color back, back_1;
911 912 913
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
914 915 916 917 918 919 920 921 922 923 924 925
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
            {
               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
            {
926
               double g, gs;
A
Andreas Dilger 已提交
927

928 929 930 931 932 933
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
                     gs = 1.0;
                     break;
934

935 936 937 938
                  case PNG_BACKGROUND_GAMMA_FILE:
                     g = 1.0 / (png_ptr->gamma);
                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
                     break;
939

940 941 942 943 944 945 946 947 948
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
                     g = 1.0 / (png_ptr->background_gamma);
                     gs = 1.0 / (png_ptr->background_gamma *
                                 png_ptr->screen_gamma);
                     break;
                  default:
                     g = 1.0;    /* back_1 */
                     gs = 1.0;   /* back */
               }
A
Andreas Dilger 已提交
949

950
               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
A
Andreas Dilger 已提交
951
               {
952
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
953
                  back.green = (png_byte)png_ptr->background.green;
954
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
955 956 957
               }
               else
               {
958 959 960 961 962 963
                  back.red = (png_byte)(pow(
                     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
                  back.green = (png_byte)(pow(
                     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
                  back.blue = (png_byte)(pow(
                     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
A
Andreas Dilger 已提交
964
               }
G
Guy Schalnat 已提交
965

966 967 968 969 970 971
               back_1.red = (png_byte)(pow(
                  (double)png_ptr->background.red/255, g) * 255.0 + .5);
               back_1.green = (png_byte)(pow(
                  (double)png_ptr->background.green/255, g) * 255.0 + .5);
               back_1.blue = (png_byte)(pow(
                  (double)png_ptr->background.blue/255, g) * 255.0 + .5);
A
Andreas Dilger 已提交
972
            }
G
Guy Schalnat 已提交
973 974
            for (i = 0; i < num_palette; i++)
            {
975
               if (i < (int)png_ptr->num_trans && png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
976
               {
977
                  if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
978 979 980
                  {
                     palette[i] = back;
                  }
981
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
G
Guy Schalnat 已提交
982
                  {
A
Andreas Dilger 已提交
983
                     png_byte v, w;
G
Guy Schalnat 已提交
984 985

                     v = png_ptr->gamma_to_1[palette[i].red];
986
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
G
Guy Schalnat 已提交
987 988 989
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
990
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
G
Guy Schalnat 已提交
991 992 993
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
994
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
G
Guy Schalnat 已提交
995 996 997 998 999 1000 1001 1002 1003 1004
                     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];
               }
            }
1005 1006 1007 1008 1009 1010 1011 1012
            /* Prevent the transformations being done again, and make sure
             * that the now spurious alpha channel is stripped - the code
             * has just reduced background composition and gamma correction
             * to a simple alpha channel strip.
             */
            png_ptr->transformations &= ~PNG_BACKGROUND;
            png_ptr->transformations &= ~PNG_GAMMA;
            png_ptr->transformations |= PNG_STRIP_ALPHA;
G
Guy Schalnat 已提交
1013
         }
1014
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1015 1016
         else
         /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
1017
         {
1018 1019 1020
            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
            double g = 1.0;
            double gs = 1.0;
G
Guy Schalnat 已提交
1021 1022

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
1023
            {
G
Guy Schalnat 已提交
1024
               case PNG_BACKGROUND_GAMMA_SCREEN:
1025
                  g = (png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1026 1027
                  gs = 1.0;
                  break;
1028

G
Guy Schalnat 已提交
1029 1030
               case PNG_BACKGROUND_GAMMA_FILE:
                  g = 1.0 / (png_ptr->gamma);
1031
                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1032
                  break;
1033

G
Guy Schalnat 已提交
1034 1035 1036
               case PNG_BACKGROUND_GAMMA_UNIQUE:
                  g = 1.0 / (png_ptr->background_gamma);
                  gs = 1.0 / (png_ptr->background_gamma *
1037
                     png_ptr->screen_gamma);
G
Guy Schalnat 已提交
1038 1039 1040
                  break;
            }

1041 1042 1043 1044 1045
            png_ptr->background_1.gray = (png_uint_16)(pow(
               (double)png_ptr->background.gray / m, g) * m + .5);
            png_ptr->background.gray = (png_uint_16)(pow(
               (double)png_ptr->background.gray / m, gs) * m + .5);

1046 1047 1048
            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 已提交
1049
            {
1050
               /* RGB or RGBA with color background */
G
Guy Schalnat 已提交
1051
               png_ptr->background_1.red = (png_uint_16)(pow(
G
Guy Schalnat 已提交
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
                  (double)png_ptr->background.red / m, g) * m + .5);
               png_ptr->background_1.green = (png_uint_16)(pow(
                  (double)png_ptr->background.green / m, g) * m + .5);
               png_ptr->background_1.blue = (png_uint_16)(pow(
                  (double)png_ptr->background.blue / m, g) * m + .5);
               png_ptr->background.red = (png_uint_16)(pow(
                  (double)png_ptr->background.red / m, gs) * m + .5);
               png_ptr->background.green = (png_uint_16)(pow(
                  (double)png_ptr->background.green / m, gs) * m + .5);
               png_ptr->background.blue = (png_uint_16)(pow(
                  (double)png_ptr->background.blue / m, gs) * m + .5);
            }
            else
            {
1066 1067 1068 1069 1070
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
               png_ptr->background_1.red = png_ptr->background_1.green
                 = png_ptr->background_1.blue = png_ptr->background_1.gray;
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
1071 1072 1073
            }
         }
      }
G
Guy Schalnat 已提交
1074
      else
1075
      /* Transformation does not include PNG_BACKGROUND */
1076
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
1077 1078
      if (color_type == PNG_COLOR_TYPE_PALETTE)
      {
1079 1080 1081
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
1082 1083 1084 1085 1086 1087 1088

         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];
         }
1089

1090 1091
         /* Done the gamma correction. */
         png_ptr->transformations &= ~PNG_GAMMA;
G
Guy Schalnat 已提交
1092 1093
      }
   }
1094
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1095
   else
G
Guy Schalnat 已提交
1096
#endif
1097
#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1098
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1099
   /* No GAMMA transformation */
1100 1101
   if ((png_ptr->transformations & PNG_BACKGROUND) &&
       (color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1102
   {
1103 1104
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
1105
      png_color back;
1106
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
1107 1108 1109 1110 1111

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

1112
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1113
      {
1114
         if (png_ptr->trans_alpha[i] == 0)
G
Guy Schalnat 已提交
1115 1116 1117
         {
            palette[i] = back;
         }
1118
         else if (png_ptr->trans_alpha[i] != 0xff)
G
Guy Schalnat 已提交
1119
         {
1120
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
1121
            png_composite(palette[i].red, palette[i].red,
1122
               png_ptr->trans_alpha[i], back.red);
A
Andreas Dilger 已提交
1123
            png_composite(palette[i].green, palette[i].green,
1124
               png_ptr->trans_alpha[i], back.green);
A
Andreas Dilger 已提交
1125
            png_composite(palette[i].blue, palette[i].blue,
1126
               png_ptr->trans_alpha[i], back.blue);
G
Guy Schalnat 已提交
1127 1128
         }
      }
1129 1130 1131 1132

      /* Handled alpha, still need to strip the channel. */
      png_ptr->transformations &= ~PNG_BACKGROUND;
      png_ptr->transformations |= PNG_STRIP_ALPHA;
G
Guy Schalnat 已提交
1133
   }
1134
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
1135

1136
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
1137
   if ((png_ptr->transformations & PNG_SHIFT) &&
1138
      (color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1139
   {
1140 1141 1142 1143 1144
      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 已提交
1145 1146 1147 1148 1149 1150 1151

      if (sr < 0 || sr > 8)
         sr = 0;
      if (sg < 0 || sg > 8)
         sg = 0;
      if (sb < 0 || sb > 8)
         sb = 0;
1152
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1153 1154 1155 1156 1157 1158
      {
         png_ptr->palette[i].red >>= sr;
         png_ptr->palette[i].green >>= sg;
         png_ptr->palette[i].blue >>= sb;
      }
   }
1159
#endif  /* PNG_READ_SHIFT_SUPPORTED */
1160
 }
1161 1162
#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1163
   if (png_ptr)
1164 1165
      return;
#endif
G
Guy Schalnat 已提交
1166 1167
}

A
Andreas Dilger 已提交
1168
/* Modify the info structure to reflect the transformations.  The
1169 1170 1171
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1172
void /* PRIVATE */
G
Guy Schalnat 已提交
1173
png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1174
{
1175
   png_debug(1, "in png_read_transform_info");
1176

1177
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
1178
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1179
   {
A
Andreas Dilger 已提交
1180 1181
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
1182 1183
         if (png_ptr->num_trans &&
              (png_ptr->transformations & PNG_EXPAND_tRNS))
A
Andreas Dilger 已提交
1184 1185 1186
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
G
Guy Schalnat 已提交
1187
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1188 1189 1190 1191 1192
         info_ptr->num_trans = 0;
      }
      else
      {
         if (png_ptr->num_trans)
1193 1194 1195 1196
         {
            if (png_ptr->transformations & PNG_EXPAND_tRNS)
              info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
         }
A
Andreas Dilger 已提交
1197 1198 1199 1200
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1201 1202 1203
   }
#endif

1204
#ifdef PNG_READ_BACKGROUND_SUPPORTED
G
Guy Schalnat 已提交
1205 1206 1207 1208 1209 1210 1211 1212
   if (png_ptr->transformations & PNG_BACKGROUND)
   {
      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
      info_ptr->num_trans = 0;
      info_ptr->background = png_ptr->background;
   }
#endif

1213
#ifdef PNG_READ_GAMMA_SUPPORTED
1214
   if (png_ptr->transformations & PNG_GAMMA)
1215 1216
   {
#ifdef PNG_FLOATING_POINT_SUPPORTED
1217 1218
      info_ptr->gamma = png_ptr->gamma;
#endif
1219 1220 1221 1222 1223
#ifdef PNG_FIXED_POINT_SUPPORTED
      info_ptr->int_gamma = png_ptr->int_gamma;
#endif
   }
#endif
1224

1225
#ifdef PNG_READ_16_TO_8_SUPPORTED
1226
   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
G
Guy Schalnat 已提交
1227
      info_ptr->bit_depth = 8;
G
Guy Schalnat 已提交
1228 1229
#endif

1230
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1231 1232 1233 1234
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
#endif

1235
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1236 1237 1238 1239
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
#endif

1240
#ifdef PNG_READ_DITHER_SUPPORTED
G
Guy Schalnat 已提交
1241 1242 1243
   if (png_ptr->transformations & PNG_DITHER)
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1244 1245
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
G
Guy Schalnat 已提交
1246 1247 1248
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
1249
   }
G
Guy Schalnat 已提交
1250 1251
#endif

1252
#ifdef PNG_READ_PACK_SUPPORTED
1253
   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
1254 1255 1256
      info_ptr->bit_depth = 8;
#endif

G
Guy Schalnat 已提交
1257
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1258 1259 1260 1261 1262
      info_ptr->channels = 1;
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
   else
      info_ptr->channels = 1;
A
Andreas Dilger 已提交
1263

1264
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1265
   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
A
Andreas Dilger 已提交
1266 1267 1268
      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
#endif

1269 1270 1271
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

1272
#ifdef PNG_READ_FILLER_SUPPORTED
1273
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1274 1275 1276
   if ((png_ptr->transformations & PNG_FILLER) &&
       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1277
   {
1278
      info_ptr->channels++;
1279
      /* If adding a true alpha channel not just filler */
1280 1281
      if (png_ptr->transformations & PNG_ADD_ALPHA)
        info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1282
   }
A
Andreas Dilger 已提交
1283 1284
#endif

1285 1286
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1287
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
1288
     {
1289
       if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1290
         info_ptr->bit_depth = png_ptr->user_transform_depth;
1291
       if (info_ptr->channels < png_ptr->user_transform_channels)
1292 1293 1294 1295
         info_ptr->channels = png_ptr->user_transform_channels;
     }
#endif

G
Guy Schalnat 已提交
1296 1297
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
      info_ptr->bit_depth);
1298

1299
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1300

1301
#if !defined(PNG_READ_EXPAND_SUPPORTED)
1302
   if (png_ptr)
1303 1304
      return;
#endif
G
Guy Schalnat 已提交
1305 1306
}

1307 1308 1309 1310
/* 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.
 */
1311
void /* PRIVATE */
G
Guy Schalnat 已提交
1312
png_do_read_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
1313
{
1314
   png_debug(1, "in png_do_read_transformations");
1315

A
Andreas Dilger 已提交
1316
   if (png_ptr->row_buf == NULL)
G
Guy Schalnat 已提交
1317
   {
1318
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
A
Andreas Dilger 已提交
1319 1320
      char msg[50];

1321 1322 1323
      png_snprintf2(msg, 50,
         "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
         png_ptr->pass);
A
Andreas Dilger 已提交
1324
      png_error(png_ptr, msg);
1325 1326 1327
#else
      png_error(png_ptr, "NULL row buffer");
#endif
G
Guy Schalnat 已提交
1328
   }
1329 1330 1331 1332
#ifdef PNG_WARN_UNINITIALIZED_ROW
   if (!(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
1333 1334
       * pixels.  This check added to libpng-1.2.19
       */
1335 1336 1337 1338 1339
#if (PNG_WARN_UNINITIALIZED_ROW==1)
      png_error(png_ptr, "Uninitialized row");
#else
      png_warning(png_ptr, "Uninitialized row");
#endif
A
Andreas Dilger 已提交
1340 1341
#endif

1342
#ifdef PNG_READ_EXPAND_SUPPORTED
A
Andreas Dilger 已提交
1343
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1344
   {
A
Andreas Dilger 已提交
1345 1346 1347
      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1348
            png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
A
Andreas Dilger 已提交
1349
      }
1350
      else
A
Andreas Dilger 已提交
1351
      {
1352 1353
         if (png_ptr->num_trans &&
             (png_ptr->transformations & PNG_EXPAND_tRNS))
A
Andreas Dilger 已提交
1354
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1355
               &(png_ptr->trans_color));
A
Andreas Dilger 已提交
1356 1357 1358 1359
         else
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
               NULL);
      }
G
Guy Schalnat 已提交
1360
   }
G
Guy Schalnat 已提交
1361 1362
#endif

1363
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1364
   if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
A
Andreas Dilger 已提交
1365
      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1366
         PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
A
Andreas Dilger 已提交
1367 1368
#endif

1369
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1370 1371 1372 1373
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
   {
      int rgb_error =
         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1374
      if (rgb_error)
1375 1376
      {
         png_ptr->rgb_to_gray_status=1;
1377
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1378
             PNG_RGB_TO_GRAY_WARN)
1379
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1380 1381
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
             PNG_RGB_TO_GRAY_ERR)
1382 1383 1384 1385 1386
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

1387
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
1388
 *
1389 1390 1391 1392
 *   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.
1393
 *
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
 *   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.
1416 1417
 */

1418
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1419 1420 1421
   /* If gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons
    */
1422
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1423
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1424 1425 1426
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

1427
#ifdef PNG_READ_16_TO_8_SUPPORTED
1428 1429 1430 1431
   if (png_ptr->transformations & PNG_16_TO_8)
      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

1432
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1433 1434 1435
   if ((png_ptr->transformations & PNG_BACKGROUND) &&
      ((png_ptr->num_trans != 0 ) ||
      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
G
Guy Schalnat 已提交
1436
      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1437
         &(png_ptr->trans_color), &(png_ptr->background)
1438
#ifdef PNG_READ_GAMMA_SUPPORTED
1439
         , &(png_ptr->background_1),
G
Guy Schalnat 已提交
1440 1441 1442
         png_ptr->gamma_table, png_ptr->gamma_from_1,
         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1443 1444 1445
         png_ptr->gamma_shift
#endif
);
G
Guy Schalnat 已提交
1446 1447
#endif

1448
#ifdef PNG_READ_GAMMA_SUPPORTED
G
Guy Schalnat 已提交
1449
   if ((png_ptr->transformations & PNG_GAMMA) &&
1450
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1451 1452 1453
       !((png_ptr->transformations & PNG_BACKGROUND) &&
       ((png_ptr->num_trans != 0) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1454
#endif
1455
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1456
      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1457 1458
          png_ptr->gamma_table, png_ptr->gamma_16_table,
          png_ptr->gamma_shift);
G
Guy Schalnat 已提交
1459 1460
#endif

1461
#ifdef PNG_READ_DITHER_SUPPORTED
G
Guy Schalnat 已提交
1462
   if (png_ptr->transformations & PNG_DITHER)
G
Guy Schalnat 已提交
1463
   {
A
Andreas Dilger 已提交
1464 1465
      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
         png_ptr->palette_lookup, png_ptr->dither_index);
1466
      if (png_ptr->row_info.rowbytes == (png_uint_32)0)
1467
         png_error(png_ptr, "png_do_dither returned rowbytes=0");
A
Andreas Dilger 已提交
1468
   }
G
Guy Schalnat 已提交
1469 1470
#endif

1471
#ifdef PNG_READ_INVERT_SUPPORTED
G
Guy Schalnat 已提交
1472
   if (png_ptr->transformations & PNG_INVERT_MONO)
G
Guy Schalnat 已提交
1473
      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1474 1475
#endif

1476
#ifdef PNG_READ_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
1477 1478 1479
   if (png_ptr->transformations & PNG_SHIFT)
      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
         &(png_ptr->shift));
G
Guy Schalnat 已提交
1480 1481
#endif

1482
#ifdef PNG_READ_PACK_SUPPORTED
G
Guy Schalnat 已提交
1483
   if (png_ptr->transformations & PNG_PACK)
G
Guy Schalnat 已提交
1484
      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1485 1486
#endif

1487
#ifdef PNG_READ_BGR_SUPPORTED
G
Guy Schalnat 已提交
1488 1489
   if (png_ptr->transformations & PNG_BGR)
      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1490 1491
#endif

1492
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
1493 1494 1495 1496
   if (png_ptr->transformations & PNG_PACKSWAP)
      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

1497
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1498
   /* If gray -> RGB, do so now only if we did not do so above */
1499 1500
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
G
Guy Schalnat 已提交
1501
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1502 1503
#endif

1504
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
1505 1506
   if (png_ptr->transformations & PNG_FILLER)
      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
A
Andreas Dilger 已提交
1507 1508 1509
         (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif

1510
#ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
1511
   if (png_ptr->transformations & PNG_PREMULTIPLY_ALPHA)
1512 1513
      png_do_read_premultiply_alpha(&(png_ptr->row_info),
         png_ptr->row_buf + 1);
1514 1515
#endif

1516
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1517 1518 1519 1520
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

1521
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
1522 1523 1524 1525
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

1526
#ifdef PNG_READ_SWAP_SUPPORTED
A
Andreas Dilger 已提交
1527 1528
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1529
#endif
1530

1531
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1532
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
1533
    {
1534
      if (png_ptr->read_user_transform_fn != NULL)
1535
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
1536 1537 1538 1539 1540 1541 1542 1543 1544
            (png_ptr,                    /* png_ptr */
               &(png_ptr->row_info),     /* row_info: */
               /*  png_uint_32 width;       width of row */
               /*  png_uint_32 rowbytes;    number of bytes in row */
               /*  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 */
1545
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
1546
      if (png_ptr->user_transform_depth)
1547
         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1548
      if (png_ptr->user_transform_channels)
1549
         png_ptr->row_info.channels = png_ptr->user_transform_channels;
1550
#endif
1551 1552
      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
         png_ptr->row_info.channels);
1553 1554
      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
         png_ptr->row_info.width);
1555
   }
1556 1557
#endif

G
Guy Schalnat 已提交
1558 1559
}

1560
#ifdef PNG_READ_PACK_SUPPORTED
1561 1562 1563 1564 1565 1566
/* 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.
 */
1567
void /* PRIVATE */
G
Guy Schalnat 已提交
1568
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
1569
{
1570
   png_debug(1, "in png_do_unpack");
1571

A
Andreas Dilger 已提交
1572
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
1573
   {
1574
      png_uint_32 i;
1575
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
1576

G
Guy Schalnat 已提交
1577 1578 1579 1580
      switch (row_info->bit_depth)
      {
         case 1:
         {
1581 1582
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
1583
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1584
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
1585
            {
1586
               *dp = (png_byte)((*sp >> shift) & 0x01);
G
Guy Schalnat 已提交
1587 1588 1589 1590
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
1591
               }
G
Guy Schalnat 已提交
1592 1593 1594 1595 1596 1597 1598
               else
                  shift++;

               dp--;
            }
            break;
         }
1599

G
Guy Schalnat 已提交
1600 1601 1602
         case 2:
         {

1603 1604
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
1605
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1606
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
1607
            {
1608
               *dp = (png_byte)((*sp >> shift) & 0x03);
G
Guy Schalnat 已提交
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift += 2;

               dp--;
            }
            break;
         }
1621

G
Guy Schalnat 已提交
1622 1623
         case 4:
         {
1624 1625
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
1626
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1627
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
1628
            {
1629
               *dp = (png_byte)((*sp >> shift) & 0x0f);
G
Guy Schalnat 已提交
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift = 4;

               dp--;
            }
            break;
         }
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
1644
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1645
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
1646 1647
   }
}
G
Guy Schalnat 已提交
1648
#endif
G
Guy Schalnat 已提交
1649

1650
#ifdef PNG_READ_SHIFT_SUPPORTED
1651 1652 1653 1654 1655
/* 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.
 */
1656
void /* PRIVATE */
A
Andreas Dilger 已提交
1657
png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
G
Guy Schalnat 已提交
1658
{
1659
   png_debug(1, "in png_do_unshift");
1660

A
Andreas Dilger 已提交
1661 1662
   if (
       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1663 1664
   {
      int shift[4];
1665 1666 1667
      int channels = 0;
      int c;
      png_uint_16 value = 0;
1668
      png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
1669 1670 1671

      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
G
Guy Schalnat 已提交
1672 1673 1674
         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 已提交
1675 1676 1677
      }
      else
      {
G
Guy Schalnat 已提交
1678
         shift[channels++] = row_info->bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
1679 1680 1681
      }
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
G
Guy Schalnat 已提交
1682
         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
1683
      }
G
Guy Schalnat 已提交
1684

A
Andreas Dilger 已提交
1685
      for (c = 0; c < channels; c++)
G
Guy Schalnat 已提交
1686
      {
A
Andreas Dilger 已提交
1687 1688
         if (shift[c] <= 0)
            shift[c] = 0;
G
Guy Schalnat 已提交
1689 1690 1691
         else
            value = 1;
      }
G
Guy Schalnat 已提交
1692

G
Guy Schalnat 已提交
1693 1694
      if (!value)
         return;
G
Guy Schalnat 已提交
1695

G
Guy Schalnat 已提交
1696
      switch (row_info->bit_depth)
G
Guy Schalnat 已提交
1697 1698 1699
      {
         case 2:
         {
A
Andreas Dilger 已提交
1700
            png_bytep bp;
1701 1702
            png_uint_32 i;
            png_uint_32 istop = row_info->rowbytes;
A
Andreas Dilger 已提交
1703

1704
            for (bp = row, i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1705 1706
            {
               *bp >>= 1;
1707
               *bp++ &= 0x55;
G
Guy Schalnat 已提交
1708 1709 1710
            }
            break;
         }
1711

G
Guy Schalnat 已提交
1712 1713
         case 4:
         {
1714
            png_bytep bp = row;
1715 1716
            png_uint_32 i;
            png_uint_32 istop = row_info->rowbytes;
1717 1718
            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
               (png_byte)((int)0xf >> shift[0]));
1719

1720
            for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1721 1722
            {
               *bp >>= shift[0];
1723
               *bp++ &= mask;
G
Guy Schalnat 已提交
1724 1725 1726
            }
            break;
         }
1727

G
Guy Schalnat 已提交
1728 1729
         case 8:
         {
1730
            png_bytep bp = row;
1731
            png_uint_32 i;
1732
            png_uint_32 istop = row_width * channels;
G
Guy Schalnat 已提交
1733

1734
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
1735
            {
1736
               *bp++ >>= shift[i%channels];
G
Guy Schalnat 已提交
1737 1738 1739
            }
            break;
         }
1740

G
Guy Schalnat 已提交
1741 1742
         case 16:
         {
1743 1744 1745
            png_bytep bp = row;
            png_uint_32 i;
            png_uint_32 istop = channels * row_width;
G
Guy Schalnat 已提交
1746

1747
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
1748
            {
1749 1750 1751 1752
               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 已提交
1753 1754 1755 1756 1757 1758
            }
            break;
         }
      }
   }
}
G
Guy Schalnat 已提交
1759
#endif
G
Guy Schalnat 已提交
1760

1761
#ifdef PNG_READ_16_TO_8_SUPPORTED
1762
/* Chop rows of bit depth 16 down to 8 */
1763
void /* PRIVATE */
G
Guy Schalnat 已提交
1764
png_do_chop(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
1765
{
1766
   png_debug(1, "in png_do_chop");
1767

A
Andreas Dilger 已提交
1768
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
1769
   {
1770 1771 1772 1773
      png_bytep sp = row;
      png_bytep dp = row;
      png_uint_32 i;
      png_uint_32 istop = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
1774

1775
      for (i = 0; i<istop; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
1776
      {
1777
#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
1778 1779 1780 1781 1782
      /* This does a more accurate scaling of the 16-bit color
       * value, rather than a simple low-byte truncation.
       *
       * What the ideal calculation should be:
       *   *dp = (((((png_uint_32)(*sp) << 8) |
1783 1784
       *          (png_uint_32)(*(sp + 1))) * 255 + 127)
       *          / (png_uint_32)65535L;
1785 1786 1787
       *
       * GRR: no, I think this is what it really should be:
       *   *dp = (((((png_uint_32)(*sp) << 8) |
1788 1789
       *           (png_uint_32)(*(sp + 1))) + 128L)
       *           / (png_uint_32)257L;
1790 1791
       *
       * GRR: here's the exact calculation with shifts:
1792 1793
       *   temp = (((png_uint_32)(*sp) << 8) |
       *           (png_uint_32)(*(sp + 1))) + 128L;
1794 1795 1796 1797 1798 1799 1800 1801
       *   *dp = (temp - (temp >> 8)) >> 8;
       *
       * Approximate calculation with shift/add instead of multiply/divide:
       *   *dp = ((((png_uint_32)(*sp) << 8) |
       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
       *
       * What we actually do to avoid extra shifting and conversion:
       */
1802

A
Andreas Dilger 已提交
1803 1804
         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
#else
1805
       /* Simply discard the low order byte */
G
Guy Schalnat 已提交
1806
         *dp = *sp;
A
Andreas Dilger 已提交
1807
#endif
G
Guy Schalnat 已提交
1808 1809
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
1810
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1811
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
1812 1813 1814 1815
   }
}
#endif

1816
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
1817
void /* PRIVATE */
A
Andreas Dilger 已提交
1818 1819
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
1820
   png_debug(1, "in png_do_read_swap_alpha");
1821

A
Andreas Dilger 已提交
1822
   {
1823
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
1824 1825 1826 1827 1828
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
1829 1830
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1831 1832
            png_byte save;
            png_uint_32 i;
1833

1834
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
1846 1847
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1848 1849
            png_byte save[2];
            png_uint_32 i;
1850

1851
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This converts from GA to AG */
         if (row_info->bit_depth == 8)
         {
1871 1872
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1873 1874
            png_byte save;
            png_uint_32 i;
1875

1876
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1877 1878 1879 1880 1881 1882 1883 1884 1885
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
         /* This converts from GGAA to AAGG */
         else
         {
1886 1887
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1888 1889 1890
            png_byte save[2];
            png_uint_32 i;

1891
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
      }
G
Guy Schalnat 已提交
1902 1903
   }
}
G
Guy Schalnat 已提交
1904
#endif
G
Guy Schalnat 已提交
1905

1906
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1907
void /* PRIVATE */
1908 1909
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
1910
   png_debug(1, "in png_do_read_invert_alpha");
1911

1912
   {
1913
      png_uint_32 row_width = row_info->width;
1914 1915 1916 1917 1918
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This inverts the alpha channel in RGBA */
         if (row_info->bit_depth == 8)
         {
1919 1920
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
1921 1922
            png_uint_32 i;

1923
            for (i = 0; i < row_width; i++)
1924
            {
1925
               *(--dp) = (png_byte)(255 - *(--sp));
1926 1927

/*             This does nothing:
1928 1929 1930
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1931 1932 1933 1934
               We can replace it with:
*/
               sp-=3;
               dp=sp;
1935 1936 1937 1938 1939
            }
         }
         /* This inverts the alpha channel in RRGGBBAA */
         else
         {
1940 1941
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
1942 1943
            png_uint_32 i;

1944
            for (i = 0; i < row_width; i++)
1945
            {
1946 1947
               *(--dp) = (png_byte)(255 - *(--sp));
               *(--dp) = (png_byte)(255 - *(--sp));
1948 1949

/*             This does nothing:
1950 1951 1952 1953 1954 1955
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1956 1957 1958 1959
               We can replace it with:
*/
               sp-=6;
               dp=sp;
1960 1961 1962 1963 1964
            }
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
1965
         /* This inverts the alpha channel in GA */
1966 1967
         if (row_info->bit_depth == 8)
         {
1968 1969
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
1970 1971
            png_uint_32 i;

1972
            for (i = 0; i < row_width; i++)
1973
            {
1974
               *(--dp) = (png_byte)(255 - *(--sp));
1975
               *(--dp) = *(--sp);
1976 1977
            }
         }
1978
         /* This inverts the alpha channel in GGAA */
1979 1980
         else
         {
1981 1982
            png_bytep sp  = row + row_info->rowbytes;
            png_bytep dp = sp;
1983 1984
            png_uint_32 i;

1985
            for (i = 0; i < row_width; i++)
1986
            {
1987 1988
               *(--dp) = (png_byte)(255 - *(--sp));
               *(--dp) = (png_byte)(255 - *(--sp));
1989
/*
1990 1991
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1992 1993 1994
*/
               sp-=2;
               dp=sp;
1995 1996 1997 1998 1999 2000 2001
            }
         }
      }
   }
}
#endif

2002
#ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
2003 2004 2005
void /* PRIVATE */
png_do_read_premultiply_alpha(png_row_infop row_info, png_bytep row)
{
2006
   png_debug(1, "in png_do_read_premultiply_alpha");
2007

2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
   {
      png_uint_32 row_width = row_info->width;
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This premultiplies the pixels with the alpha channel in RGBA */
         if (row_info->bit_depth == 8)
         {
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
                      png_uint_16 a = 0;
            png_uint_32 i;

            for (i = 0; i < row_width; i++)
            {
                              a = *(--sp); --dp;

               *(--dp) = (*(--sp) * a) / 255;
               *(--dp) = (*(--sp) * a) / 255;
               *(--dp) = (*(--sp) * a) / 255;
            }
         }
         /* This premultiplies the pixels with the alpha channel in RRGGBBAA */
         else
         {
            png_uint_16p sp = (png_uint_16p)(row + row_info->rowbytes);
            png_uint_16p dp = sp;
                      png_uint_32 a = 0;
            png_uint_32 i;

            for (i = 0; i < row_width; i++)
            {
                              a = *(--sp); --dp;
               *(--dp) = (png_uint_16) ((*(--sp) * a) / 65535);
               *(--dp) = (png_uint_16) ((*(--sp) * a) / 65535);
               *(--dp) = (png_uint_16) ((*(--sp) * a) / 65535);
            }
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         /* This premultiplies the pixels with the alpha channel in GA */
         if (row_info->bit_depth == 8)
         {
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
            png_uint_16 a = 0;
                      png_uint_32 i;

            for (i = 0; i < row_width; i++)
            {
               a = *(--sp); --dp;
               *(--dp) = (*(--sp) * a) / 255;
            }
         }
         /* This premultiplies the pixels with the alpha channel in GGAA */
         else
         {
            png_uint_16p sp  = (png_uint_16p) (row + row_info->rowbytes);
            png_uint_16p dp  = sp;
                      png_uint_32 a = 0;
                      png_uint_32 i;

            for (i = 0; i < row_width; i++)
            {
                              a = *(--sp); --dp;
               *(--dp) = (png_uint_16) ((*(--sp) * a) / 65535);
            }
         }
      }
   }
}
#endif

2081
#ifdef PNG_READ_FILLER_SUPPORTED
A
Andreas Dilger 已提交
2082
/* Add filler channel if we have RGB color */
2083
void /* PRIVATE */
G
Guy Schalnat 已提交
2084
png_do_read_filler(png_row_infop row_info, png_bytep row,
A
Andreas Dilger 已提交
2085
   png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
2086
{
G
Guy Schalnat 已提交
2087
   png_uint_32 i;
2088 2089
   png_uint_32 row_width = row_info->width;

2090
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2091
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
2092

2093
   png_debug(1, "in png_do_read_filler");
2094

A
Andreas Dilger 已提交
2095
   if (
2096
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
2097
   {
2098
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2099
      {
2100 2101
         /* This changes the data from G to GX */
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2102
         {
2103 2104
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
2105 2106
            for (i = 1; i < row_width; i++)
            {
2107
               *(--dp) = lo_filler;
2108 2109
               *(--dp) = *(--sp);
            }
2110
            *(--dp) = lo_filler;
2111 2112 2113 2114 2115 2116 2117
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      /* This changes the data from G to XG */
         else
         {
2118 2119
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
2120 2121 2122
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
2123
               *(--dp) = lo_filler;
2124 2125 2126 2127 2128 2129
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
2130
      else if (row_info->bit_depth == 16)
2131 2132 2133 2134
      {
         /* This changes the data from GG to GGXX */
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2135 2136
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2137 2138 2139
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2140
               *(--dp) = lo_filler;
2141 2142 2143
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2144 2145
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2146 2147
            row_info->channels = 2;
            row_info->pixel_depth = 32;
2148
            row_info->rowbytes = row_width * 4;
2149 2150 2151 2152
         }
         /* This changes the data from GG to XXGG */
         else
         {
2153 2154
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2155 2156 2157 2158 2159
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2160
               *(--dp) = lo_filler;
2161 2162
            }
            row_info->channels = 2;
2163 2164
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
2165
         }
G
Guy Schalnat 已提交
2166
      }
2167 2168 2169
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
2170
      if (row_info->bit_depth == 8)
2171 2172 2173 2174
      {
         /* This changes the data from RGB to RGBX */
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
2175 2176
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
2177 2178
            for (i = 1; i < row_width; i++)
            {
2179
               *(--dp) = lo_filler;
2180 2181 2182 2183
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2184
            *(--dp) = lo_filler;
2185 2186 2187 2188
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
A
Andreas Dilger 已提交
2189
      /* This changes the data from RGB to XRGB */
2190 2191
         else
         {
2192 2193
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
2194 2195 2196 2197 2198
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
2199
               *(--dp) = lo_filler;
2200 2201 2202 2203 2204 2205
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
2206
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
2207
      {
2208 2209
         /* This changes the data from RRGGBB to RRGGBBXX */
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
2210
         {
2211 2212
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2213 2214 2215
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
2216
               *(--dp) = lo_filler;
2217 2218 2219 2220 2221 2222 2223
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
2224 2225
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
2226 2227
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2228
            row_info->rowbytes = row_width * 8;
2229 2230 2231 2232
         }
         /* This changes the data from RRGGBB to XXRRGGBB */
         else
         {
2233 2234
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2235 2236 2237 2238 2239 2240 2241 2242 2243
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2244
               *(--dp) = lo_filler;
2245 2246 2247
            }
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2248
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2249
         }
G
Guy Schalnat 已提交
2250
      }
2251
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2252
}
G
Guy Schalnat 已提交
2253
#endif
G
Guy Schalnat 已提交
2254

2255
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2256
/* Expand grayscale files to RGB, with or without alpha */
2257
void /* PRIVATE */
G
Guy Schalnat 已提交
2258
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2259
{
G
Guy Schalnat 已提交
2260
   png_uint_32 i;
2261
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2262

2263
   png_debug(1, "in png_do_gray_to_rgb");
2264

A
Andreas Dilger 已提交
2265
   if (row_info->bit_depth >= 8 &&
G
Guy Schalnat 已提交
2266 2267 2268 2269 2270 2271
      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
2272 2273
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2274
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2275 2276 2277
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
2278
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2279 2280 2281 2282
            }
         }
         else
         {
2283 2284
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2285
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2286 2287 2288 2289 2290
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2291 2292
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2293 2294 2295 2296 2297 2298 2299
            }
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
2300 2301
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2302
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2303 2304 2305 2306
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
2307
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2308 2309 2310 2311
            }
         }
         else
         {
2312 2313
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2314
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2315 2316 2317 2318 2319 2320 2321
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2322 2323
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2324 2325 2326
            }
         }
      }
G
Guy Schalnat 已提交
2327
      row_info->channels += (png_byte)2;
G
Guy Schalnat 已提交
2328
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
G
Guy Schalnat 已提交
2329 2330
      row_info->pixel_depth = (png_byte)(row_info->channels *
         row_info->bit_depth);
2331
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
2332 2333
   }
}
G
Guy Schalnat 已提交
2334
#endif
G
Guy Schalnat 已提交
2335

2336
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2337
/* Reduce RGB files to grayscale, with or without alpha
2338
 * using the equation given in Poynton's ColorFAQ at
2339
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
2340
 * New link:
2341
 * <http://www.poynton.com/notes/colour_and_gamma/>
2342
 * Charles Poynton poynton at poynton.com
2343 2344 2345 2346
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
 *  We approximate this with
2347
 *
2348
 *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
2349 2350 2351
 *
 *  which can be expressed with integers as
 *
2352
 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2353 2354 2355 2356 2357
 *
 *  The calculation is to be done in a linear colorspace.
 *
 *  Other integer coefficents can be used via png_set_rgb_to_gray().
 */
2358
int /* PRIVATE */
2359 2360 2361 2362 2363 2364 2365 2366
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;

2367
   png_debug(1, "in png_do_rgb_to_gray");
2368

2369 2370 2371
   if (
      (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
2372 2373 2374
      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;
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390

      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++)];
2391
                  if (red != green || red != blue)
2392 2393 2394
                  {
                     rgb_error |= 1;
                     *(dp++) = png_ptr->gamma_from_1[
2395
                       (rc*red + gc*green + bc*blue)>>15];
2396 2397
                  }
                  else
2398
                     *(dp++) = *(sp - 1);
2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
               }
            }
            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++);
2411
                  if (red != green || red != blue)
2412 2413
                  {
                     rgb_error |= 1;
2414
                     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2415 2416
                  }
                  else
2417
                     *(dp++) = *(sp - 1);
2418 2419 2420
               }
            }
         }
2421

2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433
         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;

2434 2435 2436
                  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;
2437

2438
                  if (red == green && red == blue)
2439 2440 2441 2442 2443 2444 2445
                     w = red;
                  else
                  {
                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
                                  png_ptr->gamma_shift][red>>8];
                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
                                  png_ptr->gamma_shift][green>>8];
2446
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2447
                                  png_ptr->gamma_shift][blue>>8];
2448
                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
2449
                                  + bc*blue_1)>>15);
2450 2451 2452 2453
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
                     rgb_error |= 1;
                  }
2454

2455 2456
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, gray16;

2468 2469 2470
                  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;
2471

2472
                  if (red != green || red != blue)
2473
                     rgb_error |= 1;
2474
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2475 2476
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494
               }
            }
         }
      }
      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++)];
2495
                  if (red != green || red != blue)
2496 2497
                     rgb_error |= 1;
                  *(dp++) =  png_ptr->gamma_from_1
2498
                             [(rc*red + gc*green + bc*blue)>>15];
2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511
                  *(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++);
2512
                  if (red != green || red != blue)
2513
                     rgb_error |= 1;
2514
                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530
                  *(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;

2531 2532 2533
                  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;
2534

2535
                  if (red == green && red == blue)
2536 2537 2538 2539 2540 2541 2542
                     w = red;
                  else
                  {
                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
                                  png_ptr->gamma_shift][red>>8];
                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
                                  png_ptr->gamma_shift][green>>8];
2543
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2544
                                  png_ptr->gamma_shift][blue>>8];
2545
                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
2546
                                  + gc * green_1 + bc * blue_1)>>15);
2547 2548 2549 2550
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
                     rgb_error |= 1;
                  }
2551

2552 2553
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565
                  *(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;
2566 2567 2568
                  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;
2569
                  if (red != green || red != blue)
2570
                     rgb_error |= 1;
2571
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2572 2573
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
2574 2575 2576 2577 2578 2579 2580 2581 2582 2583
                  *(dp++) = *(sp++);  /* alpha */
                  *(dp++) = *(sp++);
               }
            }
         }
      }
   row_info->channels -= (png_byte)2;
      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
      row_info->pixel_depth = (png_byte)(row_info->channels *
         row_info->bit_depth);
2584
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2585 2586 2587 2588 2589
   }
   return rgb_error;
}
#endif

2590 2591 2592 2593 2594
/* 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
 * of code.
 */
2595
void PNGAPI
G
Guy Schalnat 已提交
2596
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
2597 2598 2599 2600 2601 2602
{
   int num_palette;
   int color_inc;
   int i;
   int v;

2603
   png_debug(1, "in png_do_build_grayscale_palette");
2604

A
Andreas Dilger 已提交
2605
   if (palette == NULL)
G
Guy Schalnat 已提交
2606 2607 2608 2609 2610 2611 2612 2613
      return;

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

G
Guy Schalnat 已提交
2615 2616 2617 2618
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
2619

G
Guy Schalnat 已提交
2620 2621 2622 2623
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
2624

G
Guy Schalnat 已提交
2625 2626 2627 2628
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
2629

G
Guy Schalnat 已提交
2630
      default:
G
Guy Schalnat 已提交
2631
         num_palette = 0;
G
Guy Schalnat 已提交
2632
         color_inc = 0;
G
Guy Schalnat 已提交
2633 2634 2635 2636 2637
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
2638 2639 2640
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
2641 2642 2643 2644
   }
}


2645
#ifdef PNG_READ_BACKGROUND_SUPPORTED
A
Andreas Dilger 已提交
2646
/* Replace any alpha or transparency with the supplied background color.
2647 2648 2649
 * "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.
 */
2650
void /* PRIVATE */
G
Guy Schalnat 已提交
2651
png_do_background(png_row_infop row_info, png_bytep row,
2652
   png_color_16p trans_color, png_color_16p background
2653
#ifdef PNG_READ_GAMMA_SUPPORTED
2654
   , png_color_16p background_1,
G
Guy Schalnat 已提交
2655
   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
G
Guy Schalnat 已提交
2656
   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2657 2658 2659
   png_uint_16pp gamma_16_to_1, int gamma_shift
#endif
   )
G
Guy Schalnat 已提交
2660
{
G
Guy Schalnat 已提交
2661
   png_bytep sp, dp;
G
Guy Schalnat 已提交
2662
   png_uint_32 i;
2663
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
2664
   int shift;
G
Guy Schalnat 已提交
2665

2666
   png_debug(1, "in png_do_background");
2667

A
Andreas Dilger 已提交
2668
   if (background != NULL &&
G
Guy Schalnat 已提交
2669
      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2670
      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color)))
G
Guy Schalnat 已提交
2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
2682
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2683
                  {
2684
                     if ((png_uint_16)((*sp >> shift) & 0x01)
2685
                        == trans_color->gray)
G
Guy Schalnat 已提交
2686
                     {
G
Guy Schalnat 已提交
2687 2688
                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
                        *sp |= (png_byte)(background->gray << shift);
G
Guy Schalnat 已提交
2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699
                     }
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
                     else
                        shift--;
                  }
                  break;
               }
2700

G
Guy Schalnat 已提交
2701 2702
               case 2:
               {
2703
#ifdef PNG_READ_GAMMA_SUPPORTED
2704
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
2705
                  {
2706 2707 2708
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2709
                     {
2710
                        if ((png_uint_16)((*sp >> shift) & 0x03)
2711
                            == trans_color->gray)
2712 2713 2714 2715 2716 2717
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        else
                        {
2718
                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
2719
                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2720
                               (p << 4) | (p << 6)] >> 6) & 0x03);
2721 2722 2723 2724 2725 2726 2727 2728 2729 2730
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
2731
                     }
2732 2733 2734 2735 2736 2737 2738
                  }
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2739
                     {
2740
                        if ((png_uint_16)((*sp >> shift) & 0x03)
2741
                            == trans_color->gray)
2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
2753 2754 2755 2756
                     }
                  }
                  break;
               }
2757

G
Guy Schalnat 已提交
2758 2759
               case 4:
               {
2760
#ifdef PNG_READ_GAMMA_SUPPORTED
2761
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
2762
                  {
2763 2764 2765
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2766
                     {
2767
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
2768
                            == trans_color->gray)
2769 2770 2771 2772 2773 2774
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        else
                        {
2775
                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2776
                           png_byte g = (png_byte)((gamma_table[p |
2777
                             (p << 4)] >> 4) & 0x0f);
2778 2779 2780 2781 2782 2783 2784 2785 2786 2787
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
2788
                     }
2789 2790 2791 2792 2793 2794 2795
                  }
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2796
                     {
2797
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
2798
                            == trans_color->gray)
2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
2810 2811 2812 2813
                     }
                  }
                  break;
               }
2814

G
Guy Schalnat 已提交
2815 2816
               case 8:
               {
2817
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
2818
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
2819
                  {
2820 2821
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
2822
                     {
2823
                        if (*sp == trans_color->gray)
G
Guy Schalnat 已提交
2824
                        {
A
Andreas Dilger 已提交
2825
                           *sp = (png_byte)background->gray;
G
Guy Schalnat 已提交
2826 2827 2828 2829 2830 2831 2832 2833
                        }
                        else
                        {
                           *sp = gamma_table[*sp];
                        }
                     }
                  }
                  else
G
Guy Schalnat 已提交
2834
#endif
G
Guy Schalnat 已提交
2835
                  {
2836 2837
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
2838
                     {
2839
                        if (*sp == trans_color->gray)
G
Guy Schalnat 已提交
2840
                        {
A
Andreas Dilger 已提交
2841
                           *sp = (png_byte)background->gray;
G
Guy Schalnat 已提交
2842 2843 2844 2845 2846
                        }
                     }
                  }
                  break;
               }
2847

G
Guy Schalnat 已提交
2848 2849
               case 16:
               {
2850
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
2851
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
2852
                  {
2853 2854
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
2855 2856 2857
                     {
                        png_uint_16 v;

2858
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2859
                        if (v == trans_color->gray)
G
Guy Schalnat 已提交
2860
                        {
2861
                           /* Background is already in screen gamma */
G
Guy Schalnat 已提交
2862 2863
                           *sp = (png_byte)((background->gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(background->gray & 0xff);
G
Guy Schalnat 已提交
2864 2865 2866
                        }
                        else
                        {
A
Andreas Dilger 已提交
2867
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
2868
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
2869
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
2870
                        }
G
Guy Schalnat 已提交
2871
                     }
G
Guy Schalnat 已提交
2872 2873
                  }
                  else
G
Guy Schalnat 已提交
2874
#endif
G
Guy Schalnat 已提交
2875
                  {
2876 2877
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
2878 2879 2880
                     {
                        png_uint_16 v;

2881
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2882
                        if (v == trans_color->gray)
G
Guy Schalnat 已提交
2883
                        {
G
Guy Schalnat 已提交
2884 2885
                           *sp = (png_byte)((background->gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(background->gray & 0xff);
G
Guy Schalnat 已提交
2886 2887 2888 2889 2890 2891 2892 2893
                        }
                     }
                  }
                  break;
               }
            }
            break;
         }
2894

G
Guy Schalnat 已提交
2895 2896 2897 2898
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
2899
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
2900
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
2901
               {
2902 2903
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
2904
                  {
2905 2906 2907
                     if (*sp == trans_color->red &&
                        *(sp + 1) == trans_color->green &&
                        *(sp + 2) == trans_color->blue)
G
Guy Schalnat 已提交
2908
                     {
A
Andreas Dilger 已提交
2909 2910 2911
                        *sp = (png_byte)background->red;
                        *(sp + 1) = (png_byte)background->green;
                        *(sp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
2912 2913 2914 2915 2916 2917 2918 2919 2920 2921
                     }
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
2922
#endif
G
Guy Schalnat 已提交
2923
               {
2924 2925
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
2926
                  {
2927 2928 2929
                     if (*sp == trans_color->red &&
                        *(sp + 1) == trans_color->green &&
                        *(sp + 2) == trans_color->blue)
G
Guy Schalnat 已提交
2930
                     {
A
Andreas Dilger 已提交
2931 2932 2933
                        *sp = (png_byte)background->red;
                        *(sp + 1) = (png_byte)background->green;
                        *(sp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
2934 2935 2936 2937
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
2938
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
2939
            {
2940
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
2941
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
2942
               {
2943 2944
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
2945
                  {
2946 2947 2948
                     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));
2949 2950
                     if (r == trans_color->red && g == trans_color->green &&
                        b == trans_color->blue)
G
Guy Schalnat 已提交
2951
                     {
2952
                        /* Background is already in screen gamma */
G
Guy Schalnat 已提交
2953 2954 2955 2956 2957 2958
                        *sp = (png_byte)((background->red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(background->red & 0xff);
                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(background->green & 0xff);
                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(background->blue & 0xff);
G
Guy Schalnat 已提交
2959 2960 2961
                     }
                     else
                     {
2962
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
2963
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
2964
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
2965
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
2966 2967
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
2968
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
2969 2970
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
2971 2972 2973 2974
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
2975
#endif
G
Guy Schalnat 已提交
2976
               {
2977 2978
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
2979
                  {
2980 2981 2982
                     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));
G
Guy Schalnat 已提交
2983

2984 2985
                     if (r == trans_color->red && g == trans_color->green &&
                        b == trans_color->blue)
G
Guy Schalnat 已提交
2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998
                     {
                        *sp = (png_byte)((background->red >> 8) & 0xff);
                        *(sp + 1) = (png_byte)(background->red & 0xff);
                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(background->green & 0xff);
                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(background->blue & 0xff);
                     }
                  }
               }
            }
            break;
         }
2999

G
Guy Schalnat 已提交
3000
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
3001
         {
A
Andreas Dilger 已提交
3002
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3003
            {
3004
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3005 3006 3007
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
3008 3009 3010
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
3011
                  {
3012
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
3013

A
Andreas Dilger 已提交
3014 3015 3016 3017 3018 3019
                     if (a == 0xff)
                     {
                        *dp = gamma_table[*sp];
                     }
                     else if (a == 0)
                     {
3020
                        /* Background is already in screen gamma */
A
Andreas Dilger 已提交
3021 3022 3023 3024 3025
                        *dp = (png_byte)background->gray;
                     }
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
3026

A
Andreas Dilger 已提交
3027 3028 3029
                        v = gamma_to_1[*sp];
                        png_composite(w, v, a, background_1->gray);
                        *dp = gamma_from_1[w];
G
Guy Schalnat 已提交
3030 3031
                     }
                  }
A
Andreas Dilger 已提交
3032 3033
               }
               else
G
Guy Schalnat 已提交
3034
#endif
A
Andreas Dilger 已提交
3035
               {
3036 3037 3038
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
3039
                  {
3040
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
3041

A
Andreas Dilger 已提交
3042 3043 3044 3045
                     if (a == 0xff)
                     {
                        *dp = *sp;
                     }
3046
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3047 3048 3049 3050 3051 3052 3053
                     else if (a == 0)
                     {
                        *dp = (png_byte)background->gray;
                     }
                     else
                     {
                        png_composite(*dp, *sp, a, background_1->gray);
G
Guy Schalnat 已提交
3054
                     }
3055 3056 3057
#else
                     *dp = (png_byte)background->gray;
#endif
G
Guy Schalnat 已提交
3058 3059
                  }
               }
A
Andreas Dilger 已提交
3060 3061 3062
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
3063
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3064 3065 3066
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3067 3068 3069
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
G
Guy Schalnat 已提交
3070
                  {
3071
                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
A
Andreas Dilger 已提交
3072 3073

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3074
                     {
A
Andreas Dilger 已提交
3075
                        png_uint_16 v;
G
Guy Schalnat 已提交
3076

A
Andreas Dilger 已提交
3077 3078 3079 3080
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
                     }
3081
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3082
                     else if (a == 0)
3083 3084 3085
#else
                     else
#endif
A
Andreas Dilger 已提交
3086
                     {
3087
                        /* Background is already in screen gamma */
A
Andreas Dilger 已提交
3088 3089 3090
                        *dp = (png_byte)((background->gray >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(background->gray & 0xff);
                     }
3091
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3092 3093 3094
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3095

A
Andreas Dilger 已提交
3096 3097 3098 3099 3100
                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
                        png_composite_16(v, g, a, background_1->gray);
                        w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
                        *dp = (png_byte)((w >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(w & 0xff);
G
Guy Schalnat 已提交
3101
                     }
3102
#endif
G
Guy Schalnat 已提交
3103
                  }
A
Andreas Dilger 已提交
3104 3105
               }
               else
G
Guy Schalnat 已提交
3106
#endif
A
Andreas Dilger 已提交
3107
               {
3108 3109 3110
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
G
Guy Schalnat 已提交
3111
                  {
3112
                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
A
Andreas Dilger 已提交
3113
                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3114
                     {
A
Andreas Dilger 已提交
3115 3116
                        png_memcpy(dp, sp, 2);
                     }
3117
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3118
                     else if (a == 0)
3119 3120 3121
#else
                     else
#endif
A
Andreas Dilger 已提交
3122 3123 3124 3125
                     {
                        *dp = (png_byte)((background->gray >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(background->gray & 0xff);
                     }
3126
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3127 3128 3129
                     else
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3130

3131
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
A
Andreas Dilger 已提交
3132 3133 3134
                        png_composite_16(v, g, a, background_1->gray);
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3135
                     }
3136
#endif
G
Guy Schalnat 已提交
3137 3138 3139 3140 3141
                  }
               }
            }
            break;
         }
3142

G
Guy Schalnat 已提交
3143 3144 3145 3146
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3147
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3148 3149
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3150
               {
3151 3152 3153
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
G
Guy Schalnat 已提交
3154
                  {
3155
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3156 3157 3158 3159 3160 3161 3162 3163 3164

                     if (a == 0xff)
                     {
                        *dp = gamma_table[*sp];
                        *(dp + 1) = gamma_table[*(sp + 1)];
                        *(dp + 2) = gamma_table[*(sp + 2)];
                     }
                     else if (a == 0)
                     {
3165
                        /* Background is already in screen gamma */
A
Andreas Dilger 已提交
3166 3167 3168
                        *dp = (png_byte)background->red;
                        *(dp + 1) = (png_byte)background->green;
                        *(dp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
3169 3170 3171
                     }
                     else
                     {
A
Andreas Dilger 已提交
3172
                        png_byte v, w;
G
Guy Schalnat 已提交
3173 3174

                        v = gamma_to_1[*sp];
A
Andreas Dilger 已提交
3175 3176
                        png_composite(w, v, a, background_1->red);
                        *dp = gamma_from_1[w];
G
Guy Schalnat 已提交
3177
                        v = gamma_to_1[*(sp + 1)];
A
Andreas Dilger 已提交
3178 3179
                        png_composite(w, v, a, background_1->green);
                        *(dp + 1) = gamma_from_1[w];
G
Guy Schalnat 已提交
3180
                        v = gamma_to_1[*(sp + 2)];
A
Andreas Dilger 已提交
3181 3182
                        png_composite(w, v, a, background_1->blue);
                        *(dp + 2) = gamma_from_1[w];
G
Guy Schalnat 已提交
3183 3184 3185 3186
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3187
#endif
G
Guy Schalnat 已提交
3188
               {
3189 3190 3191
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
G
Guy Schalnat 已提交
3192
                  {
3193
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3194 3195 3196 3197 3198 3199 3200 3201 3202

                     if (a == 0xff)
                     {
                        *dp = *sp;
                        *(dp + 1) = *(sp + 1);
                        *(dp + 2) = *(sp + 2);
                     }
                     else if (a == 0)
                     {
A
Andreas Dilger 已提交
3203 3204 3205
                        *dp = (png_byte)background->red;
                        *(dp + 1) = (png_byte)background->green;
                        *(dp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
3206 3207 3208
                     }
                     else
                     {
A
Andreas Dilger 已提交
3209 3210 3211 3212 3213
                        png_composite(*dp, *sp, a, background->red);
                        png_composite(*(dp + 1), *(sp + 1), a,
                           background->green);
                        png_composite(*(dp + 2), *(sp + 2), a,
                           background->blue);
G
Guy Schalnat 已提交
3214 3215 3216 3217
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3218
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3219
            {
3220
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3221 3222
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
3223
               {
3224 3225 3226
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
G
Guy Schalnat 已提交
3227
                  {
3228 3229
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
G
Guy Schalnat 已提交
3230 3231 3232 3233
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3234
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3235 3236
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3237
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3238 3239
                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3240
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3241 3242
                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3243 3244 3245
                     }
                     else if (a == 0)
                     {
3246
                        /* Background is already in screen gamma */
G
Guy Schalnat 已提交
3247 3248 3249 3250 3251 3252
                        *dp = (png_byte)((background->red >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(background->red & 0xff);
                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(background->green & 0xff);
                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(background->blue & 0xff);
G
Guy Schalnat 已提交
3253 3254 3255
                     }
                     else
                     {
A
Andreas Dilger 已提交
3256 3257 3258
                        png_uint_16 v, w, x;

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3259
                        png_composite_16(w, v, a, background_1->red);
A
Andreas Dilger 已提交
3260 3261 3262 3263
                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
                        *dp = (png_byte)((x >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(x & 0xff);
                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3264
                        png_composite_16(w, v, a, background_1->green);
A
Andreas Dilger 已提交
3265 3266 3267 3268
                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
                        *(dp + 2) = (png_byte)((x >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(x & 0xff);
                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3269
                        png_composite_16(w, v, a, background_1->blue);
A
Andreas Dilger 已提交
3270 3271 3272
                        x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
                        *(dp + 4) = (png_byte)((x >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(x & 0xff);
G
Guy Schalnat 已提交
3273 3274 3275 3276
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3277
#endif
G
Guy Schalnat 已提交
3278
               {
3279 3280 3281
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
G
Guy Schalnat 已提交
3282
                  {
3283 3284
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                        << 8) + (png_uint_16)(*(sp + 7)));
G
Guy Schalnat 已提交
3285 3286
                     if (a == (png_uint_16)0xffff)
                     {
G
Guy Schalnat 已提交
3287
                        png_memcpy(dp, sp, 6);
G
Guy Schalnat 已提交
3288 3289 3290
                     }
                     else if (a == 0)
                     {
G
Guy Schalnat 已提交
3291 3292 3293 3294 3295 3296 3297 3298
                        *dp = (png_byte)((background->red >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(background->red & 0xff);
                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(background->green & 0xff);
                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(background->blue & 0xff);
                     }
                     else
G
Guy Schalnat 已提交
3299
                     {
3300
                        png_uint_16 v;
A
Andreas Dilger 已提交
3301

3302 3303 3304 3305 3306
                        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 已提交
3307 3308

                        png_composite_16(v, r, a, background->red);
G
Guy Schalnat 已提交
3309 3310
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3311
                        png_composite_16(v, g, a, background->green);
G
Guy Schalnat 已提交
3312 3313
                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(v & 0xff);
3314
                        png_composite_16(v, b, a, background->blue);
G
Guy Schalnat 已提交
3315 3316 3317 3318 3319 3320 3321 3322 3323
                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(v & 0xff);
                     }
                  }
               }
            }
            break;
         }
      }
A
Andreas Dilger 已提交
3324

G
Guy Schalnat 已提交
3325 3326 3327
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
G
Guy Schalnat 已提交
3328
         row_info->channels--;
G
Guy Schalnat 已提交
3329 3330
         row_info->pixel_depth = (png_byte)(row_info->channels *
            row_info->bit_depth);
3331
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3332 3333 3334
      }
   }
}
G
Guy Schalnat 已提交
3335
#endif
G
Guy Schalnat 已提交
3336

3337
#ifdef PNG_READ_GAMMA_SUPPORTED
A
Andreas Dilger 已提交
3338
/* Gamma correct the image, avoiding the alpha channel.  Make sure
3339
 * you do this after you deal with the transparency issue on grayscale
3340
 * or RGB images. If your bit depth is 8, use gamma_table, if it
3341 3342 3343
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
3344
void /* PRIVATE */
G
Guy Schalnat 已提交
3345 3346
png_do_gamma(png_row_infop row_info, png_bytep row,
   png_bytep gamma_table, png_uint_16pp gamma_16_table,
G
Guy Schalnat 已提交
3347 3348
   int gamma_shift)
{
G
Guy Schalnat 已提交
3349
   png_bytep sp;
G
Guy Schalnat 已提交
3350
   png_uint_32 i;
3351
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3352

3353
   png_debug(1, "in png_do_gamma");
3354

A
Andreas Dilger 已提交
3355 3356 3357
   if (
       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
3358 3359 3360 3361 3362 3363 3364
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3365 3366
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3367 3368 3369 3370 3371 3372 3373 3374 3375
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
A
Andreas Dilger 已提交
3376
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3377
            {
3378 3379
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3380 3381 3382
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
3383
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3384 3385 3386
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
A
Andreas Dilger 已提交
3387
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3388 3389
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3390
                  sp += 2;
A
Andreas Dilger 已提交
3391
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3392 3393 3394 3395 3396 3397 3398
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
3399

G
Guy Schalnat 已提交
3400 3401 3402 3403
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3404 3405
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3406
               {
G
Guy Schalnat 已提交
3407 3408 3409 3410 3411 3412 3413 3414 3415
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  sp++;
               }
            }
A
Andreas Dilger 已提交
3416
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3417
            {
3418 3419
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3420
               {
3421
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3422 3423
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3424
                  sp += 2;
A
Andreas Dilger 已提交
3425
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3426 3427 3428
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
A
Andreas Dilger 已提交
3429
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3430 3431 3432 3433 3434
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
3435 3436
            break;
         }
3437

G
Guy Schalnat 已提交
3438 3439 3440 3441
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3442 3443
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3444 3445
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
3446
                  sp += 2;
G
Guy Schalnat 已提交
3447 3448
               }
            }
A
Andreas Dilger 已提交
3449
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3450
            {
3451 3452
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3453
               {
3454
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3455 3456
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3457 3458 3459 3460 3461
                  sp += 4;
               }
            }
            break;
         }
3462

G
Guy Schalnat 已提交
3463 3464
         case PNG_COLOR_TYPE_GRAY:
         {
3465 3466
            if (row_info->bit_depth == 2)
            {
3467 3468
               sp = row;
               for (i = 0; i < row_width; i += 4)
3469 3470 3471 3472 3473 3474
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

3475 3476
                  *sp = (png_byte)(
                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
3477 3478
                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
                        ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3479
                        ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3480 3481 3482
                  sp++;
               }
            }
3483

A
Andreas Dilger 已提交
3484
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
3485
            {
3486 3487
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
3488 3489 3490 3491
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

3492 3493
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
3494 3495 3496
                  sp++;
               }
            }
3497

A
Andreas Dilger 已提交
3498 3499
            else if (row_info->bit_depth == 8)
            {
3500 3501
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3502 3503 3504 3505 3506
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
3507

G
Guy Schalnat 已提交
3508 3509
            else if (row_info->bit_depth == 16)
            {
3510 3511
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3512
               {
3513
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3514 3515
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3516 3517 3518 3519 3520 3521 3522 3523
                  sp += 2;
               }
            }
            break;
         }
      }
   }
}
G
Guy Schalnat 已提交
3524
#endif
G
Guy Schalnat 已提交
3525

3526
#ifdef PNG_READ_EXPAND_SUPPORTED
3527
/* Expands a palette row to an RGB or RGBA row depending
3528 3529
 * upon whether you supply trans and num_trans.
 */
3530
void /* PRIVATE */
G
Guy Schalnat 已提交
3531
png_do_expand_palette(png_row_infop row_info, png_bytep row,
3532
   png_colorp palette, png_bytep trans_alpha, int num_trans)
G
Guy Schalnat 已提交
3533
{
G
Guy Schalnat 已提交
3534
   int shift, value;
G
Guy Schalnat 已提交
3535
   png_bytep sp, dp;
G
Guy Schalnat 已提交
3536
   png_uint_32 i;
3537
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3538

3539
   png_debug(1, "in png_do_expand_palette");
3540

A
Andreas Dilger 已提交
3541 3542
   if (
       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
3543 3544 3545 3546 3547 3548 3549
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
3550 3551
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
3552
               shift = 7 - (int)((row_width + 7) & 0x07);
3553
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3554
               {
3555
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570
                     *dp = 1;
                  else
                     *dp = 0;
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
                  else
                     shift++;

                  dp--;
               }
               break;
            }
3571

G
Guy Schalnat 已提交
3572 3573
            case 2:
            {
3574 3575
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
3576
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3577
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3578
               {
3579
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
3580
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
3593

G
Guy Schalnat 已提交
3594 3595
            case 4:
            {
3596 3597
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
3598
               shift = (int)((row_width & 0x01) << 2);
3599
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3600
               {
3601
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
3602
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
3618
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
3619 3620 3621 3622 3623
      }
      switch (row_info->bit_depth)
      {
         case 8:
         {
3624
            if (trans_alpha != NULL)
G
Guy Schalnat 已提交
3625
            {
3626 3627
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
3628

3629
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3630
               {
A
Andreas Dilger 已提交
3631
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
3632 3633
                     *dp-- = 0xff;
                  else
3634
                     *dp-- = trans_alpha[*sp];
G
Guy Schalnat 已提交
3635 3636 3637 3638 3639 3640 3641
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
3642
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
3643 3644 3645 3646 3647
               row_info->color_type = 6;
               row_info->channels = 4;
            }
            else
            {
3648 3649
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
3650

3651
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3652 3653 3654 3655 3656 3657
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
3658

G
Guy Schalnat 已提交
3659 3660
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
3661
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
3662 3663 3664 3665 3666 3667 3668 3669 3670
               row_info->color_type = 2;
               row_info->channels = 3;
            }
            break;
         }
      }
   }
}

3671 3672
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
 * expanded transparency value is supplied, an alpha channel is built.
3673
 */
3674
void /* PRIVATE */
G
Guy Schalnat 已提交
3675
png_do_expand(png_row_infop row_info, png_bytep row,
G
Guy Schalnat 已提交
3676
   png_color_16p trans_value)
G
Guy Schalnat 已提交
3677
{
G
Guy Schalnat 已提交
3678
   int shift, value;
G
Guy Schalnat 已提交
3679
   png_bytep sp, dp;
G
Guy Schalnat 已提交
3680
   png_uint_32 i;
3681
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3682

3683
   png_debug(1, "in png_do_expand");
3684

G
Guy Schalnat 已提交
3685
   {
A
Andreas Dilger 已提交
3686
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
3687
      {
3688
         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
A
Andreas Dilger 已提交
3689 3690

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
3691
         {
A
Andreas Dilger 已提交
3692
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
3693
            {
A
Andreas Dilger 已提交
3694
               case 1:
G
Guy Schalnat 已提交
3695
               {
3696
                  gray = (png_uint_16)((gray&0x01)*0xff);
3697 3698
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
3699
                  shift = 7 - (int)((row_width + 7) & 0x07);
3700
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3701
                  {
3702
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
3703 3704 3705 3706 3707 3708 3709 3710 3711 3712
                        *dp = 0xff;
                     else
                        *dp = 0;
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
                     else
                        shift++;
G
Guy Schalnat 已提交
3713

A
Andreas Dilger 已提交
3714 3715 3716
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
3717
               }
3718

A
Andreas Dilger 已提交
3719
               case 2:
G
Guy Schalnat 已提交
3720
               {
3721
                  gray = (png_uint_16)((gray&0x03)*0x55);
3722 3723
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
3724
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3725
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3726
                  {
3727
                     value = (*sp >> shift) & 0x03;
A
Andreas Dilger 已提交
3728 3729 3730 3731 3732 3733 3734 3735 3736
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
                     else
                        shift += 2;
G
Guy Schalnat 已提交
3737

A
Andreas Dilger 已提交
3738 3739 3740
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
3741
               }
3742

A
Andreas Dilger 已提交
3743
               case 4:
G
Guy Schalnat 已提交
3744
               {
3745
                  gray = (png_uint_16)((gray&0x0f)*0x11);
3746 3747
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
3748
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3749
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3750
                  {
3751
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
3752 3753 3754 3755 3756 3757 3758 3759
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
                     else
                        shift = 4;
G
Guy Schalnat 已提交
3760

A
Andreas Dilger 已提交
3761 3762 3763
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
3764 3765
               }
            }
3766

A
Andreas Dilger 已提交
3767 3768
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
3769
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
3770
         }
A
Andreas Dilger 已提交
3771

A
Andreas Dilger 已提交
3772
         if (trans_value != NULL)
G
Guy Schalnat 已提交
3773
         {
A
Andreas Dilger 已提交
3774
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3775
            {
3776
               gray = gray & 0xff;
3777 3778 3779
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 1) - 1;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3780
               {
A
Andreas Dilger 已提交
3781 3782 3783 3784 3785
                  if (*sp == gray)
                     *dp-- = 0;
                  else
                     *dp-- = 0xff;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
3786
               }
A
Andreas Dilger 已提交
3787
            }
3788

A
Andreas Dilger 已提交
3789 3790
            else if (row_info->bit_depth == 16)
            {
3791 3792
               png_byte gray_high = (gray >> 8) & 0xff;
               png_byte gray_low = gray & 0xff;
A
Andreas Dilger 已提交
3793 3794
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
3795
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3796
               {
3797
                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
A
Andreas Dilger 已提交
3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
3809 3810
               }
            }
3811

A
Andreas Dilger 已提交
3812 3813 3814
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3815 3816
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
3817 3818 3819 3820 3821 3822
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
      {
         if (row_info->bit_depth == 8)
         {
3823 3824 3825
            png_byte red = trans_value->red & 0xff;
            png_byte green = trans_value->green & 0xff;
            png_byte blue = trans_value->blue & 0xff;
G
Guy Schalnat 已提交
3826
            sp = row + (png_size_t)row_info->rowbytes - 1;
3827 3828
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3829
            {
3830
               if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
G
Guy Schalnat 已提交
3831 3832 3833 3834 3835 3836 3837 3838 3839 3840
                  *dp-- = 0;
               else
                  *dp-- = 0xff;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
3841 3842 3843 3844 3845 3846
            png_byte red_high = (trans_value->red >> 8) & 0xff;
            png_byte green_high = (trans_value->green >> 8) & 0xff;
            png_byte blue_high = (trans_value->blue >> 8) & 0xff;
            png_byte red_low = trans_value->red & 0xff;
            png_byte green_low = trans_value->green & 0xff;
            png_byte blue_low = trans_value->blue & 0xff;
A
Andreas Dilger 已提交
3847
            sp = row + row_info->rowbytes - 1;
3848 3849
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3850
            {
3851 3852 3853 3854 3855 3856
               if (*(sp - 5) == red_high &&
                  *(sp - 4) == red_low &&
                  *(sp - 3) == green_high &&
                  *(sp - 2) == green_low &&
                  *(sp - 1) == blue_high &&
                  *(sp    ) == blue_low)
G
Guy Schalnat 已提交
3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
3870
               *dp-- = *sp--;
G
Guy Schalnat 已提交
3871 3872 3873 3874 3875
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
3876
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3877
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3878 3879 3880
      }
   }
}
G
Guy Schalnat 已提交
3881
#endif
G
Guy Schalnat 已提交
3882

3883
#ifdef PNG_READ_DITHER_SUPPORTED
3884
void /* PRIVATE */
G
Guy Schalnat 已提交
3885
png_do_dither(png_row_infop row_info, png_bytep row,
G
Guy Schalnat 已提交
3886
    png_bytep palette_lookup, png_bytep dither_lookup)
G
Guy Schalnat 已提交
3887
{
G
Guy Schalnat 已提交
3888
   png_bytep sp, dp;
G
Guy Schalnat 已提交
3889
   png_uint_32 i;
3890
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3891

3892
   png_debug(1, "in png_do_dither");
3893

G
Guy Schalnat 已提交
3894 3895 3896 3897 3898 3899 3900
   {
      if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
         palette_lookup && row_info->bit_depth == 8)
      {
         int r, g, b, p;
         sp = row;
         dp = row;
3901
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3902 3903 3904 3905 3906
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

3907 3908 3909 3910 3911 3912 3913
            /* 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);
             */
G
Guy Schalnat 已提交
3914 3915 3916 3917
            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
G
Guy Schalnat 已提交
3918
               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
G
Guy Schalnat 已提交
3919 3920 3921 3922 3923 3924 3925 3926 3927
               (PNG_DITHER_BLUE_BITS)) |
               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
               ((1 << PNG_DITHER_BLUE_BITS) - 1));

            *dp++ = palette_lookup[p];
         }
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
3928
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3929 3930
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
A
Andreas Dilger 已提交
3931
         palette_lookup != NULL && row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3932 3933 3934 3935
      {
         int r, g, b, p;
         sp = row;
         dp = row;
3936
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3937 3938 3939 3940 3941 3942 3943
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
G
Guy Schalnat 已提交
3944
               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
G
Guy Schalnat 已提交
3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956
               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
               (PNG_DITHER_BLUE_BITS)) |
               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
               ((1 << PNG_DITHER_BLUE_BITS) - 1));

            *dp++ = palette_lookup[p];
         }
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
         row_info->channels = 1;
         row_info->pixel_depth = row_info->bit_depth;
3957
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
G
Guy Schalnat 已提交
3958 3959 3960
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
         dither_lookup && row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3961
      {
G
Guy Schalnat 已提交
3962
         sp = row;
3963
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3964 3965 3966 3967 3968 3969
         {
            *sp = dither_lookup[*sp];
         }
      }
   }
}
G
Guy Schalnat 已提交
3970
#endif
G
Guy Schalnat 已提交
3971

3972
#ifdef PNG_FLOATING_POINT_SUPPORTED
3973
#ifdef PNG_READ_GAMMA_SUPPORTED
3974 3975
static PNG_CONST int png_gamma_shift[] =
   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
G
Guy Schalnat 已提交
3976

A
Andreas Dilger 已提交
3977
/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
3978 3979 3980
 * tables, we don't make a full table if we are reducing to 8-bit in
 * the future.  Note also how the gamma_16 tables are segmented so that
 * we don't need to allocate > 64K chunks for a full 16-bit table.
3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009
 *
 * See the PNG extensions document for an integer algorithm for creating
 * the gamma tables.  Maybe we will implement that here someday.
 *
 * We should only reach this point if
 *
 *      the file_gamma is known (i.e., the gAMA or sRGB chunk is present,
 *      or the application has provided a file_gamma)
 *
 *   AND
 *      {
 *         the screen_gamma is known
 *
 *      OR
 *
 *         RGB_to_gray transformation is being performed
 *      }
 *
 *   AND
 *      {
 *         the screen_gamma is different from the reciprocal of the
 *         file_gamma by more than the specified threshold
 *
 *      OR
 *
 *         a background color has been specified and the file_gamma
 *         and screen_gamma are not 1.0, within the specified threshold.
 *      }
 *
4010
 */
4011
void /* PRIVATE */
G
Guy Schalnat 已提交
4012
png_build_gamma_table(png_structp png_ptr)
G
Guy Schalnat 已提交
4013
{
4014
  png_debug(1, "in png_build_gamma_table");
4015 4016

  if (png_ptr->bit_depth <= 8)
4017
  {
4018 4019
     int i;
     double g;
G
Guy Schalnat 已提交
4020

4021 4022
     if (png_ptr->screen_gamma > .000001)
        g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4023

4024 4025
     else
        g = 1.0;
G
Guy Schalnat 已提交
4026

4027 4028
     png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
        (png_uint_32)256);
G
Guy Schalnat 已提交
4029

4030 4031 4032 4033 4034
     for (i = 0; i < 256; i++)
     {
        png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
           g) * 255.0 + .5);
     }
G
Guy Schalnat 已提交
4035

4036
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4037 4038 4039
   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
     if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
     {
4040

4041
        g = 1.0 / (png_ptr->gamma);
G
Guy Schalnat 已提交
4042

4043 4044
        png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
           (png_uint_32)256);
G
Guy Schalnat 已提交
4045

4046 4047 4048 4049 4050
        for (i = 0; i < 256; i++)
        {
           png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
              g) * 255.0 + .5);
        }
G
Guy Schalnat 已提交
4051

4052

4053 4054
        png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
           (png_uint_32)256);
G
Guy Schalnat 已提交
4055

4056
        if (png_ptr->screen_gamma > 0.000001)
4057
           g = 1.0 / png_ptr->screen_gamma;
4058

4059
        else
4060
           g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
4061

4062 4063 4064 4065
        for (i = 0; i < 256; i++)
        {
           png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
              g) * 255.0 + .5);
4066

4067 4068
        }
     }
4069
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4070 4071 4072 4073 4074 4075 4076
  }
  else
  {
     double g;
     int i, j, shift, num;
     int sig_bit;
     png_uint_32 ig;
G
Guy Schalnat 已提交
4077

4078 4079 4080
     if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
     {
        sig_bit = (int)png_ptr->sig_bit.red;
4081

4082 4083
        if ((int)png_ptr->sig_bit.green > sig_bit)
           sig_bit = png_ptr->sig_bit.green;
4084

4085 4086 4087 4088 4089 4090 4091
        if ((int)png_ptr->sig_bit.blue > sig_bit)
           sig_bit = png_ptr->sig_bit.blue;
     }
     else
     {
        sig_bit = (int)png_ptr->sig_bit.gray;
     }
G
Guy Schalnat 已提交
4092

4093 4094
     if (sig_bit > 0)
        shift = 16 - sig_bit;
4095

4096 4097
     else
        shift = 0;
G
Guy Schalnat 已提交
4098

4099 4100 4101 4102 4103
     if (png_ptr->transformations & PNG_16_TO_8)
     {
        if (shift < (16 - PNG_MAX_GAMMA_8))
           shift = (16 - PNG_MAX_GAMMA_8);
     }
G
Guy Schalnat 已提交
4104

4105 4106
     if (shift > 8)
        shift = 8;
4107

4108 4109
     if (shift < 0)
        shift = 0;
G
Guy Schalnat 已提交
4110

4111
     png_ptr->gamma_shift = (png_byte)shift;
G
Guy Schalnat 已提交
4112

4113
     num = (1 << (8 - shift));
G
Guy Schalnat 已提交
4114

4115 4116 4117 4118
     if (png_ptr->screen_gamma > .000001)
        g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
     else
        g = 1.0;
G
Guy Schalnat 已提交
4119

4120
     png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr,
4121
        (png_uint_32)(num * png_sizeof(png_uint_16p)));
G
Guy Schalnat 已提交
4122

4123 4124 4125 4126
     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
     {
        double fin, fout;
        png_uint_32 last, max;
G
Guy Schalnat 已提交
4127

4128 4129 4130
        for (i = 0; i < num; i++)
        {
           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4131
              (png_uint_32)(256 * png_sizeof(png_uint_16)));
4132
        }
G
Guy Schalnat 已提交
4133

4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160
        g = 1.0 / g;
        last = 0;
        for (i = 0; i < 256; i++)
        {
           fout = ((double)i + 0.5) / 256.0;
           fin = pow(fout, g);
           max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
           while (last <= max)
           {
              png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
                 [(int)(last >> (8 - shift))] = (png_uint_16)(
                 (png_uint_16)i | ((png_uint_16)i << 8));
              last++;
           }
        }
        while (last < ((png_uint_32)num << 8))
        {
           png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
              [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
           last++;
        }
     }
     else
     {
        for (i = 0; i < num; i++)
        {
           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4161
              (png_uint_32)(256 * png_sizeof(png_uint_16)));
G
Guy Schalnat 已提交
4162

4163
           ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4164

4165 4166 4167 4168 4169 4170 4171 4172
           for (j = 0; j < 256; j++)
           {
              png_ptr->gamma_16_table[i][j] =
                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
                    65535.0, g) * 65535.0 + .5);
           }
        }
     }
G
Guy Schalnat 已提交
4173

4174
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4175 4176 4177
   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
     if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
     {
4178

4179
        g = 1.0 / (png_ptr->gamma);
G
Guy Schalnat 已提交
4180

4181
        png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr,
4182
           (png_uint_32)(num * png_sizeof(png_uint_16p )));
G
Guy Schalnat 已提交
4183

4184 4185 4186
        for (i = 0; i < num; i++)
        {
           png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4187
              (png_uint_32)(256 * png_sizeof(png_uint_16)));
G
Guy Schalnat 已提交
4188

4189 4190 4191 4192 4193 4194 4195 4196 4197
           ig = (((png_uint_32)i *
              (png_uint_32)png_gamma_shift[shift]) >> 4);
           for (j = 0; j < 256; j++)
           {
              png_ptr->gamma_16_to_1[i][j] =
                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
                    65535.0, g) * 65535.0 + .5);
           }
        }
4198

4199
        if (png_ptr->screen_gamma > 0.000001)
4200
           g = 1.0 / png_ptr->screen_gamma;
4201

4202
        else
4203
           g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
G
Guy Schalnat 已提交
4204

4205
        png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr,
4206
           (png_uint_32)(num * png_sizeof(png_uint_16p)));
G
Guy Schalnat 已提交
4207

4208 4209 4210
        for (i = 0; i < num; i++)
        {
           png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4211
              (png_uint_32)(256 * png_sizeof(png_uint_16)));
G
Guy Schalnat 已提交
4212

4213 4214
           ig = (((png_uint_32)i *
              (png_uint_32)png_gamma_shift[shift]) >> 4);
4215

4216 4217 4218 4219 4220 4221 4222 4223
           for (j = 0; j < 256; j++)
           {
              png_ptr->gamma_16_from_1[i][j] =
                 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
                    65535.0, g) * 65535.0 + .5);
           }
        }
     }
4224
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4225
  }
G
Guy Schalnat 已提交
4226
}
G
Guy Schalnat 已提交
4227
#endif
4228 4229
/* To do: install integer version of png_build_gamma_table here */
#endif
G
Guy Schalnat 已提交
4230

4231
#ifdef PNG_MNG_FEATURES_SUPPORTED
4232
/* Undoes intrapixel differencing  */
4233 4234 4235
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
4236
   png_debug(1, "in png_do_read_intrapixel");
4237

4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
      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;
4250

4251 4252
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
4253

4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
            *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
            *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
         }
      }
      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;
4270

4271 4272
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
4273

4274 4275 4276 4277 4278
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4279 4280 4281 4282 4283
            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);
4284 4285 4286 4287
            *(rp  ) = (png_byte)((red >> 8) & 0xff);
            *(rp+1) = (png_byte)(red & 0xff);
            *(rp+4) = (png_byte)((blue >> 8) & 0xff);
            *(rp+5) = (png_byte)(blue & 0xff);
4288 4289 4290 4291 4292
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
4293
#endif /* PNG_READ_SUPPORTED */