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