pngrtran.c revision 0640679f04398a7d06319d5c47b0f71bf82854a0
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. */
22void PNGAPI
23png_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 */
78void PNGAPI
79png_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 */
102void PNGAPI
103png_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)
112void PNGAPI
113png_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
131typedef struct png_dsort_struct
132{
133   struct png_dsort_struct FAR * next;
134   png_byte left;
135   png_byte right;
136} png_dsort;
137typedef png_dsort FAR *       png_dsortp;
138typedef png_dsort FAR * FAR * png_dsortpp;
139
140void PNGAPI
141png_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 */
526void PNGAPI
527png_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 */
545void PNGAPI
546png_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. */
572void PNGAPI
573png_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. */
583void PNGAPI
584png_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 */
596void PNGAPI
597png_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. */
607void PNGAPI
608png_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)
617void PNGAPI
618png_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
632void PNGAPI
633png_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
643void PNGAPI
644png_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)
694void PNGAPI
695png_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 */
715void /* PRIVATE */
716png_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 */
1122void /* PRIVATE */
1123png_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) && \
1241defined(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 */
1266void /* PRIVATE */
1267png_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/*
1341From 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 */
1512void /* PRIVATE */
1513png_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 */
1602void /* PRIVATE */
1603png_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 */
1708void /* PRIVATE */
1709png_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)
1762void /* PRIVATE */
1763png_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)
1854void /* PRIVATE */
1855png_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 */
1953void /* PRIVATE */
1954png_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 */
2129void /* PRIVATE */
2130png_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 */
2230int /* PRIVATE */
2231png_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 */
2469void PNGAPI
2470png_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)
2515void /* PRIVATE */
2516png_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 */
2700void /* PRIVATE */
2701png_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 */
3389void /* PRIVATE */
3390png_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 */
3571void /* PRIVATE */
3572png_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 */
3714void /* PRIVATE */
3715png_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)
3921void /* PRIVATE */
3922png_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)
4013static 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 */
4021void /* PRIVATE */
4022png_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  */
4234void /* PRIVATE */
4235png_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 */
4293