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