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

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

#define PNG_INTERNAL
#include "png.h"

19
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
20
void PNGAPI
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
{
   png_debug(1, "in png_set_crc_action\n");
   /* Tell libpng how we react to CRC errors in critical chunks */
   switch (crit_action)
   {
      case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
         break;
      case PNG_CRC_WARN_USE:                               /* warn/use data */
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
         break;
      case PNG_CRC_QUIET_USE:                             /* quiet/use data */
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
                           PNG_FLAG_CRC_CRITICAL_IGNORE;
         break;
      case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
         png_warning(png_ptr, "Can't discard critical data on CRC error.");
      case PNG_CRC_ERROR_QUIT:                                /* error/quit */
      case PNG_CRC_DEFAULT:
      default:
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
         break;
   }

   switch (ancil_action)
   {
      case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
         break;
      case PNG_CRC_WARN_USE:                              /* warn/use data */
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
         break;
      case PNG_CRC_QUIET_USE:                            /* quiet/use data */
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
         break;
      case PNG_CRC_ERROR_QUIT:                               /* error/quit */
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
         break;
      case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
      case PNG_CRC_DEFAULT:
      default:
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
         break;
   }
}

72 73
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
    defined(PNG_FLOATING_POINT_SUPPORTED)
G
Guy Schalnat 已提交
74
/* handle alpha and tRNS via a background color */
75
void PNGAPI
G
Guy Schalnat 已提交
76 77
png_set_background(png_structp png_ptr,
   png_color_16p background_color, int background_gamma_code,
G
Guy Schalnat 已提交
78
   int need_expand, double background_gamma)
G
Guy Schalnat 已提交
79
{
A
Andreas Dilger 已提交
80
   png_debug(1, "in png_set_background\n");
A
Andreas Dilger 已提交
81 82 83 84 85 86
   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
   {
      png_warning(png_ptr, "Application must supply a known background gamma");
      return;
   }

G
Guy Schalnat 已提交
87
   png_ptr->transformations |= PNG_BACKGROUND;
88 89
   png_memcpy(&(png_ptr->background), background_color,
      png_sizeof(png_color_16));
G
Guy Schalnat 已提交
90
   png_ptr->background_gamma = (float)background_gamma;
G
Guy Schalnat 已提交
91
   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
G
Guy Schalnat 已提交
92
   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
93 94 95 96

   /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
    * (in which case need_expand is superfluous anyway), the background color
    * might actually be gray yet not be flagged as such. This is not a problem
97
    * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
98 99 100 101 102
    * decide when to do the png_do_gray_to_rgb() transformation.
    */
   if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
       (!need_expand && background_color->red == background_color->green &&
        background_color->red == background_color->blue))
103
      png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
G
Guy Schalnat 已提交
104
}
G
Guy Schalnat 已提交
105
#endif
G
Guy Schalnat 已提交
106

G
Guy Schalnat 已提交
107
#if defined(PNG_READ_16_TO_8_SUPPORTED)
G
Guy Schalnat 已提交
108
/* strip 16 bit depth files to 8 bit depth */
109
void PNGAPI
G
Guy Schalnat 已提交
110
png_set_strip_16(png_structp png_ptr)
G
Guy Schalnat 已提交
111
{
A
Andreas Dilger 已提交
112
   png_debug(1, "in png_set_strip_16\n");
G
Guy Schalnat 已提交
113 114
   png_ptr->transformations |= PNG_16_TO_8;
}
G
Guy Schalnat 已提交
115
#endif
G
Guy Schalnat 已提交
116

A
Andreas Dilger 已提交
117
#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
118
void PNGAPI
A
Andreas Dilger 已提交
119 120 121 122 123 124 125
png_set_strip_alpha(png_structp png_ptr)
{
   png_debug(1, "in png_set_strip_alpha\n");
   png_ptr->transformations |= PNG_STRIP_ALPHA;
}
#endif

G
Guy Schalnat 已提交
126
#if defined(PNG_READ_DITHER_SUPPORTED)
A
Andreas Dilger 已提交
127
/* Dither file to 8 bit.  Supply a palette, the current number
128 129 130 131 132 133 134
 * 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 已提交
135 136

typedef struct png_dsort_struct
G
Guy Schalnat 已提交
137
{
G
Guy Schalnat 已提交
138
   struct png_dsort_struct FAR * next;
G
Guy Schalnat 已提交
139 140
   png_byte left;
   png_byte right;
G
Guy Schalnat 已提交
141 142 143
} png_dsort;
typedef png_dsort FAR *       png_dsortp;
typedef png_dsort FAR * FAR * png_dsortpp;
G
Guy Schalnat 已提交
144

145
void PNGAPI
G
Guy Schalnat 已提交
146 147
png_set_dither(png_structp png_ptr, png_colorp palette,
   int num_palette, int maximum_colors, png_uint_16p histogram,
G
Guy Schalnat 已提交
148 149
   int full_dither)
{
A
Andreas Dilger 已提交
150
   png_debug(1, "in png_set_dither\n");
G
Guy Schalnat 已提交
151 152
   png_ptr->transformations |= PNG_DITHER;

G
Guy Schalnat 已提交
153
   if (!full_dither)
G
Guy Schalnat 已提交
154 155 156
   {
      int i;

A
Andreas Dilger 已提交
157
      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
158
         (png_uint_32)(num_palette * png_sizeof (png_byte)));
G
Guy Schalnat 已提交
159
      for (i = 0; i < num_palette; i++)
G
Guy Schalnat 已提交
160
         png_ptr->dither_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
161 162 163 164
   }

   if (num_palette > maximum_colors)
   {
A
Andreas Dilger 已提交
165
      if (histogram != NULL)
G
Guy Schalnat 已提交
166
      {
A
Andreas Dilger 已提交
167 168
         /* This is easy enough, just throw out the least used colors.
            Perhaps not the best solution, but good enough. */
G
Guy Schalnat 已提交
169 170 171 172

         int i;

         /* initialize an array to sort colors */
173
         png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
174
            (png_uint_32)(num_palette * png_sizeof (png_byte)));
G
Guy Schalnat 已提交
175

176
         /* initialize the dither_sort array */
G
Guy Schalnat 已提交
177
         for (i = 0; i < num_palette; i++)
178
            png_ptr->dither_sort[i] = (png_byte)i;
G
Guy Schalnat 已提交
179

A
Andreas Dilger 已提交
180
         /* Find the least used palette entries by starting a
G
Guy Schalnat 已提交
181 182 183 184 185 186 187 188
            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. */

         for (i = num_palette - 1; i >= maximum_colors; i--)
         {
            int done; /* to stop early if the list is pre-sorted */
G
Guy Schalnat 已提交
189
            int j;
G
Guy Schalnat 已提交
190 191 192 193

            done = 1;
            for (j = 0; j < i; j++)
            {
194 195
               if (histogram[png_ptr->dither_sort[j]]
                   < histogram[png_ptr->dither_sort[j + 1]])
G
Guy Schalnat 已提交
196 197 198
               {
                  png_byte t;

199 200 201
                  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 已提交
202 203 204 205 206 207 208 209 210 211
                  done = 0;
               }
            }
            if (done)
               break;
         }

         /* swap the palette around, and set up a table, if necessary */
         if (full_dither)
         {
212
            int j = num_palette;
G
Guy Schalnat 已提交
213 214 215

            /* put all the useful colors within the max, but don't
               move the others */
216
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
217
            {
218
               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
219 220 221
               {
                  do
                     j--;
222
                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
223 224
                  palette[i] = palette[j];
               }
G
Guy Schalnat 已提交
225
            }
G
Guy Schalnat 已提交
226 227 228
         }
         else
         {
229
            int j = num_palette;
G
Guy Schalnat 已提交
230

G
Guy Schalnat 已提交
231
            /* move all the used colors inside the max limit, and
G
Guy Schalnat 已提交
232
               develop a translation table */
233
            for (i = 0; i < maximum_colors; i++)
G
Guy Schalnat 已提交
234 235
            {
               /* only move the colors we need to */
236
               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
G
Guy Schalnat 已提交
237 238 239 240 241
               {
                  png_color tmp_color;

                  do
                     j--;
242
                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
G
Guy Schalnat 已提交
243 244 245 246 247

                  tmp_color = palette[j];
                  palette[j] = palette[i];
                  palette[i] = tmp_color;
                  /* indicate where the color went */
G
Guy Schalnat 已提交
248 249
                  png_ptr->dither_index[j] = (png_byte)i;
                  png_ptr->dither_index[i] = (png_byte)j;
G
Guy Schalnat 已提交
250 251
               }
            }
A
Andreas Dilger 已提交
252 253

            /* find closest color for those colors we are not using */
G
Guy Schalnat 已提交
254 255
            for (i = 0; i < num_palette; i++)
            {
256
               if ((int)png_ptr->dither_index[i] >= maximum_colors)
G
Guy Schalnat 已提交
257
               {
A
Andreas Dilger 已提交
258
                  int min_d, k, min_k, d_index;
G
Guy Schalnat 已提交
259

G
Guy Schalnat 已提交
260
                  /* find the closest color to one we threw out */
A
Andreas Dilger 已提交
261 262 263
                  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 已提交
264 265 266
                  {
                     int d;

A
Andreas Dilger 已提交
267
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
G
Guy Schalnat 已提交
268 269 270 271

                     if (d < min_d)
                     {
                        min_d = d;
A
Andreas Dilger 已提交
272
                        min_k = k;
G
Guy Schalnat 已提交
273 274
                     }
                  }
G
Guy Schalnat 已提交
275
                  /* point to closest color */
A
Andreas Dilger 已提交
276
                  png_ptr->dither_index[i] = (png_byte)min_k;
G
Guy Schalnat 已提交
277 278 279
               }
            }
         }
280 281
         png_free(png_ptr, png_ptr->dither_sort);
         png_ptr->dither_sort=NULL;
G
Guy Schalnat 已提交
282 283 284
      }
      else
      {
A
Andreas Dilger 已提交
285
         /* This is much harder to do simply (and quickly).  Perhaps
G
Guy Schalnat 已提交
286 287 288 289
            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).
290 291
            [We don't understand this at all, so if someone wants to
             work on improving it, be our guest - AED, GRP]
G
Guy Schalnat 已提交
292 293 294 295
            */
         int i;
         int max_d;
         int num_new_palette;
296
         png_dsortp t;
G
Guy Schalnat 已提交
297
         png_dsortpp hash;
298 299

         t=NULL;
G
Guy Schalnat 已提交
300 301

         /* initialize palette index arrays */
302
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
303
            (png_uint_32)(num_palette * png_sizeof (png_byte)));
304
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
305
            (png_uint_32)(num_palette * png_sizeof (png_byte)));
G
Guy Schalnat 已提交
306 307 308 309

         /* initialize the sort array */
         for (i = 0; i < num_palette; i++)
         {
310 311
            png_ptr->index_to_palette[i] = (png_byte)i;
            png_ptr->palette_to_index[i] = (png_byte)i;
G
Guy Schalnat 已提交
312 313
         }

314
         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
315
            png_sizeof (png_dsortp)));
G
Guy Schalnat 已提交
316
         for (i = 0; i < 769; i++)
A
Andreas Dilger 已提交
317
            hash[i] = NULL;
318
/*         png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
G
Guy Schalnat 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331

         num_new_palette = num_palette;

         /* 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.
            */
         max_d = 96;

G
Guy Schalnat 已提交
332
         while (num_new_palette > maximum_colors)
G
Guy Schalnat 已提交
333 334 335 336 337 338 339 340 341
         {
            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 已提交
342
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
G
Guy Schalnat 已提交
343 344 345 346

                  if (d <= max_d)
                  {

347
                     t = (png_dsortp)png_malloc_warn(png_ptr,
348
                         (png_uint_32)(png_sizeof(png_dsort)));
349 350
                     if (t == NULL)
                         break;
G
Guy Schalnat 已提交
351
                     t->next = hash[d];
G
Guy Schalnat 已提交
352 353
                     t->left = (png_byte)i;
                     t->right = (png_byte)j;
G
Guy Schalnat 已提交
354 355 356
                     hash[d] = t;
                  }
               }
357 358
               if (t == NULL)
                  break;
G
Guy Schalnat 已提交
359 360
            }

361
            if (t != NULL)
G
Guy Schalnat 已提交
362 363
            for (i = 0; i <= max_d; i++)
            {
A
Andreas Dilger 已提交
364
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
365
               {
G
Guy Schalnat 已提交
366
                  png_dsortp p;
G
Guy Schalnat 已提交
367 368 369

                  for (p = hash[i]; p; p = p->next)
                  {
370 371 372 373
                     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 已提交
374 375 376
                     {
                        int j, next_j;

377
                        if (num_new_palette & 0x01)
G
Guy Schalnat 已提交
378 379 380 381 382 383 384 385 386 387 388
                        {
                           j = p->left;
                           next_j = p->right;
                        }
                        else
                        {
                           j = p->right;
                           next_j = p->left;
                        }

                        num_new_palette--;
389 390
                        palette[png_ptr->index_to_palette[j]]
                          = palette[num_new_palette];
G
Guy Schalnat 已提交
391 392 393 394 395 396 397
                        if (!full_dither)
                        {
                           int k;

                           for (k = 0; k < num_palette; k++)
                           {
                              if (png_ptr->dither_index[k] ==
398
                                 png_ptr->index_to_palette[j])
G
Guy Schalnat 已提交
399
                                 png_ptr->dither_index[k] =
400
                                    png_ptr->index_to_palette[next_j];
401
                              if ((int)png_ptr->dither_index[k] ==
G
Guy Schalnat 已提交
402 403
                                 num_new_palette)
                                 png_ptr->dither_index[k] =
404
                                    png_ptr->index_to_palette[j];
G
Guy Schalnat 已提交
405 406 407
                           }
                        }

408 409 410 411
                        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 已提交
412

413 414
                        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 已提交
415 416 417 418 419 420 421 422 423 424 425
                     }
                     if (num_new_palette <= maximum_colors)
                        break;
                  }
                  if (num_new_palette <= maximum_colors)
                     break;
               }
            }

            for (i = 0; i < 769; i++)
            {
A
Andreas Dilger 已提交
426
               if (hash[i] != NULL)
G
Guy Schalnat 已提交
427
               {
428
                  png_dsortp p = hash[i];
G
Guy Schalnat 已提交
429 430 431
                  while (p)
                  {
                     t = p->next;
A
Andreas Dilger 已提交
432
                     png_free(png_ptr, p);
G
Guy Schalnat 已提交
433 434 435 436 437 438 439
                     p = t;
                  }
               }
               hash[i] = 0;
            }
            max_d += 96;
         }
A
Andreas Dilger 已提交
440
         png_free(png_ptr, hash);
441 442 443 444
         png_free(png_ptr, png_ptr->palette_to_index);
         png_free(png_ptr, png_ptr->index_to_palette);
         png_ptr->palette_to_index=NULL;
         png_ptr->index_to_palette=NULL;
G
Guy Schalnat 已提交
445 446 447
      }
      num_palette = maximum_colors;
   }
A
Andreas Dilger 已提交
448
   if (png_ptr->palette == NULL)
