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