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