1
2/* pngrtran.c - transforms the data in a row for PNG readers
3 *
4 * libpng version  1.2.7 - September 12, 2004
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (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 * in pngtrans.c.
14 */
15
16#define PNG_INTERNAL
17#include "png.h"
18
19/* Set the action on getting a CRC error for an ancillary or critical chunk. */
20void PNGAPI
21png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
22{
23   png_debug(1, "in png_set_crc_action\n");
24   /* Tell libpng how we react to CRC errors in critical chunks */
25   switch (crit_action)
26   {
27      case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
28         break;
29      case PNG_CRC_WARN_USE:                               /* warn/use data */
30         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
31         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
32         break;
33      case PNG_CRC_QUIET_USE:                             /* quiet/use data */
34         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
35         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
36                           PNG_FLAG_CRC_CRITICAL_IGNORE;
37         break;
38      case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
39         png_warning(png_ptr, "Can't discard critical data on CRC error.");
40      case PNG_CRC_ERROR_QUIT:                                /* error/quit */
41      case PNG_CRC_DEFAULT:
42      default:
43         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
44         break;
45   }
46
47   switch (ancil_action)
48   {
49      case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
50         break;
51      case PNG_CRC_WARN_USE:                              /* warn/use data */
52         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
53         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
54         break;
55      case PNG_CRC_QUIET_USE:                            /* quiet/use data */
56         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
57         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
58                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
59         break;
60      case PNG_CRC_ERROR_QUIT:                               /* error/quit */
61         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
62         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
63         break;
64      case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
65      case PNG_CRC_DEFAULT:
66      default:
67         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
68         break;
69   }
70}
71
72#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
73    defined(PNG_FLOATING_POINT_SUPPORTED)
74/* handle alpha and tRNS via a background color */
75void PNGAPI
76png_set_background(png_structp png_ptr,
77   png_color_16p background_color, int background_gamma_code,
78   int need_expand, double background_gamma)
79{
80   png_debug(1, "in png_set_background\n");
81   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
82   {
83      png_warning(png_ptr, "Application must supply a known background gamma");
84      return;
85   }
86
87   png_ptr->transformations |= PNG_BACKGROUND;
88   png_memcpy(&(png_ptr->background), background_color,
89      png_sizeof(png_color_16));
90   png_ptr->background_gamma = (float)background_gamma;
91   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
92   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
93
94   /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
95    * (in which case need_expand is superfluous anyway), the background color
96    * 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    * decide when to do the png_do_gray_to_rgb() transformation.
99    */
100   if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
101       (!need_expand && background_color->red == background_color->green &&
102        background_color->red == background_color->blue))
103      png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
104}
105#endif
106
107#if defined(PNG_READ_16_TO_8_SUPPORTED)
108/* strip 16 bit depth files to 8 bit depth */
109void PNGAPI
110png_set_strip_16(png_structp png_ptr)
111{
112   png_debug(1, "in png_set_strip_16\n");
113   png_ptr->transformations |= PNG_16_TO_8;
114}
115#endif
116
117#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
118void PNGAPI
119png_set_strip_alpha(png_structp png_ptr)
120{
121   png_debug(1, "in png_set_strip_alpha\n");
122   png_ptr->transformations |= PNG_STRIP_ALPHA;
123}
124#endif
125
126#if defined(PNG_READ_DITHER_SUPPORTED)
127/* Dither file to 8 bit.  Supply a palette, the current number
128 * of elements in the palette, the maximum number of elements
129 * allowed, and a histogram if possible.  If the current number
130 * of colors is greater then the maximum number, the palette will be
131 * modified to fit in the maximum number.  "full_dither" indicates
132 * whether we need a dithering cube set up for RGB images, or if we
133 * simply are reducing the number of colors in a paletted image.
134 */
135
136typedef struct png_dsort_struct
137{
138   struct png_dsort_struct FAR * next;
139   png_byte left;
140   png_byte right;
141} png_dsort;
142typedef png_dsort FAR *       png_dsortp;
143typedef png_dsort FAR * FAR * png_dsortpp;
144
145void PNGAPI
146png_set_dither(png_structp png_ptr, png_colorp palette,
147   int num_palette, int maximum_colors, png_uint_16p histogram,
148   int full_dither)
149{
150   png_debug(1, "in png_set_dither\n");
151   png_ptr->transformations |= PNG_DITHER;
152
153   if (!full_dither)
154   {
155      int i;
156
157      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
158         (png_uint_32)(num_palette * png_sizeof (png_byte)));
159      for (i = 0; i < num_palette; i++)
160         png_ptr->dither_index[i] = (png_byte)i;
161   }
162
163   if (num_palette > maximum_colors)
164   {
165      if (histogram != NULL)
166      {
167         /* This is easy enough, just throw out the least used colors.
168            Perhaps not the best solution, but good enough. */
169
170         int i;
171
172         /* 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)));
175
176         /* initialize the dither_sort array */
177         for (i = 0; i < num_palette; i++)
178            png_ptr->dither_sort[i] = (png_byte)i;
179
180         /* Find the least used palette entries by starting a
181            bubble sort, and running it until we have sorted
182            out enough colors.  Note that we don't care about
183            sorting all the colors, just finding which are
184            least used. */
185
186         for (i = num_palette - 1; i >= maximum_colors; i--)
187         {
188            int done; /* to stop early if the list is pre-sorted */
189            int j;
190
191            done = 1;
192            for (j = 0; j < i; j++)
193            {
194               if (histogram[png_ptr->dither_sort[j]]
195                   < histogram[png_ptr->dither_sort[j + 1]])
196               {
197                  png_byte t;
198
199                  t = png_ptr->dither_sort[j];
200                  png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
201                  png_ptr->dither_sort[j + 1] = t;
202                  done = 0;
203               }
204            }
205            if (done)
206               break;
207         }
208
209         /* swap the palette around, and set up a table, if necessary */
210         if (full_dither)
211         {
212            int j = num_palette;
213
214            /* put all the useful colors within the max, but don't
215               move the others */
216            for (i = 0; i < maximum_colors; i++)
217            {
218               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
219               {
220                  do
221                     j--;
222                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
223                  palette[i] = palette[j];
224               }
225            }
226         }
227         else
228         {
229            int j = num_palette;
230
231            /* move all the used colors inside the max limit, and
232               develop a translation table */
233            for (i = 0; i < maximum_colors; i++)
234            {
235               /* only move the colors we need to */
236               if ((int)png_ptr->dither_sort[i] >= maximum_colors)
237               {
238                  png_color tmp_color;
239
240                  do
241                     j--;
242                  while ((int)png_ptr->dither_sort[j] >= maximum_colors);
243
244                  tmp_color = palette[j];
245                  palette[j] = palette[i];
246                  palette[i] = tmp_color;
247                  /* indicate where the color went */
248                  png_ptr->dither_index[j] = (png_byte)i;
249                  png_ptr->dither_index[i] = (png_byte)j;
250               }
251            }
252
253            /* find closest color for those colors we are not using */
254            for (i = 0; i < num_palette; i++)
255            {
256               if ((int)png_ptr->dither_index[i] >= maximum_colors)
257               {
258                  int min_d, k, min_k, d_index;
259
260                  /* find the closest color to one we threw out */
261                  d_index = png_ptr->dither_index[i];
262                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
263                  for (k = 1, min_k = 0; k < maximum_colors; k++)
264                  {
265                     int d;
266
267                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
268
269                     if (d < min_d)
270                     {
271                        min_d = d;
272                        min_k = k;
273                     }
274                  }
275                  /* point to closest color */
276                  png_ptr->dither_index[i] = (png_byte)min_k;
277               }
278            }
279         }
280         png_free(png_ptr, png_ptr->dither_sort);
281         png_ptr->dither_sort=NULL;
282      }
283      else
284      {
285         /* This is much harder to do simply (and quickly).  Perhaps
286            we need to go through a median cut routine, but those
287            don't always behave themselves with only a few colors
288            as input.  So we will just find the closest two colors,
289            and throw out one of them (chosen somewhat randomly).
290            [We don't understand this at all, so if someone wants to
291             work on improving it, be our guest - AED, GRP]
292            */
293         int i;
294         int max_d;
295         int num_new_palette;
296         png_dsortp t;
297         png_dsortpp hash;
298
299         t=NULL;
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)));
306
307         /* initialize the sort array */
308         for (i = 0; i < num_palette; i++)
309         {
310            png_ptr->index_to_palette[i] = (png_byte)i;
311            png_ptr->palette_to_index[i] = (png_byte)i;
312         }
313
314         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
315            png_sizeof (png_dsortp)));
316         for (i = 0; i < 769; i++)
317            hash[i] = NULL;
318/*         png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
319
320         num_new_palette = num_palette;
321
322         /* initial wild guess at how far apart the farthest pixel
323            pair we will be eliminating will be.  Larger
324            numbers mean more areas will be allocated, Smaller
325            numbers run the risk of not saving enough data, and
326            having to do this all over again.
327
328            I have not done extensive checking on this number.
329            */
330         max_d = 96;
331
332         while (num_new_palette > maximum_colors)
333         {
334            for (i = 0; i < num_new_palette - 1; i++)
335            {
336               int j;
337
338               for (j = i + 1; j < num_new_palette; j++)
339               {
340                  int d;
341
342                  d = PNG_COLOR_DIST(palette[i], palette[j]);
343
344                  if (d <= max_d)
345                  {
346
347                     t = (png_dsortp)png_malloc_warn(png_ptr,
348                         (png_uint_32)(png_sizeof(png_dsort)));
349                     if (t == NULL)
350                         break;
351                     t->next = hash[d];
352                     t->left = (png_byte)i;
353                     t->right = (png_byte)j;
354                     hash[d] = t;
355                  }
356               }
357               if (t == NULL)
358                  break;
359            }
360
361            if (t != NULL)
362            for (i = 0; i <= max_d; i++)
363            {
364               if (hash[i] != NULL)
365               {
366                  png_dsortp p;
367
368                  for (p = hash[i]; p; p = p->next)
369                  {
370                     if ((int)png_ptr->index_to_palette[p->left]
371                        < num_new_palette &&
372                        (int)png_ptr->index_to_palette[p->right]
373                        < num_new_palette)
374                     {
375                        int j, next_j;
376
377                        if (num_new_palette & 0x01)
378                        {
379                           j = p->left;
380                           next_j = p->right;
381                        }
382                        else
383                        {
384                           j = p->right;
385                           next_j = p->left;
386                        }
387
388                        num_new_palette--;
389                        palette[png_ptr->index_to_palette[j]]
390                          = palette[num_new_palette];
391                        if (!full_dither)
392                        {
393                           int k;
394
395                           for (k = 0; k < num_palette; k++)
396                           {
397                              if (png_ptr->dither_index[k] ==
398                                 png_ptr->index_to_palette[j])
399                                 png_ptr->dither_index[k] =
400                                    png_ptr->index_to_palette[next_j];
401                              if ((int)png_ptr->dither_index[k] ==
402                                 num_new_palette)
403                                 png_ptr->dither_index[k] =
404                                    png_ptr->index_to_palette[j];
405                           }
406                        }
407
408                        png_ptr->index_to_palette[png_ptr->palette_to_index
409                           [num_new_palette]] = png_ptr->index_to_palette[j];
410                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
411                           = png_ptr->palette_to_index[num_new_palette];
412
413                        png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
414                        png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
415                     }
416                     if (num_new_palette <= maximum_colors)
417                        break;
418                  }
419                  if (num_new_palette <= maximum_colors)
420                     break;
421               }
422            }
423
424            for (i = 0; i < 769; i++)
425            {
426               if (hash[i] != NULL)
427               {
428                  png_dsortp p = hash[i];
429                  while (p)
430                  {
431                     t = p->next;
432                     png_free(png_ptr, p);
433                     p = t;
434                  }
435               }
436               hash[i] = 0;
437            }
438            max_d += 96;
439         }
440         png_free(png_ptr, hash);
441         png_free(png_ptr, png_ptr->palette_to_index);
442         png_free(png_ptr, png_ptr->index_to_palette);
443         png_ptr->palette_to_index=NULL;
444         png_ptr->index_to_palette=NULL;
445      }
446      num_palette = maximum_colors;
447   }
448   if (png_ptr->palette == NULL)
449   {
450      png_ptr->palette = palette;
451   }
452   png_ptr->num_palette = (png_uint_16)num_palette;
453
454   if (full_dither)
455   {
456      int i;
457      png_bytep distance;
458      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
459         PNG_DITHER_BLUE_BITS;
460      int num_red = (1 << PNG_DITHER_RED_BITS);
461      int num_green = (1 << PNG_DITHER_GREEN_BITS);
462      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
463      png_size_t num_entries = ((png_size_t)1 << total_bits);
464
465      png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
466         (png_uint_32)(num_entries * png_sizeof (png_byte)));
467
468      png_memset(png_ptr->palette_lookup, 0, num_entries *
469         png_sizeof (png_byte));
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      for (i = 0; i < num_palette; i++)
477      {
478         int ir, ig, ib;
479         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
480         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
481         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
482
483         for (ir = 0; ir < num_red; ir++)
484         {
485            /* int dr = abs(ir - r); */
486            int dr = ((ir > r) ? ir - r : r - ir);
487            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
488
489            for (ig = 0; ig < num_green; ig++)
490            {
491               /* int dg = abs(ig - g); */
492               int dg = ((ig > g) ? ig - g : g - ig);
493               int dt = dr + dg;
494               int dm = ((dr > dg) ? dr : dg);
495               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
496
497               for (ib = 0; ib < num_blue; ib++)
498               {
499                  int d_index = index_g | ib;
500                  /* int db = abs(ib - b); */
501                  int db = ((ib > b) ? ib - b : b - ib);
502                  int dmax = ((dm > db) ? dm : db);
503                  int d = dmax + dt + db;
504
505                  if (d < (int)distance[d_index])
506                  {
507                     distance[d_index] = (png_byte)d;
508                     png_ptr->palette_lookup[d_index] = (png_byte)i;
509                  }
510               }
511            }
512         }
513      }
514
515      png_free(png_ptr, distance);
516   }
517}
518#endif
519
520#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
521/* Transform the image from the file_gamma to the screen_gamma.  We
522 * only do transformations on images where the file_gamma and screen_gamma
523 * are not close reciprocals, otherwise it slows things down slightly, and
524 * also needlessly introduces small errors.
525 *
526 * We will turn off gamma transformation later if no semitransparent entries
527 * are present in the tRNS array for palette images.  We can't do it here
528 * because we don't necessarily have the tRNS chunk yet.
529 */
530void PNGAPI
531png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
532{
533   png_debug(1, "in png_set_gamma\n");
534   if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
535       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
536       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
537     png_ptr->transformations |= PNG_GAMMA;
538   png_ptr->gamma = (float)file_gamma;
539   png_ptr->screen_gamma = (float)scrn_gamma;
540}
541#endif
542
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 * to alpha channels.
547 */
548void PNGAPI
549png_set_expand(png_structp png_ptr)
550{
551   png_debug(1, "in png_set_expand\n");
552   png_ptr->transformations |= PNG_EXPAND;
553}
554
555/* GRR 19990627:  the following three functions currently are identical
556 *  to png_set_expand().  However, it is entirely reasonable that someone
557 *  might wish to expand an indexed image to RGB but *not* expand a single,
558 *  fully transparent palette entry to a full alpha channel--perhaps instead
559 *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
560 *  the transparent color with a particular RGB value, or drop tRNS entirely.
561 *  IOW, a future version of the library may make the transformations flag
562 *  a bit more fine-grained, with separate bits for each of these three
563 *  functions.
564 *
565 *  More to the point, these functions make it obvious what libpng will be
566 *  doing, whereas "expand" can (and does) mean any number of things.
567 */
568
569/* Expand paletted images to RGB. */
570void PNGAPI
571png_set_palette_to_rgb(png_structp png_ptr)
572{
573   png_debug(1, "in png_set_expand\n");
574   png_ptr->transformations |= PNG_EXPAND;
575}
576
577/* Expand grayscale images of less than 8-bit depth to 8 bits. */
578void PNGAPI
579png_set_gray_1_2_4_to_8(png_structp png_ptr)
580{
581   png_debug(1, "in png_set_expand\n");
582   png_ptr->transformations |= PNG_EXPAND;
583}
584
585/* Expand tRNS chunks to alpha channels. */
586void PNGAPI
587png_set_tRNS_to_alpha(png_structp png_ptr)
588{
589   png_debug(1, "in png_set_expand\n");
590   png_ptr->transformations |= PNG_EXPAND;
591}
592#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
593
594#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
595void PNGAPI
596png_set_gray_to_rgb(png_structp png_ptr)
597{
598   png_debug(1, "in png_set_gray_to_rgb\n");
599   png_ptr->transformations |= PNG_GRAY_TO_RGB;
600}
601#endif
602
603#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
604#if defined(PNG_FLOATING_POINT_SUPPORTED)
605/* Convert a RGB image to a grayscale of the same width.  This allows us,
606 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
607 */
608
609void PNGAPI
610png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
611   double green)
612{
613      int red_fixed = (int)((float)red*100000.0 + 0.5);
614      int green_fixed = (int)((float)green*100000.0 + 0.5);
615      png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
616}
617#endif
618
619void PNGAPI
620png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
621   png_fixed_point red, png_fixed_point green)
622{
623   png_debug(1, "in png_set_rgb_to_gray\n");
624   switch(error_action)
625   {
626      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
627              break;
628      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
629              break;
630      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
631   }
632   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
633#if defined(PNG_READ_EXPAND_SUPPORTED)
634      png_ptr->transformations |= PNG_EXPAND;
635#else
636   {
637      png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
638      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
639   }
640#endif
641   {
642      png_uint_16 red_int, green_int;
643      if(red < 0 || green < 0)
644      {
645         red_int   =  6968; /* .212671 * 32768 + .5 */
646         green_int = 23434; /* .715160 * 32768 + .5 */
647      }
648      else if(red + green < 100000L)
649      {
650        red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
651        green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
652      }
653      else
654      {
655         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
656         red_int   =  6968;
657         green_int = 23434;
658      }
659      png_ptr->rgb_to_gray_red_coeff   = red_int;
660      png_ptr->rgb_to_gray_green_coeff = green_int;
661      png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
662   }
663}
664#endif
665
666#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
667    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
668    defined(PNG_LEGACY_SUPPORTED)
669void PNGAPI
670png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
671   read_user_transform_fn)
672{
673   png_debug(1, "in png_set_read_user_transform_fn\n");
674#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
675   png_ptr->transformations |= PNG_USER_TRANSFORM;
676   png_ptr->read_user_transform_fn = read_user_transform_fn;
677#endif
678#ifdef PNG_LEGACY_SUPPORTED
679   if(read_user_transform_fn)
680      png_warning(png_ptr,
681        "This version of libpng does not support user transforms");
682#endif
683}
684#endif
685
686/* Initialize everything needed for the read.  This includes modifying
687 * the palette.
688 */
689void /* PRIVATE */
690png_init_read_transformations(png_structp png_ptr)
691{
692   png_debug(1, "in png_init_read_transformations\n");
693#if defined(PNG_USELESS_TESTS_SUPPORTED)
694   if(png_ptr != NULL)
695#endif
696  {
697#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
698 || defined(PNG_READ_GAMMA_SUPPORTED)
699   int color_type = png_ptr->color_type;
700#endif
701
702#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
703   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
704       (png_ptr->transformations & PNG_EXPAND))
705   {
706      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
707      {
708         /* expand background chunk. */
709         switch (png_ptr->bit_depth)
710         {
711            case 1:
712               png_ptr->background.gray *= (png_uint_16)0xff;
713               png_ptr->background.red = png_ptr->background.green
714                 =  png_ptr->background.blue = png_ptr->background.gray;
715               break;
716            case 2:
717               png_ptr->background.gray *= (png_uint_16)0x55;
718               png_ptr->background.red = png_ptr->background.green
719                 = png_ptr->background.blue = png_ptr->background.gray;
720               break;
721            case 4:
722               png_ptr->background.gray *= (png_uint_16)0x11;
723               png_ptr->background.red = png_ptr->background.green
724                 = png_ptr->background.blue = png_ptr->background.gray;
725               break;
726            case 8:
727            case 16:
728               png_ptr->background.red = png_ptr->background.green
729                 = png_ptr->background.blue = png_ptr->background.gray;
730               break;
731         }
732      }
733      else if (color_type == PNG_COLOR_TYPE_PALETTE)
734      {
735         png_ptr->background.red   =
736            png_ptr->palette[png_ptr->background.index].red;
737         png_ptr->background.green =
738            png_ptr->palette[png_ptr->background.index].green;
739         png_ptr->background.blue  =
740            png_ptr->palette[png_ptr->background.index].blue;
741
742#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
743        if (png_ptr->transformations & PNG_INVERT_ALPHA)
744        {
745#if defined(PNG_READ_EXPAND_SUPPORTED)
746           if (!(png_ptr->transformations & PNG_EXPAND))
747#endif
748           {
749           /* invert the alpha channel (in tRNS) unless the pixels are
750              going to be expanded, in which case leave it for later */
751              int i,istop;
752              istop=(int)png_ptr->num_trans;
753              for (i=0; i<istop; i++)
754                 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
755           }
756        }
757#endif
758
759      }
760   }
761#endif
762
763#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
764   png_ptr->background_1 = png_ptr->background;
765#endif
766#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
767
768   if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
769       && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
770         < PNG_GAMMA_THRESHOLD))
771   {
772    int i,k;
773    k=0;
774    for (i=0; i<png_ptr->num_trans; i++)
775    {
776      if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
777        k=1; /* partial transparency is present */
778    }
779    if (k == 0)
780      png_ptr->transformations &= (~PNG_GAMMA);
781   }
782
783   if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
784   {
785      png_build_gamma_table(png_ptr);
786#if defined(PNG_READ_BACKGROUND_SUPPORTED)
787      if (png_ptr->transformations & PNG_BACKGROUND)
788      {
789         if (color_type == PNG_COLOR_TYPE_PALETTE)
790         {
791           /* could skip if no transparency and
792           */
793            png_color back, back_1;
794            png_colorp palette = png_ptr->palette;
795            int num_palette = png_ptr->num_palette;
796            int i;
797            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
798            {
799               back.red = png_ptr->gamma_table[png_ptr->background.red];
800               back.green = png_ptr->gamma_table[png_ptr->background.green];
801               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
802
803               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
804               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
805               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
806            }
807            else
808            {
809               double g, gs;
810
811               switch (png_ptr->background_gamma_type)
812               {
813                  case PNG_BACKGROUND_GAMMA_SCREEN:
814                     g = (png_ptr->screen_gamma);
815                     gs = 1.0;
816                     break;
817                  case PNG_BACKGROUND_GAMMA_FILE:
818                     g = 1.0 / (png_ptr->gamma);
819                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
820                     break;
821                  case PNG_BACKGROUND_GAMMA_UNIQUE:
822                     g = 1.0 / (png_ptr->background_gamma);
823                     gs = 1.0 / (png_ptr->background_gamma *
824                                 png_ptr->screen_gamma);
825                     break;
826                  default:
827                     g = 1.0;    /* back_1 */
828                     gs = 1.0;   /* back */
829               }
830
831               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
832               {
833                  back.red   = (png_byte)png_ptr->background.red;
834                  back.green = (png_byte)png_ptr->background.green;
835                  back.blue  = (png_byte)png_ptr->background.blue;
836               }
837               else
838               {
839                  back.red = (png_byte)(pow(
840                     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
841                  back.green = (png_byte)(pow(
842                     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
843                  back.blue = (png_byte)(pow(
844                     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
845               }
846
847               back_1.red = (png_byte)(pow(
848                  (double)png_ptr->background.red/255, g) * 255.0 + .5);
849               back_1.green = (png_byte)(pow(
850                  (double)png_ptr->background.green/255, g) * 255.0 + .5);
851               back_1.blue = (png_byte)(pow(
852                  (double)png_ptr->background.blue/255, g) * 255.0 + .5);
853            }
854            for (i = 0; i < num_palette; i++)
855            {
856               if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
857               {
858                  if (png_ptr->trans[i] == 0)
859                  {
860                     palette[i] = back;
861                  }
862                  else /* if (png_ptr->trans[i] != 0xff) */
863                  {
864                     png_byte v, w;
865
866                     v = png_ptr->gamma_to_1[palette[i].red];
867                     png_composite(w, v, png_ptr->trans[i], back_1.red);
868                     palette[i].red = png_ptr->gamma_from_1[w];
869
870                     v = png_ptr->gamma_to_1[palette[i].green];
871                     png_composite(w, v, png_ptr->trans[i], back_1.green);
872                     palette[i].green = png_ptr->gamma_from_1[w];
873
874                     v = png_ptr->gamma_to_1[palette[i].blue];
875                     png_composite(w, v, png_ptr->trans[i], back_1.blue);
876                     palette[i].blue = png_ptr->gamma_from_1[w];
877                  }
878               }
879               else
880               {
881                  palette[i].red = png_ptr->gamma_table[palette[i].red];
882                  palette[i].green = png_ptr->gamma_table[palette[i].green];
883                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
884               }
885            }
886         }
887         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
888         else
889         /* color_type != PNG_COLOR_TYPE_PALETTE */
890         {
891            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
892            double g = 1.0;
893            double gs = 1.0;
894
895            switch (png_ptr->background_gamma_type)
896            {
897               case PNG_BACKGROUND_GAMMA_SCREEN:
898                  g = (png_ptr->screen_gamma);
899                  gs = 1.0;
900                  break;
901               case PNG_BACKGROUND_GAMMA_FILE:
902                  g = 1.0 / (png_ptr->gamma);
903                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
904                  break;
905               case PNG_BACKGROUND_GAMMA_UNIQUE:
906                  g = 1.0 / (png_ptr->background_gamma);
907                  gs = 1.0 / (png_ptr->background_gamma *
908                     png_ptr->screen_gamma);
909                  break;
910            }
911
912            png_ptr->background_1.gray = (png_uint_16)(pow(
913               (double)png_ptr->background.gray / m, g) * m + .5);
914            png_ptr->background.gray = (png_uint_16)(pow(
915               (double)png_ptr->background.gray / m, gs) * m + .5);
916
917            if ((png_ptr->background.red != png_ptr->background.green) ||
918                (png_ptr->background.red != png_ptr->background.blue) ||
919                (png_ptr->background.red != png_ptr->background.gray))
920            {
921               /* RGB or RGBA with color background */
922               png_ptr->background_1.red = (png_uint_16)(pow(
923                  (double)png_ptr->background.red / m, g) * m + .5);
924               png_ptr->background_1.green = (png_uint_16)(pow(
925                  (double)png_ptr->background.green / m, g) * m + .5);
926               png_ptr->background_1.blue = (png_uint_16)(pow(
927                  (double)png_ptr->background.blue / m, g) * m + .5);
928               png_ptr->background.red = (png_uint_16)(pow(
929                  (double)png_ptr->background.red / m, gs) * m + .5);
930               png_ptr->background.green = (png_uint_16)(pow(
931                  (double)png_ptr->background.green / m, gs) * m + .5);
932               png_ptr->background.blue = (png_uint_16)(pow(
933                  (double)png_ptr->background.blue / m, gs) * m + .5);
934            }
935            else
936            {
937               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
938               png_ptr->background_1.red = png_ptr->background_1.green
939                 = png_ptr->background_1.blue = png_ptr->background_1.gray;
940               png_ptr->background.red = png_ptr->background.green
941                 = png_ptr->background.blue = png_ptr->background.gray;
942            }
943         }
944      }
945      else
946      /* transformation does not include PNG_BACKGROUND */
947#endif /* PNG_READ_BACKGROUND_SUPPORTED */
948      if (color_type == PNG_COLOR_TYPE_PALETTE)
949      {
950         png_colorp palette = png_ptr->palette;
951         int num_palette = png_ptr->num_palette;
952         int i;
953
954         for (i = 0; i < num_palette; i++)
955         {
956            palette[i].red = png_ptr->gamma_table[palette[i].red];
957            palette[i].green = png_ptr->gamma_table[palette[i].green];
958            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
959         }
960      }
961   }
962#if defined(PNG_READ_BACKGROUND_SUPPORTED)
963   else
964#endif
965#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
966#if defined(PNG_READ_BACKGROUND_SUPPORTED)
967   /* No GAMMA transformation */
968   if ((png_ptr->transformations & PNG_BACKGROUND) &&
969       (color_type == PNG_COLOR_TYPE_PALETTE))
970   {
971      int i;
972      int istop = (int)png_ptr->num_trans;
973      png_color back;
974      png_colorp palette = png_ptr->palette;
975
976      back.red   = (png_byte)png_ptr->background.red;
977      back.green = (png_byte)png_ptr->background.green;
978      back.blue  = (png_byte)png_ptr->background.blue;
979
980      for (i = 0; i < istop; i++)
981      {
982         if (png_ptr->trans[i] == 0)
983         {
984            palette[i] = back;
985         }
986         else if (png_ptr->trans[i] != 0xff)
987         {
988            /* The png_composite() macro is defined in png.h */
989            png_composite(palette[i].red, palette[i].red,
990               png_ptr->trans[i], back.red);
991            png_composite(palette[i].green, palette[i].green,
992               png_ptr->trans[i], back.green);
993            png_composite(palette[i].blue, palette[i].blue,
994               png_ptr->trans[i], back.blue);
995         }
996      }
997   }
998#endif /* PNG_READ_BACKGROUND_SUPPORTED */
999
1000#if defined(PNG_READ_SHIFT_SUPPORTED)
1001   if ((png_ptr->transformations & PNG_SHIFT) &&
1002      (color_type == PNG_COLOR_TYPE_PALETTE))
1003   {
1004      png_uint_16 i;
1005      png_uint_16 istop = png_ptr->num_palette;
1006      int sr = 8 - png_ptr->sig_bit.red;
1007      int sg = 8 - png_ptr->sig_bit.green;
1008      int sb = 8 - png_ptr->sig_bit.blue;
1009
1010      if (sr < 0 || sr > 8)
1011         sr = 0;
1012      if (sg < 0 || sg > 8)
1013         sg = 0;
1014      if (sb < 0 || sb > 8)
1015         sb = 0;
1016      for (i = 0; i < istop; i++)
1017      {
1018         png_ptr->palette[i].red >>= sr;
1019         png_ptr->palette[i].green >>= sg;
1020         png_ptr->palette[i].blue >>= sb;
1021      }
1022   }
1023#endif  /* PNG_READ_SHIFT_SUPPORTED */
1024 }
1025#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1026 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1027   if(png_ptr)
1028      return;
1029#endif
1030}
1031
1032/* Modify the info structure to reflect the transformations.  The
1033 * info should be updated so a PNG file could be written with it,
1034 * assuming the transformations result in valid PNG data.
1035 */
1036void /* PRIVATE */
1037png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1038{
1039   png_debug(1, "in png_read_transform_info\n");
1040#if defined(PNG_READ_EXPAND_SUPPORTED)
1041   if (png_ptr->transformations & PNG_EXPAND)
1042   {
1043      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1044      {
1045         if (png_ptr->num_trans)
1046            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1047         else
1048            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1049         info_ptr->bit_depth = 8;
1050         info_ptr->num_trans = 0;
1051      }
1052      else
1053      {
1054         if (png_ptr->num_trans)
1055            info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1056         if (info_ptr->bit_depth < 8)
1057            info_ptr->bit_depth = 8;
1058         info_ptr->num_trans = 0;
1059      }
1060   }
1061#endif
1062
1063#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1064   if (png_ptr->transformations & PNG_BACKGROUND)
1065   {
1066      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1067      info_ptr->num_trans = 0;
1068      info_ptr->background = png_ptr->background;
1069   }
1070#endif
1071
1072#if defined(PNG_READ_GAMMA_SUPPORTED)
1073   if (png_ptr->transformations & PNG_GAMMA)
1074   {
1075#ifdef PNG_FLOATING_POINT_SUPPORTED
1076      info_ptr->gamma = png_ptr->gamma;
1077#endif
1078#ifdef PNG_FIXED_POINT_SUPPORTED
1079      info_ptr->int_gamma = png_ptr->int_gamma;
1080#endif
1081   }
1082#endif
1083
1084#if defined(PNG_READ_16_TO_8_SUPPORTED)
1085   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1086      info_ptr->bit_depth = 8;
1087#endif
1088
1089#if defined(PNG_READ_DITHER_SUPPORTED)
1090   if (png_ptr->transformations & PNG_DITHER)
1091   {
1092      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1093         (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1094         png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1095      {
1096         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1097      }
1098   }
1099#endif
1100
1101#if defined(PNG_READ_PACK_SUPPORTED)
1102   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1103      info_ptr->bit_depth = 8;
1104#endif
1105
1106#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1107   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1108      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1109#endif
1110
1111#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1112   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1113      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1114#endif
1115
1116   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1117      info_ptr->channels = 1;
1118   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1119      info_ptr->channels = 3;
1120   else
1121      info_ptr->channels = 1;
1122
1123#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1124   if (png_ptr->transformations & PNG_STRIP_ALPHA)
1125      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1126#endif
1127
1128   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1129      info_ptr->channels++;
1130
1131#if defined(PNG_READ_FILLER_SUPPORTED)
1132   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1133   if ((png_ptr->transformations & PNG_FILLER) &&
1134       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1135       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1136   {
1137      info_ptr->channels++;
1138      /* if adding a true alpha channel not just filler */
1139#if !defined(PNG_1_0_X)
1140      if (png_ptr->transformations & PNG_ADD_ALPHA)
1141        info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1142#endif
1143   }
1144#endif
1145
1146#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1147defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1148   if(png_ptr->transformations & PNG_USER_TRANSFORM)
1149     {
1150       if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1151         info_ptr->bit_depth = png_ptr->user_transform_depth;
1152       if(info_ptr->channels < png_ptr->user_transform_channels)
1153         info_ptr->channels = png_ptr->user_transform_channels;
1154     }
1155#endif
1156
1157   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1158      info_ptr->bit_depth);
1159
1160   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
1161
1162#if !defined(PNG_READ_EXPAND_SUPPORTED)
1163   if(png_ptr)
1164      return;
1165#endif
1166}
1167
1168/* Transform the row.  The order of transformations is significant,
1169 * and is very touchy.  If you add a transformation, take care to
1170 * decide how it fits in with the other transformations here.
1171 */
1172void /* PRIVATE */
1173png_do_read_transformations(png_structp png_ptr)
1174{
1175   png_debug(1, "in png_do_read_transformations\n");
1176#if !defined(PNG_USELESS_TESTS_SUPPORTED)
1177   if (png_ptr->row_buf == NULL)
1178   {
1179#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1180      char msg[50];
1181
1182      sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1183         png_ptr->pass);
1184      png_error(png_ptr, msg);
1185#else
1186      png_error(png_ptr, "NULL row buffer");
1187#endif
1188   }
1189#endif
1190
1191#if defined(PNG_READ_EXPAND_SUPPORTED)
1192   if (png_ptr->transformations & PNG_EXPAND)
1193   {
1194      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1195      {
1196         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1197            png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1198      }
1199      else
1200      {
1201         if (png_ptr->num_trans)
1202            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1203               &(png_ptr->trans_values));
1204         else
1205            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1206               NULL);
1207      }
1208   }
1209#endif
1210
1211#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1212   if (png_ptr->transformations & PNG_STRIP_ALPHA)
1213      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1214         PNG_FLAG_FILLER_AFTER);
1215#endif
1216
1217#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1218   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1219   {
1220      int rgb_error =
1221         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1222      if(rgb_error)
1223      {
1224         png_ptr->rgb_to_gray_status=1;
1225         if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1226            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1227         if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1228            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1229      }
1230   }
1231#endif
1232
1233/*
1234From Andreas Dilger e-mail to png-implement, 26 March 1998:
1235
1236  In most cases, the "simple transparency" should be done prior to doing
1237  gray-to-RGB, or you will have to test 3x as many bytes to check if a
1238  pixel is transparent.  You would also need to make sure that the
1239  transparency information is upgraded to RGB.
1240
1241  To summarize, the current flow is:
1242  - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1243                                  with background "in place" if transparent,
1244                                  convert to RGB if necessary
1245  - Gray + alpha -> composite with gray background and remove alpha bytes,
1246                                  convert to RGB if necessary
1247
1248  To support RGB backgrounds for gray images we need:
1249  - Gray + simple transparency -> convert to RGB + simple transparency, compare
1250                                  3 or 6 bytes and composite with background
1251                                  "in place" if transparent (3x compare/pixel
1252                                  compared to doing composite with gray bkgrnd)
1253  - Gray + alpha -> convert to RGB + alpha, composite with background and
1254                                  remove alpha bytes (3x float operations/pixel
1255                                  compared with composite on gray background)
1256
1257  Greg's change will do this.  The reason it wasn't done before is for
1258  performance, as this increases the per-pixel operations.  If we would check
1259  in advance if the background was gray or RGB, and position the gray-to-RGB
1260  transform appropriately, then it would save a lot of work/time.
1261 */
1262
1263#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1264   /* if gray -> RGB, do so now only if background is non-gray; else do later
1265    * for performance reasons */
1266   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1267       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1268      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1269#endif
1270
1271#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1272   if ((png_ptr->transformations & PNG_BACKGROUND) &&
1273      ((png_ptr->num_trans != 0 ) ||
1274      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1275      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1276         &(png_ptr->trans_values), &(png_ptr->background)
1277#if defined(PNG_READ_GAMMA_SUPPORTED)
1278         , &(png_ptr->background_1),
1279         png_ptr->gamma_table, png_ptr->gamma_from_1,
1280         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1281         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1282         png_ptr->gamma_shift
1283#endif
1284);
1285#endif
1286
1287#if defined(PNG_READ_GAMMA_SUPPORTED)
1288   if ((png_ptr->transformations & PNG_GAMMA) &&
1289#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1290      !((png_ptr->transformations & PNG_BACKGROUND) &&
1291      ((png_ptr->num_trans != 0) ||
1292      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1293#endif
1294      (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1295      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1296         png_ptr->gamma_table, png_ptr->gamma_16_table,
1297         png_ptr->gamma_shift);
1298#endif
1299
1300#if defined(PNG_READ_16_TO_8_SUPPORTED)
1301   if (png_ptr->transformations & PNG_16_TO_8)
1302      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1303#endif
1304
1305#if defined(PNG_READ_DITHER_SUPPORTED)
1306   if (png_ptr->transformations & PNG_DITHER)
1307   {
1308      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1309         png_ptr->palette_lookup, png_ptr->dither_index);
1310      if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1311         png_error(png_ptr, "png_do_dither returned rowbytes=0");
1312   }
1313#endif
1314
1315#if defined(PNG_READ_INVERT_SUPPORTED)
1316   if (png_ptr->transformations & PNG_INVERT_MONO)
1317      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1318#endif
1319
1320#if defined(PNG_READ_SHIFT_SUPPORTED)
1321   if (png_ptr->transformations & PNG_SHIFT)
1322      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1323         &(png_ptr->shift));
1324#endif
1325
1326#if defined(PNG_READ_PACK_SUPPORTED)
1327   if (png_ptr->transformations & PNG_PACK)
1328      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1329#endif
1330
1331#if defined(PNG_READ_BGR_SUPPORTED)
1332   if (png_ptr->transformations & PNG_BGR)
1333      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1334#endif
1335
1336#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1337   if (png_ptr->transformations & PNG_PACKSWAP)
1338      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1339#endif
1340
1341#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1342   /* if gray -> RGB, do so now only if we did not do so above */
1343   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1344       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1345      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1346#endif
1347
1348#if defined(PNG_READ_FILLER_SUPPORTED)
1349   if (png_ptr->transformations & PNG_FILLER)
1350      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1351         (png_uint_32)png_ptr->filler, png_ptr->flags);
1352#endif
1353
1354#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1355   if (png_ptr->transformations & PNG_INVERT_ALPHA)
1356      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1357#endif
1358
1359#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1360   if (png_ptr->transformations & PNG_SWAP_ALPHA)
1361      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1362#endif
1363
1364#if defined(PNG_READ_SWAP_SUPPORTED)
1365   if (png_ptr->transformations & PNG_SWAP_BYTES)
1366      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1367#endif
1368
1369#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1370   if (png_ptr->transformations & PNG_USER_TRANSFORM)
1371    {
1372      if(png_ptr->read_user_transform_fn != NULL)
1373        (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1374          (png_ptr,                    /* png_ptr */
1375           &(png_ptr->row_info),       /* row_info:     */
1376             /*  png_uint_32 width;          width of row */
1377             /*  png_uint_32 rowbytes;       number of bytes in row */
1378             /*  png_byte color_type;        color type of pixels */
1379             /*  png_byte bit_depth;         bit depth of samples */
1380             /*  png_byte channels;          number of channels (1-4) */
1381             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
1382           png_ptr->row_buf + 1);      /* start of pixel data for row */
1383#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1384      if(png_ptr->user_transform_depth)
1385         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1386      if(png_ptr->user_transform_channels)
1387         png_ptr->row_info.channels = png_ptr->user_transform_channels;
1388#endif
1389      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1390         png_ptr->row_info.channels);
1391      png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1392         png_ptr->row_info.width);
1393   }
1394#endif
1395
1396}
1397
1398#if defined(PNG_READ_PACK_SUPPORTED)
1399/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1400 * without changing the actual values.  Thus, if you had a row with
1401 * a bit depth of 1, you would end up with bytes that only contained
1402 * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
1403 * png_do_shift() after this.
1404 */
1405void /* PRIVATE */
1406png_do_unpack(png_row_infop row_info, png_bytep row)
1407{
1408   png_debug(1, "in png_do_unpack\n");
1409#if defined(PNG_USELESS_TESTS_SUPPORTED)
1410   if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1411#else
1412   if (row_info->bit_depth < 8)
1413#endif
1414   {
1415      png_uint_32 i;
1416      png_uint_32 row_width=row_info->width;
1417
1418      switch (row_info->bit_depth)
1419      {
1420         case 1:
1421         {
1422            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1423            png_bytep dp = row + (png_size_t)row_width - 1;
1424            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1425            for (i = 0; i < row_width; i++)
1426            {
1427               *dp = (png_byte)((*sp >> shift) & 0x01);
1428               if (shift == 7)
1429               {
1430                  shift = 0;
1431                  sp--;
1432               }
1433               else
1434                  shift++;
1435
1436               dp--;
1437            }
1438            break;
1439         }
1440         case 2:
1441         {
1442
1443            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1444            png_bytep dp = row + (png_size_t)row_width - 1;
1445            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1446            for (i = 0; i < row_width; i++)
1447            {
1448               *dp = (png_byte)((*sp >> shift) & 0x03);
1449               if (shift == 6)
1450               {
1451                  shift = 0;
1452                  sp--;
1453               }
1454               else
1455                  shift += 2;
1456
1457               dp--;
1458            }
1459            break;
1460         }
1461         case 4:
1462         {
1463            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1464            png_bytep dp = row + (png_size_t)row_width - 1;
1465            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1466            for (i = 0; i < row_width; i++)
1467            {
1468               *dp = (png_byte)((*sp >> shift) & 0x0f);
1469               if (shift == 4)
1470               {
1471                  shift = 0;
1472                  sp--;
1473               }
1474               else
1475                  shift = 4;
1476
1477               dp--;
1478            }
1479            break;
1480         }
1481      }
1482      row_info->bit_depth = 8;
1483      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1484      row_info->rowbytes = row_width * row_info->channels;
1485   }
1486}
1487#endif
1488
1489#if defined(PNG_READ_SHIFT_SUPPORTED)
1490/* Reverse the effects of png_do_shift.  This routine merely shifts the
1491 * pixels back to their significant bits values.  Thus, if you have
1492 * a row of bit depth 8, but only 5 are significant, this will shift
1493 * the values back to 0 through 31.
1494 */
1495void /* PRIVATE */
1496png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1497{
1498   png_debug(1, "in png_do_unshift\n");
1499   if (
1500#if defined(PNG_USELESS_TESTS_SUPPORTED)
1501       row != NULL && row_info != NULL && sig_bits != NULL &&
1502#endif
1503       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1504   {
1505      int shift[4];
1506      int channels = 0;
1507      int c;
1508      png_uint_16 value = 0;
1509      png_uint_32 row_width = row_info->width;
1510
1511      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1512      {
1513         shift[channels++] = row_info->bit_depth - sig_bits->red;
1514         shift[channels++] = row_info->bit_depth - sig_bits->green;
1515         shift[channels++] = row_info->bit_depth - sig_bits->blue;
1516      }
1517      else
1518      {
1519         shift[channels++] = row_info->bit_depth - sig_bits->gray;
1520      }
1521      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1522      {
1523         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1524      }
1525
1526      for (c = 0; c < channels; c++)
1527      {
1528         if (shift[c] <= 0)
1529            shift[c] = 0;
1530         else
1531            value = 1;
1532      }
1533
1534      if (!value)
1535         return;
1536
1537      switch (row_info->bit_depth)
1538      {
1539         case 2:
1540         {
1541            png_bytep bp;
1542            png_uint_32 i;
1543            png_uint_32 istop = row_info->rowbytes;
1544
1545            for (bp = row, i = 0; i < istop; i++)
1546            {
1547               *bp >>= 1;
1548               *bp++ &= 0x55;
1549            }
1550            break;
1551         }
1552         case 4:
1553         {
1554            png_bytep bp = row;
1555            png_uint_32 i;
1556            png_uint_32 istop = row_info->rowbytes;
1557            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1558               (png_byte)((int)0xf >> shift[0]));
1559
1560            for (i = 0; i < istop; i++)
1561            {
1562               *bp >>= shift[0];
1563               *bp++ &= mask;
1564            }
1565            break;
1566         }
1567         case 8:
1568         {
1569            png_bytep bp = row;
1570            png_uint_32 i;
1571            png_uint_32 istop = row_width * channels;
1572
1573            for (i = 0; i < istop; i++)
1574            {
1575               *bp++ >>= shift[i%channels];
1576            }
1577            break;
1578         }
1579         case 16:
1580         {
1581            png_bytep bp = row;
1582            png_uint_32 i;
1583            png_uint_32 istop = channels * row_width;
1584
1585            for (i = 0; i < istop; i++)
1586            {
1587               value = (png_uint_16)((*bp << 8) + *(bp + 1));
1588               value >>= shift[i%channels];
1589               *bp++ = (png_byte)(value >> 8);
1590               *bp++ = (png_byte)(value & 0xff);
1591            }
1592            break;
1593         }
1594      }
1595   }
1596}
1597#endif
1598
1599#if defined(PNG_READ_16_TO_8_SUPPORTED)
1600/* chop rows of bit depth 16 down to 8 */
1601void /* PRIVATE */
1602png_do_chop(png_row_infop row_info, png_bytep row)
1603{
1604   png_debug(1, "in png_do_chop\n");
1605#if defined(PNG_USELESS_TESTS_SUPPORTED)
1606   if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1607#else
1608   if (row_info->bit_depth == 16)
1609#endif
1610   {
1611      png_bytep sp = row;
1612      png_bytep dp = row;
1613      png_uint_32 i;
1614      png_uint_32 istop = row_info->width * row_info->channels;
1615
1616      for (i = 0; i<istop; i++, sp += 2, dp++)
1617      {
1618#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1619      /* This does a more accurate scaling of the 16-bit color
1620       * value, rather than a simple low-byte truncation.
1621       *
1622       * What the ideal calculation should be:
1623       *   *dp = (((((png_uint_32)(*sp) << 8) |
1624       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1625       *
1626       * GRR: no, I think this is what it really should be:
1627       *   *dp = (((((png_uint_32)(*sp) << 8) |
1628       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1629       *
1630       * GRR: here's the exact calculation with shifts:
1631       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1632       *   *dp = (temp - (temp >> 8)) >> 8;
1633       *
1634       * Approximate calculation with shift/add instead of multiply/divide:
1635       *   *dp = ((((png_uint_32)(*sp) << 8) |
1636       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1637       *
1638       * What we actually do to avoid extra shifting and conversion:
1639       */
1640
1641         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1642#else
1643       /* Simply discard the low order byte */
1644         *dp = *sp;
1645#endif
1646      }
1647      row_info->bit_depth = 8;
1648      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1649      row_info->rowbytes = row_info->width * row_info->channels;
1650   }
1651}
1652#endif
1653
1654#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1655void /* PRIVATE */
1656png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1657{
1658   png_debug(1, "in png_do_read_swap_alpha\n");
1659#if defined(PNG_USELESS_TESTS_SUPPORTED)
1660   if (row != NULL && row_info != NULL)
1661#endif
1662   {
1663      png_uint_32 row_width = row_info->width;
1664      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1665      {
1666         /* This converts from RGBA to ARGB */
1667         if (row_info->bit_depth == 8)
1668         {
1669            png_bytep sp = row + row_info->rowbytes;
1670            png_bytep dp = sp;
1671            png_byte save;
1672            png_uint_32 i;
1673
1674            for (i = 0; i < row_width; i++)
1675            {
1676               save = *(--sp);
1677               *(--dp) = *(--sp);
1678               *(--dp) = *(--sp);
1679               *(--dp) = *(--sp);
1680               *(--dp) = save;
1681            }
1682         }
1683         /* This converts from RRGGBBAA to AARRGGBB */
1684         else
1685         {
1686            png_bytep sp = row + row_info->rowbytes;
1687            png_bytep dp = sp;
1688            png_byte save[2];
1689            png_uint_32 i;
1690
1691            for (i = 0; i < row_width; i++)
1692            {
1693               save[0] = *(--sp);
1694               save[1] = *(--sp);
1695               *(--dp) = *(--sp);
1696               *(--dp) = *(--sp);
1697               *(--dp) = *(--sp);
1698               *(--dp) = *(--sp);
1699               *(--dp) = *(--sp);
1700               *(--dp) = *(--sp);
1701               *(--dp) = save[0];
1702               *(--dp) = save[1];
1703            }
1704         }
1705      }
1706      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1707      {
1708         /* This converts from GA to AG */
1709         if (row_info->bit_depth == 8)
1710         {
1711            png_bytep sp = row + row_info->rowbytes;
1712            png_bytep dp = sp;
1713            png_byte save;
1714            png_uint_32 i;
1715
1716            for (i = 0; i < row_width; i++)
1717            {
1718               save = *(--sp);
1719               *(--dp) = *(--sp);
1720               *(--dp) = save;
1721            }
1722         }
1723         /* This converts from GGAA to AAGG */
1724         else
1725         {
1726            png_bytep sp = row + row_info->rowbytes;
1727            png_bytep dp = sp;
1728            png_byte save[2];
1729            png_uint_32 i;
1730
1731            for (i = 0; i < row_width; i++)
1732            {
1733               save[0] = *(--sp);
1734               save[1] = *(--sp);
1735               *(--dp) = *(--sp);
1736               *(--dp) = *(--sp);
1737               *(--dp) = save[0];
1738               *(--dp) = save[1];
1739            }
1740         }
1741      }
1742   }
1743}
1744#endif
1745
1746#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1747void /* PRIVATE */
1748png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1749{
1750   png_debug(1, "in png_do_read_invert_alpha\n");
1751#if defined(PNG_USELESS_TESTS_SUPPORTED)
1752   if (row != NULL && row_info != NULL)
1753#endif
1754   {
1755      png_uint_32 row_width = row_info->width;
1756      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1757      {
1758         /* This inverts the alpha channel in RGBA */
1759         if (row_info->bit_depth == 8)
1760         {
1761            png_bytep sp = row + row_info->rowbytes;
1762            png_bytep dp = sp;
1763            png_uint_32 i;
1764
1765            for (i = 0; i < row_width; i++)
1766            {
1767               *(--dp) = (png_byte)(255 - *(--sp));
1768
1769/*             This does nothing:
1770               *(--dp) = *(--sp);
1771               *(--dp) = *(--sp);
1772               *(--dp) = *(--sp);
1773               We can replace it with:
1774*/
1775               sp-=3;
1776               dp=sp;
1777            }
1778         }
1779         /* This inverts the alpha channel in RRGGBBAA */
1780         else
1781         {
1782            png_bytep sp = row + row_info->rowbytes;
1783            png_bytep dp = sp;
1784            png_uint_32 i;
1785
1786            for (i = 0; i < row_width; i++)
1787            {
1788               *(--dp) = (png_byte)(255 - *(--sp));
1789               *(--dp) = (png_byte)(255 - *(--sp));
1790
1791/*             This does nothing:
1792               *(--dp) = *(--sp);
1793               *(--dp) = *(--sp);
1794               *(--dp) = *(--sp);
1795               *(--dp) = *(--sp);
1796               *(--dp) = *(--sp);
1797               *(--dp) = *(--sp);
1798               We can replace it with:
1799*/
1800               sp-=6;
1801               dp=sp;
1802            }
1803         }
1804      }
1805      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1806      {
1807         /* This inverts the alpha channel in GA */
1808         if (row_info->bit_depth == 8)
1809         {
1810            png_bytep sp = row + row_info->rowbytes;
1811            png_bytep dp = sp;
1812            png_uint_32 i;
1813
1814            for (i = 0; i < row_width; i++)
1815            {
1816               *(--dp) = (png_byte)(255 - *(--sp));
1817               *(--dp) = *(--sp);
1818            }
1819         }
1820         /* This inverts the alpha channel in GGAA */
1821         else
1822         {
1823            png_bytep sp  = row + row_info->rowbytes;
1824            png_bytep dp = sp;
1825            png_uint_32 i;
1826
1827            for (i = 0; i < row_width; i++)
1828            {
1829               *(--dp) = (png_byte)(255 - *(--sp));
1830               *(--dp) = (png_byte)(255 - *(--sp));
1831/*
1832               *(--dp) = *(--sp);
1833               *(--dp) = *(--sp);
1834*/
1835               sp-=2;
1836               dp=sp;
1837            }
1838         }
1839      }
1840   }
1841}
1842#endif
1843
1844#if defined(PNG_READ_FILLER_SUPPORTED)
1845/* Add filler channel if we have RGB color */
1846void /* PRIVATE */
1847png_do_read_filler(png_row_infop row_info, png_bytep row,
1848   png_uint_32 filler, png_uint_32 flags)
1849{
1850   png_uint_32 i;
1851   png_uint_32 row_width = row_info->width;
1852
1853   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1854   png_byte lo_filler = (png_byte)(filler & 0xff);
1855
1856   png_debug(1, "in png_do_read_filler\n");
1857   if (
1858#if defined(PNG_USELESS_TESTS_SUPPORTED)
1859       row != NULL  && row_info != NULL &&
1860#endif
1861       row_info->color_type == PNG_COLOR_TYPE_GRAY)
1862   {
1863      if(row_info->bit_depth == 8)
1864      {
1865         /* This changes the data from G to GX */
1866         if (flags & PNG_FLAG_FILLER_AFTER)
1867         {
1868            png_bytep sp = row + (png_size_t)row_width;
1869            png_bytep dp =  sp + (png_size_t)row_width;
1870            for (i = 1; i < row_width; i++)
1871            {
1872               *(--dp) = lo_filler;
1873               *(--dp) = *(--sp);
1874            }
1875            *(--dp) = lo_filler;
1876            row_info->channels = 2;
1877            row_info->pixel_depth = 16;
1878            row_info->rowbytes = row_width * 2;
1879         }
1880      /* This changes the data from G to XG */
1881         else
1882         {
1883            png_bytep sp = row + (png_size_t)row_width;
1884            png_bytep dp = sp  + (png_size_t)row_width;
1885            for (i = 0; i < row_width; i++)
1886            {
1887               *(--dp) = *(--sp);
1888               *(--dp) = lo_filler;
1889            }
1890            row_info->channels = 2;
1891            row_info->pixel_depth = 16;
1892            row_info->rowbytes = row_width * 2;
1893         }
1894      }
1895      else if(row_info->bit_depth == 16)
1896      {
1897         /* This changes the data from GG to GGXX */
1898         if (flags & PNG_FLAG_FILLER_AFTER)
1899         {
1900            png_bytep sp = row + (png_size_t)row_width * 2;
1901            png_bytep dp = sp  + (png_size_t)row_width * 2;
1902            for (i = 1; i < row_width; i++)
1903            {
1904               *(--dp) = hi_filler;
1905               *(--dp) = lo_filler;
1906               *(--dp) = *(--sp);
1907               *(--dp) = *(--sp);
1908            }
1909            *(--dp) = hi_filler;
1910            *(--dp) = lo_filler;
1911            row_info->channels = 2;
1912            row_info->pixel_depth = 32;
1913            row_info->rowbytes = row_width * 4;
1914         }
1915         /* This changes the data from GG to XXGG */
1916         else
1917         {
1918            png_bytep sp = row + (png_size_t)row_width * 2;
1919            png_bytep dp = sp  + (png_size_t)row_width * 2;
1920            for (i = 0; i < row_width; i++)
1921            {
1922               *(--dp) = *(--sp);
1923               *(--dp) = *(--sp);
1924               *(--dp) = hi_filler;
1925               *(--dp) = lo_filler;
1926            }
1927            row_info->channels = 2;
1928            row_info->pixel_depth = 32;
1929            row_info->rowbytes = row_width * 4;
1930         }
1931      }
1932   } /* COLOR_TYPE == GRAY */
1933   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1934   {
1935      if(row_info->bit_depth == 8)
1936      {
1937         /* This changes the data from RGB to RGBX */
1938         if (flags & PNG_FLAG_FILLER_AFTER)
1939         {
1940            png_bytep sp = row + (png_size_t)row_width * 3;
1941            png_bytep dp = sp  + (png_size_t)row_width;
1942            for (i = 1; i < row_width; i++)
1943            {
1944               *(--dp) = lo_filler;
1945               *(--dp) = *(--sp);
1946               *(--dp) = *(--sp);
1947               *(--dp) = *(--sp);
1948            }
1949            *(--dp) = lo_filler;
1950            row_info->channels = 4;
1951            row_info->pixel_depth = 32;
1952            row_info->rowbytes = row_width * 4;
1953         }
1954      /* This changes the data from RGB to XRGB */
1955         else
1956         {
1957            png_bytep sp = row + (png_size_t)row_width * 3;
1958            png_bytep dp = sp + (png_size_t)row_width;
1959            for (i = 0; i < row_width; i++)
1960            {
1961               *(--dp) = *(--sp);
1962               *(--dp) = *(--sp);
1963               *(--dp) = *(--sp);
1964               *(--dp) = lo_filler;
1965            }
1966            row_info->channels = 4;
1967            row_info->pixel_depth = 32;
1968            row_info->rowbytes = row_width * 4;
1969         }
1970      }
1971      else if(row_info->bit_depth == 16)
1972      {
1973         /* This changes the data from RRGGBB to RRGGBBXX */
1974         if (flags & PNG_FLAG_FILLER_AFTER)
1975         {
1976            png_bytep sp = row + (png_size_t)row_width * 6;
1977            png_bytep dp = sp  + (png_size_t)row_width * 2;
1978            for (i = 1; i < row_width; i++)
1979            {
1980               *(--dp) = hi_filler;
1981               *(--dp) = lo_filler;
1982               *(--dp) = *(--sp);
1983               *(--dp) = *(--sp);
1984               *(--dp) = *(--sp);
1985               *(--dp) = *(--sp);
1986               *(--dp) = *(--sp);
1987               *(--dp) = *(--sp);
1988            }
1989            *(--dp) = hi_filler;
1990            *(--dp) = lo_filler;
1991            row_info->channels = 4;
1992            row_info->pixel_depth = 64;
1993            row_info->rowbytes = row_width * 8;
1994         }
1995         /* This changes the data from RRGGBB to XXRRGGBB */
1996         else
1997         {
1998            png_bytep sp = row + (png_size_t)row_width * 6;
1999            png_bytep dp = sp  + (png_size_t)row_width * 2;
2000            for (i = 0; i < row_width; i++)
2001            {
2002               *(--dp) = *(--sp);
2003               *(--dp) = *(--sp);
2004               *(--dp) = *(--sp);
2005               *(--dp) = *(--sp);
2006               *(--dp) = *(--sp);
2007               *(--dp) = *(--sp);
2008               *(--dp) = hi_filler;
2009               *(--dp) = lo_filler;
2010            }
2011            row_info->channels = 4;
2012            row_info->pixel_depth = 64;
2013            row_info->rowbytes = row_width * 8;
2014         }
2015      }
2016   } /* COLOR_TYPE == RGB */
2017}
2018#endif
2019
2020#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2021/* expand grayscale files to RGB, with or without alpha */
2022void /* PRIVATE */
2023png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2024{
2025   png_uint_32 i;
2026   png_uint_32 row_width = row_info->width;
2027
2028   png_debug(1, "in png_do_gray_to_rgb\n");
2029   if (row_info->bit_depth >= 8 &&
2030#if defined(PNG_USELESS_TESTS_SUPPORTED)
2031       row != NULL && row_info != NULL &&
2032#endif
2033      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2034   {
2035      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2036      {
2037         if (row_info->bit_depth == 8)
2038         {
2039            png_bytep sp = row + (png_size_t)row_width - 1;
2040            png_bytep dp = sp  + (png_size_t)row_width * 2;
2041            for (i = 0; i < row_width; i++)
2042            {
2043               *(dp--) = *sp;
2044               *(dp--) = *sp;
2045               *(dp--) = *(sp--);
2046            }
2047         }
2048         else
2049         {
2050            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2051            png_bytep dp = sp  + (png_size_t)row_width * 4;
2052            for (i = 0; i < row_width; i++)
2053            {
2054               *(dp--) = *sp;
2055               *(dp--) = *(sp - 1);
2056               *(dp--) = *sp;
2057               *(dp--) = *(sp - 1);
2058               *(dp--) = *(sp--);
2059               *(dp--) = *(sp--);
2060            }
2061         }
2062      }
2063      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2064      {
2065         if (row_info->bit_depth == 8)
2066         {
2067            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2068            png_bytep dp = sp  + (png_size_t)row_width * 2;
2069            for (i = 0; i < row_width; i++)
2070            {
2071               *(dp--) = *(sp--);
2072               *(dp--) = *sp;
2073               *(dp--) = *sp;
2074               *(dp--) = *(sp--);
2075            }
2076         }
2077         else
2078         {
2079            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2080            png_bytep dp = sp  + (png_size_t)row_width * 4;
2081            for (i = 0; i < row_width; i++)
2082            {
2083               *(dp--) = *(sp--);
2084               *(dp--) = *(sp--);
2085               *(dp--) = *sp;
2086               *(dp--) = *(sp - 1);
2087               *(dp--) = *sp;
2088               *(dp--) = *(sp - 1);
2089               *(dp--) = *(sp--);
2090               *(dp--) = *(sp--);
2091            }
2092         }
2093      }
2094      row_info->channels += (png_byte)2;
2095      row_info->color_type |= PNG_COLOR_MASK_COLOR;
2096      row_info->pixel_depth = (png_byte)(row_info->channels *
2097         row_info->bit_depth);
2098      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2099   }
2100}
2101#endif
2102
2103#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2104/* reduce RGB files to grayscale, with or without alpha
2105 * using the equation given in Poynton's ColorFAQ at
2106 * <http://www.inforamp.net/~poynton/>
2107 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
2108 *
2109 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2110 *
2111 *  We approximate this with
2112 *
2113 *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
2114 *
2115 *  which can be expressed with integers as
2116 *
2117 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2118 *
2119 *  The calculation is to be done in a linear colorspace.
2120 *
2121 *  Other integer coefficents can be used via png_set_rgb_to_gray().
2122 */
2123int /* PRIVATE */
2124png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2125
2126{
2127   png_uint_32 i;
2128
2129   png_uint_32 row_width = row_info->width;
2130   int rgb_error = 0;
2131
2132   png_debug(1, "in png_do_rgb_to_gray\n");
2133   if (
2134#if defined(PNG_USELESS_TESTS_SUPPORTED)
2135       row != NULL && row_info != NULL &&
2136#endif
2137      (row_info->color_type & PNG_COLOR_MASK_COLOR))
2138   {
2139      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2140      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2141      png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2142
2143      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2144      {
2145         if (row_info->bit_depth == 8)
2146         {
2147#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2148            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2149            {
2150               png_bytep sp = row;
2151               png_bytep dp = row;
2152
2153               for (i = 0; i < row_width; i++)
2154               {
2155                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
2156                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
2157                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
2158                  if(red != green || red != blue)
2159                  {
2160                     rgb_error |= 1;
2161                     *(dp++) = png_ptr->gamma_from_1[
2162                       (rc*red+gc*green+bc*blue)>>15];
2163                  }
2164                  else
2165                     *(dp++) = *(sp-1);
2166               }
2167            }
2168            else
2169#endif
2170            {
2171               png_bytep sp = row;
2172               png_bytep dp = row;
2173               for (i = 0; i < row_width; i++)
2174               {
2175                  png_byte red   = *(sp++);
2176                  png_byte green = *(sp++);
2177                  png_byte blue  = *(sp++);
2178                  if(red != green || red != blue)
2179                  {
2180                     rgb_error |= 1;
2181                     *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2182                  }
2183                  else
2184                     *(dp++) = *(sp-1);
2185               }
2186            }
2187         }
2188
2189         else /* RGB bit_depth == 16 */
2190         {
2191#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2192            if (png_ptr->gamma_16_to_1 != NULL &&
2193                png_ptr->gamma_16_from_1 != NULL)
2194            {
2195               png_bytep sp = row;
2196               png_bytep dp = row;
2197               for (i = 0; i < row_width; i++)
2198               {
2199                  png_uint_16 red, green, blue, w;
2200
2201                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2202                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2203                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2204
2205                  if(red == green && red == blue)
2206                     w = red;
2207                  else
2208                  {
2209                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
2210                                  png_ptr->gamma_shift][red>>8];
2211                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2212                                  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                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2218                         png_ptr->gamma_shift][gray16 >> 8];
2219                     rgb_error |= 1;
2220                  }
2221
2222                  *(dp++) = (png_byte)((w>>8) & 0xff);
2223                  *(dp++) = (png_byte)(w & 0xff);
2224               }
2225            }
2226            else
2227#endif
2228            {
2229               png_bytep sp = row;
2230               png_bytep dp = row;
2231               for (i = 0; i < row_width; i++)
2232               {
2233                  png_uint_16 red, green, blue, gray16;
2234
2235                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2236                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2237                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2238
2239                  if(red != green || red != blue)
2240                     rgb_error |= 1;
2241                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2242                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
2243                  *(dp++) = (png_byte)(gray16 & 0xff);
2244               }
2245            }
2246         }
2247      }
2248      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2249      {
2250         if (row_info->bit_depth == 8)
2251         {
2252#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2253            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2254            {
2255               png_bytep sp = row;
2256               png_bytep dp = row;
2257               for (i = 0; i < row_width; i++)
2258               {
2259                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
2260                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
2261                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
2262                  if(red != green || red != blue)
2263                     rgb_error |= 1;
2264                  *(dp++) =  png_ptr->gamma_from_1
2265                             [(rc*red + gc*green + bc*blue)>>15];
2266                  *(dp++) = *(sp++);  /* alpha */
2267               }
2268            }
2269            else
2270#endif
2271            {
2272               png_bytep sp = row;
2273               png_bytep dp = row;
2274               for (i = 0; i < row_width; i++)
2275               {
2276                  png_byte red   = *(sp++);
2277                  png_byte green = *(sp++);
2278                  png_byte blue  = *(sp++);
2279                  if(red != green || red != blue)
2280                     rgb_error |= 1;
2281                  *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
2282                  *(dp++) = *(sp++);  /* alpha */
2283               }
2284            }
2285         }
2286         else /* RGBA bit_depth == 16 */
2287         {
2288#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2289            if (png_ptr->gamma_16_to_1 != NULL &&
2290                png_ptr->gamma_16_from_1 != NULL)
2291            {
2292               png_bytep sp = row;
2293               png_bytep dp = row;
2294               for (i = 0; i < row_width; i++)
2295               {
2296                  png_uint_16 red, green, blue, w;
2297
2298                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2299                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2300                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2301
2302                  if(red == green && red == blue)
2303                     w = red;
2304                  else
2305                  {
2306                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
2307                                  png_ptr->gamma_shift][red>>8];
2308                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2309                                  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                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2315                         png_ptr->gamma_shift][gray16 >> 8];
2316                     rgb_error |= 1;
2317                  }
2318
2319                  *(dp++) = (png_byte)((w>>8) & 0xff);
2320                  *(dp++) = (png_byte)(w & 0xff);
2321                  *(dp++) = *(sp++);  /* alpha */
2322                  *(dp++) = *(sp++);
2323               }
2324            }
2325            else
2326#endif
2327            {
2328               png_bytep sp = row;
2329               png_bytep dp = row;
2330               for (i = 0; i < row_width; i++)
2331               {
2332                  png_uint_16 red, green, blue, gray16;
2333                  red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2334                  green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2335                  blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2336                  if(red != green || red != blue)
2337                     rgb_error |= 1;
2338                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2339                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
2340                  *(dp++) = (png_byte)(gray16 & 0xff);
2341                  *(dp++) = *(sp++);  /* alpha */
2342                  *(dp++) = *(sp++);
2343               }
2344            }
2345         }
2346      }
2347   row_info->channels -= (png_byte)2;
2348      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2349      row_info->pixel_depth = (png_byte)(row_info->channels *
2350         row_info->bit_depth);
2351      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2352   }
2353   return rgb_error;
2354}
2355#endif
2356
2357/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
2358 * large of png_color.  This lets grayscale images be treated as
2359 * paletted.  Most useful for gamma correction and simplification
2360 * of code.
2361 */
2362void PNGAPI
2363png_build_grayscale_palette(int bit_depth, png_colorp palette)
2364{
2365   int num_palette;
2366   int color_inc;
2367   int i;
2368   int v;
2369
2370   png_debug(1, "in png_do_build_grayscale_palette\n");
2371   if (palette == NULL)
2372      return;
2373
2374   switch (bit_depth)
2375   {
2376      case 1:
2377         num_palette = 2;
2378         color_inc = 0xff;
2379         break;
2380      case 2:
2381         num_palette = 4;
2382         color_inc = 0x55;
2383         break;
2384      case 4:
2385         num_palette = 16;
2386         color_inc = 0x11;
2387         break;
2388      case 8:
2389         num_palette = 256;
2390         color_inc = 1;
2391         break;
2392      default:
2393         num_palette = 0;
2394         color_inc = 0;
2395         break;
2396   }
2397
2398   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2399   {
2400      palette[i].red = (png_byte)v;
2401      palette[i].green = (png_byte)v;
2402      palette[i].blue = (png_byte)v;
2403   }
2404}
2405
2406/* This function is currently unused.  Do we really need it? */
2407#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2408void /* PRIVATE */
2409png_correct_palette(png_structp png_ptr, png_colorp palette,
2410   int num_palette)
2411{
2412   png_debug(1, "in png_correct_palette\n");
2413#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2414    defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2415   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2416   {
2417      png_color back, back_1;
2418
2419      if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2420      {
2421         back.red = png_ptr->gamma_table[png_ptr->background.red];
2422         back.green = png_ptr->gamma_table[png_ptr->background.green];
2423         back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2424
2425         back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2426         back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2427         back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2428      }
2429      else
2430      {
2431         double g;
2432
2433         g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2434
2435         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2436             fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2437         {
2438            back.red = png_ptr->background.red;
2439            back.green = png_ptr->background.green;
2440            back.blue = png_ptr->background.blue;
2441         }
2442         else
2443         {
2444            back.red =
2445               (png_byte)(pow((double)png_ptr->background.red/255, g) *
2446                255.0 + 0.5);
2447            back.green =
2448               (png_byte)(pow((double)png_ptr->background.green/255, g) *
2449                255.0 + 0.5);
2450            back.blue =
2451               (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2452                255.0 + 0.5);
2453         }
2454
2455         g = 1.0 / png_ptr->background_gamma;
2456
2457         back_1.red =
2458            (png_byte)(pow((double)png_ptr->background.red/255, g) *
2459             255.0 + 0.5);
2460         back_1.green =
2461            (png_byte)(pow((double)png_ptr->background.green/255, g) *
2462             255.0 + 0.5);
2463         back_1.blue =
2464            (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2465             255.0 + 0.5);
2466      }
2467
2468      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2469      {
2470         png_uint_32 i;
2471
2472         for (i = 0; i < (png_uint_32)num_palette; i++)
2473         {
2474            if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2475            {
2476               palette[i] = back;
2477            }
2478            else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2479            {
2480               png_byte v, w;
2481
2482               v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2483               png_composite(w, v, png_ptr->trans[i], back_1.red);
2484               palette[i].red = png_ptr->gamma_from_1[w];
2485
2486               v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2487               png_composite(w, v, png_ptr->trans[i], back_1.green);
2488               palette[i].green = png_ptr->gamma_from_1[w];
2489
2490               v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2491               png_composite(w, v, png_ptr->trans[i], back_1.blue);
2492               palette[i].blue = png_ptr->gamma_from_1[w];
2493            }
2494            else
2495            {
2496               palette[i].red = png_ptr->gamma_table[palette[i].red];
2497               palette[i].green = png_ptr->gamma_table[palette[i].green];
2498               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2499            }
2500         }
2501      }
2502      else
2503      {
2504         int i;
2505
2506         for (i = 0; i < num_palette; i++)
2507         {
2508            if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2509            {
2510               palette[i] = back;
2511            }
2512            else
2513            {
2514               palette[i].red = png_ptr->gamma_table[palette[i].red];
2515               palette[i].green = png_ptr->gamma_table[palette[i].green];
2516               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2517            }
2518         }
2519      }
2520   }
2521   else
2522#endif
2523#if defined(PNG_READ_GAMMA_SUPPORTED)
2524   if (png_ptr->transformations & PNG_GAMMA)
2525   {
2526      int i;
2527
2528      for (i = 0; i < num_palette; i++)
2529      {
2530         palette[i].red = png_ptr->gamma_table[palette[i].red];
2531         palette[i].green = png_ptr->gamma_table[palette[i].green];
2532         palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2533      }
2534   }
2535#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2536   else
2537#endif
2538#endif
2539#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2540   if (png_ptr->transformations & PNG_BACKGROUND)
2541   {
2542      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2543      {
2544         png_color back;
2545
2546         back.red   = (png_byte)png_ptr->background.red;
2547         back.green = (png_byte)png_ptr->background.green;
2548         back.blue  = (png_byte)png_ptr->background.blue;
2549
2550         for (i = 0; i < (int)png_ptr->num_trans; i++)
2551         {
2552            if (png_ptr->trans[i] == 0)
2553            {
2554               palette[i].red = back.red;
2555               palette[i].green = back.green;
2556               palette[i].blue = back.blue;
2557            }
2558            else if (png_ptr->trans[i] != 0xff)
2559            {
2560               png_composite(palette[i].red, png_ptr->palette[i].red,
2561                  png_ptr->trans[i], back.red);
2562               png_composite(palette[i].green, png_ptr->palette[i].green,
2563                  png_ptr->trans[i], back.green);
2564               png_composite(palette[i].blue, png_ptr->palette[i].blue,
2565                  png_ptr->trans[i], back.blue);
2566            }
2567         }
2568      }
2569      else /* assume grayscale palette (what else could it be?) */
2570      {
2571         int i;
2572
2573         for (i = 0; i < num_palette; i++)
2574         {
2575            if (i == (png_byte)png_ptr->trans_values.gray)
2576            {
2577               palette[i].red = (png_byte)png_ptr->background.red;
2578               palette[i].green = (png_byte)png_ptr->background.green;
2579               palette[i].blue = (png_byte)png_ptr->background.blue;
2580            }
2581         }
2582      }
2583   }
2584#endif
2585}
2586#endif
2587
2588#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2589/* Replace any alpha or transparency with the supplied background color.
2590 * "background" is already in the screen gamma, while "background_1" is
2591 * at a gamma of 1.0.  Paletted files have already been taken care of.
2592 */
2593void /* PRIVATE */
2594png_do_background(png_row_infop row_info, png_bytep row,
2595   png_color_16p trans_values, png_color_16p background
2596#if defined(PNG_READ_GAMMA_SUPPORTED)
2597   , png_color_16p background_1,
2598   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2599   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2600   png_uint_16pp gamma_16_to_1, int gamma_shift
2601#endif
2602   )
2603{
2604   png_bytep sp, dp;
2605   png_uint_32 i;
2606   png_uint_32 row_width=row_info->width;
2607   int shift;
2608
2609   png_debug(1, "in png_do_background\n");
2610   if (background != NULL &&
2611#if defined(PNG_USELESS_TESTS_SUPPORTED)
2612       row != NULL && row_info != NULL &&
2613#endif
2614      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2615      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2616   {
2617      switch (row_info->color_type)
2618      {
2619         case PNG_COLOR_TYPE_GRAY:
2620         {
2621            switch (row_info->bit_depth)
2622            {
2623               case 1:
2624               {
2625                  sp = row;
2626                  shift = 7;
2627                  for (i = 0; i < row_width; i++)
2628                  {
2629                     if ((png_uint_16)((*sp >> shift) & 0x01)
2630                        == trans_values->gray)
2631                     {
2632                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2633                        *sp |= (png_byte)(background->gray << shift);
2634                     }
2635                     if (!shift)
2636                     {
2637                        shift = 7;
2638                        sp++;
2639                     }
2640                     else
2641                        shift--;
2642                  }
2643                  break;
2644               }
2645               case 2:
2646               {
2647#if defined(PNG_READ_GAMMA_SUPPORTED)
2648                  if (gamma_table != NULL)
2649                  {
2650                     sp = row;
2651                     shift = 6;
2652                     for (i = 0; i < row_width; i++)
2653                     {
2654                        if ((png_uint_16)((*sp >> shift) & 0x03)
2655                            == trans_values->gray)
2656                        {
2657                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2658                           *sp |= (png_byte)(background->gray << shift);
2659                        }
2660                        else
2661                        {
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                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2666                           *sp |= (png_byte)(g << shift);
2667                        }
2668                        if (!shift)
2669                        {
2670                           shift = 6;
2671                           sp++;
2672                        }
2673                        else
2674                           shift -= 2;
2675                     }
2676                  }
2677                  else
2678#endif
2679                  {
2680                     sp = row;
2681                     shift = 6;
2682                     for (i = 0; i < row_width; i++)
2683                     {
2684                        if ((png_uint_16)((*sp >> shift) & 0x03)
2685                            == trans_values->gray)
2686                        {
2687                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2688                           *sp |= (png_byte)(background->gray << shift);
2689                        }
2690                        if (!shift)
2691                        {
2692                           shift = 6;
2693                           sp++;
2694                        }
2695                        else
2696                           shift -= 2;
2697                     }
2698                  }
2699                  break;
2700               }
2701               case 4:
2702               {
2703#if defined(PNG_READ_GAMMA_SUPPORTED)
2704                  if (gamma_table != NULL)
2705                  {
2706                     sp = row;
2707                     shift = 4;
2708                     for (i = 0; i < row_width; i++)
2709                     {
2710                        if ((png_uint_16)((*sp >> shift) & 0x0f)
2711                            == trans_values->gray)
2712                        {
2713                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2714                           *sp |= (png_byte)(background->gray << shift);
2715                        }
2716                        else
2717                        {
2718                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2719                           png_byte g = (png_byte)((gamma_table[p |
2720                             (p << 4)] >> 4) & 0x0f);
2721                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2722                           *sp |= (png_byte)(g << shift);
2723                        }
2724                        if (!shift)
2725                        {
2726                           shift = 4;
2727                           sp++;
2728                        }
2729                        else
2730                           shift -= 4;
2731                     }
2732                  }
2733                  else
2734#endif
2735                  {
2736                     sp = row;
2737                     shift = 4;
2738                     for (i = 0; i < row_width; i++)
2739                     {
2740                        if ((png_uint_16)((*sp >> shift) & 0x0f)
2741                            == trans_values->gray)
2742                        {
2743                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2744                           *sp |= (png_byte)(background->gray << shift);
2745                        }
2746                        if (!shift)
2747                        {
2748                           shift = 4;
2749                           sp++;
2750                        }
2751                        else
2752                           shift -= 4;
2753                     }
2754                  }
2755                  break;
2756               }
2757               case 8:
2758               {
2759#if defined(PNG_READ_GAMMA_SUPPORTED)
2760                  if (gamma_table != NULL)
2761                  {
2762                     sp = row;
2763                     for (i = 0; i < row_width; i++, sp++)
2764                     {
2765                        if (*sp == trans_values->gray)
2766                        {
2767                           *sp = (png_byte)background->gray;
2768                        }
2769                        else
2770                        {
2771                           *sp = gamma_table[*sp];
2772                        }
2773                     }
2774                  }
2775                  else
2776#endif
2777                  {
2778                     sp = row;
2779                     for (i = 0; i < row_width; i++, sp++)
2780                     {
2781                        if (*sp == trans_values->gray)
2782                        {
2783                           *sp = (png_byte)background->gray;
2784                        }
2785                     }
2786                  }
2787                  break;
2788               }
2789               case 16:
2790               {
2791#if defined(PNG_READ_GAMMA_SUPPORTED)
2792                  if (gamma_16 != NULL)
2793                  {
2794                     sp = row;
2795                     for (i = 0; i < row_width; i++, sp += 2)
2796                     {
2797                        png_uint_16 v;
2798
2799                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2800                        if (v == trans_values->gray)
2801                        {
2802                           /* background is already in screen gamma */
2803                           *sp = (png_byte)((background->gray >> 8) & 0xff);
2804                           *(sp + 1) = (png_byte)(background->gray & 0xff);
2805                        }
2806                        else
2807                        {
2808                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2809                           *sp = (png_byte)((v >> 8) & 0xff);
2810                           *(sp + 1) = (png_byte)(v & 0xff);
2811                        }
2812                     }
2813                  }
2814                  else
2815#endif
2816                  {
2817                     sp = row;
2818                     for (i = 0; i < row_width; i++, sp += 2)
2819                     {
2820                        png_uint_16 v;
2821
2822                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2823                        if (v == trans_values->gray)
2824                        {
2825                           *sp = (png_byte)((background->gray >> 8) & 0xff);
2826                           *(sp + 1) = (png_byte)(background->gray & 0xff);
2827                        }
2828                     }
2829                  }
2830                  break;
2831               }
2832            }
2833            break;
2834         }
2835         case PNG_COLOR_TYPE_RGB:
2836         {
2837            if (row_info->bit_depth == 8)
2838            {
2839#if defined(PNG_READ_GAMMA_SUPPORTED)
2840               if (gamma_table != NULL)
2841               {
2842                  sp = row;
2843                  for (i = 0; i < row_width; i++, sp += 3)
2844                  {
2845                     if (*sp == trans_values->red &&
2846                        *(sp + 1) == trans_values->green &&
2847                        *(sp + 2) == trans_values->blue)
2848                     {
2849                        *sp = (png_byte)background->red;
2850                        *(sp + 1) = (png_byte)background->green;
2851                        *(sp + 2) = (png_byte)background->blue;
2852                     }
2853                     else
2854                     {
2855                        *sp = gamma_table[*sp];
2856                        *(sp + 1) = gamma_table[*(sp + 1)];
2857                        *(sp + 2) = gamma_table[*(sp + 2)];
2858                     }
2859                  }
2860               }
2861               else
2862#endif
2863               {
2864                  sp = row;
2865                  for (i = 0; i < row_width; i++, sp += 3)
2866                  {
2867                     if (*sp == trans_values->red &&
2868                        *(sp + 1) == trans_values->green &&
2869                        *(sp + 2) == trans_values->blue)
2870                     {
2871                        *sp = (png_byte)background->red;
2872                        *(sp + 1) = (png_byte)background->green;
2873                        *(sp + 2) = (png_byte)background->blue;
2874                     }
2875                  }
2876               }
2877            }
2878            else /* if (row_info->bit_depth == 16) */
2879            {
2880#if defined(PNG_READ_GAMMA_SUPPORTED)
2881               if (gamma_16 != NULL)
2882               {
2883                  sp = row;
2884                  for (i = 0; i < row_width; i++, sp += 6)
2885                  {
2886                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2887                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2888                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2889                     if (r == trans_values->red && g == trans_values->green &&
2890                        b == trans_values->blue)
2891                     {
2892                        /* background is already in screen gamma */
2893                        *sp = (png_byte)((background->red >> 8) & 0xff);
2894                        *(sp + 1) = (png_byte)(background->red & 0xff);
2895                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2896                        *(sp + 3) = (png_byte)(background->green & 0xff);
2897                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2898                        *(sp + 5) = (png_byte)(background->blue & 0xff);
2899                     }
2900                     else
2901                     {
2902                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2903                        *sp = (png_byte)((v >> 8) & 0xff);
2904                        *(sp + 1) = (png_byte)(v & 0xff);
2905                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
2906                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2907                        *(sp + 3) = (png_byte)(v & 0xff);
2908                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
2909                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2910                        *(sp + 5) = (png_byte)(v & 0xff);
2911                     }
2912                  }
2913               }
2914               else
2915#endif
2916               {
2917                  sp = row;
2918                  for (i = 0; i < row_width; i++, sp += 6)
2919                  {
2920                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2921                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2922                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2923
2924                     if (r == trans_values->red && g == trans_values->green &&
2925                        b == trans_values->blue)
2926                     {
2927                        *sp = (png_byte)((background->red >> 8) & 0xff);
2928                        *(sp + 1) = (png_byte)(background->red & 0xff);
2929                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2930                        *(sp + 3) = (png_byte)(background->green & 0xff);
2931                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2932                        *(sp + 5) = (png_byte)(background->blue & 0xff);
2933                     }
2934                  }
2935               }
2936            }
2937            break;
2938         }
2939         case PNG_COLOR_TYPE_GRAY_ALPHA:
2940         {
2941            if (row_info->bit_depth == 8)
2942            {
2943#if defined(PNG_READ_GAMMA_SUPPORTED)
2944               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2945                   gamma_table != NULL)
2946               {
2947                  sp = row;
2948                  dp = row;
2949                  for (i = 0; i < row_width; i++, sp += 2, dp++)
2950                  {
2951                     png_uint_16 a = *(sp + 1);
2952
2953                     if (a == 0xff)
2954                     {
2955                        *dp = gamma_table[*sp];
2956                     }
2957                     else if (a == 0)
2958                     {
2959                        /* background is already in screen gamma */
2960                        *dp = (png_byte)background->gray;
2961                     }
2962                     else
2963                     {
2964                        png_byte v, w;
2965
2966                        v = gamma_to_1[*sp];
2967                        png_composite(w, v, a, background_1->gray);
2968                        *dp = gamma_from_1[w];
2969                     }
2970                  }
2971               }
2972               else
2973#endif
2974               {
2975                  sp = row;
2976                  dp = row;
2977                  for (i = 0; i < row_width; i++, sp += 2, dp++)
2978                  {
2979                     png_byte a = *(sp + 1);
2980
2981                     if (a == 0xff)
2982                     {
2983                        *dp = *sp;
2984                     }
2985#if defined(PNG_READ_GAMMA_SUPPORTED)
2986                     else if (a == 0)
2987                     {
2988                        *dp = (png_byte)background->gray;
2989                     }
2990                     else
2991                     {
2992                        png_composite(*dp, *sp, a, background_1->gray);
2993                     }
2994#else
2995                     *dp = (png_byte)background->gray;
2996#endif
2997                  }
2998               }
2999            }
3000            else /* if (png_ptr->bit_depth == 16) */
3001            {
3002#if defined(PNG_READ_GAMMA_SUPPORTED)
3003               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3004                   gamma_16_to_1 != NULL)
3005               {
3006                  sp = row;
3007                  dp = row;
3008                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3009                  {
3010                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3011
3012                     if (a == (png_uint_16)0xffff)
3013                     {
3014                        png_uint_16 v;
3015
3016                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3017                        *dp = (png_byte)((v >> 8) & 0xff);
3018                        *(dp + 1) = (png_byte)(v & 0xff);
3019                     }
3020#if defined(PNG_READ_GAMMA_SUPPORTED)
3021                     else if (a == 0)
3022#else
3023                     else
3024#endif
3025                     {
3026                        /* background is already in screen gamma */
3027                        *dp = (png_byte)((background->gray >> 8) & 0xff);
3028                        *(dp + 1) = (png_byte)(background->gray & 0xff);
3029                     }
3030#if defined(PNG_READ_GAMMA_SUPPORTED)
3031                     else
3032                     {
3033                        png_uint_16 g, v, w;
3034
3035                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3036                        png_composite_16(v, g, a, background_1->gray);
3037                        w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3038                        *dp = (png_byte)((w >> 8) & 0xff);
3039                        *(dp + 1) = (png_byte)(w & 0xff);
3040                     }
3041#endif
3042                  }
3043               }
3044               else
3045#endif
3046               {
3047                  sp = row;
3048                  dp = row;
3049                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3050                  {
3051                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3052                     if (a == (png_uint_16)0xffff)
3053                     {
3054                        png_memcpy(dp, sp, 2);
3055                     }
3056#if defined(PNG_READ_GAMMA_SUPPORTED)
3057                     else if (a == 0)
3058#else
3059                     else
3060#endif
3061                     {
3062                        *dp = (png_byte)((background->gray >> 8) & 0xff);
3063                        *(dp + 1) = (png_byte)(background->gray & 0xff);
3064                     }
3065#if defined(PNG_READ_GAMMA_SUPPORTED)
3066                     else
3067                     {
3068                        png_uint_16 g, v;
3069
3070                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3071                        png_composite_16(v, g, a, background_1->gray);
3072                        *dp = (png_byte)((v >> 8) & 0xff);
3073                        *(dp + 1) = (png_byte)(v & 0xff);
3074                     }
3075#endif
3076                  }
3077               }
3078            }
3079            break;
3080         }
3081         case PNG_COLOR_TYPE_RGB_ALPHA:
3082         {
3083            if (row_info->bit_depth == 8)
3084            {
3085#if defined(PNG_READ_GAMMA_SUPPORTED)
3086               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3087                   gamma_table != NULL)
3088               {
3089                  sp = row;
3090                  dp = row;
3091                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3092                  {
3093                     png_byte a = *(sp + 3);
3094
3095                     if (a == 0xff)
3096                     {
3097                        *dp = gamma_table[*sp];
3098                        *(dp + 1) = gamma_table[*(sp + 1)];
3099                        *(dp + 2) = gamma_table[*(sp + 2)];
3100                     }
3101                     else if (a == 0)
3102                     {
3103                        /* background is already in screen gamma */
3104                        *dp = (png_byte)background->red;
3105                        *(dp + 1) = (png_byte)background->green;
3106                        *(dp + 2) = (png_byte)background->blue;
3107                     }
3108                     else
3109                     {
3110                        png_byte v, w;
3111
3112                        v = gamma_to_1[*sp];
3113                        png_composite(w, v, a, background_1->red);
3114                        *dp = gamma_from_1[w];
3115                        v = gamma_to_1[*(sp + 1)];
3116                        png_composite(w, v, a, background_1->green);
3117                        *(dp + 1) = gamma_from_1[w];
3118                        v = gamma_to_1[*(sp + 2)];
3119                        png_composite(w, v, a, background_1->blue);
3120                        *(dp + 2) = gamma_from_1[w];
3121                     }
3122                  }
3123               }
3124               else
3125#endif
3126               {
3127                  sp = row;
3128                  dp = row;
3129                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3130                  {
3131                     png_byte a = *(sp + 3);
3132
3133                     if (a == 0xff)
3134                     {
3135                        *dp = *sp;
3136                        *(dp + 1) = *(sp + 1);
3137                        *(dp + 2) = *(sp + 2);
3138                     }
3139                     else if (a == 0)
3140                     {
3141                        *dp = (png_byte)background->red;
3142                        *(dp + 1) = (png_byte)background->green;
3143                        *(dp + 2) = (png_byte)background->blue;
3144                     }
3145                     else
3146                     {
3147                        png_composite(*dp, *sp, a, background->red);
3148                        png_composite(*(dp + 1), *(sp + 1), a,
3149                           background->green);
3150                        png_composite(*(dp + 2), *(sp + 2), a,
3151                           background->blue);
3152                     }
3153                  }
3154               }
3155            }
3156            else /* if (row_info->bit_depth == 16) */
3157            {
3158#if defined(PNG_READ_GAMMA_SUPPORTED)
3159               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3160                   gamma_16_to_1 != NULL)
3161               {
3162                  sp = row;
3163                  dp = row;
3164                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3165                  {
3166                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3167                         << 8) + (png_uint_16)(*(sp + 7)));
3168                     if (a == (png_uint_16)0xffff)
3169                     {
3170                        png_uint_16 v;
3171
3172                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3173                        *dp = (png_byte)((v >> 8) & 0xff);
3174                        *(dp + 1) = (png_byte)(v & 0xff);
3175                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3176                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3177                        *(dp + 3) = (png_byte)(v & 0xff);
3178                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3179                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3180                        *(dp + 5) = (png_byte)(v & 0xff);
3181                     }
3182                     else if (a == 0)
3183                     {
3184                        /* background is already in screen gamma */
3185                        *dp = (png_byte)((background->red >> 8) & 0xff);
3186                        *(dp + 1) = (png_byte)(background->red & 0xff);
3187                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3188                        *(dp + 3) = (png_byte)(background->green & 0xff);
3189                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3190                        *(dp + 5) = (png_byte)(background->blue & 0xff);
3191                     }
3192                     else
3193                     {
3194                        png_uint_16 v, w, x;
3195
3196                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3197                        png_composite_16(w, v, a, background_1->red);
3198                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3199                        *dp = (png_byte)((x >> 8) & 0xff);
3200                        *(dp + 1) = (png_byte)(x & 0xff);
3201                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3202                        png_composite_16(w, v, a, background_1->green);
3203                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3204                        *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3205                        *(dp + 3) = (png_byte)(x & 0xff);
3206                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3207                        png_composite_16(w, v, a, background_1->blue);
3208                        x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3209                        *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3210                        *(dp + 5) = (png_byte)(x & 0xff);
3211                     }
3212                  }
3213               }
3214               else
3215#endif
3216               {
3217                  sp = row;
3218                  dp = row;
3219                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3220                  {
3221                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3222                        << 8) + (png_uint_16)(*(sp + 7)));
3223                     if (a == (png_uint_16)0xffff)
3224                     {
3225                        png_memcpy(dp, sp, 6);
3226                     }
3227                     else if (a == 0)
3228                     {
3229                        *dp = (png_byte)((background->red >> 8) & 0xff);
3230                        *(dp + 1) = (png_byte)(background->red & 0xff);
3231                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3232                        *(dp + 3) = (png_byte)(background->green & 0xff);
3233                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3234                        *(dp + 5) = (png_byte)(background->blue & 0xff);
3235                     }
3236                     else
3237                     {
3238                        png_uint_16 v;
3239
3240                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3241                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3242                            + *(sp + 3));
3243                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3244                            + *(sp + 5));
3245
3246                        png_composite_16(v, r, a, background->red);
3247                        *dp = (png_byte)((v >> 8) & 0xff);
3248                        *(dp + 1) = (png_byte)(v & 0xff);
3249                        png_composite_16(v, g, a, background->green);
3250                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3251                        *(dp + 3) = (png_byte)(v & 0xff);
3252                        png_composite_16(v, b, a, background->blue);
3253                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3254                        *(dp + 5) = (png_byte)(v & 0xff);
3255                     }
3256                  }
3257               }
3258            }
3259            break;
3260         }
3261      }
3262
3263      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3264      {
3265         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3266         row_info->channels--;
3267         row_info->pixel_depth = (png_byte)(row_info->channels *
3268            row_info->bit_depth);
3269         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3270      }
3271   }
3272}
3273#endif
3274
3275#if defined(PNG_READ_GAMMA_SUPPORTED)
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 * is 16, use gamma_16_table and gamma_shift.  Build these with
3280 * build_gamma_table().
3281 */
3282void /* PRIVATE */
3283png_do_gamma(png_row_infop row_info, png_bytep row,
3284   png_bytep gamma_table, png_uint_16pp gamma_16_table,
3285   int gamma_shift)
3286{
3287   png_bytep sp;
3288   png_uint_32 i;
3289   png_uint_32 row_width=row_info->width;
3290
3291   png_debug(1, "in png_do_gamma\n");
3292   if (
3293#if defined(PNG_USELESS_TESTS_SUPPORTED)
3294       row != NULL && row_info != NULL &&
3295#endif
3296       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3297        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3298   {
3299      switch (row_info->color_type)
3300      {
3301         case PNG_COLOR_TYPE_RGB:
3302         {
3303            if (row_info->bit_depth == 8)
3304            {
3305               sp = row;
3306               for (i = 0; i < row_width; i++)
3307               {
3308                  *sp = gamma_table[*sp];
3309                  sp++;
3310                  *sp = gamma_table[*sp];
3311                  sp++;
3312                  *sp = gamma_table[*sp];
3313                  sp++;
3314               }
3315            }
3316            else /* if (row_info->bit_depth == 16) */
3317            {
3318               sp = row;
3319               for (i = 0; i < row_width; i++)
3320               {
3321                  png_uint_16 v;
3322
3323                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3324                  *sp = (png_byte)((v >> 8) & 0xff);
3325                  *(sp + 1) = (png_byte)(v & 0xff);
3326                  sp += 2;
3327                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3328                  *sp = (png_byte)((v >> 8) & 0xff);
3329                  *(sp + 1) = (png_byte)(v & 0xff);
3330                  sp += 2;
3331                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3332                  *sp = (png_byte)((v >> 8) & 0xff);
3333                  *(sp + 1) = (png_byte)(v & 0xff);
3334                  sp += 2;
3335               }
3336            }
3337            break;
3338         }
3339         case PNG_COLOR_TYPE_RGB_ALPHA:
3340         {
3341            if (row_info->bit_depth == 8)
3342            {
3343               sp = row;
3344               for (i = 0; i < row_width; i++)
3345               {
3346                  *sp = gamma_table[*sp];
3347                  sp++;
3348                  *sp = gamma_table[*sp];
3349                  sp++;
3350                  *sp = gamma_table[*sp];
3351                  sp++;
3352                  sp++;
3353               }
3354            }
3355            else /* if (row_info->bit_depth == 16) */
3356            {
3357               sp = row;
3358               for (i = 0; i < row_width; i++)
3359               {
3360                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3361                  *sp = (png_byte)((v >> 8) & 0xff);
3362                  *(sp + 1) = (png_byte)(v & 0xff);
3363                  sp += 2;
3364                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3365                  *sp = (png_byte)((v >> 8) & 0xff);
3366                  *(sp + 1) = (png_byte)(v & 0xff);
3367                  sp += 2;
3368                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3369                  *sp = (png_byte)((v >> 8) & 0xff);
3370                  *(sp + 1) = (png_byte)(v & 0xff);
3371                  sp += 4;
3372               }
3373            }
3374            break;
3375         }
3376         case PNG_COLOR_TYPE_GRAY_ALPHA:
3377         {
3378            if (row_info->bit_depth == 8)
3379            {
3380               sp = row;
3381               for (i = 0; i < row_width; i++)
3382               {
3383                  *sp = gamma_table[*sp];
3384                  sp += 2;
3385               }
3386            }
3387            else /* if (row_info->bit_depth == 16) */
3388            {
3389               sp = row;
3390               for (i = 0; i < row_width; i++)
3391               {
3392                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3393                  *sp = (png_byte)((v >> 8) & 0xff);
3394                  *(sp + 1) = (png_byte)(v & 0xff);
3395                  sp += 4;
3396               }
3397            }
3398            break;
3399         }
3400         case PNG_COLOR_TYPE_GRAY:
3401         {
3402            if (row_info->bit_depth == 2)
3403            {
3404               sp = row;
3405               for (i = 0; i < row_width; i += 4)
3406               {
3407                  int a = *sp & 0xc0;
3408                  int b = *sp & 0x30;
3409                  int c = *sp & 0x0c;
3410                  int d = *sp & 0x03;
3411
3412                  *sp = (png_byte)(
3413                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
3414                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3415                        ((((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                  sp++;
3418               }
3419            }
3420            if (row_info->bit_depth == 4)
3421            {
3422               sp = row;
3423               for (i = 0; i < row_width; i += 2)
3424               {
3425                  int msb = *sp & 0xf0;
3426                  int lsb = *sp & 0x0f;
3427
3428                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3429                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3430                  sp++;
3431               }
3432            }
3433            else if (row_info->bit_depth == 8)
3434            {
3435               sp = row;
3436               for (i = 0; i < row_width; i++)
3437               {
3438                  *sp = gamma_table[*sp];
3439                  sp++;
3440               }
3441            }
3442            else if (row_info->bit_depth == 16)
3443            {
3444               sp = row;
3445               for (i = 0; i < row_width; i++)
3446               {
3447                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3448                  *sp = (png_byte)((v >> 8) & 0xff);
3449                  *(sp + 1) = (png_byte)(v & 0xff);
3450                  sp += 2;
3451               }
3452            }
3453            break;
3454         }
3455      }
3456   }
3457}
3458#endif
3459
3460#if defined(PNG_READ_EXPAND_SUPPORTED)
3461/* Expands a palette row to an RGB or RGBA row depending
3462 * upon whether you supply trans and num_trans.
3463 */
3464void /* PRIVATE */
3465png_do_expand_palette(png_row_infop row_info, png_bytep row,
3466   png_colorp palette, png_bytep trans, int num_trans)
3467{
3468   int shift, value;
3469   png_bytep sp, dp;
3470   png_uint_32 i;
3471   png_uint_32 row_width=row_info->width;
3472
3473   png_debug(1, "in png_do_expand_palette\n");
3474   if (
3475#if defined(PNG_USELESS_TESTS_SUPPORTED)
3476       row != NULL && row_info != NULL &&
3477#endif
3478       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3479   {
3480      if (row_info->bit_depth < 8)
3481      {
3482         switch (row_info->bit_depth)
3483         {
3484            case 1:
3485            {
3486               sp = row + (png_size_t)((row_width - 1) >> 3);
3487               dp = row + (png_size_t)row_width - 1;
3488               shift = 7 - (int)((row_width + 7) & 0x07);
3489               for (i = 0; i < row_width; i++)
3490               {
3491                  if ((*sp >> shift) & 0x01)
3492                     *dp = 1;
3493                  else
3494                     *dp = 0;
3495                  if (shift == 7)
3496                  {
3497                     shift = 0;
3498                     sp--;
3499                  }
3500                  else
3501                     shift++;
3502
3503                  dp--;
3504               }
3505               break;
3506            }
3507            case 2:
3508            {
3509               sp = row + (png_size_t)((row_width - 1) >> 2);
3510               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++)
3513               {
3514                  value = (*sp >> shift) & 0x03;
3515                  *dp = (png_byte)value;
3516                  if (shift == 6)
3517                  {
3518                     shift = 0;
3519                     sp--;
3520                  }
3521                  else
3522                     shift += 2;
3523
3524                  dp--;
3525               }
3526               break;
3527            }
3528            case 4:
3529            {
3530               sp = row + (png_size_t)((row_width - 1) >> 1);
3531               dp = row + (png_size_t)row_width - 1;
3532               shift = (int)((row_width & 0x01) << 2);
3533               for (i = 0; i < row_width; i++)
3534               {
3535                  value = (*sp >> shift) & 0x0f;
3536                  *dp = (png_byte)value;
3537                  if (shift == 4)
3538                  {
3539                     shift = 0;
3540                     sp--;
3541                  }
3542                  else
3543                     shift += 4;
3544
3545                  dp--;
3546               }
3547               break;
3548            }
3549         }
3550         row_info->bit_depth = 8;
3551         row_info->pixel_depth = 8;
3552         row_info->rowbytes = row_width;
3553      }
3554      switch (row_info->bit_depth)
3555      {
3556         case 8:
3557         {
3558            if (trans != NULL)
3559            {
3560               sp = row + (png_size_t)row_width - 1;
3561               dp = row + (png_size_t)(row_width << 2) - 1;
3562
3563               for (i = 0; i < row_width; i++)
3564               {
3565                  if ((int)(*sp) >= num_trans)
3566                     *dp-- = 0xff;
3567                  else
3568                     *dp-- = trans[*sp];
3569                  *dp-- = palette[*sp].blue;
3570                  *dp-- = palette[*sp].green;
3571                  *dp-- = palette[*sp].red;
3572                  sp--;
3573               }
3574               row_info->bit_depth = 8;
3575               row_info->pixel_depth = 32;
3576               row_info->rowbytes = row_width * 4;
3577               row_info->color_type = 6;
3578               row_info->channels = 4;
3579            }
3580            else
3581            {
3582               sp = row + (png_size_t)row_width - 1;
3583               dp = row + (png_size_t)(row_width * 3) - 1;
3584
3585               for (i = 0; i < row_width; i++)
3586               {
3587                  *dp-- = palette[*sp].blue;
3588                  *dp-- = palette[*sp].green;
3589                  *dp-- = palette[*sp].red;
3590                  sp--;
3591               }
3592               row_info->bit_depth = 8;
3593               row_info->pixel_depth = 24;
3594               row_info->rowbytes = row_width * 3;
3595               row_info->color_type = 2;
3596               row_info->channels = 3;
3597            }
3598            break;
3599         }
3600      }
3601   }
3602}
3603
3604/* If the bit depth < 8, it is expanded to 8.  Also, if the
3605 * transparency value is supplied, an alpha channel is built.
3606 */
3607void /* PRIVATE */
3608png_do_expand(png_row_infop row_info, png_bytep row,
3609   png_color_16p trans_value)
3610{
3611   int shift, value;
3612   png_bytep sp, dp;
3613   png_uint_32 i;
3614   png_uint_32 row_width=row_info->width;
3615
3616   png_debug(1, "in png_do_expand\n");
3617#if defined(PNG_USELESS_TESTS_SUPPORTED)
3618   if (row != NULL && row_info != NULL)
3619#endif
3620   {
3621      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3622      {
3623         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3624
3625         if (row_info->bit_depth < 8)
3626         {
3627            switch (row_info->bit_depth)
3628            {
3629               case 1:
3630               {
3631                  gray = (png_uint_16)(gray*0xff);
3632                  sp = row + (png_size_t)((row_width - 1) >> 3);
3633                  dp = row + (png_size_t)row_width - 1;
3634                  shift = 7 - (int)((row_width + 7) & 0x07);
3635                  for (i = 0; i < row_width; i++)
3636                  {
3637                     if ((*sp >> shift) & 0x01)
3638                        *dp = 0xff;
3639                     else
3640                        *dp = 0;
3641                     if (shift == 7)
3642                     {
3643                        shift = 0;
3644                        sp--;
3645                     }
3646                     else
3647                        shift++;
3648
3649                     dp--;
3650                  }
3651                  break;
3652               }
3653               case 2:
3654               {
3655                  gray = (png_uint_16)(gray*0x55);
3656                  sp = row + (png_size_t)((row_width - 1) >> 2);
3657                  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++)
3660                  {
3661                     value = (*sp >> shift) & 0x03;
3662                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
3663                        (value << 6));
3664                     if (shift == 6)
3665                     {
3666                        shift = 0;
3667                        sp--;
3668                     }
3669                     else
3670                        shift += 2;
3671
3672                     dp--;
3673                  }
3674                  break;
3675               }
3676               case 4:
3677               {
3678                  gray = (png_uint_16)(gray*0x11);
3679                  sp = row + (png_size_t)((row_width - 1) >> 1);
3680                  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++)
3683                  {
3684                     value = (*sp >> shift) & 0x0f;
3685                     *dp = (png_byte)(value | (value << 4));
3686                     if (shift == 4)
3687                     {
3688                        shift = 0;
3689                        sp--;
3690                     }
3691                     else
3692                        shift = 4;
3693
3694                     dp--;
3695                  }
3696                  break;
3697               }
3698            }
3699            row_info->bit_depth = 8;
3700            row_info->pixel_depth = 8;
3701            row_info->rowbytes = row_width;
3702         }
3703
3704         if (trans_value != NULL)
3705         {
3706            if (row_info->bit_depth == 8)
3707            {
3708               sp = row + (png_size_t)row_width - 1;
3709               dp = row + (png_size_t)(row_width << 1) - 1;
3710               for (i = 0; i < row_width; i++)
3711               {
3712                  if (*sp == gray)
3713                     *dp-- = 0;
3714                  else
3715                     *dp-- = 0xff;
3716                  *dp-- = *sp--;
3717               }
3718            }
3719            else if (row_info->bit_depth == 16)
3720            {
3721               sp = row + row_info->rowbytes - 1;
3722               dp = row + (row_info->rowbytes << 1) - 1;
3723               for (i = 0; i < row_width; i++)
3724               {
3725                  if (((png_uint_16)*(sp) |
3726                     ((png_uint_16)*(sp - 1) << 8)) == gray)
3727                  {
3728                     *dp-- = 0;
3729                     *dp-- = 0;
3730                  }
3731                  else
3732                  {
3733                     *dp-- = 0xff;
3734                     *dp-- = 0xff;
3735                  }
3736                  *dp-- = *sp--;
3737                  *dp-- = *sp--;
3738               }
3739            }
3740            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3741            row_info->channels = 2;
3742            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3743            row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3744               row_width);
3745         }
3746      }
3747      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3748      {
3749         if (row_info->bit_depth == 8)
3750         {
3751            sp = row + (png_size_t)row_info->rowbytes - 1;
3752            dp = row + (png_size_t)(row_width << 2) - 1;
3753            for (i = 0; i < row_width; i++)
3754            {
3755               if (*(sp - 2) == trans_value->red &&
3756                  *(sp - 1) == trans_value->green &&
3757                  *(sp - 0) == trans_value->blue)
3758                  *dp-- = 0;
3759               else
3760                  *dp-- = 0xff;
3761               *dp-- = *sp--;
3762               *dp-- = *sp--;
3763               *dp-- = *sp--;
3764            }
3765         }
3766         else if (row_info->bit_depth == 16)
3767         {
3768            sp = row + row_info->rowbytes - 1;
3769            dp = row + (png_size_t)(row_width << 3) - 1;
3770            for (i = 0; i < row_width; i++)
3771            {
3772               if ((((png_uint_16)*(sp - 4) |
3773                  ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
3774                  (((png_uint_16)*(sp - 2) |
3775                  ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3776                  (((png_uint_16)*(sp - 0) |
3777                  ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3778               {
3779                  *dp-- = 0;
3780                  *dp-- = 0;
3781               }
3782               else
3783               {
3784                  *dp-- = 0xff;
3785                  *dp-- = 0xff;
3786               }
3787               *dp-- = *sp--;
3788               *dp-- = *sp--;
3789               *dp-- = *sp--;
3790               *dp-- = *sp--;
3791               *dp-- = *sp--;
3792               *dp-- = *sp--;
3793            }
3794         }
3795         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3796         row_info->channels = 4;
3797         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3798         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3799      }
3800   }
3801}
3802#endif
3803
3804#if defined(PNG_READ_DITHER_SUPPORTED)
3805void /* PRIVATE */
3806png_do_dither(png_row_infop row_info, png_bytep row,
3807    png_bytep palette_lookup, png_bytep dither_lookup)
3808{
3809   png_bytep sp, dp;
3810   png_uint_32 i;
3811   png_uint_32 row_width=row_info->width;
3812
3813   png_debug(1, "in png_do_dither\n");
3814#if defined(PNG_USELESS_TESTS_SUPPORTED)
3815   if (row != NULL && row_info != NULL)
3816#endif
3817   {
3818      if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3819         palette_lookup && row_info->bit_depth == 8)
3820      {
3821         int r, g, b, p;
3822         sp = row;
3823         dp = row;
3824         for (i = 0; i < row_width; i++)
3825         {
3826            r = *sp++;
3827            g = *sp++;
3828            b = *sp++;
3829
3830            /* this looks real messy, but the compiler will reduce
3831               it down to a reasonable formula.  For example, with
3832               5 bits per color, we get:
3833               p = (((r >> 3) & 0x1f) << 10) |
3834                  (((g >> 3) & 0x1f) << 5) |
3835                  ((b >> 3) & 0x1f);
3836               */
3837            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3838               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3839               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3840               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3841               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3842               (PNG_DITHER_BLUE_BITS)) |
3843               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3844               ((1 << PNG_DITHER_BLUE_BITS) - 1));
3845
3846            *dp++ = palette_lookup[p];
3847         }
3848         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3849         row_info->channels = 1;
3850         row_info->pixel_depth = row_info->bit_depth;
3851         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3852      }
3853      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3854         palette_lookup != NULL && row_info->bit_depth == 8)
3855      {
3856         int r, g, b, p;
3857         sp = row;
3858         dp = row;
3859         for (i = 0; i < row_width; i++)
3860         {
3861            r = *sp++;
3862            g = *sp++;
3863            b = *sp++;
3864            sp++;
3865
3866            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3867               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3868               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3869               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3870               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3871               (PNG_DITHER_BLUE_BITS)) |
3872               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3873               ((1 << PNG_DITHER_BLUE_BITS) - 1));
3874
3875            *dp++ = palette_lookup[p];
3876         }
3877         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3878         row_info->channels = 1;
3879         row_info->pixel_depth = row_info->bit_depth;
3880         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3881      }
3882      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3883         dither_lookup && row_info->bit_depth == 8)
3884      {
3885         sp = row;
3886         for (i = 0; i < row_width; i++, sp++)
3887         {
3888            *sp = dither_lookup[*sp];
3889         }
3890      }
3891   }
3892}
3893#endif
3894
3895#ifdef PNG_FLOATING_POINT_SUPPORTED
3896#if defined(PNG_READ_GAMMA_SUPPORTED)
3897static int png_gamma_shift[] =
3898   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3899
3900/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
3901 * tables, we don't make a full table if we are reducing to 8-bit in
3902 * the future.  Note also how the gamma_16 tables are segmented so that
3903 * we don't need to allocate > 64K chunks for a full 16-bit table.
3904 */
3905void /* PRIVATE */
3906png_build_gamma_table(png_structp png_ptr)
3907{
3908  png_debug(1, "in png_build_gamma_table\n");
3909  if(png_ptr->gamma != 0.0)
3910  {
3911   if (png_ptr->bit_depth <= 8)
3912   {
3913      int i;
3914      double g;
3915
3916      if (png_ptr->screen_gamma > .000001)
3917         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3918      else
3919         g = 1.0;
3920
3921      png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
3922         (png_uint_32)256);
3923
3924      for (i = 0; i < 256; i++)
3925      {
3926         png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3927            g) * 255.0 + .5);
3928      }
3929
3930#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3931    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3932      if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
3933      {
3934
3935         g = 1.0 / (png_ptr->gamma);
3936
3937         png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
3938            (png_uint_32)256);
3939
3940         for (i = 0; i < 256; i++)
3941         {
3942            png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3943               g) * 255.0 + .5);
3944         }
3945
3946
3947         png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
3948            (png_uint_32)256);
3949
3950         if(png_ptr->screen_gamma > 0.000001)
3951            g = 1.0 / png_ptr->screen_gamma;
3952         else
3953            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
3954
3955         for (i = 0; i < 256; i++)
3956         {
3957            png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3958               g) * 255.0 + .5);
3959
3960         }
3961      }
3962#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
3963   }
3964   else
3965   {
3966      double g;
3967      int i, j, shift, num;
3968      int sig_bit;
3969      png_uint_32 ig;
3970
3971      if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3972      {
3973         sig_bit = (int)png_ptr->sig_bit.red;
3974         if ((int)png_ptr->sig_bit.green > sig_bit)
3975            sig_bit = png_ptr->sig_bit.green;
3976         if ((int)png_ptr->sig_bit.blue > sig_bit)
3977            sig_bit = png_ptr->sig_bit.blue;
3978      }
3979      else
3980      {
3981         sig_bit = (int)png_ptr->sig_bit.gray;
3982      }
3983
3984      if (sig_bit > 0)
3985         shift = 16 - sig_bit;
3986      else
3987         shift = 0;
3988
3989      if (png_ptr->transformations & PNG_16_TO_8)
3990      {
3991         if (shift < (16 - PNG_MAX_GAMMA_8))
3992            shift = (16 - PNG_MAX_GAMMA_8);
3993      }
3994
3995      if (shift > 8)
3996         shift = 8;
3997      if (shift < 0)
3998         shift = 0;
3999
4000      png_ptr->gamma_shift = (png_byte)shift;
4001
4002      num = (1 << (8 - shift));
4003
4004      if (png_ptr->screen_gamma > .000001)
4005         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4006      else
4007         g = 1.0;
4008
4009      png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4010         (png_uint_32)(num * png_sizeof (png_uint_16p)));
4011
4012      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4013      {
4014         double fin, fout;
4015         png_uint_32 last, max;
4016
4017         for (i = 0; i < num; i++)
4018         {
4019            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4020               (png_uint_32)(256 * png_sizeof (png_uint_16)));
4021         }
4022
4023         g = 1.0 / g;
4024         last = 0;
4025         for (i = 0; i < 256; i++)
4026         {
4027            fout = ((double)i + 0.5) / 256.0;
4028            fin = pow(fout, g);
4029            max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4030            while (last <= max)
4031            {
4032               png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4033                  [(int)(last >> (8 - shift))] = (png_uint_16)(
4034                  (png_uint_16)i | ((png_uint_16)i << 8));
4035               last++;
4036            }
4037         }
4038         while (last < ((png_uint_32)num << 8))
4039         {
4040            png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4041               [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4042            last++;
4043         }
4044      }
4045      else
4046      {
4047         for (i = 0; i < num; i++)
4048         {
4049            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4050               (png_uint_32)(256 * png_sizeof (png_uint_16)));
4051
4052            ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4053            for (j = 0; j < 256; j++)
4054            {
4055               png_ptr->gamma_16_table[i][j] =
4056                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4057                     65535.0, g) * 65535.0 + .5);
4058            }
4059         }
4060      }
4061
4062#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4063    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4064      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4065      {
4066
4067         g = 1.0 / (png_ptr->gamma);
4068
4069         png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4070            (png_uint_32)(num * png_sizeof (png_uint_16p )));
4071
4072         for (i = 0; i < num; i++)
4073         {
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)));
4076
4077            ig = (((png_uint_32)i *
4078               (png_uint_32)png_gamma_shift[shift]) >> 4);
4079            for (j = 0; j < 256; j++)
4080            {
4081               png_ptr->gamma_16_to_1[i][j] =
4082                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4083                     65535.0, g) * 65535.0 + .5);
4084            }
4085         }
4086
4087         if(png_ptr->screen_gamma > 0.000001)
4088            g = 1.0 / png_ptr->screen_gamma;
4089         else
4090            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
4091
4092         png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4093            (png_uint_32)(num * png_sizeof (png_uint_16p)));
4094
4095         for (i = 0; i < num; i++)
4096         {
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)));
4099
4100            ig = (((png_uint_32)i *
4101               (png_uint_32)png_gamma_shift[shift]) >> 4);
4102            for (j = 0; j < 256; j++)
4103            {
4104               png_ptr->gamma_16_from_1[i][j] =
4105                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4106                     65535.0, g) * 65535.0 + .5);
4107            }
4108         }
4109      }
4110#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4111   }
4112 }
4113}
4114#endif
4115/* To do: install integer version of png_build_gamma_table here */
4116#endif
4117
4118#if defined(PNG_MNG_FEATURES_SUPPORTED)
4119/* undoes intrapixel differencing  */
4120void /* PRIVATE */
4121png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4122{
4123   png_debug(1, "in png_do_read_intrapixel\n");
4124   if (
4125#if defined(PNG_USELESS_TESTS_SUPPORTED)
4126       row != NULL && row_info != NULL &&
4127#endif
4128       (row_info->color_type & PNG_COLOR_MASK_COLOR))
4129   {
4130      int bytes_per_pixel;
4131      png_uint_32 row_width = row_info->width;
4132      if (row_info->bit_depth == 8)
4133      {
4134         png_bytep rp;
4135         png_uint_32 i;
4136
4137         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4138            bytes_per_pixel = 3;
4139         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4140            bytes_per_pixel = 4;
4141         else
4142            return;
4143
4144         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4145         {
4146            *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4147            *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4148         }
4149      }
4150      else if (row_info->bit_depth == 16)
4151      {
4152         png_bytep rp;
4153         png_uint_32 i;
4154
4155         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4156            bytes_per_pixel = 6;
4157         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4158            bytes_per_pixel = 8;
4159         else
4160            return;
4161
4162         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4163         {
4164            png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
4165            png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
4166            png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
4167            png_uint_32 red  = (png_uint_32)((s0+s1+65536L) & 0xffffL);
4168            png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
4169            *(rp  ) = (png_byte)((red >> 8) & 0xff);
4170            *(rp+1) = (png_byte)(red & 0xff);
4171            *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4172            *(rp+5) = (png_byte)(blue & 0xff);
4173         }
4174      }
4175   }
4176}
4177#endif /* PNG_MNG_FEATURES_SUPPORTED */
4178