G
Guy Schalnat 已提交
449
   {
G
Guy Schalnat 已提交
450 451
      png_ptr->palette = palette;
   }
G
Guy Schalnat 已提交
452
   png_ptr->num_palette = (png_uint_16)num_palette;
G
Guy Schalnat 已提交
453 454 455 456

   if (full_dither)
   {
      int i;
G
Guy Schalnat 已提交
457
      png_bytep distance;
458
      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
G
Guy Schalnat 已提交
459
         PNG_DITHER_BLUE_BITS;
460 461 462 463
      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 已提交
464

A
Andreas Dilger 已提交
465
      png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
466
         (png_uint_32)(num_entries * png_sizeof (png_byte)));
467

468 469
      png_memset(png_ptr->palette_lookup, 0, num_entries *
         png_sizeof (png_byte));
G
Guy Schalnat 已提交
470

471
      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
472
         png_sizeof(png_byte)));
473

474
      png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
475 476 477

      for (i = 0; i < num_palette; i++)
      {
478 479 480 481
         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 已提交
482 483 484

         for (ir = 0; ir < num_red; ir++)
         {
485 486
            /* int dr = abs(ir - r); */
            int dr = ((ir > r) ? ir - r : r - ir);
487
            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
G
Guy Schalnat 已提交
488 489

            for (ig = 0; ig < num_green; ig++)
G
Guy Schalnat 已提交
490
            {
491 492
               /* int dg = abs(ig - g); */
               int dg = ((ig > g) ? ig - g : g - ig);
493 494 495
               int dt = dr + dg;
               int dm = ((dr > dg) ? dr : dg);
               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
G
Guy Schalnat 已提交
496 497

               for (ib = 0; ib < num_blue; ib++)
G
Guy Schalnat 已提交
498
               {
499
                  int d_index = index_g | ib;
500 501
                  /* int db = abs(ib - b); */
                  int db = ((ib > b) ? ib - b : b - ib);
502 503
                  int dmax = ((dm > db) ? dm : db);
                  int d = dmax + dt + db;
G
Guy Schalnat 已提交
504

505
                  if (d < (int)distance[d_index])
G
Guy Schalnat 已提交
506
                  {
A
Andreas Dilger 已提交
507 508
                     distance[d_index] = (png_byte)d;
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
G
Guy Schalnat 已提交
509 510
                  }
               }
511 512 513
            }
         }
      }
G
Guy Schalnat 已提交
514

A
Andreas Dilger 已提交
515
      png_free(png_ptr, distance);
G
Guy Schalnat 已提交
516 517
   }
}
G
Guy Schalnat 已提交
518
#endif
G
Guy Schalnat 已提交
519

520
#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
A
Andreas Dilger 已提交
521
/* Transform the image from the file_gamma to the screen_gamma.  We
522 523 524
 * 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.
525 526 527 528
 *
 * 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.
529
 */
530
void PNGAPI
531
png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
G
Guy Schalnat 已提交
532
{
A
Andreas Dilger 已提交
533
   png_debug(1, "in png_set_gamma\n");
534 535 536 537
   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 已提交
538
   png_ptr->gamma = (float)file_gamma;
539
   png_ptr->screen_gamma = (float)scrn_gamma;
G
Guy Schalnat 已提交
540
}
G
Guy Schalnat 已提交
541
#endif
G
Guy Schalnat 已提交
542

G
Guy Schalnat 已提交
543
#if defined(PNG_READ_EXPAND_SUPPORTED)
544
/* Expand paletted images to RGB, expand grayscale images of
545
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
546 547
 * to alpha channels.
 */
548
void PNGAPI
G
Guy Schalnat 已提交
549
png_set_expand(png_structp png_ptr)
G
Guy Schalnat 已提交
550
{
A
Andreas Dilger 已提交
551
   png_debug(1, "in png_set_expand\n");
G
Guy Schalnat 已提交
552 553
   png_ptr->transformations |= PNG_EXPAND;
}
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

/* 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.
 */

/* Expand paletted images to RGB. */
570
void PNGAPI
571 572 573 574 575 576 577
png_set_palette_to_rgb(png_structp png_ptr)
{
   png_debug(1, "in png_set_expand\n");
   png_ptr->transformations |= PNG_EXPAND;
}

/* Expand grayscale images of less than 8-bit depth to 8 bits. */
578
void PNGAPI
579 580 581 582 583 584 585
png_set_gray_1_2_4_to_8(png_structp png_ptr)
{
   png_debug(1, "in png_set_expand\n");
   png_ptr->transformations |= PNG_EXPAND;
}

/* Expand tRNS chunks to alpha channels. */
586
void PNGAPI
587 588 589 590 591 592
png_set_tRNS_to_alpha(png_structp png_ptr)
{
   png_debug(1, "in png_set_expand\n");
   png_ptr->transformations |= PNG_EXPAND;
}
#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
G
Guy Schalnat 已提交
593

G
Guy Schalnat 已提交
594
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
595
void PNGAPI
G
Guy Schalnat 已提交
596
png_set_gray_to_rgb(png_structp png_ptr)
G
Guy Schalnat 已提交
597
{
A
Andreas Dilger 已提交
598
   png_debug(1, "in png_set_gray_to_rgb\n");
G
Guy Schalnat 已提交
599 600
   png_ptr->transformations |= PNG_GRAY_TO_RGB;
}
G
Guy Schalnat 已提交
601
#endif
G
Guy Schalnat 已提交
602

603 604
#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
#if defined(PNG_FLOATING_POINT_SUPPORTED)
605 606
/* 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.
607
 */
608

609
void PNGAPI
610
png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
611 612 613 614 615 616 617 618
   double green)
{
      int red_fixed = (int)((float)red*100000.0 + 0.5);
      int green_fixed = (int)((float)green*100000.0 + 0.5);
      png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
}
#endif

619
void PNGAPI
620 621
png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
   png_fixed_point red, png_fixed_point green)
A
Andreas Dilger 已提交
622
{
A
Andreas Dilger 已提交
623
   png_debug(1, "in png_set_rgb_to_gray\n");
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
   switch(error_action)
   {
      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
              break;
      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
              break;
      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
   }
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#if defined(PNG_READ_EXPAND_SUPPORTED)
      png_ptr->transformations |= PNG_EXPAND;
#else
   {
      png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
   }
#endif
   {
642
      png_uint_16 red_int, green_int;
643
      if(red < 0 || green < 0)
644
      {
645 646
         red_int   =  6968; /* .212671 * 32768 + .5 */
         green_int = 23434; /* .715160 * 32768 + .5 */
647
      }
648 649 650 651 652 653
      else if(red + green < 100000L)
      {
        red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
        green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
      }
      else
654 655
      {
         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
656 657
         red_int   =  6968;
         green_int = 23434;
658
      }
659 660 661
      png_ptr->rgb_to_gray_red_coeff   = red_int;
      png_ptr->rgb_to_gray_green_coeff = green_int;
      png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
662
   }
A
Andreas Dilger 已提交
663 664 665
}
#endif

666 667 668
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
    defined(PNG_LEGACY_SUPPORTED)
669
void PNGAPI
670 671 672 673
png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
   read_user_transform_fn)
{
   png_debug(1, "in png_set_read_user_transform_fn\n");
674
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
675 676
   png_ptr->transformations |= PNG_USER_TRANSFORM;
   png_ptr->read_user_transform_fn = read_user_transform_fn;
677 678 679 680 681 682
#endif
#ifdef PNG_LEGACY_SUPPORTED
   if(read_user_transform_fn)
      png_warning(png_ptr,
        "This version of libpng does not support user transforms");
#endif
683 684 685
}
#endif

A
Andreas Dilger 已提交
686
/* Initialize everything needed for the read.  This includes modifying
687 688
 * the palette.
 */
689
void /* PRIVATE */
G
Guy Schalnat 已提交
690
png_init_read_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
691
{
692
   png_debug(1, "in png_init_read_transformations\n");
693
#if defined(PNG_USELESS_TESTS_SUPPORTED)
694 695 696 697 698 699
   if(png_ptr != NULL)
#endif
  {
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
 || defined(PNG_READ_GAMMA_SUPPORTED)
   int color_type = png_ptr->color_type;
700
#endif
G
Guy Schalnat 已提交
701

G
Guy Schalnat 已提交
702
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
703 704
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
       (png_ptr->transformations & PNG_EXPAND))
G
Guy Schalnat 已提交
705
   {
706
      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
G
Guy Schalnat 已提交
707
      {
G
Guy Schalnat 已提交
708
         /* expand background chunk. */
G
Guy Schalnat 已提交
709 710 711
         switch (png_ptr->bit_depth)
         {
            case 1:
G
Guy Schalnat 已提交
712
               png_ptr->background.gray *= (png_uint_16)0xff;
713 714
               png_ptr->background.red = png_ptr->background.green
                 =  png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
715 716
               break;
            case 2:
G
Guy Schalnat 已提交
717
               png_ptr->background.gray *= (png_uint_16)0x55;
718 719
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
720 721
               break;
            case 4:
G
Guy Schalnat 已提交
722
               png_ptr->background.gray *= (png_uint_16)0x11;
723 724
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
725 726 727
               break;
            case 8:
            case 16:
728 729
               png_ptr->background.red = png_ptr->background.green
                 = png_ptr->background.blue = png_ptr->background.gray;
G
Guy Schalnat 已提交
730 731 732
               break;
         }
      }
G
Guy Schalnat 已提交
733
      else if (color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
734
      {
G
Guy Schalnat 已提交
735
         png_ptr->background.red   =
G
Guy Schalnat 已提交
736 737 738
            png_ptr->palette[png_ptr->background.index].red;
         png_ptr->background.green =
            png_ptr->palette[png_ptr->background.index].green;
G
Guy Schalnat 已提交
739
         png_ptr->background.blue  =
G
Guy Schalnat 已提交
740
            png_ptr->palette[png_ptr->background.index].blue;
741 742 743 744 745

#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
        if (png_ptr->transformations & PNG_INVERT_ALPHA)
        {
#if defined(PNG_READ_EXPAND_SUPPORTED)
746
           if (!(png_ptr->transformations & PNG_EXPAND))
747 748
#endif
           {
749
           /* invert the alpha channel (in tRNS) unless the pixels are
750
              going to be expanded, in which case leave it for later */
751 752 753
              int i,istop;
              istop=(int)png_ptr->num_trans;
              for (i=0; i<istop; i++)
754
                 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
755 756 757 758
           }
        }
#endif

G
Guy Schalnat 已提交
759 760
      }
   }
G
Guy Schalnat 已提交
761
#endif
G
Guy Schalnat 已提交
762

763
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
G
Guy Schalnat 已提交
764
   png_ptr->background_1 = png_ptr->background;
G
Guy Schalnat 已提交
765
#endif
766
#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

   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))
   {
    int i,k;
    k=0;
    for (i=0; i<png_ptr->num_trans; i++)
    {
      if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
        k=1; /* partial transparency is present */
    }
    if (k == 0)
      png_ptr->transformations &= (~PNG_GAMMA);
   }

783
   if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
