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