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