source: trunk/third/libpng/pngrtran.c @ 20647

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