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