G
Guy Schalnat 已提交
784 785
   {
      png_build_gamma_table(png_ptr);
G
Guy Schalnat 已提交
786
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
G
Guy Schalnat 已提交
787
      if (png_ptr->transformations & PNG_BACKGROUND)
G
Guy Schalnat 已提交
788
      {
G
Guy Schalnat 已提交
789 790
         if (color_type == PNG_COLOR_TYPE_PALETTE)
         {
791 792
           /* could skip if no transparency and 
           */
G
Guy Schalnat 已提交
793
            png_color back, back_1;
794 795 796
            png_colorp palette = png_ptr->palette;
            int num_palette = png_ptr->num_palette;
            int i;
A
Andreas Dilger 已提交
797 798 799 800 801 802 803 804 805 806 807 808
            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
            {
809
               double g, gs;
A
Andreas Dilger 已提交
810

811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
               switch (png_ptr->background_gamma_type)
               {
                  case PNG_BACKGROUND_GAMMA_SCREEN:
                     g = (png_ptr->screen_gamma);
                     gs = 1.0;
                     break;
                  case PNG_BACKGROUND_GAMMA_FILE:
                     g = 1.0 / (png_ptr->gamma);
                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
                     break;
                  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 已提交
830

831
               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
A
Andreas Dilger 已提交
832
               {
833
                  back.red   = (png_byte)png_ptr->background.red;
A
Andreas Dilger 已提交
834
                  back.green = (png_byte)png_ptr->background.green;
835
                  back.blue  = (png_byte)png_ptr->background.blue;
A
Andreas Dilger 已提交
836 837 838
               }
               else
               {
839 840 841 842 843 844
                  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 已提交
845
               }
G
Guy Schalnat 已提交
846

847 848 849 850 851 852
               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 已提交
853
            }
G
Guy Schalnat 已提交
854 855
            for (i = 0; i < num_palette; i++)
            {
A
Andreas Dilger 已提交
856
               if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
G
Guy Schalnat 已提交
857 858 859 860 861
               {
                  if (png_ptr->trans[i] == 0)
                  {
                     palette[i] = back;
                  }
A
Andreas Dilger 已提交
862
                  else /* if (png_ptr->trans[i] != 0xff) */
G
Guy Schalnat 已提交
863
                  {
A
Andreas Dilger 已提交
864
                     png_byte v, w;
G
Guy Schalnat 已提交
865 866

                     v = png_ptr->gamma_to_1[palette[i].red];
A
Andreas Dilger 已提交
867
                     png_composite(w, v, png_ptr->trans[i], back_1.red);
G
Guy Schalnat 已提交
868 869 870
                     palette[i].red = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].green];
A
Andreas Dilger 已提交
871
                     png_composite(w, v, png_ptr->trans[i], back_1.green);
G
Guy Schalnat 已提交
872 873 874
                     palette[i].green = png_ptr->gamma_from_1[w];

                     v = png_ptr->gamma_to_1[palette[i].blue];
A
Andreas Dilger 已提交
875
                     png_composite(w, v, png_ptr->trans[i], back_1.blue);
G
Guy Schalnat 已提交
876 877 878 879 880 881 882 883 884 885 886
                     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];
               }
            }
         }
887
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
888 889
         else
         /* color_type != PNG_COLOR_TYPE_PALETTE */
G
Guy Schalnat 已提交
890
         {
891 892 893
            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
            double g = 1.0;
            double gs = 1.0;
G
Guy Schalnat 已提交
894 895

            switch (png_ptr->background_gamma_type)
G
Guy Schalnat 已提交
896
            {
G
Guy Schalnat 已提交
897
               case PNG_BACKGROUND_GAMMA_SCREEN:
898
                  g = (png_ptr->screen_gamma);
G
Guy Schalnat 已提交
899 900 901 902
                  gs = 1.0;
                  break;
               case PNG_BACKGROUND_GAMMA_FILE:
                  g = 1.0 / (png_ptr->gamma);
903
                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
G
Guy Schalnat 已提交
904 905 906 907
                  break;
               case PNG_BACKGROUND_GAMMA_UNIQUE:
                  g = 1.0 / (png_ptr->background_gamma);
                  gs = 1.0 / (png_ptr->background_gamma *
908
                     png_ptr->screen_gamma);
G
Guy Schalnat 已提交
909 910 911
                  break;
            }

912 913 914 915 916
            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);

917 918 919
            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 已提交
920
            {
921
               /* RGB or RGBA with color background */
G
Guy Schalnat 已提交
922
               png_ptr->background_1.red = (png_uint_16)(pow(
G
Guy Schalnat 已提交
923 924 925 926 927 928 929 930 931 932 933 934 935 936
                  (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
            {
937 938 939 940 941
               /* 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 已提交
942 943 944
            }
         }
      }
G
Guy Schalnat 已提交
945
      else
946
      /* transformation does not include PNG_BACKGROUND */
947
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
948 949
      if (color_type == PNG_COLOR_TYPE_PALETTE)
      {
950 951 952
         png_colorp palette = png_ptr->palette;
         int num_palette = png_ptr->num_palette;
         int i;
G
Guy Schalnat 已提交
953 954 955 956 957 958 959 960 961 962 963

         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];
         }
      }
   }
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
   else
G
Guy Schalnat 已提交
964
#endif
965
#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
G
Guy Schalnat 已提交
966
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
967
   /* No GAMMA transformation */
968 969
   if ((png_ptr->transformations & PNG_BACKGROUND) &&
       (color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
970
   {
971 972
      int i;
      int istop = (int)png_ptr->num_trans;
G
Guy Schalnat 已提交
973
      png_color back;
974
      png_colorp palette = png_ptr->palette;
G
Guy Schalnat 已提交
975 976 977 978 979

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

980
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
981 982 983 984 985 986 987
      {
         if (png_ptr->trans[i] == 0)
         {
            palette[i] = back;
         }
         else if (png_ptr->trans[i] != 0xff)
         {
988
            /* The png_composite() macro is defined in png.h */
A
Andreas Dilger 已提交
989 990 991 992 993 994
            png_composite(palette[i].red, palette[i].red,
               png_ptr->trans[i], back.red);
            png_composite(palette[i].green, palette[i].green,
               png_ptr->trans[i], back.green);
            png_composite(palette[i].blue, palette[i].blue,
               png_ptr->trans[i], back.blue);
G
Guy Schalnat 已提交
995 996
         }
      }
G
Guy Schalnat 已提交
997
   }
998
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
G
Guy Schalnat 已提交
999

G
Guy Schalnat 已提交
1000
#if defined(PNG_READ_SHIFT_SUPPORTED)
G
Guy Schalnat 已提交
1001
   if ((png_ptr->transformations & PNG_SHIFT) &&
1002
      (color_type == PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1003
   {
1004 1005 1006 1007 1008
      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 已提交
1009 1010 1011 1012 1013 1014 1015

      if (sr < 0 || sr > 8)
         sr = 0;
      if (sg < 0 || sg > 8)
         sg = 0;
      if (sb < 0 || sb > 8)
         sb = 0;
1016
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1017 1018 1019 1020 1021 1022
      {
         png_ptr->palette[i].red >>= sr;
         png_ptr->palette[i].green >>= sg;
         png_ptr->palette[i].blue >>= sb;
      }
   }
1023
#endif  /* PNG_READ_SHIFT_SUPPORTED */
1024
 }
1025 1026 1027 1028 1029
#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
   if(png_ptr)
      return;
#endif
G
Guy Schalnat 已提交
1030 1031
}

A
Andreas Dilger 已提交
1032
/* Modify the info structure to reflect the transformations.  The
1033 1034 1035
 * info should be updated so a PNG file could be written with it,
 * assuming the transformations result in valid PNG data.
 */
1036
void /* PRIVATE */
G
Guy Schalnat 已提交
1037
png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1038
{
A
Andreas Dilger 已提交
1039
   png_debug(1, "in png_read_transform_info\n");
G
Guy Schalnat 已提交
1040
#if defined(PNG_READ_EXPAND_SUPPORTED)
A
Andreas Dilger 已提交
1041
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1042
   {
A
Andreas Dilger 已提交
1043 1044 1045 1046 1047 1048
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         if (png_ptr->num_trans)
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         else
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
G
Guy Schalnat 已提交
1049
         info_ptr->bit_depth = 8;
A
Andreas Dilger 已提交
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
         info_ptr->num_trans = 0;
      }
      else
      {
         if (png_ptr->num_trans)
            info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
         if (info_ptr->bit_depth < 8)
            info_ptr->bit_depth = 8;
         info_ptr->num_trans = 0;
      }
G
Guy Schalnat 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
   }
#endif

#if defined(PNG_READ_BACKGROUND_SUPPORTED)
   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

1072 1073
#if defined(PNG_READ_GAMMA_SUPPORTED)
   if (png_ptr->transformations & PNG_GAMMA)
1074 1075
   {
#ifdef PNG_FLOATING_POINT_SUPPORTED
1076 1077
      info_ptr->gamma = png_ptr->gamma;
#endif
1078 1079 1080 1081 1082
#ifdef PNG_FIXED_POINT_SUPPORTED
      info_ptr->int_gamma = png_ptr->int_gamma;
#endif
   }
#endif
1083

G
Guy Schalnat 已提交
1084
#if defined(PNG_READ_16_TO_8_SUPPORTED)
1085
   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
G
Guy Schalnat 已提交
1086
      info_ptr->bit_depth = 8;
G
Guy Schalnat 已提交
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
#endif

#if defined(PNG_READ_DITHER_SUPPORTED)
   if (png_ptr->transformations & PNG_DITHER)
   {
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
         (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
         png_ptr->palette_lookup && info_ptr->bit_depth == 8)
      {
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
      }
G
Guy Schalnat 已提交
1098
   }
G
Guy Schalnat 已提交
1099 1100 1101
#endif

#if defined(PNG_READ_PACK_SUPPORTED)
1102
   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
G
Guy Schalnat 已提交
1103 1104 1105 1106
      info_ptr->bit_depth = 8;
#endif

#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1107
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
G
Guy Schalnat 已提交
1108 1109
      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
#endif
A
Andreas Dilger 已提交
1110

1111 1112 1113 1114 1115
#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
#endif

G
Guy Schalnat 已提交
1116
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1117 1118 1119 1120 1121
      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 已提交
1122

1123
#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1124
   if (png_ptr->transformations & PNG_STRIP_ALPHA)
A
Andreas Dilger 已提交
1125 1126 1127
      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
#endif

1128 1129 1130
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;

A
Andreas Dilger 已提交
1131
#if defined(PNG_READ_FILLER_SUPPORTED)
1132
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1133 1134 1135
   if ((png_ptr->transformations & PNG_FILLER) &&
       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1136
   {
1137
      info_ptr->channels++;
1138 1139 1140 1141
#if 0 /* if adding a true alpha channel not just filler */
      info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
#endif
   }
A
Andreas Dilger 已提交
1142 1143
#endif

1144 1145
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1146 1147 1148 1149 1150 1151 1152 1153 1154
   if(png_ptr->transformations & PNG_USER_TRANSFORM)
     {
       if(info_ptr->bit_depth < png_ptr->user_transform_depth)
         info_ptr->bit_depth = png_ptr->user_transform_depth;
       if(info_ptr->channels < png_ptr->user_transform_channels)
         info_ptr->channels = png_ptr->user_transform_channels;
     }
#endif

G
Guy Schalnat 已提交
1155 1156
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
      info_ptr->bit_depth);
1157 1158

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

1160 1161 1162 1163
#if !defined(PNG_READ_EXPAND_SUPPORTED)
   if(png_ptr)
      return;
#endif
G
Guy Schalnat 已提交
1164 1165
}

1166 1167 1168 1169
/* 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.
 */
1170
void /* PRIVATE */
G
Guy Schalnat 已提交
1171
png_do_read_transformations(png_structp png_ptr)
G
Guy Schalnat 已提交
1172
{
A
Andreas Dilger 已提交
1173 1174 1175
   png_debug(1, "in png_do_read_transformations\n");
#if !defined(PNG_USELESS_TESTS_SUPPORTED)
   if (png_ptr->row_buf == NULL)
G
Guy Schalnat 已提交
1176
   {
1177
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
A
Andreas Dilger 已提交
1178 1179 1180 1181 1182
      char msg[50];

      sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
         png_ptr->pass);
      png_error(png_ptr, msg);
1183 1184 1185
#else
      png_error(png_ptr, "NULL row buffer");
#endif
G
Guy Schalnat 已提交
1186
   }
A
Andreas Dilger 已提交
1187 1188 1189 1190
#endif

#if defined(PNG_READ_EXPAND_SUPPORTED)
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
1191
   {
A
Andreas Dilger 已提交
1192 1193 1194 1195 1196
      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
            png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
      }
1197
      else
A
Andreas Dilger 已提交
1198 1199 1200 1201 1202 1203 1204 1205
      {
         if (png_ptr->num_trans)
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
               &(png_ptr->trans_values));
         else
            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
               NULL);
      }
G
Guy Schalnat 已提交
1206
   }
G
Guy Schalnat 已提交
1207 1208
#endif

A
Andreas Dilger 已提交
1209 1210 1211 1212 1213 1214
#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
   if (png_ptr->transformations & PNG_STRIP_ALPHA)
      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
         PNG_FLAG_FILLER_AFTER);
#endif

1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
   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);
      if(rgb_error)
      {
         png_ptr->rgb_to_gray_status=1;
         if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
         if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
      }
   }
#endif

1231 1232 1233 1234 1235
/*
From Andreas Dilger e-mail to png-implement, 26 March 1998:

  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
1236
  pixel is transparent.  You would also need to make sure that the
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
  transparency information is upgraded to RGB.

  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.
 */

#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   /* if gray -> RGB, do so now only if background is non-gray; else do later
    * for performance reasons */
1264
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1265
       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1266 1267 1268
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

G
Guy Schalnat 已提交
1269
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1270 1271 1272
   if ((png_ptr->transformations & PNG_BACKGROUND) &&
      ((png_ptr->num_trans != 0 ) ||
      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
G
Guy Schalnat 已提交
1273
      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1274 1275 1276
         &(png_ptr->trans_values), &(png_ptr->background)
#if defined(PNG_READ_GAMMA_SUPPORTED)
         , &(png_ptr->background_1),
G
Guy Schalnat 已提交
1277 1278 1279
         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,
1280 1281 1282
         png_ptr->gamma_shift
#endif
);
G
Guy Schalnat 已提交
1283 1284 1285 1286
#endif

#if defined(PNG_READ_GAMMA_SUPPORTED)
   if ((png_ptr->transformations & PNG_GAMMA) &&
1287 1288 1289 1290 1291
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
      !((png_ptr->transformations & PNG_BACKGROUND) &&
      ((png_ptr->num_trans != 0) ||
      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
#endif
A
Andreas Dilger 已提交
1292
      (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
G
Guy Schalnat 已提交
1293 1294 1295
      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
         png_ptr->gamma_table, png_ptr->gamma_16_table,
         png_ptr->gamma_shift);
G
Guy Schalnat 已提交
1296 1297 1298
#endif

#if defined(PNG_READ_16_TO_8_SUPPORTED)
G
Guy Schalnat 已提交
1299 1300
   if (png_ptr->transformations & PNG_16_TO_8)
      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1301 1302 1303
#endif

#if defined(PNG_READ_DITHER_SUPPORTED)
G
Guy Schalnat 已提交
1304
   if (png_ptr->transformations & PNG_DITHER)
G
Guy Schalnat 已提交
1305
   {
A
Andreas Dilger 已提交
1306 1307
      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
         png_ptr->palette_lookup, png_ptr->dither_index);
1308 1309
      if(png_ptr->row_info.rowbytes == (png_uint_32)0)
         png_error(png_ptr, "png_do_dither returned rowbytes=0");
A
Andreas Dilger 已提交
1310
   }
G
Guy Schalnat 已提交
1311 1312 1313
#endif

#if defined(PNG_READ_INVERT_SUPPORTED)
G
Guy Schalnat 已提交
1314
   if (png_ptr->transformations & PNG_INVERT_MONO)
G
Guy Schalnat 已提交
1315
      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1316 1317 1318
#endif

#if defined(PNG_READ_SHIFT_SUPPORTED)
G
Guy Schalnat 已提交
1319 1320 1321
   if (png_ptr->transformations & PNG_SHIFT)
      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
         &(png_ptr->shift));
G
Guy Schalnat 已提交
1322 1323 1324
#endif

#if defined(PNG_READ_PACK_SUPPORTED)
G
Guy Schalnat 已提交
1325
   if (png_ptr->transformations & PNG_PACK)
G
Guy Schalnat 已提交
1326
      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1327 1328 1329
#endif

#if defined(PNG_READ_BGR_SUPPORTED)
G
Guy Schalnat 已提交
1330 1331
   if (png_ptr->transformations & PNG_BGR)
      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1332 1333
#endif

A
Andreas Dilger 已提交
1334 1335 1336 1337 1338
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
   if (png_ptr->transformations & PNG_PACKSWAP)
      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

G
Guy Schalnat 已提交
1339
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1340
   /* if gray -> RGB, do so now only if we did not do so above */
1341 1342
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
G
Guy Schalnat 已提交
1343
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1344 1345 1346 1347 1348
#endif

#if defined(PNG_READ_FILLER_SUPPORTED)
   if (png_ptr->transformations & PNG_FILLER)
      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
A
Andreas Dilger 已提交
1349 1350 1351
         (png_uint_32)png_ptr->filler, png_ptr->flags);
#endif

1352 1353 1354 1355 1356
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

1357 1358 1359 1360 1361
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

A
Andreas Dilger 已提交
1362 1363 1364
#if defined(PNG_READ_SWAP_SUPPORTED)
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
1365
#endif
1366 1367 1368

#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
1369
    {
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
      if(png_ptr->read_user_transform_fn != NULL)
        (*(png_ptr->read_user_transform_fn)) /* user read transform function */
          (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 */
1381
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1382 1383 1384 1385
      if(png_ptr->user_transform_depth)
         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
      if(png_ptr->user_transform_channels)
         png_ptr->row_info.channels = png_ptr->user_transform_channels;
1386
#endif
1387 1388
      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
         png_ptr->row_info.channels);
1389 1390
      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
         png_ptr->row_info.width);
1391
   }
1392 1393
#endif

G
Guy Schalnat 已提交
1394 1395
}

G
Guy Schalnat 已提交
1396
#if defined(PNG_READ_PACK_SUPPORTED)
1397 1398 1399 1400 1401 1402
/* 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.
 */
