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