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