1403
void /* PRIVATE */
G
Guy Schalnat 已提交
1404
png_do_unpack(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
1405
{
A
Andreas Dilger 已提交
1406 1407 1408 1409 1410 1411
   png_debug(1, "in png_do_unpack\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
#else
   if (row_info->bit_depth < 8)
#endif
G
Guy Schalnat 已提交
1412
   {
1413
      png_uint_32 i;
1414
      png_uint_32 row_width=row_info->width;
A
Andreas Dilger 已提交
1415

G
Guy Schalnat 已提交
1416 1417 1418 1419
      switch (row_info->bit_depth)
      {
         case 1:
         {
1420 1421
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
            png_bytep dp = row + (png_size_t)row_width - 1;
1422
            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1423
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
1424
            {
1425
               *dp = (png_byte)((*sp >> shift) & 0x01);
G
Guy Schalnat 已提交
1426 1427 1428 1429
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
G
Guy Schalnat 已提交
1430
               }
G
Guy Schalnat 已提交
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
               else
                  shift++;

               dp--;
            }
            break;
         }
         case 2:
         {

1441 1442
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
            png_bytep dp = row + (png_size_t)row_width - 1;
1443
            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1444
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
1445
            {
1446
               *dp = (png_byte)((*sp >> shift) & 0x03);
G
Guy Schalnat 已提交
1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift += 2;

               dp--;
            }
            break;
         }
         case 4:
         {
1461 1462
            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
            png_bytep dp = row + (png_size_t)row_width - 1;
1463
            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1464
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
1465
            {
1466
               *dp = (png_byte)((*sp >> shift) & 0x0f);
G
Guy Schalnat 已提交
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift = 4;

               dp--;
            }
            break;
         }
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
1481
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1482
      row_info->rowbytes = row_width * row_info->channels;
G
Guy Schalnat 已提交
1483 1484
   }
}
G
Guy Schalnat 已提交
1485
#endif
G
Guy Schalnat 已提交
1486

G
Guy Schalnat 已提交
1487
#if defined(PNG_READ_SHIFT_SUPPORTED)
1488 1489 1490 1491 1492
/* 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.
 */
1493
void /* PRIVATE */
A
Andreas Dilger 已提交
1494
png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
G
Guy Schalnat 已提交
1495
{
A
Andreas Dilger 已提交
1496 1497 1498 1499 1500 1501
   png_debug(1, "in png_do_unshift\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL && sig_bits != NULL &&
#endif
       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1502 1503
   {
      int shift[4];
1504 1505 1506
      int channels = 0;
      int c;
      png_uint_16 value = 0;
1507
      png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
1508 1509 1510

      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
G
Guy Schalnat 已提交
1511 1512 1513
         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 已提交
1514 1515 1516
      }
      else
      {
G
Guy Schalnat 已提交
1517
         shift[channels++] = row_info->bit_depth - sig_bits->gray;
G
Guy Schalnat 已提交
1518 1519 1520
      }
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
G
Guy Schalnat 已提交
1521
         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
G
Guy Schalnat 已提交
1522
      }
G
Guy Schalnat 已提交
1523

A
Andreas Dilger 已提交
1524
      for (c = 0; c < channels; c++)
G
Guy Schalnat 已提交
1525
      {
A
Andreas Dilger 已提交
1526 1527
         if (shift[c] <= 0)
            shift[c] = 0;
G
Guy Schalnat 已提交
1528 1529 1530
         else
            value = 1;
      }
G
Guy Schalnat 已提交
1531

G
Guy Schalnat 已提交
1532 1533
      if (!value)
         return;
G
Guy Schalnat 已提交
1534

G
Guy Schalnat 已提交
1535
      switch (row_info->bit_depth)
G
Guy Schalnat 已提交
1536 1537 1538
      {
         case 2:
         {
A
Andreas Dilger 已提交
1539
            png_bytep bp;
1540 1541
            png_uint_32 i;
            png_uint_32 istop = row_info->rowbytes;
A
Andreas Dilger 已提交
1542

1543
            for (bp = row, i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1544 1545
            {
               *bp >>= 1;
1546
               *bp++ &= 0x55;
G
Guy Schalnat 已提交
1547 1548 1549 1550 1551
            }
            break;
         }
         case 4:
         {
1552
            png_bytep bp = row;
1553 1554
            png_uint_32 i;
            png_uint_32 istop = row_info->rowbytes;
1555 1556
            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
               (png_byte)((int)0xf >> shift[0]));
1557

1558
            for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1559 1560
            {
               *bp >>= shift[0];
1561
               *bp++ &= mask;
G
Guy Schalnat 已提交
1562 1563 1564 1565 1566
            }
            break;
         }
         case 8:
         {
1567
            png_bytep bp = row;
1568
            png_uint_32 i;
1569
            png_uint_32 istop = row_width * channels;
G
Guy Schalnat 已提交
1570

1571
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
1572
            {
1573
               *bp++ >>= shift[i%channels];
G
Guy Schalnat 已提交
1574 1575 1576 1577 1578
            }
            break;
         }
         case 16:
         {
1579 1580 1581
            png_bytep bp = row;
            png_uint_32 i;
            png_uint_32 istop = channels * row_width;
G
Guy Schalnat 已提交
1582

1583
            for (i = 0; i < istop; i++)
A
Andreas Dilger 已提交
1584
            {
1585 1586 1587 1588
               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 已提交
1589 1590 1591 1592 1593 1594
            }
            break;
         }
      }
   }
}
G
Guy Schalnat 已提交
1595
#endif
G
Guy Schalnat 已提交
1596

G
Guy Schalnat 已提交
1597
#if defined(PNG_READ_16_TO_8_SUPPORTED)
G
Guy Schalnat 已提交
1598
/* chop rows of bit depth 16 down to 8 */
1599
void /* PRIVATE */
G
Guy Schalnat 已提交
1600
png_do_chop(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
1601
{
A
Andreas Dilger 已提交
1602 1603 1604 1605 1606 1607
   png_debug(1, "in png_do_chop\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
#else
   if (row_info->bit_depth == 16)
#endif
G
Guy Schalnat 已提交
1608
   {
1609 1610 1611 1612
      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 已提交
1613

1614
      for (i = 0; i<istop; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
1615
      {
A
Andreas Dilger 已提交
1616
#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
      /* 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) |
       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
       *
       * GRR: no, I think this is what it really should be:
       *   *dp = (((((png_uint_32)(*sp) << 8) |
       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
       *
       * GRR: here's the exact calculation with shifts:
       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
       *   *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:
       */
1638

A
Andreas Dilger 已提交
1639 1640
         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
#else
1641
       /* Simply discard the low order byte */
G
Guy Schalnat 已提交
1642
         *dp = *sp;
A
Andreas Dilger 已提交
1643
#endif
G
Guy Schalnat 已提交
1644 1645
      }
      row_info->bit_depth = 8;
G
Guy Schalnat 已提交
1646
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1647
      row_info->rowbytes = row_info->width * row_info->channels;
A
Andreas Dilger 已提交
1648 1649 1650 1651 1652
   }
}
#endif

#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1653
void /* PRIVATE */
A
Andreas Dilger 已提交
1654 1655 1656 1657 1658 1659 1660
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
   png_debug(1, "in png_do_read_swap_alpha\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL)
#endif
   {
1661
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
1662 1663 1664 1665 1666
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This converts from RGBA to ARGB */
         if (row_info->bit_depth == 8)
         {
1667 1668
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1669 1670
            png_byte save;
            png_uint_32 i;
1671

1672
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
         /* This converts from RRGGBBAA to AARRGGBB */
         else
         {
1684 1685
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1686 1687
            png_byte save[2];
            png_uint_32 i;
1688

1689
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708
            {
               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)
         {
1709 1710
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1711 1712
            png_byte save;
            png_uint_32 i;
1713

1714
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1715 1716 1717 1718 1719 1720 1721 1722 1723
            {
               save = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save;
            }
         }
         /* This converts from GGAA to AAGG */
         else
         {
1724 1725
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
A
Andreas Dilger 已提交
1726 1727 1728
            png_byte save[2];
            png_uint_32 i;

1729
            for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
            {
               save[0] = *(--sp);
               save[1] = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = save[0];
               *(--dp) = save[1];
            }
         }
      }
G
Guy Schalnat 已提交
1740 1741
   }
}
G
Guy Schalnat 已提交
1742
#endif
G
Guy Schalnat 已提交
1743

1744
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1745
void /* PRIVATE */
1746 1747 1748 1749 1750 1751 1752
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
   png_debug(1, "in png_do_read_invert_alpha\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL)
#endif
   {
1753
      png_uint_32 row_width = row_info->width;
1754 1755 1756 1757 1758
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         /* This inverts the alpha channel in RGBA */
         if (row_info->bit_depth == 8)
         {
1759 1760
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
1761 1762
            png_uint_32 i;

1763
            for (i = 0; i < row_width; i++)
1764
            {
1765
               *(--dp) = (png_byte)(255 - *(--sp));
1766 1767

/*             This does nothing:
1768 1769 1770
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1771 1772 1773 1774
               We can replace it with:
*/
               sp-=3;
               dp=sp;
1775 1776 1777 1778 1779
            }
         }
         /* This inverts the alpha channel in RRGGBBAA */
         else
         {
1780 1781
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
1782 1783
            png_uint_32 i;

1784
            for (i = 0; i < row_width; i++)
1785
            {
1786 1787
               *(--dp) = (png_byte)(255 - *(--sp));
               *(--dp) = (png_byte)(255 - *(--sp));
1788 1789

/*             This does nothing:
1790 1791 1792 1793 1794 1795
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1796 1797 1798 1799
               We can replace it with:
*/
               sp-=6;
               dp=sp;
1800 1801 1802 1803 1804
            }
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
1805
         /* This inverts the alpha channel in GA */
1806 1807
         if (row_info->bit_depth == 8)
         {
1808 1809
            png_bytep sp = row + row_info->rowbytes;
            png_bytep dp = sp;
1810 1811
            png_uint_32 i;

1812
            for (i = 0; i < row_width; i++)
1813
            {
1814
               *(--dp) = (png_byte)(255 - *(--sp));
1815
               *(--dp) = *(--sp);
1816 1817
            }
         }
1818
         /* This inverts the alpha channel in GGAA */
1819 1820
         else
         {
1821 1822
            png_bytep sp  = row + row_info->rowbytes;
            png_bytep dp = sp;
1823 1824
            png_uint_32 i;

1825
            for (i = 0; i < row_width; i++)
1826
            {
1827 1828
               *(--dp) = (png_byte)(255 - *(--sp));
               *(--dp) = (png_byte)(255 - *(--sp));
1829
/*
1830 1831
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1832 1833 1834
*/
               sp-=2;
               dp=sp;
1835 1836 1837 1838 1839 1840 1841
            }
         }
      }
   }
}
#endif

G
Guy Schalnat 已提交
1842
#if defined(PNG_READ_FILLER_SUPPORTED)
A
Andreas Dilger 已提交
1843
/* Add filler channel if we have RGB color */
1844
void /* PRIVATE */
G
Guy Schalnat 已提交
1845
png_do_read_filler(png_row_infop row_info, png_bytep row,
A
Andreas Dilger 已提交
1846
   png_uint_32 filler, png_uint_32 flags)
G
Guy Schalnat 已提交
1847
{
G
Guy Schalnat 已提交
1848
   png_uint_32 i;
1849 1850
   png_uint_32 row_width = row_info->width;

1851
   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1852
   png_byte lo_filler = (png_byte)(filler & 0xff);
A
Andreas Dilger 已提交
1853 1854 1855 1856 1857 1858

   png_debug(1, "in png_do_read_filler\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL  && row_info != NULL &&
#endif
1859
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
1860
   {
1861
      if(row_info->bit_depth == 8)
G
Guy Schalnat 已提交
1862
      {
1863 1864
         /* This changes the data from G to GX */
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
1865
         {
1866 1867
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp =  sp + (png_size_t)row_width;
1868 1869
            for (i = 1; i < row_width; i++)
            {
1870
               *(--dp) = lo_filler;
1871 1872
               *(--dp) = *(--sp);
            }
1873
            *(--dp) = lo_filler;
1874 1875 1876 1877 1878 1879 1880
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      /* This changes the data from G to XG */
         else
         {
1881 1882
            png_bytep sp = row + (png_size_t)row_width;
            png_bytep dp = sp  + (png_size_t)row_width;
1883 1884 1885
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
1886
               *(--dp) = lo_filler;
1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897
            }
            row_info->channels = 2;
            row_info->pixel_depth = 16;
            row_info->rowbytes = row_width * 2;
         }
      }
      else if(row_info->bit_depth == 16)
      {
         /* This changes the data from GG to GGXX */
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
1898 1899
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
1900 1901 1902
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
1903
               *(--dp) = lo_filler;
1904 1905 1906
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
1907 1908
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
1909 1910
            row_info->channels = 2;
            row_info->pixel_depth = 32;
1911
            row_info->rowbytes = row_width * 4;
1912 1913 1914 1915
         }
         /* This changes the data from GG to XXGG */
         else
         {
1916 1917
            png_bytep sp = row + (png_size_t)row_width * 2;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
1918 1919 1920 1921 1922
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
1923
               *(--dp) = lo_filler;
1924 1925
            }
            row_info->channels = 2;
1926 1927
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
1928
         }
G
Guy Schalnat 已提交
1929
      }
1930
      row_info->color_type |= PNG_COLOR_MASK_ALPHA;
1931 1932 1933 1934 1935 1936 1937 1938
   } /* COLOR_TYPE == GRAY */
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   {
      if(row_info->bit_depth == 8)
      {
         /* This changes the data from RGB to RGBX */
         if (flags & PNG_FLAG_FILLER_AFTER)
         {
1939 1940
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp  + (png_size_t)row_width;
1941 1942
            for (i = 1; i < row_width; i++)
            {
1943
               *(--dp) = lo_filler;
1944 1945 1946 1947
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
1948
            *(--dp) = lo_filler;
1949 1950 1951 1952
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
A
Andreas Dilger 已提交
1953
      /* This changes the data from RGB to XRGB */
1954 1955
         else
         {
1956 1957
            png_bytep sp = row + (png_size_t)row_width * 3;
            png_bytep dp = sp + (png_size_t)row_width;
1958 1959 1960 1961 1962
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
1963
               *(--dp) = lo_filler;
1964 1965 1966 1967 1968 1969 1970
            }
            row_info->channels = 4;
            row_info->pixel_depth = 32;
            row_info->rowbytes = row_width * 4;
         }
      }
      else if(row_info->bit_depth == 16)
G
Guy Schalnat 已提交
1971
      {
1972 1973
         /* This changes the data from RRGGBB to RRGGBBXX */
         if (flags & PNG_FLAG_FILLER_AFTER)
G
Guy Schalnat 已提交
1974
         {
1975 1976
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
1977 1978 1979
            for (i = 1; i < row_width; i++)
            {
               *(--dp) = hi_filler;
1980
               *(--dp) = lo_filler;
1981 1982 1983 1984 1985 1986 1987
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
            }
1988 1989
            *(--dp) = hi_filler;
            *(--dp) = lo_filler;
1990 1991
            row_info->channels = 4;
            row_info->pixel_depth = 64;
1992
            row_info->rowbytes = row_width * 8;
1993 1994 1995 1996
         }
         /* This changes the data from RRGGBB to XXRRGGBB */
         else
         {
1997 1998
            png_bytep sp = row + (png_size_t)row_width * 6;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
1999 2000 2001 2002 2003 2004 2005 2006 2007
            for (i = 0; i < row_width; i++)
            {
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = *(--sp);
               *(--dp) = hi_filler;
2008
               *(--dp) = lo_filler;
2009 2010 2011
            }
            row_info->channels = 4;
            row_info->pixel_depth = 64;
2012
            row_info->rowbytes = row_width * 8;
G
Guy Schalnat 已提交
2013
         }
G
Guy Schalnat 已提交
2014
      }
2015
      row_info->color_type |= PNG_COLOR_MASK_ALPHA;
2016
   } /* COLOR_TYPE == RGB */
G
Guy Schalnat 已提交
2017
}
G
Guy Schalnat 已提交
2018
#endif
G
Guy Schalnat 已提交
2019

G
Guy Schalnat 已提交
2020
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
A
Andreas Dilger 已提交
2021
/* expand grayscale files to RGB, with or without alpha */
2022
void /* PRIVATE */
G
Guy Schalnat 已提交
2023
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
2024
{
G
Guy Schalnat 已提交
2025
   png_uint_32 i;
2026
   png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2027

A
Andreas Dilger 已提交
2028 2029 2030 2031 2032
   png_debug(1, "in png_do_gray_to_rgb\n");
   if (row_info->bit_depth >= 8 &&
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
G
Guy Schalnat 已提交
2033 2034 2035 2036 2037 2038
      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (row_info->bit_depth == 8)
         {
2039 2040
            png_bytep sp = row + (png_size_t)row_width - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2041
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2042 2043 2044
            {
               *(dp--) = *sp;
               *(dp--) = *sp;
2045
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2046 2047 2048 2049
            }
         }
         else
         {
2050 2051
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2052
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2053 2054 2055 2056 2057
            {
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2058 2059
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2060 2061 2062 2063 2064 2065 2066
            }
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
2067 2068
            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 2;
2069
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2070 2071 2072 2073
            {
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *sp;
2074
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2075 2076 2077 2078
            }
         }
         else
         {
2079 2080
            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
            png_bytep dp = sp  + (png_size_t)row_width * 4;
2081
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2082 2083 2084 2085 2086 2087 2088
            {
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
               *(dp--) = *sp;
               *(dp--) = *(sp - 1);
2089 2090
               *(dp--) = *(sp--);
               *(dp--) = *(sp--);
G
Guy Schalnat 已提交
2091 2092 2093
            }
         }
      }
G
Guy Schalnat 已提交
2094
      row_info->channels += (png_byte)2;
G
Guy Schalnat 已提交
2095
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
G
Guy Schalnat 已提交
2096 2097
      row_info->pixel_depth = (png_byte)(row_info->channels *
         row_info->bit_depth);
2098
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
G
Guy Schalnat 已提交
2099 2100
   }
}
G
Guy Schalnat 已提交
2101
#endif
G
Guy Schalnat 已提交
2102

2103
#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2104
/* reduce RGB files to grayscale, with or without alpha
2105 2106 2107 2108 2109 2110 2111
 * using the equation given in Poynton's ColorFAQ at
 * <http://www.inforamp.net/~poynton/>
 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
 *
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
 *
 *  We approximate this with
2112
 *
2113
 *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
2114 2115 2116
 *
 *  which can be expressed with integers as
 *
2117
 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2118 2119 2120 2121 2122
 *
 *  The calculation is to be done in a linear colorspace.
 *
 *  Other integer coefficents can be used via png_set_rgb_to_gray().
 */
2123
int /* PRIVATE */
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138
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;

   png_debug(1, "in png_do_rgb_to_gray\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
      (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
2139 2140 2141
      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;
2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161

      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++)];
                  if(red != green || red != blue)
                  {
                     rgb_error |= 1;
                     *(dp++) = png_ptr->gamma_from_1[
2162
                       (rc*red+gc*green+bc*blue)>>15];
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180
                  }
                  else
                     *(dp++) = *(sp-1);
               }
            }
            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++);
                  if(red != green || red != blue)
                  {
                     rgb_error |= 1;
2181
                     *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2182 2183 2184 2185 2186 2187
                  }
                  else
                     *(dp++) = *(sp-1);
               }
            }
         }
