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) & 0xff);
3709                            *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3710                         }
3711 
3712                         else
3713                         {
3714                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3715                            *sp = (png_byte)((v >> 8) & 0xff);
3716                            *(sp + 1) = (png_byte)(v & 0xff);
3717                         }
3718                      }
3719                   }
3720                   else
3721 #endif
3722                   {
3723                      sp = row;
3724                      for (i = 0; i < row_width; i++, sp += 2)
3725                      {
3726                         png_uint_16 v;
3727 
3728                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3729 
3730                         if (v == png_ptr->trans_color.gray)
3731                         {
3732                            *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
3733                            *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3734                         }
3735                      }
3736                   }
3737                   break;
3738                }
3739 
3740                default:
3741                   break;
3742             }
3743             break;
3744          }
3745 
3746          case PNG_COLOR_TYPE_RGB:
3747          {
3748             if (row_info->bit_depth == 8)
3749             {
3750 #ifdef PNG_READ_GAMMA_SUPPORTED
3751                if (gamma_table != NULL)
3752                {
3753                   sp = row;
3754                   for (i = 0; i < row_width; i++, sp += 3)
3755                   {
3756                      if (*sp == png_ptr->trans_color.red &&
3757                          *(sp + 1) == png_ptr->trans_color.green &&
3758                          *(sp + 2) == png_ptr->trans_color.blue)
3759                      {
3760                         *sp = (png_byte)png_ptr->background.red;
3761                         *(sp + 1) = (png_byte)png_ptr->background.green;
3762                         *(sp + 2) = (png_byte)png_ptr->background.blue;
3763                      }
3764 
3765                      else
3766                      {
3767                         *sp = gamma_table[*sp];
3768                         *(sp + 1) = gamma_table[*(sp + 1)];
3769                         *(sp + 2) = gamma_table[*(sp + 2)];
3770                      }
3771                   }
3772                }
3773                else
3774 #endif
3775                {
3776                   sp = row;
3777                   for (i = 0; i < row_width; i++, sp += 3)
3778                   {
3779                      if (*sp == png_ptr->trans_color.red &&
3780                          *(sp + 1) == png_ptr->trans_color.green &&
3781                          *(sp + 2) == png_ptr->trans_color.blue)
3782                      {
3783                         *sp = (png_byte)png_ptr->background.red;
3784                         *(sp + 1) = (png_byte)png_ptr->background.green;
3785                         *(sp + 2) = (png_byte)png_ptr->background.blue;
3786                      }
3787                   }
3788                }
3789             }
3790             else /* if (row_info->bit_depth == 16) */
3791             {
3792 #ifdef PNG_READ_GAMMA_SUPPORTED
3793                if (gamma_16 != NULL)
3794                {
3795                   sp = row;
3796                   for (i = 0; i < row_width; i++, sp += 6)
3797                   {
3798                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3799 
3800                      png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3801                          + *(sp + 3));
3802 
3803                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3804                          + *(sp + 5));
3805 
3806                      if (r == png_ptr->trans_color.red &&
3807                          g == png_ptr->trans_color.green &&
3808                          b == png_ptr->trans_color.blue)
3809                      {
3810                         /* Background is already in screen gamma */
3811                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3812                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3813                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
3814                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
3815                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
3816                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3817                      }
3818 
3819                      else
3820                      {
3821                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3822                         *sp = (png_byte)((v >> 8) & 0xff);
3823                         *(sp + 1) = (png_byte)(v & 0xff);
3824 
3825                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3826                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3827                         *(sp + 3) = (png_byte)(v & 0xff);
3828 
3829                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3830                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3831                         *(sp + 5) = (png_byte)(v & 0xff);
3832                      }
3833                   }
3834                }
3835 
3836                else
3837 #endif
3838                {
3839                   sp = row;
3840                   for (i = 0; i < row_width; i++, sp += 6)
3841                   {
3842                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3843 
3844                      png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3845                          + *(sp + 3));
3846 
3847                      png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3848                          + *(sp + 5));
3849 
3850                      if (r == png_ptr->trans_color.red &&
3851                          g == png_ptr->trans_color.green &&
3852                          b == png_ptr->trans_color.blue)
3853                      {
3854                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3855                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3856                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
3857                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
3858                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
3859                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3860                      }
3861                   }
3862                }
3863             }
3864             break;
3865          }
3866 
3867          case PNG_COLOR_TYPE_GRAY_ALPHA:
3868          {
3869             if (row_info->bit_depth == 8)
3870             {
3871 #ifdef PNG_READ_GAMMA_SUPPORTED
3872                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3873                    gamma_table != NULL)
3874                {
3875                   sp = row;
3876                   for (i = 0; i < row_width; i++, sp += 2)
3877                   {
3878                      png_uint_16 a = *(sp + 1);
3879 
3880                      if (a == 0xff)
3881                         *sp = gamma_table[*sp];
3882 
3883                      else if (a == 0)
3884                      {
3885                         /* Background is already in screen gamma */
3886                         *sp = (png_byte)png_ptr->background.gray;
3887                      }
3888 
3889                      else
3890                      {
3891                         png_byte v, w;
3892 
3893                         v = gamma_to_1[*sp];
3894                         png_composite(w, v, a, png_ptr->background_1.gray);
3895                         if (!optimize)
3896                            w = gamma_from_1[w];
3897                         *sp = w;
3898                      }
3899                   }
3900                }
3901                else
3902 #endif
3903                {
3904                   sp = row;
3905                   for (i = 0; i < row_width; i++, sp += 2)
3906                   {
3907                      png_byte a = *(sp + 1);
3908 
3909                      if (a == 0)
3910                         *sp = (png_byte)png_ptr->background.gray;
3911 
3912                      else if (a < 0xff)
3913                         png_composite(*sp, *sp, a, png_ptr->background_1.gray);
3914                   }
3915                }
3916             }
3917             else /* if (png_ptr->bit_depth == 16) */
3918             {
3919 #ifdef PNG_READ_GAMMA_SUPPORTED
3920                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3921                    gamma_16_to_1 != NULL)
3922                {
3923                   sp = row;
3924                   for (i = 0; i < row_width; i++, sp += 4)
3925                   {
3926                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3927                          + *(sp + 3));
3928 
3929                      if (a == (png_uint_16)0xffff)
3930                      {
3931                         png_uint_16 v;
3932 
3933                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3934                         *sp = (png_byte)((v >> 8) & 0xff);
3935                         *(sp + 1) = (png_byte)(v & 0xff);
3936                      }
3937 
3938                      else if (a == 0)
3939                      {
3940                         /* Background is already in screen gamma */
3941                         *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
3942                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3943                      }
3944 
3945                      else
3946                      {
3947                         png_uint_16 g, v, w;
3948 
3949                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3950                         png_composite_16(v, g, a, png_ptr->background_1.gray);
3951                         if (optimize)
3952                            w = v;
3953                         else
3954                            w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3955                         *sp = (png_byte)((w >> 8) & 0xff);
3956                         *(sp + 1) = (png_byte)(w & 0xff);
3957                      }
3958                   }
3959                }
3960                else
3961 #endif
3962                {
3963                   sp = row;
3964                   for (i = 0; i < row_width; i++, sp += 4)
3965                   {
3966                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3967                          + *(sp + 3));
3968 
3969                      if (a == 0)
3970                      {
3971                         *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
3972                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3973                      }
3974 
3975                      else if (a < 0xffff)
3976                      {
3977                         png_uint_16 g, v;
3978 
3979                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3980                         png_composite_16(v, g, a, png_ptr->background_1.gray);
3981                         *sp = (png_byte)((v >> 8) & 0xff);
3982                         *(sp + 1) = (png_byte)(v & 0xff);
3983                      }
3984                   }
3985                }
3986             }
3987             break;
3988          }
3989 
3990          case PNG_COLOR_TYPE_RGB_ALPHA:
3991          {
3992             if (row_info->bit_depth == 8)
3993             {
3994 #ifdef PNG_READ_GAMMA_SUPPORTED
3995                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3996                    gamma_table != NULL)
3997                {
3998                   sp = row;
3999                   for (i = 0; i < row_width; i++, sp += 4)
4000                   {
4001                      png_byte a = *(sp + 3);
4002 
4003                      if (a == 0xff)
4004                      {
4005                         *sp = gamma_table[*sp];
4006                         *(sp + 1) = gamma_table[*(sp + 1)];
4007                         *(sp + 2) = gamma_table[*(sp + 2)];
4008                      }
4009 
4010                      else if (a == 0)
4011                      {
4012                         /* Background is already in screen gamma */
4013                         *sp = (png_byte)png_ptr->background.red;
4014                         *(sp + 1) = (png_byte)png_ptr->background.green;
4015                         *(sp + 2) = (png_byte)png_ptr->background.blue;
4016                      }
4017 
4018                      else
4019                      {
4020                         png_byte v, w;
4021 
4022                         v = gamma_to_1[*sp];
4023                         png_composite(w, v, a, png_ptr->background_1.red);
4024                         if (!optimize) w = gamma_from_1[w];
4025                         *sp = w;
4026 
4027                         v = gamma_to_1[*(sp + 1)];
4028                         png_composite(w, v, a, png_ptr->background_1.green);
4029                         if (!optimize) w = gamma_from_1[w];
4030                         *(sp + 1) = w;
4031 
4032                         v = gamma_to_1[*(sp + 2)];
4033                         png_composite(w, v, a, png_ptr->background_1.blue);
4034                         if (!optimize) w = gamma_from_1[w];
4035                         *(sp + 2) = w;
4036                      }
4037                   }
4038                }
4039                else
4040 #endif
4041                {
4042                   sp = row;
4043                   for (i = 0; i < row_width; i++, sp += 4)
4044                   {
4045                      png_byte a = *(sp + 3);
4046 
4047                      if (a == 0)
4048                      {
4049                         *sp = (png_byte)png_ptr->background.red;
4050                         *(sp + 1) = (png_byte)png_ptr->background.green;
4051                         *(sp + 2) = (png_byte)png_ptr->background.blue;
4052                      }
4053 
4054                      else if (a < 0xff)
4055                      {
4056                         png_composite(*sp, *sp, a, png_ptr->background.red);
4057 
4058                         png_composite(*(sp + 1), *(sp + 1), a,
4059                             png_ptr->background.green);
4060 
4061                         png_composite(*(sp + 2), *(sp + 2), a,
4062                             png_ptr->background.blue);
4063                      }
4064                   }
4065                }
4066             }
4067             else /* if (row_info->bit_depth == 16) */
4068             {
4069 #ifdef PNG_READ_GAMMA_SUPPORTED
4070                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
4071                    gamma_16_to_1 != NULL)
4072                {
4073                   sp = row;
4074                   for (i = 0; i < row_width; i++, sp += 8)
4075                   {
4076                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
4077                          << 8) + (png_uint_16)(*(sp + 7)));
4078 
4079                      if (a == (png_uint_16)0xffff)
4080                      {
4081                         png_uint_16 v;
4082 
4083                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
4084                         *sp = (png_byte)((v >> 8) & 0xff);
4085                         *(sp + 1) = (png_byte)(v & 0xff);
4086 
4087                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
4088                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
4089                         *(sp + 3) = (png_byte)(v & 0xff);
4090 
4091                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
4092                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
4093                         *(sp + 5) = (png_byte)(v & 0xff);
4094                      }
4095 
4096                      else if (a == 0)
4097                      {
4098                         /* Background is already in screen gamma */
4099                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
4100                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
4101                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
4102                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
4103                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
4104                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
4105                      }
4106 
4107                      else
4108                      {
4109                         png_uint_16 v, w;
4110 
4111                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
4112                         png_composite_16(w, v, a, png_ptr->background_1.red);
4113                         if (!optimize)
4114                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4115                         *sp = (png_byte)((w >> 8) & 0xff);
4116                         *(sp + 1) = (png_byte)(w & 0xff);
4117 
4118                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
4119                         png_composite_16(w, v, a, png_ptr->background_1.green);
4120                         if (!optimize)
4121                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4122 
4123                         *(sp + 2) = (png_byte)((w >> 8) & 0xff);
4124                         *(sp + 3) = (png_byte)(w & 0xff);
4125 
4126                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
4127                         png_composite_16(w, v, a, png_ptr->background_1.blue);
4128                         if (!optimize)
4129                            w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
4130 
4131                         *(sp + 4) = (png_byte)((w >> 8) & 0xff);
4132                         *(sp + 5) = (png_byte)(w & 0xff);
4133                      }
4134                   }
4135                }
4136 
4137                else
4138 #endif
4139                {
4140                   sp = row;
4141                   for (i = 0; i < row_width; i++, sp += 8)
4142                   {
4143                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
4144                          << 8) + (png_uint_16)(*(sp + 7)));
4145 
4146                      if (a == 0)
4147                      {
4148                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
4149                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
4150                         *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
4151                         *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
4152                         *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
4153                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
4154                      }
4155 
4156                      else if (a < 0xffff)
4157                      {
4158                         png_uint_16 v;
4159 
4160                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
4161                         png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
4162                             + *(sp + 3));
4163                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
4164                             + *(sp + 5));
4165 
4166                         png_composite_16(v, r, a, png_ptr->background.red);
4167                         *sp = (png_byte)((v >> 8) & 0xff);
4168                         *(sp + 1) = (png_byte)(v & 0xff);
4169 
4170                         png_composite_16(v, g, a, png_ptr->background.green);
4171                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
4172                         *(sp + 3) = (png_byte)(v & 0xff);
4173 
4174                         png_composite_16(v, b, a, png_ptr->background.blue);
4175                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
4176                         *(sp + 5) = (png_byte)(v & 0xff);
4177                      }
4178                   }
4179                }
4180             }
4181             break;
4182          }
4183 
4184          default:
4185             break;
4186       }
4187    }
4188 }
4189 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
4190 
4191 #ifdef PNG_READ_GAMMA_SUPPORTED
4192 /* Gamma correct the image, avoiding the alpha channel.  Make sure
4193  * you do this after you deal with the transparency issue on grayscale
4194  * or RGB images. If your bit depth is 8, use gamma_table, if it
4195  * is 16, use gamma_16_table and gamma_shift.  Build these with
4196  * build_gamma_table().
4197  */
4198 void /* PRIVATE */
png_do_gamma(png_row_infop row_info,png_bytep row,png_structp png_ptr)4199 png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
4200 {
4201    png_const_bytep gamma_table = png_ptr->gamma_table;
4202    png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
4203    int gamma_shift = png_ptr->gamma_shift;
4204 
4205    png_bytep sp;
4206    png_uint_32 i;
4207    png_uint_32 row_width=row_info->width;
4208 
4209    png_debug(1, "in png_do_gamma");
4210 
4211    if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
4212        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
4213    {
4214       switch (row_info->color_type)
4215       {
4216          case PNG_COLOR_TYPE_RGB:
4217          {
4218             if (row_info->bit_depth == 8)
4219             {
4220                sp = row;
4221                for (i = 0; i < row_width; i++)
4222                {
4223                   *sp = gamma_table[*sp];
4224                   sp++;
4225                   *sp = gamma_table[*sp];
4226                   sp++;
4227                   *sp = gamma_table[*sp];
4228                   sp++;
4229                }
4230             }
4231 
4232             else /* if (row_info->bit_depth == 16) */
4233             {
4234                sp = row;
4235                for (i = 0; i < row_width; i++)
4236                {
4237                   png_uint_16 v;
4238 
4239                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4240                   *sp = (png_byte)((v >> 8) & 0xff);
4241                   *(sp + 1) = (png_byte)(v & 0xff);
4242                   sp += 2;
4243 
4244                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4245                   *sp = (png_byte)((v >> 8) & 0xff);
4246                   *(sp + 1) = (png_byte)(v & 0xff);
4247                   sp += 2;
4248 
4249                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4250                   *sp = (png_byte)((v >> 8) & 0xff);
4251                   *(sp + 1) = (png_byte)(v & 0xff);
4252                   sp += 2;
4253                }
4254             }
4255             break;
4256          }
4257 
4258          case PNG_COLOR_TYPE_RGB_ALPHA:
4259          {
4260             if (row_info->bit_depth == 8)
4261             {
4262                sp = row;
4263                for (i = 0; i < row_width; i++)
4264                {
4265                   *sp = gamma_table[*sp];
4266                   sp++;
4267 
4268                   *sp = gamma_table[*sp];
4269                   sp++;
4270 
4271                   *sp = gamma_table[*sp];
4272                   sp++;
4273 
4274                   sp++;
4275                }
4276             }
4277 
4278             else /* if (row_info->bit_depth == 16) */
4279             {
4280                sp = row;
4281                for (i = 0; i < row_width; i++)
4282                {
4283                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4284                   *sp = (png_byte)((v >> 8) & 0xff);
4285                   *(sp + 1) = (png_byte)(v & 0xff);
4286                   sp += 2;
4287 
4288                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4289                   *sp = (png_byte)((v >> 8) & 0xff);
4290                   *(sp + 1) = (png_byte)(v & 0xff);
4291                   sp += 2;
4292 
4293                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4294                   *sp = (png_byte)((v >> 8) & 0xff);
4295                   *(sp + 1) = (png_byte)(v & 0xff);
4296                   sp += 4;
4297                }
4298             }
4299             break;
4300          }
4301 
4302          case PNG_COLOR_TYPE_GRAY_ALPHA:
4303          {
4304             if (row_info->bit_depth == 8)
4305             {
4306                sp = row;
4307                for (i = 0; i < row_width; i++)
4308                {
4309                   *sp = gamma_table[*sp];
4310                   sp += 2;
4311                }
4312             }
4313 
4314             else /* if (row_info->bit_depth == 16) */
4315             {
4316                sp = row;
4317                for (i = 0; i < row_width; i++)
4318                {
4319                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4320                   *sp = (png_byte)((v >> 8) & 0xff);
4321                   *(sp + 1) = (png_byte)(v & 0xff);
4322                   sp += 4;
4323                }
4324             }
4325             break;
4326          }
4327 
4328          case PNG_COLOR_TYPE_GRAY:
4329          {
4330             if (row_info->bit_depth == 2)
4331             {
4332                sp = row;
4333                for (i = 0; i < row_width; i += 4)
4334                {
4335                   int a = *sp & 0xc0;
4336                   int b = *sp & 0x30;
4337                   int c = *sp & 0x0c;
4338                   int d = *sp & 0x03;
4339 
4340                   *sp = (png_byte)(
4341                       ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
4342                       ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
4343                       ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
4344                       ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4345                   sp++;
4346                }
4347             }
4348 
4349             if (row_info->bit_depth == 4)
4350             {
4351                sp = row;
4352                for (i = 0; i < row_width; i += 2)
4353                {
4354                   int msb = *sp & 0xf0;
4355                   int lsb = *sp & 0x0f;
4356 
4357                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4358                       | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
4359                   sp++;
4360                }
4361             }
4362 
4363             else if (row_info->bit_depth == 8)
4364             {
4365                sp = row;
4366                for (i = 0; i < row_width; i++)
4367                {
4368                   *sp = gamma_table[*sp];
4369                   sp++;
4370                }
4371             }
4372 
4373             else if (row_info->bit_depth == 16)
4374             {
4375                sp = row;
4376                for (i = 0; i < row_width; i++)
4377                {
4378                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4379                   *sp = (png_byte)((v >> 8) & 0xff);
4380                   *(sp + 1) = (png_byte)(v & 0xff);
4381                   sp += 2;
4382                }
4383             }
4384             break;
4385          }
4386 
4387          default:
4388             break;
4389       }
4390    }
4391 }
4392 #endif
4393 
4394 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4395 /* Encode the alpha channel to the output gamma (the input channel is always
4396  * linear.)  Called only with color types that have an alpha channel.  Needs the
4397  * from_1 tables.
4398  */
4399 void /* PRIVATE */
png_do_encode_alpha(png_row_infop row_info,png_bytep row,png_structp png_ptr)4400 png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
4401 {
4402    png_uint_32 row_width = row_info->width;
4403 
4404    png_debug(1, "in png_do_encode_alpha");
4405 
4406    if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
4407    {
4408       if (row_info->bit_depth == 8)
4409       {
4410          PNG_CONST png_bytep table = png_ptr->gamma_from_1;
4411 
4412          if (table != NULL)
4413          {
4414             PNG_CONST int step =
4415                (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4416 
4417             /* The alpha channel is the last component: */
4418             row += step - 1;
4419 
4420             for (; row_width > 0; --row_width, row += step)
4421                *row = table[*row];
4422 
4423             return;
4424          }
4425       }
4426 
4427       else if (row_info->bit_depth == 16)
4428       {
4429          PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
4430          PNG_CONST int gamma_shift = png_ptr->gamma_shift;
4431 
4432          if (table != NULL)
4433          {
4434             PNG_CONST int step =
4435                (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4436 
4437             /* The alpha channel is the last component: */
4438             row += step - 2;
4439 
4440             for (; row_width > 0; --row_width, row += step)
4441             {
4442                png_uint_16 v;
4443 
4444                v = table[*(row + 1) >> gamma_shift][*row];
4445                *row = (png_byte)((v >> 8) & 0xff);
4446                *(row + 1) = (png_byte)(v & 0xff);
4447             }
4448 
4449             return;
4450          }
4451       }
4452    }
4453 
4454    /* Only get to here if called with a weird row_info; no harm has been done,
4455     * so just issue a warning.
4456     */
4457    png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4458 }
4459 #endif
4460 
4461 #ifdef PNG_READ_EXPAND_SUPPORTED
4462 /* Expands a palette row to an RGB or RGBA row depending
4463  * upon whether you supply trans and num_trans.
4464  */
4465 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)4466 png_do_expand_palette(png_row_infop row_info, png_bytep row,
4467    png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
4468 {
4469    int shift, value;
4470    png_bytep sp, dp;
4471    png_uint_32 i;
4472    png_uint_32 row_width=row_info->width;
4473 
4474    png_debug(1, "in png_do_expand_palette");
4475 
4476    if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4477    {
4478       if (row_info->bit_depth < 8)
4479       {
4480          switch (row_info->bit_depth)
4481          {
4482             case 1:
4483             {
4484                sp = row + (png_size_t)((row_width - 1) >> 3);
4485                dp = row + (png_size_t)row_width - 1;
4486                shift = 7 - (int)((row_width + 7) & 0x07);
4487                for (i = 0; i < row_width; i++)
4488                {
4489                   if ((*sp >> shift) & 0x01)
4490                      *dp = 1;
4491 
4492                   else
4493                      *dp = 0;
4494 
4495                   if (shift == 7)
4496                   {
4497                      shift = 0;
4498                      sp--;
4499                   }
4500 
4501                   else
4502                      shift++;
4503 
4504                   dp--;
4505                }
4506                break;
4507             }
4508 
4509             case 2:
4510             {
4511                sp = row + (png_size_t)((row_width - 1) >> 2);
4512                dp = row + (png_size_t)row_width - 1;
4513                shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4514                for (i = 0; i < row_width; i++)
4515                {
4516                   value = (*sp >> shift) & 0x03;
4517                   *dp = (png_byte)value;
4518                   if (shift == 6)
4519                   {
4520                      shift = 0;
4521                      sp--;
4522                   }
4523 
4524                   else
4525                      shift += 2;
4526 
4527                   dp--;
4528                }
4529                break;
4530             }
4531 
4532             case 4:
4533             {
4534                sp = row + (png_size_t)((row_width - 1) >> 1);
4535                dp = row + (png_size_t)row_width - 1;
4536                shift = (int)((row_width & 0x01) << 2);
4537                for (i = 0; i < row_width; i++)
4538                {
4539                   value = (*sp >> shift) & 0x0f;
4540                   *dp = (png_byte)value;
4541                   if (shift == 4)
4542                   {
4543                      shift = 0;
4544                      sp--;
4545                   }
4546 
4547                   else
4548                      shift += 4;
4549 
4550                   dp--;
4551                }
4552                break;
4553             }
4554 
4555             default:
4556                break;
4557          }
4558          row_info->bit_depth = 8;
4559          row_info->pixel_depth = 8;
4560          row_info->rowbytes = row_width;
4561       }
4562 
4563       if (row_info->bit_depth == 8)
4564       {
4565          {
4566             if (num_trans > 0)
4567             {
4568                sp = row + (png_size_t)row_width - 1;
4569                dp = row + (png_size_t)(row_width << 2) - 1;
4570 
4571                for (i = 0; i < row_width; i++)
4572                {
4573                   if ((int)(*sp) >= num_trans)
4574                      *dp-- = 0xff;
4575 
4576                   else
4577                      *dp-- = trans_alpha[*sp];
4578 
4579                   *dp-- = palette[*sp].blue;
4580                   *dp-- = palette[*sp].green;
4581                   *dp-- = palette[*sp].red;
4582                   sp--;
4583                }
4584                row_info->bit_depth = 8;
4585                row_info->pixel_depth = 32;
4586                row_info->rowbytes = row_width * 4;
4587                row_info->color_type = 6;
4588                row_info->channels = 4;
4589             }
4590 
4591             else
4592             {
4593                sp = row + (png_size_t)row_width - 1;
4594                dp = row + (png_size_t)(row_width * 3) - 1;
4595 
4596                for (i = 0; i < row_width; i++)
4597                {
4598                   *dp-- = palette[*sp].blue;
4599                   *dp-- = palette[*sp].green;
4600                   *dp-- = palette[*sp].red;
4601                   sp--;
4602                }
4603 
4604                row_info->bit_depth = 8;
4605                row_info->pixel_depth = 24;
4606                row_info->rowbytes = row_width * 3;
4607                row_info->color_type = 2;
4608                row_info->channels = 3;
4609             }
4610          }
4611       }
4612    }
4613 }
4614 
4615 /* If the bit depth < 8, it is expanded to 8.  Also, if the already
4616  * expanded transparency value is supplied, an alpha channel is built.
4617  */
4618 void /* PRIVATE */
png_do_expand(png_row_infop row_info,png_bytep row,png_const_color_16p trans_color)4619 png_do_expand(png_row_infop row_info, png_bytep row,
4620     png_const_color_16p trans_color)
4621 {
4622    int shift, value;
4623    png_bytep sp, dp;
4624    png_uint_32 i;
4625    png_uint_32 row_width=row_info->width;
4626 
4627    png_debug(1, "in png_do_expand");
4628 
4629    {
4630       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
4631       {
4632          png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
4633 
4634          if (row_info->bit_depth < 8)
4635          {
4636             switch (row_info->bit_depth)
4637             {
4638                case 1:
4639                {
4640                   gray = (png_uint_16)((gray & 0x01) * 0xff);
4641                   sp = row + (png_size_t)((row_width - 1) >> 3);
4642                   dp = row + (png_size_t)row_width - 1;
4643                   shift = 7 - (int)((row_width + 7) & 0x07);
4644                   for (i = 0; i < row_width; i++)
4645                   {
4646                      if ((*sp >> shift) & 0x01)
4647                         *dp = 0xff;
4648 
4649                      else
4650                         *dp = 0;
4651 
4652                      if (shift == 7)
4653                      {
4654                         shift = 0;
4655                         sp--;
4656                      }
4657 
4658                      else
4659                         shift++;
4660 
4661                      dp--;
4662                   }
4663                   break;
4664                }
4665 
4666                case 2:
4667                {
4668                   gray = (png_uint_16)((gray & 0x03) * 0x55);
4669                   sp = row + (png_size_t)((row_width - 1) >> 2);
4670                   dp = row + (png_size_t)row_width - 1;
4671                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4672                   for (i = 0; i < row_width; i++)
4673                   {
4674                      value = (*sp >> shift) & 0x03;
4675                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
4676                         (value << 6));
4677                      if (shift == 6)
4678                      {
4679                         shift = 0;
4680                         sp--;
4681                      }
4682 
4683                      else
4684                         shift += 2;
4685 
4686                      dp--;
4687                   }
4688                   break;
4689                }
4690 
4691                case 4:
4692                {
4693                   gray = (png_uint_16)((gray & 0x0f) * 0x11);
4694                   sp = row + (png_size_t)((row_width - 1) >> 1);
4695                   dp = row + (png_size_t)row_width - 1;
4696                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4697                   for (i = 0; i < row_width; i++)
4698                   {
4699                      value = (*sp >> shift) & 0x0f;
4700                      *dp = (png_byte)(value | (value << 4));
4701                      if (shift == 4)
4702                      {
4703                         shift = 0;
4704                         sp--;
4705                      }
4706 
4707                      else
4708                         shift = 4;
4709 
4710                      dp--;
4711                   }
4712                   break;
4713                }
4714 
4715                default:
4716                   break;
4717             }
4718 
4719             row_info->bit_depth = 8;
4720             row_info->pixel_depth = 8;
4721             row_info->rowbytes = row_width;
4722          }
4723 
4724          if (trans_color != NULL)
4725          {
4726             if (row_info->bit_depth == 8)
4727             {
4728                gray = gray & 0xff;
4729                sp = row + (png_size_t)row_width - 1;
4730                dp = row + (png_size_t)(row_width << 1) - 1;
4731 
4732                for (i = 0; i < row_width; i++)
4733                {
4734                   if (*sp == gray)
4735                      *dp-- = 0;
4736 
4737                   else
4738                      *dp-- = 0xff;
4739 
4740                   *dp-- = *sp--;
4741                }
4742             }
4743 
4744             else if (row_info->bit_depth == 16)
4745             {
4746                png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
4747                png_byte gray_low = (png_byte)(gray & 0xff);
4748                sp = row + row_info->rowbytes - 1;
4749                dp = row + (row_info->rowbytes << 1) - 1;
4750                for (i = 0; i < row_width; i++)
4751                {
4752                   if (*(sp - 1) == gray_high && *(sp) == gray_low)
4753                   {
4754                      *dp-- = 0;
4755                      *dp-- = 0;
4756                   }
4757 
4758                   else
4759                   {
4760                      *dp-- = 0xff;
4761                      *dp-- = 0xff;
4762                   }
4763 
4764                   *dp-- = *sp--;
4765                   *dp-- = *sp--;
4766                }
4767             }
4768 
4769             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
4770             row_info->channels = 2;
4771             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4772             row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
4773                row_width);
4774          }
4775       }
4776       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
4777       {
4778          if (row_info->bit_depth == 8)
4779          {
4780             png_byte red = (png_byte)(trans_color->red & 0xff);
4781             png_byte green = (png_byte)(trans_color->green & 0xff);
4782             png_byte blue = (png_byte)(trans_color->blue & 0xff);
4783             sp = row + (png_size_t)row_info->rowbytes - 1;
4784             dp = row + (png_size_t)(row_width << 2) - 1;
4785             for (i = 0; i < row_width; i++)
4786             {
4787                if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
4788                   *dp-- = 0;
4789 
4790                else
4791                   *dp-- = 0xff;
4792 
4793                *dp-- = *sp--;
4794                *dp-- = *sp--;
4795                *dp-- = *sp--;
4796             }
4797          }
4798          else if (row_info->bit_depth == 16)
4799          {
4800             png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
4801             png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
4802             png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
4803             png_byte red_low = (png_byte)(trans_color->red & 0xff);
4804             png_byte green_low = (png_byte)(trans_color->green & 0xff);
4805             png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
4806             sp = row + row_info->rowbytes - 1;
4807             dp = row + (png_size_t)(row_width << 3) - 1;
4808             for (i = 0; i < row_width; i++)
4809             {
4810                if (*(sp - 5) == red_high &&
4811                    *(sp - 4) == red_low &&
4812                    *(sp - 3) == green_high &&
4813                    *(sp - 2) == green_low &&
4814                    *(sp - 1) == blue_high &&
4815                    *(sp    ) == blue_low)
4816                {
4817                   *dp-- = 0;
4818                   *dp-- = 0;
4819                }
4820 
4821                else
4822                {
4823                   *dp-- = 0xff;
4824                   *dp-- = 0xff;
4825                }
4826 
4827                *dp-- = *sp--;
4828                *dp-- = *sp--;
4829                *dp-- = *sp--;
4830                *dp-- = *sp--;
4831                *dp-- = *sp--;
4832                *dp-- = *sp--;
4833             }
4834          }
4835          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
4836          row_info->channels = 4;
4837          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4838          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4839       }
4840    }
4841 }
4842 #endif
4843 
4844 #ifdef PNG_READ_EXPAND_16_SUPPORTED
4845 /* If the bit depth is 8 and the color type is not a palette type expand the
4846  * whole row to 16 bits.  Has no effect otherwise.
4847  */
4848 void /* PRIVATE */
png_do_expand_16(png_row_infop row_info,png_bytep row)4849 png_do_expand_16(png_row_infop row_info, png_bytep row)
4850 {
4851    if (row_info->bit_depth == 8 &&
4852       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
4853    {
4854       /* The row have a sequence of bytes containing [0..255] and we need
4855        * to turn it into another row containing [0..65535], to do this we
4856        * calculate:
4857        *
4858        *  (input / 255) * 65535
4859        *
4860        *  Which happens to be exactly input * 257 and this can be achieved
4861        *  simply by byte replication in place (copying backwards).
4862        */
4863       png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
4864       png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
4865       while (dp > sp)
4866          dp[-2] = dp[-1] = *--sp, dp -= 2;
4867 
4868       row_info->rowbytes *= 2;
4869       row_info->bit_depth = 16;
4870       row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4871    }
4872 }
4873 #endif
4874 
4875 #ifdef PNG_READ_QUANTIZE_SUPPORTED
4876 void /* PRIVATE */
png_do_quantize(png_row_infop row_info,png_bytep row,png_const_bytep palette_lookup,png_const_bytep quantize_lookup)4877 png_do_quantize(png_row_infop row_info, png_bytep row,
4878     png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
4879 {
4880    png_bytep sp, dp;
4881    png_uint_32 i;
4882    png_uint_32 row_width=row_info->width;
4883 
4884    png_debug(1, "in png_do_quantize");
4885 
4886    if (row_info->bit_depth == 8)
4887    {
4888       if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
4889       {
4890          int r, g, b, p;
4891          sp = row;
4892          dp = row;
4893          for (i = 0; i < row_width; i++)
4894          {
4895             r = *sp++;
4896             g = *sp++;
4897             b = *sp++;
4898 
4899             /* This looks real messy, but the compiler will reduce
4900              * it down to a reasonable formula.  For example, with
4901              * 5 bits per color, we get:
4902              * p = (((r >> 3) & 0x1f) << 10) |
4903              *    (((g >> 3) & 0x1f) << 5) |
4904              *    ((b >> 3) & 0x1f);
4905              */
4906             p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4907                 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4908                 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4909                 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4910                 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4911                 (PNG_QUANTIZE_BLUE_BITS)) |
4912                 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4913                 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4914 
4915             *dp++ = palette_lookup[p];
4916          }
4917 
4918          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4919          row_info->channels = 1;
4920          row_info->pixel_depth = row_info->bit_depth;
4921          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4922       }
4923 
4924       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4925          palette_lookup != NULL)
4926       {
4927          int r, g, b, p;
4928          sp = row;
4929          dp = row;
4930          for (i = 0; i < row_width; i++)
4931          {
4932             r = *sp++;
4933             g = *sp++;
4934             b = *sp++;
4935             sp++;
4936 
4937             p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4938                 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4939                 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4940                 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4941                 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4942                 (PNG_QUANTIZE_BLUE_BITS)) |
4943                 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4944                 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4945 
4946             *dp++ = palette_lookup[p];
4947          }
4948 
4949          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4950          row_info->channels = 1;
4951          row_info->pixel_depth = row_info->bit_depth;
4952          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4953       }
4954 
4955       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4956          quantize_lookup)
4957       {
4958          sp = row;
4959 
4960          for (i = 0; i < row_width; i++, sp++)
4961          {
4962             *sp = quantize_lookup[*sp];
4963          }
4964       }
4965    }
4966 }
4967 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
4968 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
4969 
4970 #ifdef PNG_MNG_FEATURES_SUPPORTED
4971 /* Undoes intrapixel differencing  */
4972 void /* PRIVATE */
png_do_read_intrapixel(png_row_infop row_info,png_bytep row)4973 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4974 {
4975    png_debug(1, "in png_do_read_intrapixel");
4976 
4977    if (
4978        (row_info->color_type & PNG_COLOR_MASK_COLOR))
4979    {
4980       int bytes_per_pixel;
4981       png_uint_32 row_width = row_info->width;
4982 
4983       if (row_info->bit_depth == 8)
4984       {
4985          png_bytep rp;
4986          png_uint_32 i;
4987 
4988          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4989             bytes_per_pixel = 3;
4990 
4991          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4992             bytes_per_pixel = 4;
4993 
4994          else
4995             return;
4996 
4997          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4998          {
4999             *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
5000             *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
5001          }
5002       }
5003       else if (row_info->bit_depth == 16)
5004       {
5005          png_bytep rp;
5006          png_uint_32 i;
5007 
5008          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
5009             bytes_per_pixel = 6;
5010 
5011          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
5012             bytes_per_pixel = 8;
5013 
5014          else
5015             return;
5016 
5017          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
5018          {
5019             png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
5020             png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
5021             png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
5022             png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
5023             png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
5024             *(rp    ) = (png_byte)((red >> 8) & 0xff);
5025             *(rp + 1) = (png_byte)(red & 0xff);
5026             *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
5027             *(rp + 5) = (png_byte)(blue & 0xff);
5028          }
5029       }
5030    }
5031 }
5032 #endif /* PNG_MNG_FEATURES_SUPPORTED */
5033 #endif /* PNG_READ_SUPPORTED */
5034