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