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