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