2188

2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200
         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;

2201 2202 2203
                  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;
2204 2205 2206 2207 2208 2209 2210 2211 2212

                  if(red == green && red == blue)
                     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];
2213
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2214
                                  png_ptr->gamma_shift][blue>>8];
2215
                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
2216
                                  + bc*blue_1)>>15);
2217 2218 2219 2220
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
                     rgb_error |= 1;
                  }
2221

2222 2223
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234
               }
            }
            else
#endif
            {
               png_bytep sp = row;
               png_bytep dp = row;
               for (i = 0; i < row_width; i++)
               {
                  png_uint_16 red, green, blue, gray16;

2235 2236 2237
                  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;
2238 2239 2240

                  if(red != green || red != blue)
                     rgb_error |= 1;
2241
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2242 2243
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
               }
            }
         }
      }
      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++)];
                  if(red != green || red != blue)
                     rgb_error |= 1;
                  *(dp++) =  png_ptr->gamma_from_1
2265
                             [(rc*red + gc*green + bc*blue)>>15];
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280
                  *(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++);
                  if(red != green || red != blue)
                     rgb_error |= 1;
2281
                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297
                  *(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;

2298 2299 2300
                  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;
2301 2302 2303 2304 2305 2306 2307 2308 2309

                  if(red == green && red == blue)
                     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];
2310
                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2311
                                  png_ptr->gamma_shift][blue>>8];
2312
                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
2313
                                  + gc * green_1 + bc * blue_1)>>15);
2314 2315 2316 2317
                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                         png_ptr->gamma_shift][gray16 >> 8];
                     rgb_error |= 1;
                  }
2318

2319 2320
                  *(dp++) = (png_byte)((w>>8) & 0xff);
                  *(dp++) = (png_byte)(w & 0xff);
2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332
                  *(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;
2333 2334 2335
                  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;
2336 2337
                  if(red != green || red != blue)
                     rgb_error |= 1;
2338
                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2339 2340
                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
                  *(dp++) = (png_byte)(gray16 & 0xff);
2341 2342 2343 2344 2345 2346 2347 2348 2349 2350
                  *(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);
2351
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2352 2353 2354 2355 2356
   }
   return rgb_error;
}
#endif

2357 2358 2359 2360 2361
/* 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.
 */
2362
void PNGAPI
G
Guy Schalnat 已提交
2363
png_build_grayscale_palette(int bit_depth, png_colorp palette)
G
Guy Schalnat 已提交
2364 2365 2366 2367 2368 2369
{
   int num_palette;
   int color_inc;
   int i;
   int v;

A
Andreas Dilger 已提交
2370 2371
   png_debug(1, "in png_do_build_grayscale_palette\n");
   if (palette == NULL)
G
Guy Schalnat 已提交
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392
      return;

   switch (bit_depth)
   {
      case 1:
         num_palette = 2;
         color_inc = 0xff;
         break;
      case 2:
         num_palette = 4;
         color_inc = 0x55;
         break;
      case 4:
         num_palette = 16;
         color_inc = 0x11;
         break;
      case 8:
         num_palette = 256;
         color_inc = 1;
         break;
      default:
G
Guy Schalnat 已提交
2393
         num_palette = 0;
G
Guy Schalnat 已提交
2394
         color_inc = 0;
G
Guy Schalnat 已提交
2395 2396 2397 2398 2399
         break;
   }

   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
   {
G
Guy Schalnat 已提交
2400 2401 2402
      palette[i].red = (png_byte)v;
      palette[i].green = (png_byte)v;
      palette[i].blue = (png_byte)v;
G
Guy Schalnat 已提交
2403 2404 2405
   }
}

A
Andreas Dilger 已提交
2406 2407
/* This function is currently unused.  Do we really need it? */
#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2408
void /* PRIVATE */
G
Guy Schalnat 已提交
2409
png_correct_palette(png_structp png_ptr, png_colorp palette,
G
Guy Schalnat 已提交
2410 2411
   int num_palette)
{
A
Andreas Dilger 已提交
2412
   png_debug(1, "in png_correct_palette\n");
2413 2414
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
    defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2415
   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
G
Guy Schalnat 已提交
2416
   {
A
Andreas Dilger 已提交
2417
      png_color back, back_1;
G
Guy Schalnat 已提交
2418

A
Andreas Dilger 已提交
2419 2420
      if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
      {
G
Guy Schalnat 已提交
2421 2422 2423
         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];
G
Guy Schalnat 已提交
2424

G
Guy Schalnat 已提交
2425 2426 2427
         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];
A
Andreas Dilger 已提交
2428 2429 2430 2431
      }
      else
      {
         double g;
G
Guy Schalnat 已提交
2432

2433
         g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
A
Andreas Dilger 已提交
2434 2435 2436

         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
             fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
G
Guy Schalnat 已提交
2437
         {
A
Andreas Dilger 已提交
2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474
            back.red = png_ptr->background.red;
            back.green = png_ptr->background.green;
            back.blue = png_ptr->background.blue;
         }
         else
         {
            back.red =
               (png_byte)(pow((double)png_ptr->background.red/255, g) *
                255.0 + 0.5);
            back.green =
               (png_byte)(pow((double)png_ptr->background.green/255, g) *
                255.0 + 0.5);
            back.blue =
               (png_byte)(pow((double)png_ptr->background.blue/255, g) *
                255.0 + 0.5);
         }

         g = 1.0 / png_ptr->background_gamma;

         back_1.red =
            (png_byte)(pow((double)png_ptr->background.red/255, g) *
             255.0 + 0.5);
         back_1.green =
            (png_byte)(pow((double)png_ptr->background.green/255, g) *
             255.0 + 0.5);
         back_1.blue =
            (png_byte)(pow((double)png_ptr->background.blue/255, g) *
             255.0 + 0.5);
      }

      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_uint_32 i;

         for (i = 0; i < (png_uint_32)num_palette; i++)
         {
            if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
G
Guy Schalnat 已提交
2475 2476 2477
            {
               palette[i] = back;
            }
A
Andreas Dilger 已提交
2478
            else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
G
Guy Schalnat 已提交
2479
            {
A
Andreas Dilger 已提交
2480
               png_byte v, w;
G
Guy Schalnat 已提交
2481 2482

               v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
A
Andreas Dilger 已提交
2483 2484
               png_composite(w, v, png_ptr->trans[i], back_1.red);
               palette[i].red = png_ptr->gamma_from_1[w];
G
Guy Schalnat 已提交
2485 2486

               v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
A
Andreas Dilger 已提交
2487 2488
               png_composite(w, v, png_ptr->trans[i], back_1.green);
               palette[i].green = png_ptr->gamma_from_1[w];
G
Guy Schalnat 已提交
2489 2490

               v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
A
Andreas Dilger 已提交
2491 2492
               png_composite(w, v, png_ptr->trans[i], back_1.blue);
               palette[i].blue = png_ptr->gamma_from_1[w];
G
Guy Schalnat 已提交
2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503
            }
            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];
            }
         }
      }
      else
      {
G
Guy Schalnat 已提交
2504
         int i;
G
Guy Schalnat 已提交
2505 2506 2507

         for (i = 0; i < num_palette; i++)
         {
A
Andreas Dilger 已提交
2508
            if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
G
Guy Schalnat 已提交
2509
            {
G
Guy Schalnat 已提交
2510
               palette[i] = back;
G
Guy Schalnat 已提交
2511 2512 2513 2514 2515 2516 2517 2518 2519 2520
            }
            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];
            }
         }
      }
   }
G
Guy Schalnat 已提交
2521 2522 2523
   else
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2524
   if (png_ptr->transformations & PNG_GAMMA)
G
Guy Schalnat 已提交
2525 2526 2527 2528 2529 2530 2531 2532 2533 2534
   {
      int i;

      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];
      }
   }
G
Guy Schalnat 已提交
2535 2536 2537 2538 2539
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
   else
#endif
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
2540
   if (png_ptr->transformations & PNG_BACKGROUND)
G
Guy Schalnat 已提交
2541
   {
G
Guy Schalnat 已提交
2542
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
2543
      {
G
Guy Schalnat 已提交
2544
         png_color back;
G
Guy Schalnat 已提交
2545

G
Guy Schalnat 已提交
2546 2547 2548
         back.red   = (png_byte)png_ptr->background.red;
         back.green = (png_byte)png_ptr->background.green;
         back.blue  = (png_byte)png_ptr->background.blue;
G
Guy Schalnat 已提交
2549

2550
         for (i = 0; i < (int)png_ptr->num_trans; i++)
G
Guy Schalnat 已提交
2551
         {
2552
            if (png_ptr->trans[i] == 0)
G
Guy Schalnat 已提交
2553
            {
G
Guy Schalnat 已提交
2554 2555 2556
               palette[i].red = back.red;
               palette[i].green = back.green;
               palette[i].blue = back.blue;
G
Guy Schalnat 已提交
2557
            }
2558
            else if (png_ptr->trans[i] != 0xff)
G
Guy Schalnat 已提交
2559
            {
A
Andreas Dilger 已提交
2560 2561 2562 2563 2564 2565
               png_composite(palette[i].red, png_ptr->palette[i].red,
                  png_ptr->trans[i], back.red);
               png_composite(palette[i].green, png_ptr->palette[i].green,
                  png_ptr->trans[i], back.green);
               png_composite(palette[i].blue, png_ptr->palette[i].blue,
                  png_ptr->trans[i], back.blue);
G
Guy Schalnat 已提交
2566 2567 2568 2569 2570 2571 2572 2573 2574
            }
         }
      }
      else /* assume grayscale palette (what else could it be?) */
      {
         int i;

         for (i = 0; i < num_palette; i++)
         {
A
Andreas Dilger 已提交
2575
            if (i == (png_byte)png_ptr->trans_values.gray)
G
Guy Schalnat 已提交
2576
            {
G
Guy Schalnat 已提交
2577 2578 2579
               palette[i].red = (png_byte)png_ptr->background.red;
               palette[i].green = (png_byte)png_ptr->background.green;
               palette[i].blue = (png_byte)png_ptr->background.blue;
G
Guy Schalnat 已提交
2580 2581 2582 2583
            }
         }
      }
   }
G
Guy Schalnat 已提交
2584
#endif
G
Guy Schalnat 已提交
2585
}
G
Guy Schalnat 已提交
2586
#endif
G
Guy Schalnat 已提交
2587

G
Guy Schalnat 已提交
2588
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
2589
/* Replace any alpha or transparency with the supplied background color.
2590 2591 2592
 * "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.
 */
2593
void /* PRIVATE */
G
Guy Schalnat 已提交
2594
png_do_background(png_row_infop row_info, png_bytep row,
2595 2596 2597
   png_color_16p trans_values, png_color_16p background
#if defined(PNG_READ_GAMMA_SUPPORTED)
   , png_color_16p background_1,
G
Guy Schalnat 已提交
2598
   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
G
Guy Schalnat 已提交
2599
   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2600 2601 2602
   png_uint_16pp gamma_16_to_1, int gamma_shift
#endif
   )
