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