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