G
Guy Schalnat 已提交
2603
{
G
Guy Schalnat 已提交
2604
   png_bytep sp, dp;
G
Guy Schalnat 已提交
2605
   png_uint_32 i;
2606
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
2607
   int shift;
G
Guy Schalnat 已提交
2608

A
Andreas Dilger 已提交
2609 2610 2611 2612 2613
   png_debug(1, "in png_do_background\n");
   if (background != NULL &&
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
G
Guy Schalnat 已提交
2614
      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
A
Andreas Dilger 已提交
2615
      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
G
Guy Schalnat 已提交
2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_GRAY:
         {
            switch (row_info->bit_depth)
            {
               case 1:
               {
                  sp = row;
                  shift = 7;
2627
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2628
                  {
2629
                     if ((png_uint_16)((*sp >> shift) & 0x01)
2630
                        == trans_values->gray)
G
Guy Schalnat 已提交
2631
                     {
G
Guy Schalnat 已提交
2632 2633
                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
                        *sp |= (png_byte)(background->gray << shift);
G
Guy Schalnat 已提交
2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646
                     }
                     if (!shift)
                     {
                        shift = 7;
                        sp++;
                     }
                     else
                        shift--;
                  }
                  break;
               }
               case 2:
               {
2647 2648
#if defined(PNG_READ_GAMMA_SUPPORTED)
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
2649
                  {
2650 2651 2652
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2653
                     {
2654
                        if ((png_uint_16)((*sp >> shift) & 0x03)
2655 2656 2657 2658 2659 2660 2661
                            == trans_values->gray)
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        else
                        {
2662
                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
2663
                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2664
                               (p << 4) | (p << 6)] >> 6) & 0x03);
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
2675
                     }
2676 2677 2678 2679 2680 2681 2682
                  }
                  else
#endif
                  {
                     sp = row;
                     shift = 6;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2683
                     {
2684
                        if ((png_uint_16)((*sp >> shift) & 0x03)
2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696
                            == trans_values->gray)
                        {
                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        if (!shift)
                        {
                           shift = 6;
                           sp++;
                        }
                        else
                           shift -= 2;
G
Guy Schalnat 已提交
2697 2698 2699 2700 2701 2702
                     }
                  }
                  break;
               }
               case 4:
               {
2703 2704
#if defined(PNG_READ_GAMMA_SUPPORTED)
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
2705
                  {
2706 2707 2708
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2709
                     {
2710
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
2711 2712 2713 2714 2715 2716 2717
                            == trans_values->gray)
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        else
                        {
2718
                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2719
                           png_byte g = (png_byte)((gamma_table[p |
2720
                             (p << 4)] >> 4) & 0x0f);
2721 2722 2723 2724 2725 2726 2727 2728 2729 2730
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(g << shift);
                        }
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
2731
                     }
2732 2733 2734 2735 2736 2737 2738
                  }
                  else
#endif
                  {
                     sp = row;
                     shift = 4;
                     for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2739
                     {
2740
                        if ((png_uint_16)((*sp >> shift) & 0x0f)
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752
                            == trans_values->gray)
                        {
                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                           *sp |= (png_byte)(background->gray << shift);
                        }
                        if (!shift)
                        {
                           shift = 4;
                           sp++;
                        }
                        else
                           shift -= 4;
G
Guy Schalnat 已提交
2753 2754 2755 2756 2757 2758
                     }
                  }
                  break;
               }
               case 8:
               {
G
Guy Schalnat 已提交
2759
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2760
                  if (gamma_table != NULL)
G
Guy Schalnat 已提交
2761
                  {
2762 2763
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
2764 2765 2766
                     {
                        if (*sp == trans_values->gray)
                        {
A
Andreas Dilger 已提交
2767
                           *sp = (png_byte)background->gray;
G
Guy Schalnat 已提交
2768 2769 2770 2771 2772 2773 2774 2775
                        }
                        else
                        {
                           *sp = gamma_table[*sp];
                        }
                     }
                  }
                  else
G
Guy Schalnat 已提交
2776
#endif
G
Guy Schalnat 已提交
2777
                  {
2778 2779
                     sp = row;
                     for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
2780 2781 2782
                     {
                        if (*sp == trans_values->gray)
                        {
A
Andreas Dilger 已提交
2783
                           *sp = (png_byte)background->gray;
G
Guy Schalnat 已提交
2784 2785 2786 2787 2788 2789 2790
                        }
                     }
                  }
                  break;
               }
               case 16:
               {
G
Guy Schalnat 已提交
2791
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2792
                  if (gamma_16 != NULL)
G
Guy Schalnat 已提交
2793
                  {
2794 2795
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
2796 2797 2798
                     {
                        png_uint_16 v;

2799
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
G
Guy Schalnat 已提交
2800 2801
                        if (v == trans_values->gray)
                        {
A
Andreas Dilger 已提交
2802
                           /* background is already in screen gamma */
G
Guy Schalnat 已提交
2803 2804
                           *sp = (png_byte)((background->gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(background->gray & 0xff);
G
Guy Schalnat 已提交
2805 2806 2807
                        }
                        else
                        {
A
Andreas Dilger 已提交
2808
                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
2809
                           *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
2810
                           *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
2811
                        }
G
Guy Schalnat 已提交
2812
                     }
G
Guy Schalnat 已提交
2813 2814
                  }
                  else
G
Guy Schalnat 已提交
2815
#endif
G
Guy Schalnat 已提交
2816
                  {
2817 2818
                     sp = row;
                     for (i = 0; i < row_width; i++, sp += 2)
G
Guy Schalnat 已提交
2819 2820 2821
                     {
                        png_uint_16 v;

2822
                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
G
Guy Schalnat 已提交
2823 2824
                        if (v == trans_values->gray)
                        {
G
Guy Schalnat 已提交
2825 2826
                           *sp = (png_byte)((background->gray >> 8) & 0xff);
                           *(sp + 1) = (png_byte)(background->gray & 0xff);
G
Guy Schalnat 已提交
2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838
                        }
                     }
                  }
                  break;
               }
            }
            break;
         }
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
G
Guy Schalnat 已提交
2839
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2840
               if (gamma_table != NULL)
G
Guy Schalnat 已提交
2841
               {
2842 2843
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
2844 2845 2846 2847 2848
                  {
                     if (*sp == trans_values->red &&
                        *(sp + 1) == trans_values->green &&
                        *(sp + 2) == trans_values->blue)
                     {
A
Andreas Dilger 已提交
2849 2850 2851
                        *sp = (png_byte)background->red;
                        *(sp + 1) = (png_byte)background->green;
                        *(sp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
2852 2853 2854 2855 2856 2857 2858 2859 2860 2861
                     }
                     else
                     {
                        *sp = gamma_table[*sp];
                        *(sp + 1) = gamma_table[*(sp + 1)];
                        *(sp + 2) = gamma_table[*(sp + 2)];
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
2862
#endif
G
Guy Schalnat 已提交
2863
               {
2864 2865
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 3)
G
Guy Schalnat 已提交
2866 2867 2868 2869 2870
                  {
                     if (*sp == trans_values->red &&
                        *(sp + 1) == trans_values->green &&
                        *(sp + 2) == trans_values->blue)
                     {
A
Andreas Dilger 已提交
2871 2872 2873
                        *sp = (png_byte)background->red;
                        *(sp + 1) = (png_byte)background->green;
                        *(sp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
2874 2875 2876 2877
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
2878
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
2879
            {
G
Guy Schalnat 已提交
2880
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2881
               if (gamma_16 != NULL)
G
Guy Schalnat 已提交
2882
               {
2883 2884
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
2885
                  {
2886 2887 2888
                     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 已提交
2889
                     if (r == trans_values->red && g == trans_values->green &&
G
Guy Schalnat 已提交
2890 2891
                        b == trans_values->blue)
                     {
A
Andreas Dilger 已提交
2892
                        /* background is already in screen gamma */
G
Guy Schalnat 已提交
2893 2894 2895 2896 2897 2898
                        *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 已提交
2899 2900 2901
                     }
                     else
                     {
2902
                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
2903
                        *sp = (png_byte)((v >> 8) & 0xff);
G
Guy Schalnat 已提交
2904
                        *(sp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
2905
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
2906 2907
                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 3) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
2908
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
2909 2910
                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(sp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
2911 2912 2913 2914
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
2915
#endif
G
Guy Schalnat 已提交
2916
               {
2917 2918
                  sp = row;
                  for (i = 0; i < row_width; i++, sp += 6)
G
Guy Schalnat 已提交
2919
                  {
2920 2921 2922
                     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 已提交
2923

A
Andreas Dilger 已提交
2924
                     if (r == trans_values->red && g == trans_values->green &&
G
Guy Schalnat 已提交
2925
                        b == trans_values->blue)
G
Guy Schalnat 已提交
2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939
                     {
                        *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;
         }
         case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
2940
         {
A
Andreas Dilger 已提交
2941
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
2942
            {
G
Guy Schalnat 已提交
2943
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2944 2945 2946
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
               {
2947 2948 2949
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
2950
                  {
2951
                     png_uint_16 a = *(sp + 1);
G
Guy Schalnat 已提交
2952

A
Andreas Dilger 已提交
2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964
                     if (a == 0xff)
                     {
                        *dp = gamma_table[*sp];
                     }
                     else if (a == 0)
                     {
                        /* background is already in screen gamma */
                        *dp = (png_byte)background->gray;
                     }
                     else
                     {
                        png_byte v, w;
G
Guy Schalnat 已提交
2965

A
Andreas Dilger 已提交
2966 2967 2968
                        v = gamma_to_1[*sp];
                        png_composite(w, v, a, background_1->gray);
                        *dp = gamma_from_1[w];
G
Guy Schalnat 已提交
2969 2970
                     }
                  }
A
Andreas Dilger 已提交
2971 2972
               }
               else
G
Guy Schalnat 已提交
2973
#endif
A
Andreas Dilger 已提交
2974
               {
2975 2976 2977
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 2, dp++)
G
Guy Schalnat 已提交
2978
                  {
2979
                     png_byte a = *(sp + 1);
G
Guy Schalnat 已提交
2980

A
Andreas Dilger 已提交
2981 2982 2983 2984
                     if (a == 0xff)
                     {
                        *dp = *sp;
                     }
2985
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
2986 2987 2988 2989 2990 2991 2992
                     else if (a == 0)
                     {
                        *dp = (png_byte)background->gray;
                     }
                     else
                     {
                        png_composite(*dp, *sp, a, background_1->gray);
G
Guy Schalnat 已提交
2993
                     }
2994 2995 2996
#else
                     *dp = (png_byte)background->gray;
#endif
G
Guy Schalnat 已提交
2997 2998
                  }
               }
A
Andreas Dilger 已提交
2999 3000 3001
            }
            else /* if (png_ptr->bit_depth == 16) */
            {
G
Guy Schalnat 已提交
3002
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3003 3004 3005
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
               {
3006 3007 3008
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
G
Guy Schalnat 已提交
3009
                  {
3010
                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
A
Andreas Dilger 已提交
3011 3012

                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3013
                     {
A
Andreas Dilger 已提交
3014
                        png_uint_16 v;
G
Guy Schalnat 已提交
3015

A
Andreas Dilger 已提交
3016 3017 3018 3019
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
                     }
3020
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3021
                     else if (a == 0)
3022 3023 3024
#else
                     else
#endif
A
Andreas Dilger 已提交
3025 3026 3027 3028 3029
                     {
                        /* background is already in screen gamma */
                        *dp = (png_byte)((background->gray >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(background->gray & 0xff);
                     }
3030
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3031 3032 3033
                     else
                     {
                        png_uint_16 g, v, w;
G
Guy Schalnat 已提交
3034

A
Andreas Dilger 已提交
3035 3036 3037 3038 3039
                        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 已提交
3040
                     }
3041
#endif
G
Guy Schalnat 已提交
3042
                  }
A
Andreas Dilger 已提交
3043 3044
               }
               else
G
Guy Schalnat 已提交
3045
#endif
A
Andreas Dilger 已提交
3046
               {
3047 3048 3049
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
G
Guy Schalnat 已提交
3050
                  {
3051
                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
A
Andreas Dilger 已提交
3052
                     if (a == (png_uint_16)0xffff)
G
Guy Schalnat 已提交
3053
                     {
A
Andreas Dilger 已提交
3054 3055
                        png_memcpy(dp, sp, 2);
                     }
3056
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3057
                     else if (a == 0)
3058 3059 3060
#else
                     else
#endif
A
Andreas Dilger 已提交
3061 3062 3063 3064
                     {
                        *dp = (png_byte)((background->gray >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(background->gray & 0xff);
                     }
3065
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3066 3067 3068
                     else
                     {
                        png_uint_16 g, v;
G
Guy Schalnat 已提交
3069

3070
                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
A
Andreas Dilger 已提交
3071 3072 3073
                        png_composite_16(v, g, a, background_1->gray);
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3074
                     }
3075
#endif
G
Guy Schalnat 已提交
3076 3077 3078 3079 3080 3081 3082 3083 3084
                  }
               }
            }
            break;
         }
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
G
Guy Schalnat 已提交
3085
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3086 3087
               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                   gamma_table != NULL)
G
Guy Schalnat 已提交
3088
               {
3089 3090 3091
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
G
Guy Schalnat 已提交
3092
                  {
3093
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3094 3095 3096 3097 3098 3099 3100 3101 3102

                     if (a == 0xff)
                     {
                        *dp = gamma_table[*sp];
                        *(dp + 1) = gamma_table[*(sp + 1)];
                        *(dp + 2) = gamma_table[*(sp + 2)];
                     }
                     else if (a == 0)
                     {
A
Andreas Dilger 已提交
3103 3104 3105 3106
                        /* background is already in screen gamma */
                        *dp = (png_byte)background->red;
                        *(dp + 1) = (png_byte)background->green;
                        *(dp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
3107 3108 3109
                     }
                     else
                     {
A
Andreas Dilger 已提交
3110
                        png_byte v, w;
G
Guy Schalnat 已提交
3111 3112

                        v = gamma_to_1[*sp];
A
Andreas Dilger 已提交
3113 3114
                        png_composite(w, v, a, background_1->red);
                        *dp = gamma_from_1[w];
G
Guy Schalnat 已提交
3115
                        v = gamma_to_1[*(sp + 1)];
A
Andreas Dilger 已提交
3116 3117
                        png_composite(w, v, a, background_1->green);
                        *(dp + 1) = gamma_from_1[w];
G
Guy Schalnat 已提交
3118
                        v = gamma_to_1[*(sp + 2)];
A
Andreas Dilger 已提交
3119 3120
                        png_composite(w, v, a, background_1->blue);
                        *(dp + 2) = gamma_from_1[w];
G
Guy Schalnat 已提交
3121 3122 3123 3124
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3125
#endif
G
Guy Schalnat 已提交
3126
               {
3127 3128 3129
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
G
Guy Schalnat 已提交
3130
                  {
3131
                     png_byte a = *(sp + 3);
G
Guy Schalnat 已提交
3132 3133 3134 3135 3136 3137 3138 3139 3140

                     if (a == 0xff)
                     {
                        *dp = *sp;
                        *(dp + 1) = *(sp + 1);
                        *(dp + 2) = *(sp + 2);
                     }
                     else if (a == 0)
                     {
A
Andreas Dilger 已提交
3141 3142 3143
                        *dp = (png_byte)background->red;
                        *(dp + 1) = (png_byte)background->green;
                        *(dp + 2) = (png_byte)background->blue;
G
Guy Schalnat 已提交
3144 3145 3146
                     }
                     else
                     {
A
Andreas Dilger 已提交
3147 3148 3149 3150 3151
                        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 已提交
3152 3153 3154 3155
                     }
                  }
               }
            }
A
Andreas Dilger 已提交
3156
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3157
            {
G
Guy Schalnat 已提交
3158
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3159 3160
               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                   gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
3161
               {
3162 3163 3164
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
G
Guy Schalnat 已提交
3165
                  {
3166 3167
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                         << 8) + (png_uint_16)(*(sp + 7)));
G
Guy Schalnat 已提交
3168 3169 3170 3171
                     if (a == (png_uint_16)0xffff)
                     {
                        png_uint_16 v;

A
Andreas Dilger 已提交
3172
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3173 3174
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3175
                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
G
Guy Schalnat 已提交
3176 3177
                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3178
                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
G
Guy Schalnat 已提交
3179 3180
                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3181 3182 3183
                     }
                     else if (a == 0)
                     {
A
Andreas Dilger 已提交
3184
                        /* background is already in screen gamma */
G
Guy Schalnat 已提交
3185 3186 3187 3188 3189 3190
                        *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 已提交
3191 3192 3193
                     }
                     else
                     {
A
Andreas Dilger 已提交
3194 3195 3196
                        png_uint_16 v, w, x;

                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3197
                        png_composite_16(w, v, a, background_1->red);
A
Andreas Dilger 已提交
3198 3199 3200 3201
                        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)];
3202
                        png_composite_16(w, v, a, background_1->green);
A
Andreas Dilger 已提交
3203 3204 3205 3206
                        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)];
3207
                        png_composite_16(w, v, a, background_1->blue);
A
Andreas Dilger 已提交
3208 3209 3210
                        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 已提交
3211 3212 3213 3214
                     }
                  }
               }
               else
G
Guy Schalnat 已提交
3215
#endif
G
Guy Schalnat 已提交
3216
               {
3217 3218 3219
                  sp = row;
                  dp = row;
                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
G
Guy Schalnat 已提交
3220
                  {
3221 3222
                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                        << 8) + (png_uint_16)(*(sp + 7)));
G
Guy Schalnat 已提交
3223 3224
                     if (a == (png_uint_16)0xffff)
                     {
G
Guy Schalnat 已提交
3225
                        png_memcpy(dp, sp, 6);
G
Guy Schalnat 已提交
3226 3227 3228
                     }
                     else if (a == 0)
                     {
G
Guy Schalnat 已提交
3229 3230 3231 3232 3233 3234 3235 3236
                        *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 已提交
3237
                     {
3238
                        png_uint_16 v;
A
Andreas Dilger 已提交
3239

3240 3241 3242 3243 3244
                        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 已提交
3245 3246

                        png_composite_16(v, r, a, background->red);
G
Guy Schalnat 已提交
3247 3248
                        *dp = (png_byte)((v >> 8) & 0xff);
                        *(dp + 1) = (png_byte)(v & 0xff);
A
Andreas Dilger 已提交
3249
                        png_composite_16(v, g, a, background->green);
G
Guy Schalnat 已提交
3250 3251
                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 3) = (png_byte)(v & 0xff);
3252
                        png_composite_16(v, b, a, background->blue);
G
Guy Schalnat 已提交
3253 3254 3255 3256 3257 3258 3259 3260 3261
                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
                        *(dp + 5) = (png_byte)(v & 0xff);
                     }
                  }
               }
            }
            break;
         }
      }
A
Andreas Dilger 已提交
3262

G
Guy Schalnat 已提交
3263 3264 3265
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
G
Guy Schalnat 已提交
3266
         row_info->channels--;
G
Guy Schalnat 已提交
3267 3268
         row_info->pixel_depth = (png_byte)(row_info->channels *
            row_info->bit_depth);
3269
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
G
Guy Schalnat 已提交
3270 3271 3272
      }
   }
}
G
Guy Schalnat 已提交
3273
#endif
G
Guy Schalnat 已提交
3274

G
Guy Schalnat 已提交
3275
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
3276
/* Gamma correct the image, avoiding the alpha channel.  Make sure
3277
 * you do this after you deal with the transparency issue on grayscale
3278
 * or RGB images. If your bit depth is 8, use gamma_table, if it
3279 3280 3281
 * is 16, use gamma_16_table and gamma_shift.  Build these with
 * build_gamma_table().
 */
3282
void /* PRIVATE */
G
Guy Schalnat 已提交
3283 3284
png_do_gamma(png_row_infop row_info, png_bytep row,
   png_bytep gamma_table, png_uint_16pp gamma_16_table,
G
Guy Schalnat 已提交
3285 3286
   int gamma_shift)
{
G
Guy Schalnat 已提交
3287
   png_bytep sp;
G
Guy Schalnat 已提交
3288
   png_uint_32 i;
3289
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3290

A
Andreas Dilger 已提交
3291 3292 3293 3294 3295 3296 3297
   png_debug(1, "in png_do_gamma\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
G
Guy Schalnat 已提交
3298 3299 3300 3301 3302 3303 3304
   {
      switch (row_info->color_type)
      {
         case PNG_COLOR_TYPE_RGB:
         {
            if (row_info->bit_depth == 8)
            {
3305 3306
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3307 3308 3309 3310 3311 3312 3313 3314 3315
               {
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
A
Andreas Dilger 已提交
3316
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3317
            {
3318 3319
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3320 3321 3322
               {
                  png_uint_16 v;

A
Andreas Dilger 已提交
3323
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3324 3325 3326
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
A
Andreas Dilger 已提交
3327
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3328 3329
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3330
                  sp += 2;
A
Andreas Dilger 已提交
3331
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
               }
            }
            break;
         }
         case PNG_COLOR_TYPE_RGB_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3343 3344
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3345
               {
G
Guy Schalnat 已提交
3346 3347 3348 3349 3350 3351 3352 3353 3354
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  *sp = gamma_table[*sp];
                  sp++;
                  sp++;
               }
            }
A
Andreas Dilger 已提交
3355
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3356
            {
3357 3358
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3359
               {
3360
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3361 3362
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3363
                  sp += 2;
A
Andreas Dilger 已提交
3364
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3365 3366 3367
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 2;
A
Andreas Dilger 已提交
3368
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3369 3370 3371 3372 3373
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
                  sp += 4;
               }
            }
G
Guy Schalnat 已提交
3374 3375 3376 3377 3378 3379
            break;
         }
         case PNG_COLOR_TYPE_GRAY_ALPHA:
         {
            if (row_info->bit_depth == 8)
            {
3380 3381
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3382 3383
               {
                  *sp = gamma_table[*sp];
A
Andreas Dilger 已提交
3384
                  sp += 2;
G
Guy Schalnat 已提交
3385 3386
               }
            }
A
Andreas Dilger 已提交
3387
            else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
3388
            {
3389 3390
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3391
               {
3392
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3393 3394
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3395 3396 3397 3398 3399 3400 3401
                  sp += 4;
               }
            }
            break;
         }
         case PNG_COLOR_TYPE_GRAY:
         {
3402 3403
            if (row_info->bit_depth == 2)
            {
3404 3405
               sp = row;
               for (i = 0; i < row_width; i += 4)
3406 3407 3408 3409 3410 3411
               {
                  int a = *sp & 0xc0;
                  int b = *sp & 0x30;
                  int c = *sp & 0x0c;
                  int d = *sp & 0x03;

3412 3413
                  *sp = (png_byte)(
                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
3414 3415
                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
                        ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3416
                        ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3417 3418 3419
                  sp++;
               }
            }
A
Andreas Dilger 已提交
3420
            if (row_info->bit_depth == 4)
G
Guy Schalnat 已提交
3421
            {
3422 3423
               sp = row;
               for (i = 0; i < row_width; i += 2)
A
Andreas Dilger 已提交
3424 3425 3426 3427
               {
                  int msb = *sp & 0xf0;
                  int lsb = *sp & 0x0f;

3428 3429
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
A
Andreas Dilger 已提交
3430 3431 3432 3433 3434
                  sp++;
               }
            }
            else if (row_info->bit_depth == 8)
            {
3435 3436
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3437 3438 3439 3440 3441 3442 3443
               {
                  *sp = gamma_table[*sp];
                  sp++;
               }
            }
            else if (row_info->bit_depth == 16)
            {
3444 3445
               sp = row;
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3446
               {
3447
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
G
Guy Schalnat 已提交
3448 3449
                  *sp = (png_byte)((v >> 8) & 0xff);
                  *(sp + 1) = (png_byte)(v & 0xff);
G
Guy Schalnat 已提交
3450 3451 3452 3453 3454 3455 3456 3457
                  sp += 2;
               }
            }
            break;
         }
      }
   }
}
G
Guy Schalnat 已提交
3458
#endif
G
Guy Schalnat 已提交
3459

G
Guy Schalnat 已提交
3460
#if defined(PNG_READ_EXPAND_SUPPORTED)
3461
/* Expands a palette row to an RGB or RGBA row depending
3462 3463
 * upon whether you supply trans and num_trans.
 */
3464
void /* PRIVATE */
G
Guy Schalnat 已提交
3465
png_do_expand_palette(png_row_infop row_info, png_bytep row,
A
Andreas Dilger 已提交
3466
   png_colorp palette, png_bytep trans, int num_trans)
G
Guy Schalnat 已提交
3467
{
G
Guy Schalnat 已提交
3468
   int shift, value;
G
Guy Schalnat 已提交
3469
   png_bytep sp, dp;
G
Guy Schalnat 已提交
3470
   png_uint_32 i;
3471
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3472

A
Andreas Dilger 已提交
3473 3474 3475 3476 3477 3478
   png_debug(1, "in png_do_expand_palette\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
3479 3480 3481 3482 3483 3484 3485
   {
      if (row_info->bit_depth < 8)
      {
         switch (row_info->bit_depth)
         {
            case 1:
            {
3486 3487
               sp = row + (png_size_t)((row_width - 1) >> 3);
               dp = row + (png_size_t)row_width - 1;
3488
               shift = 7 - (int)((row_width + 7) & 0x07);
3489
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3490
               {
3491
                  if ((*sp >> shift) & 0x01)
G
Guy Schalnat 已提交
3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508
                     *dp = 1;
                  else
                     *dp = 0;
                  if (shift == 7)
                  {
                     shift = 0;
                     sp--;
                  }
                  else
                     shift++;

                  dp--;
               }
               break;
            }
            case 2:
            {
3509 3510
               sp = row + (png_size_t)((row_width - 1) >> 2);
               dp = row + (png_size_t)row_width - 1;
3511
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3512
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3513
               {
3514
                  value = (*sp >> shift) & 0x03;
G
Guy Schalnat 已提交
3515
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529
                  if (shift == 6)
                  {
                     shift = 0;
                     sp--;
                  }
                  else
                     shift += 2;

                  dp--;
               }
               break;
            }
            case 4:
            {
3530 3531
               sp = row + (png_size_t)((row_width - 1) >> 1);
               dp = row + (png_size_t)row_width - 1;
3532
               shift = (int)((row_width & 0x01) << 2);
3533
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3534
               {
3535
                  value = (*sp >> shift) & 0x0f;
G
Guy Schalnat 已提交
3536
                  *dp = (png_byte)value;
G
Guy Schalnat 已提交
3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551
                  if (shift == 4)
                  {
                     shift = 0;
                     sp--;
                  }
                  else
                     shift += 4;

                  dp--;
               }
               break;
            }
         }
         row_info->bit_depth = 8;
         row_info->pixel_depth = 8;
3552
         row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
3553 3554 3555 3556 3557
      }
      switch (row_info->bit_depth)
      {
         case 8:
         {
A
Andreas Dilger 已提交
3558
            if (trans != NULL)
G
Guy Schalnat 已提交
3559
            {
3560 3561
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width << 2) - 1;
G
Guy Schalnat 已提交
3562

3563
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3564
               {
A
Andreas Dilger 已提交
3565
                  if ((int)(*sp) >= num_trans)
G
Guy Schalnat 已提交
3566 3567 3568 3569 3570 3571 3572 3573 3574 3575
                     *dp-- = 0xff;
                  else
                     *dp-- = trans[*sp];
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 32;
3576
               row_info->rowbytes = row_width * 4;
G
Guy Schalnat 已提交
3577 3578 3579 3580 3581
               row_info->color_type = 6;
               row_info->channels = 4;
            }
            else
            {
3582 3583
               sp = row + (png_size_t)row_width - 1;
               dp = row + (png_size_t)(row_width * 3) - 1;
G
Guy Schalnat 已提交
3584

3585
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3586 3587 3588 3589 3590 3591 3592 3593
               {
                  *dp-- = palette[*sp].blue;
                  *dp-- = palette[*sp].green;
                  *dp-- = palette[*sp].red;
                  sp--;
               }
               row_info->bit_depth = 8;
               row_info->pixel_depth = 24;
3594
               row_info->rowbytes = row_width * 3;
G
Guy Schalnat 已提交
3595 3596 3597 3598 3599 3600 3601 3602 3603
               row_info->color_type = 2;
               row_info->channels = 3;
            }
            break;
         }
      }
   }
}

3604 3605 3606
/* If the bit depth < 8, it is expanded to 8.  Also, if the
 * transparency value is supplied, an alpha channel is built.
 */
3607
void /* PRIVATE */
G
Guy Schalnat 已提交
3608
png_do_expand(png_row_infop row_info, png_bytep row,
G
Guy Schalnat 已提交
3609
   png_color_16p trans_value)
G
Guy Schalnat 已提交
3610
{
G
Guy Schalnat 已提交
3611
   int shift, value;
G
Guy Schalnat 已提交
3612
   png_bytep sp, dp;
G
Guy Schalnat 已提交
3613
   png_uint_32 i;
3614
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3615

A
Andreas Dilger 已提交
3616 3617 3618 3619
   png_debug(1, "in png_do_expand\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL)
#endif
G
Guy Schalnat 已提交
3620
   {
A
Andreas Dilger 已提交
3621
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
3622
      {
3623
         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
A
Andreas Dilger 已提交
3624 3625

         if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
3626
         {
A
Andreas Dilger 已提交
3627
            switch (row_info->bit_depth)
G
Guy Schalnat 已提交
3628
            {
A
Andreas Dilger 已提交
3629
               case 1:
G
Guy Schalnat 已提交
3630
               {
3631
                  gray = (png_uint_16)(gray*0xff);
3632 3633
                  sp = row + (png_size_t)((row_width - 1) >> 3);
                  dp = row + (png_size_t)row_width - 1;
3634
                  shift = 7 - (int)((row_width + 7) & 0x07);
3635
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3636
                  {
3637
                     if ((*sp >> shift) & 0x01)
A
Andreas Dilger 已提交
3638 3639 3640 3641 3642 3643 3644 3645 3646 3647
                        *dp = 0xff;
                     else
                        *dp = 0;
                     if (shift == 7)
                     {
                        shift = 0;
                        sp--;
                     }
                     else
                        shift++;
G
Guy Schalnat 已提交
3648

A
Andreas Dilger 已提交
3649 3650 3651
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
3652
               }
A
Andreas Dilger 已提交
3653
               case 2:
G
Guy Schalnat 已提交
3654
               {
3655
                  gray = (png_uint_16)(gray*0x55);
3656 3657
                  sp = row + (png_size_t)((row_width - 1) >> 2);
                  dp = row + (png_size_t)row_width - 1;
3658
                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3659
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3660
                  {
3661
                     value = (*sp >> shift) & 0x03;
A
Andreas Dilger 已提交
3662 3663 3664 3665 3666 3667 3668 3669 3670
                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
                        (value << 6));
                     if (shift == 6)
                     {
                        shift = 0;
                        sp--;
                     }
                     else
                        shift += 2;
G
Guy Schalnat 已提交
3671

A
Andreas Dilger 已提交
3672 3673 3674
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
3675
               }
A
Andreas Dilger 已提交
3676
               case 4:
G
Guy Schalnat 已提交
3677
               {
3678
                  gray = (png_uint_16)(gray*0x11);
3679 3680
                  sp = row + (png_size_t)((row_width - 1) >> 1);
                  dp = row + (png_size_t)row_width - 1;
3681
                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3682
                  for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3683
                  {
3684
                     value = (*sp >> shift) & 0x0f;
A
Andreas Dilger 已提交
3685 3686 3687 3688 3689 3690 3691 3692
                     *dp = (png_byte)(value | (value << 4));
                     if (shift == 4)
                     {
                        shift = 0;
                        sp--;
                     }
                     else
                        shift = 4;
G
Guy Schalnat 已提交
3693

A
Andreas Dilger 已提交
3694 3695 3696
                     dp--;
                  }
                  break;
G
Guy Schalnat 已提交
3697 3698
               }
            }
A
Andreas Dilger 已提交
3699 3700
            row_info->bit_depth = 8;
            row_info->pixel_depth = 8;
3701
            row_info->rowbytes = row_width;
G
Guy Schalnat 已提交
3702
         }
A
Andreas Dilger 已提交
3703

A
Andreas Dilger 已提交
3704
         if (trans_value != NULL)
G
Guy Schalnat 已提交
3705
         {
A
Andreas Dilger 已提交
3706
            if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3707
            {
3708 3709 3710
               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 已提交
3711
               {
A
Andreas Dilger 已提交
3712 3713 3714 3715 3716
                  if (*sp == gray)
                     *dp-- = 0;
                  else
                     *dp-- = 0xff;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
3717
               }
A
Andreas Dilger 已提交
3718 3719 3720
            }
            else if (row_info->bit_depth == 16)
            {
A
Andreas Dilger 已提交
3721 3722
               sp = row + row_info->rowbytes - 1;
               dp = row + (row_info->rowbytes << 1) - 1;
3723
               for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3724
               {
A
Andreas Dilger 已提交
3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737
                  if (((png_uint_16)*(sp) |
                     ((png_uint_16)*(sp - 1) << 8)) == gray)
                  {
                     *dp-- = 0;
                     *dp-- = 0;
                  }
                  else
                  {
                     *dp-- = 0xff;
                     *dp-- = 0xff;
                  }
                  *dp-- = *sp--;
                  *dp-- = *sp--;
G
Guy Schalnat 已提交
3738 3739
               }
            }
A
Andreas Dilger 已提交
3740 3741 3742
            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
            row_info->channels = 2;
            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3743 3744
            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
               row_width);
G
Guy Schalnat 已提交
3745 3746 3747 3748 3749 3750 3751
         }
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
      {
         if (row_info->bit_depth == 8)
         {
            sp = row + (png_size_t)row_info->rowbytes - 1;
3752 3753
            dp = row + (png_size_t)(row_width << 2) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3754
            {
G
Guy Schalnat 已提交
3755
               if (*(sp - 2) == trans_value->red &&
G
Guy Schalnat 已提交
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767
                  *(sp - 1) == trans_value->green &&
                  *(sp - 0) == trans_value->blue)
                  *dp-- = 0;
               else
                  *dp-- = 0xff;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
            }
         }
         else if (row_info->bit_depth == 16)
         {
A
Andreas Dilger 已提交
3768
            sp = row + row_info->rowbytes - 1;
3769 3770
            dp = row + (png_size_t)(row_width << 3) - 1;
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3771 3772
            {
               if ((((png_uint_16)*(sp - 4) |
G
Guy Schalnat 已提交
3773
                  ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
G
Guy Schalnat 已提交
3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790
                  (((png_uint_16)*(sp - 2) |
                  ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
                  (((png_uint_16)*(sp - 0) |
                  ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
               {
                  *dp-- = 0;
                  *dp-- = 0;
               }
               else
               {
                  *dp-- = 0xff;
                  *dp-- = 0xff;
               }
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
               *dp-- = *sp--;
G
Guy Schalnat 已提交
3791
               *dp-- = *sp--;
G
Guy Schalnat 已提交
3792 3793 3794 3795 3796
               *dp-- = *sp--;
            }
         }
         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
         row_info->channels = 4;
G
Guy Schalnat 已提交
3797
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3798
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
G
Guy Schalnat 已提交
3799 3800 3801
      }
   }
}
G
Guy Schalnat 已提交
3802
#endif
G
Guy Schalnat 已提交
3803

G
Guy Schalnat 已提交
3804
#if defined(PNG_READ_DITHER_SUPPORTED)
3805
void /* PRIVATE */
G
Guy Schalnat 已提交
3806
png_do_dither(png_row_infop row_info, png_bytep row,
G
Guy Schalnat 已提交
3807
    png_bytep palette_lookup, png_bytep dither_lookup)
G
Guy Schalnat 已提交
3808
{
G
Guy Schalnat 已提交
3809
   png_bytep sp, dp;
G
Guy Schalnat 已提交
3810
   png_uint_32 i;
3811
   png_uint_32 row_width=row_info->width;
G
Guy Schalnat 已提交
3812

A
Andreas Dilger 已提交
3813 3814 3815 3816
   png_debug(1, "in png_do_dither\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL)
#endif
G
Guy Schalnat 已提交
3817 3818 3819 3820 3821 3822 3823
   {
      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;
3824
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;

            /* 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);
               */
            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 已提交
3841
               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
G
Guy Schalnat 已提交
3842 3843 3844 3845 3846 3847 3848 3849 3850
               (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;
3851
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
G
Guy Schalnat 已提交
3852 3853
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
A
Andreas Dilger 已提交
3854
         palette_lookup != NULL && row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3855 3856 3857 3858
      {
         int r, g, b, p;
         sp = row;
         dp = row;
3859
         for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
3860 3861 3862 3863 3864 3865 3866
         {
            r = *sp++;
            g = *sp++;
            b = *sp++;
            sp++;

            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
G
Guy Schalnat 已提交
3867
               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
G
Guy Schalnat 已提交
3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879
               (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;
3880
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
G
Guy Schalnat 已提交
3881 3882 3883
      }
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
         dither_lookup && row_info->bit_depth == 8)
G
Guy Schalnat 已提交
3884
      {
G
Guy Schalnat 已提交
3885
         sp = row;
3886
         for (i = 0; i < row_width; i++, sp++)
G
Guy Schalnat 已提交
3887 3888 3889 3890 3891 3892
         {
            *sp = dither_lookup[*sp];
         }
      }
   }
}
G
Guy Schalnat 已提交
3893
#endif
G
Guy Schalnat 已提交
3894

3895
#ifdef PNG_FLOATING_POINT_SUPPORTED
G
Guy Schalnat 已提交
3896
#if defined(PNG_READ_GAMMA_SUPPORTED)
G
Guy Schalnat 已提交
3897 3898 3899
static int png_gamma_shift[] =
   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};

A
Andreas Dilger 已提交
3900
/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
3901 3902 3903 3904
 * 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.
 */
3905
void /* PRIVATE */
G
Guy Schalnat 已提交
3906
png_build_gamma_table(png_structp png_ptr)
G
Guy Schalnat 已提交
3907
{
3908 3909 3910
  png_debug(1, "in png_build_gamma_table\n");
  if(png_ptr->gamma != 0.0)
  {
G
Guy Schalnat 已提交
3911 3912 3913 3914 3915
   if (png_ptr->bit_depth <= 8)
   {
      int i;
      double g;

3916 3917 3918 3919
      if (png_ptr->screen_gamma > .000001)
         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
      else
         g = 1.0;
G
Guy Schalnat 已提交
3920

A
Andreas Dilger 已提交
3921
      png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
G
Guy Schalnat 已提交
3922 3923 3924 3925 3926 3927 3928 3929
         (png_uint_32)256);

      for (i = 0; i < 256; i++)
      {
         png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
            g) * 255.0 + .5);
      }

3930 3931
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3932
      if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
G
Guy Schalnat 已提交
3933
      {
3934

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

A
Andreas Dilger 已提交
3937
         png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
G
Guy Schalnat 已提交
3938 3939 3940 3941 3942 3943 3944 3945
            (png_uint_32)256);

         for (i = 0; i < 256; i++)
         {
            png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
               g) * 255.0 + .5);
         }

3946

A
Andreas Dilger 已提交
3947
         png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
G
Guy Schalnat 已提交
3948 3949
            (png_uint_32)256);

3950 3951 3952 3953 3954
         if(png_ptr->screen_gamma > 0.000001)
            g = 1.0 / png_ptr->screen_gamma;
         else
            g = png_ptr->gamma;   /* probably doing rgb_to_gray */

G
Guy Schalnat 已提交
3955 3956 3957 3958
         for (i = 0; i < 256; i++)
         {
            png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
               g) * 255.0 + .5);
3959

G
Guy Schalnat 已提交
3960 3961
         }
      }
3962
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
G
Guy Schalnat 已提交
3963
   }
G
Guy Schalnat 已提交
3964
   else
G
Guy Schalnat 已提交
3965 3966
   {
      double g;
G
Guy Schalnat 已提交
3967 3968 3969
      int i, j, shift, num;
      int sig_bit;
      png_uint_32 ig;
G
Guy Schalnat 已提交
3970 3971

      if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
G
Guy Schalnat 已提交
3972
      {
G
Guy Schalnat 已提交
3973 3974 3975 3976
         sig_bit = (int)png_ptr->sig_bit.red;
         if ((int)png_ptr->sig_bit.green > sig_bit)
            sig_bit = png_ptr->sig_bit.green;
         if ((int)png_ptr->sig_bit.blue > sig_bit)
G
Guy Schalnat 已提交
3977
            sig_bit = png_ptr->sig_bit.blue;
G
Guy Schalnat 已提交
3978 3979 3980 3981
      }
      else
      {
         sig_bit = (int)png_ptr->sig_bit.gray;
G
Guy Schalnat 已提交
3982
      }
G
Guy Schalnat 已提交
3983 3984 3985 3986

      if (sig_bit > 0)
         shift = 16 - sig_bit;
      else
G
Guy Schalnat 已提交
3987
         shift = 0;
G
Guy Schalnat 已提交
3988 3989 3990 3991 3992 3993 3994

      if (png_ptr->transformations & PNG_16_TO_8)
      {
         if (shift < (16 - PNG_MAX_GAMMA_8))
            shift = (16 - PNG_MAX_GAMMA_8);
      }

G
Guy Schalnat 已提交
3995
      if (shift > 8)
G
Guy Schalnat 已提交
3996 3997 3998 3999
         shift = 8;
      if (shift < 0)
         shift = 0;

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

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

4004 4005 4006 4007
      if (png_ptr->screen_gamma > .000001)
         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
      else
         g = 1.0;
G
Guy Schalnat 已提交
4008

A
Andreas Dilger 已提交
4009
      png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4010
         (png_uint_32)(num * png_sizeof (png_uint_16p)));
G
Guy Schalnat 已提交
4011

4012
      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
G
Guy Schalnat 已提交
4013 4014 4015 4016 4017 4018
      {
         double fin, fout;
         png_uint_32 last, max;

         for (i = 0; i < num; i++)
         {
A
Andreas Dilger 已提交
4019
            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4020
               (png_uint_32)(256 * png_sizeof (png_uint_16)));
G
Guy Schalnat 已提交
4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040
         }

         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))]
A
Andreas Dilger 已提交
4041
               [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
G
Guy Schalnat 已提交
4042
            last++;
G
Guy Schalnat 已提交
4043
         }
G
Guy Schalnat 已提交
4044
      }
G
Guy Schalnat 已提交
4045 4046 4047 4048
      else
      {
         for (i = 0; i < num; i++)
         {
A
Andreas Dilger 已提交
4049
            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4050
               (png_uint_32)(256 * png_sizeof (png_uint_16)));
G
Guy Schalnat 已提交
4051

A
Andreas Dilger 已提交
4052
            ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
G
Guy Schalnat 已提交
4053
            for (j = 0; j < 256; j++)
G
Guy Schalnat 已提交
4054 4055 4056 4057 4058 4059 4060 4061
            {
               png_ptr->gamma_16_table[i][j] =
                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
                     65535.0, g) * 65535.0 + .5);
            }
         }
      }

4062 4063 4064
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
G
Guy Schalnat 已提交
4065
      {
4066

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

A
Andreas Dilger 已提交
4069
         png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4070
            (png_uint_32)(num * png_sizeof (png_uint_16p )));
G
Guy Schalnat 已提交
4071 4072 4073

         for (i = 0; i < num; i++)
         {
A
Andreas Dilger 已提交
4074
            png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4075
               (png_uint_32)(256 * png_sizeof (png_uint_16)));
G
Guy Schalnat 已提交
4076 4077 4078 4079 4080 4081 4082 4083 4084 4085

            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);
            }
         }
4086 4087 4088 4089 4090

         if(png_ptr->screen_gamma > 0.000001)
            g = 1.0 / png_ptr->screen_gamma;
         else
            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
G
Guy Schalnat 已提交
4091

A
Andreas Dilger 已提交
4092
         png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4093
            (png_uint_32)(num * png_sizeof (png_uint_16p)));
G
Guy Schalnat 已提交
4094 4095 4096

         for (i = 0; i < num; i++)
         {
A
Andreas Dilger 已提交
4097
            png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4098
               (png_uint_32)(256 * png_sizeof (png_uint_16)));
G
Guy Schalnat 已提交
4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109

            ig = (((png_uint_32)i *
               (png_uint_32)png_gamma_shift[shift]) >> 4);
            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);
            }
         }
      }
4110
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
G
Guy Schalnat 已提交
4111
   }
4112
 }
G
Guy Schalnat 已提交
4113
}
G
Guy Schalnat 已提交
4114
#endif
4115 4116
/* To do: install integer version of png_build_gamma_table here */
#endif
G
Guy Schalnat 已提交
4117

4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 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 4161 4162 4163
#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* undoes intrapixel differencing  */
void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
   png_debug(1, "in png_do_read_intrapixel\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
       (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;
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
         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;
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
4164 4165 4166 4167 4168 4169 4170 4171 4172
            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);
            *(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);
4173 4174 4175 4176 4177
         }
      }
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */