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