Cleanup: Get this rid of "this->" in fpdfsdk/
[pdfium.git] / samples / fx_lpng / lpng_v163 / fx_pngrtran.c
1 /* pngrtran.c - transforms the data in a row for PNG readers\r
2  *\r
3  * Last changed in libpng 1.6.2 [April 25, 2013]\r
4  * Copyright (c) 1998-2013 Glenn Randers-Pehrson\r
5  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)\r
6  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)\r
7  *\r
8  * This code is released under the libpng license.\r
9  * For conditions of distribution and use, see the disclaimer\r
10  * and license in png.h\r
11  *\r
12  * This file contains functions optionally called by an application\r
13  * in order to tell libpng how to handle data when reading a PNG.\r
14  * Transformations that are used in both reading and writing are\r
15  * in pngtrans.c.\r
16  */\r
17 \r
18 #include "pngpriv.h"\r
19 \r
20 #ifdef PNG_READ_SUPPORTED\r
21 \r
22 /* Set the action on getting a CRC error for an ancillary or critical chunk. */\r
23 void PNGAPI\r
24 png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)\r
25 {\r
26    png_debug(1, "in png_set_crc_action");\r
27 \r
28    if (png_ptr == NULL)\r
29       return;\r
30 \r
31    /* Tell libpng how we react to CRC errors in critical chunks */\r
32    switch (crit_action)\r
33    {\r
34       case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */\r
35          break;\r
36 \r
37       case PNG_CRC_WARN_USE:                               /* Warn/use data */\r
38          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;\r
39          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;\r
40          break;\r
41 \r
42       case PNG_CRC_QUIET_USE:                             /* Quiet/use data */\r
43          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;\r
44          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |\r
45                            PNG_FLAG_CRC_CRITICAL_IGNORE;\r
46          break;\r
47 \r
48       case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */\r
49          png_warning(png_ptr,\r
50             "Can't discard critical data on CRC error");\r
51       case PNG_CRC_ERROR_QUIT:                                /* Error/quit */\r
52 \r
53       case PNG_CRC_DEFAULT:\r
54       default:\r
55          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;\r
56          break;\r
57    }\r
58 \r
59    /* Tell libpng how we react to CRC errors in ancillary chunks */\r
60    switch (ancil_action)\r
61    {\r
62       case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */\r
63          break;\r
64 \r
65       case PNG_CRC_WARN_USE:                              /* Warn/use data */\r
66          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;\r
67          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;\r
68          break;\r
69 \r
70       case PNG_CRC_QUIET_USE:                            /* Quiet/use data */\r
71          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;\r
72          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |\r
73                            PNG_FLAG_CRC_ANCILLARY_NOWARN;\r
74          break;\r
75 \r
76       case PNG_CRC_ERROR_QUIT:                               /* Error/quit */\r
77          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;\r
78          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;\r
79          break;\r
80 \r
81       case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */\r
82 \r
83       case PNG_CRC_DEFAULT:\r
84       default:\r
85          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;\r
86          break;\r
87    }\r
88 }\r
89 \r
90 #ifdef PNG_READ_TRANSFORMS_SUPPORTED\r
91 /* Is it OK to set a transformation now?  Only if png_start_read_image or\r
92  * png_read_update_info have not been called.  It is not necessary for the IHDR\r
93  * to have been read in all cases, the parameter allows for this check too.\r
94  */\r
95 static int\r
96 png_rtran_ok(png_structrp png_ptr, int need_IHDR)\r
97 {\r
98    if (png_ptr != NULL)\r
99    {\r
100       if (png_ptr->flags & PNG_FLAG_ROW_INIT)\r
101          png_app_error(png_ptr,\r
102             "invalid after png_start_read_image or png_read_update_info");\r
103 \r
104       else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)\r
105          png_app_error(png_ptr, "invalid before the PNG header has been read");\r
106 \r
107       else\r
108       {\r
109          /* Turn on failure to initialize correctly for all transforms. */\r
110          png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;\r
111 \r
112          return 1; /* Ok */\r
113       }\r
114    }\r
115 \r
116    return 0; /* no png_error possible! */\r
117 }\r
118 #endif\r
119 \r
120 #ifdef PNG_READ_BACKGROUND_SUPPORTED\r
121 /* Handle alpha and tRNS via a background color */\r
122 void PNGFAPI\r
123 png_set_background_fixed(png_structrp png_ptr,\r
124     png_const_color_16p background_color, int background_gamma_code,\r
125     int need_expand, png_fixed_point background_gamma)\r
126 {\r
127    png_debug(1, "in png_set_background_fixed");\r
128 \r
129    if (!png_rtran_ok(png_ptr, 0) || background_color == NULL)\r
130       return;\r
131 \r
132    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)\r
133    {\r
134       png_warning(png_ptr, "Application must supply a known background gamma");\r
135       return;\r
136    }\r
137 \r
138    png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;\r
139    png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
140    png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
141 \r
142    png_ptr->background = *background_color;\r
143    png_ptr->background_gamma = background_gamma;\r
144    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);\r
145    if (need_expand)\r
146       png_ptr->transformations |= PNG_BACKGROUND_EXPAND;\r
147    else\r
148       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;\r
149 }\r
150 \r
151 #  ifdef PNG_FLOATING_POINT_SUPPORTED\r
152 void PNGAPI\r
153 png_set_background(png_structrp png_ptr,\r
154     png_const_color_16p background_color, int background_gamma_code,\r
155     int need_expand, double background_gamma)\r
156 {\r
157    png_set_background_fixed(png_ptr, background_color, background_gamma_code,\r
158       need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));\r
159 }\r
160 #  endif  /* FLOATING_POINT */\r
161 #endif /* READ_BACKGROUND */\r
162 \r
163 /* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the\r
164  * one that pngrtran does first (scale) happens.  This is necessary to allow the\r
165  * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.\r
166  */\r
167 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED\r
168 void PNGAPI\r
169 png_set_scale_16(png_structrp png_ptr)\r
170 {\r
171    png_debug(1, "in png_set_scale_16");\r
172 \r
173    if (!png_rtran_ok(png_ptr, 0))\r
174       return;\r
175 \r
176    png_ptr->transformations |= PNG_SCALE_16_TO_8;\r
177 }\r
178 #endif\r
179 \r
180 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED\r
181 /* Chop 16-bit depth files to 8-bit depth */\r
182 void PNGAPI\r
183 png_set_strip_16(png_structrp png_ptr)\r
184 {\r
185    png_debug(1, "in png_set_strip_16");\r
186 \r
187    if (!png_rtran_ok(png_ptr, 0))\r
188       return;\r
189 \r
190    png_ptr->transformations |= PNG_16_TO_8;\r
191 }\r
192 #endif\r
193 \r
194 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED\r
195 void PNGAPI\r
196 png_set_strip_alpha(png_structrp png_ptr)\r
197 {\r
198    png_debug(1, "in png_set_strip_alpha");\r
199 \r
200    if (!png_rtran_ok(png_ptr, 0))\r
201       return;\r
202 \r
203    png_ptr->transformations |= PNG_STRIP_ALPHA;\r
204 }\r
205 #endif\r
206 \r
207 #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)\r
208 static png_fixed_point\r
209 translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,\r
210    int is_screen)\r
211 {\r
212    /* Check for flag values.  The main reason for having the old Mac value as a\r
213     * flag is that it is pretty near impossible to work out what the correct\r
214     * value is from Apple documentation - a working Mac system is needed to\r
215     * discover the value!\r
216     */\r
217    if (output_gamma == PNG_DEFAULT_sRGB ||\r
218       output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)\r
219    {\r
220       /* If there is no sRGB support this just sets the gamma to the standard\r
221        * sRGB value.  (This is a side effect of using this function!)\r
222        */\r
223 #     ifdef PNG_READ_sRGB_SUPPORTED\r
224          png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;\r
225 #     else\r
226          PNG_UNUSED(png_ptr)\r
227 #     endif\r
228       if (is_screen)\r
229          output_gamma = PNG_GAMMA_sRGB;\r
230       else\r
231          output_gamma = PNG_GAMMA_sRGB_INVERSE;\r
232    }\r
233 \r
234    else if (output_gamma == PNG_GAMMA_MAC_18 ||\r
235       output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)\r
236    {\r
237       if (is_screen)\r
238          output_gamma = PNG_GAMMA_MAC_OLD;\r
239       else\r
240          output_gamma = PNG_GAMMA_MAC_INVERSE;\r
241    }\r
242 \r
243    return output_gamma;\r
244 }\r
245 \r
246 #  ifdef PNG_FLOATING_POINT_SUPPORTED\r
247 static png_fixed_point\r
248 convert_gamma_value(png_structrp png_ptr, double output_gamma)\r
249 {\r
250    /* The following silently ignores cases where fixed point (times 100,000)\r
251     * gamma values are passed to the floating point API.  This is safe and it\r
252     * means the fixed point constants work just fine with the floating point\r
253     * API.  The alternative would just lead to undetected errors and spurious\r
254     * bug reports.  Negative values fail inside the _fixed API unless they\r
255     * correspond to the flag values.\r
256     */\r
257    if (output_gamma > 0 && output_gamma < 128)\r
258       output_gamma *= PNG_FP_1;\r
259 \r
260    /* This preserves -1 and -2 exactly: */\r
261    output_gamma = floor(output_gamma + .5);\r
262 \r
263    if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)\r
264       png_fixed_error(png_ptr, "gamma value");\r
265 \r
266    return (png_fixed_point)output_gamma;\r
267 }\r
268 #  endif\r
269 #endif /* READ_ALPHA_MODE || READ_GAMMA */\r
270 \r
271 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED\r
272 void PNGFAPI\r
273 png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,\r
274    png_fixed_point output_gamma)\r
275 {\r
276    int compose = 0;\r
277    png_fixed_point file_gamma;\r
278 \r
279    png_debug(1, "in png_set_alpha_mode");\r
280 \r
281    if (!png_rtran_ok(png_ptr, 0))\r
282       return;\r
283 \r
284    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);\r
285 \r
286    /* Validate the value to ensure it is in a reasonable range. The value\r
287     * is expected to be 1 or greater, but this range test allows for some\r
288     * viewing correction values.  The intent is to weed out users of this API\r
289     * who use the inverse of the gamma value accidentally!  Since some of these\r
290     * values are reasonable this may have to be changed.\r
291     */\r
292    if (output_gamma < 70000 || output_gamma > 300000)\r
293       png_error(png_ptr, "output gamma out of expected range");\r
294 \r
295    /* The default file gamma is the inverse of the output gamma; the output\r
296     * gamma may be changed below so get the file value first:\r
297     */\r
298    file_gamma = png_reciprocal(output_gamma);\r
299 \r
300    /* There are really 8 possibilities here, composed of any combination\r
301     * of:\r
302     *\r
303     *    premultiply the color channels\r
304     *    do not encode non-opaque pixels\r
305     *    encode the alpha as well as the color channels\r
306     *\r
307     * The differences disappear if the input/output ('screen') gamma is 1.0,\r
308     * because then the encoding is a no-op and there is only the choice of\r
309     * premultiplying the color channels or not.\r
310     *\r
311     * png_set_alpha_mode and png_set_background interact because both use\r
312     * png_compose to do the work.  Calling both is only useful when\r
313     * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along\r
314     * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.\r
315     */\r
316    switch (mode)\r
317    {\r
318       case PNG_ALPHA_PNG:        /* default: png standard */\r
319          /* No compose, but it may be set by png_set_background! */\r
320          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
321          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
322          break;\r
323 \r
324       case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */\r
325          compose = 1;\r
326          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
327          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
328          /* The output is linear: */\r
329          output_gamma = PNG_FP_1;\r
330          break;\r
331 \r
332       case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */\r
333          compose = 1;\r
334          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
335          png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;\r
336          /* output_gamma records the encoding of opaque pixels! */\r
337          break;\r
338 \r
339       case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */\r
340          compose = 1;\r
341          png_ptr->transformations |= PNG_ENCODE_ALPHA;\r
342          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
343          break;\r
344 \r
345       default:\r
346          png_error(png_ptr, "invalid alpha mode");\r
347    }\r
348 \r
349    /* Only set the default gamma if the file gamma has not been set (this has\r
350     * the side effect that the gamma in a second call to png_set_alpha_mode will\r
351     * be ignored.)\r
352     */\r
353    if (png_ptr->colorspace.gamma == 0)\r
354    {\r
355       png_ptr->colorspace.gamma = file_gamma;\r
356       png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;\r
357    }\r
358 \r
359    /* But always set the output gamma: */\r
360    png_ptr->screen_gamma = output_gamma;\r
361 \r
362    /* Finally, if pre-multiplying, set the background fields to achieve the\r
363     * desired result.\r
364     */\r
365    if (compose)\r
366    {\r
367       /* And obtain alpha pre-multiplication by composing on black: */\r
368       memset(&png_ptr->background, 0, (sizeof png_ptr->background));\r
369       png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */\r
370       png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;\r
371       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;\r
372 \r
373       if (png_ptr->transformations & PNG_COMPOSE)\r
374          png_error(png_ptr,\r
375             "conflicting calls to set alpha mode and background");\r
376 \r
377       png_ptr->transformations |= PNG_COMPOSE;\r
378    }\r
379 }\r
380 \r
381 #  ifdef PNG_FLOATING_POINT_SUPPORTED\r
382 void PNGAPI\r
383 png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)\r
384 {\r
385    png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,\r
386       output_gamma));\r
387 }\r
388 #  endif\r
389 #endif\r
390 \r
391 #ifdef PNG_READ_QUANTIZE_SUPPORTED\r
392 /* Dither file to 8-bit.  Supply a palette, the current number\r
393  * of elements in the palette, the maximum number of elements\r
394  * allowed, and a histogram if possible.  If the current number\r
395  * of colors is greater then the maximum number, the palette will be\r
396  * modified to fit in the maximum number.  "full_quantize" indicates\r
397  * whether we need a quantizing cube set up for RGB images, or if we\r
398  * simply are reducing the number of colors in a paletted image.\r
399  */\r
400 \r
401 typedef struct png_dsort_struct\r
402 {\r
403    struct png_dsort_struct * next;\r
404    png_byte left;\r
405    png_byte right;\r
406 } png_dsort;\r
407 typedef png_dsort *   png_dsortp;\r
408 typedef png_dsort * * png_dsortpp;\r
409 \r
410 void PNGAPI\r
411 png_set_quantize(png_structrp png_ptr, png_colorp palette,\r
412     int num_palette, int maximum_colors, png_const_uint_16p histogram,\r
413     int full_quantize)\r
414 {\r
415    png_debug(1, "in png_set_quantize");\r
416 \r
417    if (!png_rtran_ok(png_ptr, 0))\r
418       return;\r
419 \r
420    png_ptr->transformations |= PNG_QUANTIZE;\r
421 \r
422    if (!full_quantize)\r
423    {\r
424       int i;\r
425 \r
426       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,\r
427           (png_uint_32)(num_palette * (sizeof (png_byte))));\r
428       for (i = 0; i < num_palette; i++)\r
429          png_ptr->quantize_index[i] = (png_byte)i;\r
430    }\r
431 \r
432    if (num_palette > maximum_colors)\r
433    {\r
434       if (histogram != NULL)\r
435       {\r
436          /* This is easy enough, just throw out the least used colors.\r
437           * Perhaps not the best solution, but good enough.\r
438           */\r
439 \r
440          int i;\r
441 \r
442          /* Initialize an array to sort colors */\r
443          png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,\r
444              (png_uint_32)(num_palette * (sizeof (png_byte))));\r
445 \r
446          /* Initialize the quantize_sort array */\r
447          for (i = 0; i < num_palette; i++)\r
448             png_ptr->quantize_sort[i] = (png_byte)i;\r
449 \r
450          /* Find the least used palette entries by starting a\r
451           * bubble sort, and running it until we have sorted\r
452           * out enough colors.  Note that we don't care about\r
453           * sorting all the colors, just finding which are\r
454           * least used.\r
455           */\r
456 \r
457          for (i = num_palette - 1; i >= maximum_colors; i--)\r
458          {\r
459             int done; /* To stop early if the list is pre-sorted */\r
460             int j;\r
461 \r
462             done = 1;\r
463             for (j = 0; j < i; j++)\r
464             {\r
465                if (histogram[png_ptr->quantize_sort[j]]\r
466                    < histogram[png_ptr->quantize_sort[j + 1]])\r
467                {\r
468                   png_byte t;\r
469 \r
470                   t = png_ptr->quantize_sort[j];\r
471                   png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];\r
472                   png_ptr->quantize_sort[j + 1] = t;\r
473                   done = 0;\r
474                }\r
475             }\r
476 \r
477             if (done)\r
478                break;\r
479          }\r
480 \r
481          /* Swap the palette around, and set up a table, if necessary */\r
482          if (full_quantize)\r
483          {\r
484             int j = num_palette;\r
485 \r
486             /* Put all the useful colors within the max, but don't\r
487              * move the others.\r
488              */\r
489             for (i = 0; i < maximum_colors; i++)\r
490             {\r
491                if ((int)png_ptr->quantize_sort[i] >= maximum_colors)\r
492                {\r
493                   do\r
494                      j--;\r
495                   while ((int)png_ptr->quantize_sort[j] >= maximum_colors);\r
496 \r
497                   palette[i] = palette[j];\r
498                }\r
499             }\r
500          }\r
501          else\r
502          {\r
503             int j = num_palette;\r
504 \r
505             /* Move all the used colors inside the max limit, and\r
506              * develop a translation table.\r
507              */\r
508             for (i = 0; i < maximum_colors; i++)\r
509             {\r
510                /* Only move the colors we need to */\r
511                if ((int)png_ptr->quantize_sort[i] >= maximum_colors)\r
512                {\r
513                   png_color tmp_color;\r
514 \r
515                   do\r
516                      j--;\r
517                   while ((int)png_ptr->quantize_sort[j] >= maximum_colors);\r
518 \r
519                   tmp_color = palette[j];\r
520                   palette[j] = palette[i];\r
521                   palette[i] = tmp_color;\r
522                   /* Indicate where the color went */\r
523                   png_ptr->quantize_index[j] = (png_byte)i;\r
524                   png_ptr->quantize_index[i] = (png_byte)j;\r
525                }\r
526             }\r
527 \r
528             /* Find closest color for those colors we are not using */\r
529             for (i = 0; i < num_palette; i++)\r
530             {\r
531                if ((int)png_ptr->quantize_index[i] >= maximum_colors)\r
532                {\r
533                   int min_d, k, min_k, d_index;\r
534 \r
535                   /* Find the closest color to one we threw out */\r
536                   d_index = png_ptr->quantize_index[i];\r
537                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);\r
538                   for (k = 1, min_k = 0; k < maximum_colors; k++)\r
539                   {\r
540                      int d;\r
541 \r
542                      d = PNG_COLOR_DIST(palette[d_index], palette[k]);\r
543 \r
544                      if (d < min_d)\r
545                      {\r
546                         min_d = d;\r
547                         min_k = k;\r
548                      }\r
549                   }\r
550                   /* Point to closest color */\r
551                   png_ptr->quantize_index[i] = (png_byte)min_k;\r
552                }\r
553             }\r
554          }\r
555          png_free(png_ptr, png_ptr->quantize_sort);\r
556          png_ptr->quantize_sort = NULL;\r
557       }\r
558       else\r
559       {\r
560          /* This is much harder to do simply (and quickly).  Perhaps\r
561           * we need to go through a median cut routine, but those\r
562           * don't always behave themselves with only a few colors\r
563           * as input.  So we will just find the closest two colors,\r
564           * and throw out one of them (chosen somewhat randomly).\r
565           * [We don't understand this at all, so if someone wants to\r
566           *  work on improving it, be our guest - AED, GRP]\r
567           */\r
568          int i;\r
569          int max_d;\r
570          int num_new_palette;\r
571          png_dsortp t;\r
572          png_dsortpp hash;\r
573 \r
574          t = NULL;\r
575 \r
576          /* Initialize palette index arrays */\r
577          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,\r
578              (png_uint_32)(num_palette * (sizeof (png_byte))));\r
579          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,\r
580              (png_uint_32)(num_palette * (sizeof (png_byte))));\r
581 \r
582          /* Initialize the sort array */\r
583          for (i = 0; i < num_palette; i++)\r
584          {\r
585             png_ptr->index_to_palette[i] = (png_byte)i;\r
586             png_ptr->palette_to_index[i] = (png_byte)i;\r
587          }\r
588 \r
589          hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *\r
590              (sizeof (png_dsortp))));\r
591 \r
592          num_new_palette = num_palette;\r
593 \r
594          /* Initial wild guess at how far apart the farthest pixel\r
595           * pair we will be eliminating will be.  Larger\r
596           * numbers mean more areas will be allocated, Smaller\r
597           * numbers run the risk of not saving enough data, and\r
598           * having to do this all over again.\r
599           *\r
600           * I have not done extensive checking on this number.\r
601           */\r
602          max_d = 96;\r
603 \r
604          while (num_new_palette > maximum_colors)\r
605          {\r
606             for (i = 0; i < num_new_palette - 1; i++)\r
607             {\r
608                int j;\r
609 \r
610                for (j = i + 1; j < num_new_palette; j++)\r
611                {\r
612                   int d;\r
613 \r
614                   d = PNG_COLOR_DIST(palette[i], palette[j]);\r
615 \r
616                   if (d <= max_d)\r
617                   {\r
618 \r
619                      t = (png_dsortp)png_malloc_warn(png_ptr,\r
620                          (png_uint_32)(sizeof (png_dsort)));\r
621 \r
622                      if (t == NULL)\r
623                          break;\r
624 \r
625                      t->next = hash[d];\r
626                      t->left = (png_byte)i;\r
627                      t->right = (png_byte)j;\r
628                      hash[d] = t;\r
629                   }\r
630                }\r
631                if (t == NULL)\r
632                   break;\r
633             }\r
634 \r
635             if (t != NULL)\r
636             for (i = 0; i <= max_d; i++)\r
637             {\r
638                if (hash[i] != NULL)\r
639                {\r
640                   png_dsortp p;\r
641 \r
642                   for (p = hash[i]; p; p = p->next)\r
643                   {\r
644                      if ((int)png_ptr->index_to_palette[p->left]\r
645                          < num_new_palette &&\r
646                          (int)png_ptr->index_to_palette[p->right]\r
647                          < num_new_palette)\r
648                      {\r
649                         int j, next_j;\r
650 \r
651                         if (num_new_palette & 0x01)\r
652                         {\r
653                            j = p->left;\r
654                            next_j = p->right;\r
655                         }\r
656                         else\r
657                         {\r
658                            j = p->right;\r
659                            next_j = p->left;\r
660                         }\r
661 \r
662                         num_new_palette--;\r
663                         palette[png_ptr->index_to_palette[j]]\r
664                             = palette[num_new_palette];\r
665                         if (!full_quantize)\r
666                         {\r
667                            int k;\r
668 \r
669                            for (k = 0; k < num_palette; k++)\r
670                            {\r
671                               if (png_ptr->quantize_index[k] ==\r
672                                   png_ptr->index_to_palette[j])\r
673                                  png_ptr->quantize_index[k] =\r
674                                      png_ptr->index_to_palette[next_j];\r
675 \r
676                               if ((int)png_ptr->quantize_index[k] ==\r
677                                   num_new_palette)\r
678                                  png_ptr->quantize_index[k] =\r
679                                      png_ptr->index_to_palette[j];\r
680                            }\r
681                         }\r
682 \r
683                         png_ptr->index_to_palette[png_ptr->palette_to_index\r
684                             [num_new_palette]] = png_ptr->index_to_palette[j];\r
685 \r
686                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]\r
687                             = png_ptr->palette_to_index[num_new_palette];\r
688 \r
689                         png_ptr->index_to_palette[j] =\r
690                             (png_byte)num_new_palette;\r
691 \r
692                         png_ptr->palette_to_index[num_new_palette] =\r
693                             (png_byte)j;\r
694                      }\r
695                      if (num_new_palette <= maximum_colors)\r
696                         break;\r
697                   }\r
698                   if (num_new_palette <= maximum_colors)\r
699                      break;\r
700                }\r
701             }\r
702 \r
703             for (i = 0; i < 769; i++)\r
704             {\r
705                if (hash[i] != NULL)\r
706                {\r
707                   png_dsortp p = hash[i];\r
708                   while (p)\r
709                   {\r
710                      t = p->next;\r
711                      png_free(png_ptr, p);\r
712                      p = t;\r
713                   }\r
714                }\r
715                hash[i] = 0;\r
716             }\r
717             max_d += 96;\r
718          }\r
719          png_free(png_ptr, hash);\r
720          png_free(png_ptr, png_ptr->palette_to_index);\r
721          png_free(png_ptr, png_ptr->index_to_palette);\r
722          png_ptr->palette_to_index = NULL;\r
723          png_ptr->index_to_palette = NULL;\r
724       }\r
725       num_palette = maximum_colors;\r
726    }\r
727    if (png_ptr->palette == NULL)\r
728    {\r
729       png_ptr->palette = palette;\r
730    }\r
731    png_ptr->num_palette = (png_uint_16)num_palette;\r
732 \r
733    if (full_quantize)\r
734    {\r
735       int i;\r
736       png_bytep distance;\r
737       int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +\r
738           PNG_QUANTIZE_BLUE_BITS;\r
739       int num_red = (1 << PNG_QUANTIZE_RED_BITS);\r
740       int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);\r
741       int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);\r
742       png_size_t num_entries = ((png_size_t)1 << total_bits);\r
743 \r
744       png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,\r
745           (png_uint_32)(num_entries * (sizeof (png_byte))));\r
746 \r
747       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *\r
748           (sizeof (png_byte))));\r
749 \r
750       memset(distance, 0xff, num_entries * (sizeof (png_byte)));\r
751 \r
752       for (i = 0; i < num_palette; i++)\r
753       {\r
754          int ir, ig, ib;\r
755          int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));\r
756          int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));\r
757          int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));\r
758 \r
759          for (ir = 0; ir < num_red; ir++)\r
760          {\r
761             /* int dr = abs(ir - r); */\r
762             int dr = ((ir > r) ? ir - r : r - ir);\r
763             int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +\r
764                 PNG_QUANTIZE_GREEN_BITS));\r
765 \r
766             for (ig = 0; ig < num_green; ig++)\r
767             {\r
768                /* int dg = abs(ig - g); */\r
769                int dg = ((ig > g) ? ig - g : g - ig);\r
770                int dt = dr + dg;\r
771                int dm = ((dr > dg) ? dr : dg);\r
772                int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);\r
773 \r
774                for (ib = 0; ib < num_blue; ib++)\r
775                {\r
776                   int d_index = index_g | ib;\r
777                   /* int db = abs(ib - b); */\r
778                   int db = ((ib > b) ? ib - b : b - ib);\r
779                   int dmax = ((dm > db) ? dm : db);\r
780                   int d = dmax + dt + db;\r
781 \r
782                   if (d < (int)distance[d_index])\r
783                   {\r
784                      distance[d_index] = (png_byte)d;\r
785                      png_ptr->palette_lookup[d_index] = (png_byte)i;\r
786                   }\r
787                }\r
788             }\r
789          }\r
790       }\r
791 \r
792       png_free(png_ptr, distance);\r
793    }\r
794 }\r
795 #endif /* PNG_READ_QUANTIZE_SUPPORTED */\r
796 \r
797 #ifdef PNG_READ_GAMMA_SUPPORTED\r
798 void PNGFAPI\r
799 png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,\r
800    png_fixed_point file_gamma)\r
801 {\r
802    png_debug(1, "in png_set_gamma_fixed");\r
803 \r
804    if (!png_rtran_ok(png_ptr, 0))\r
805       return;\r
806 \r
807    /* New in libpng-1.5.4 - reserve particular negative values as flags. */\r
808    scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);\r
809    file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);\r
810 \r
811    /* Checking the gamma values for being >0 was added in 1.5.4 along with the\r
812     * premultiplied alpha support; this actually hides an undocumented feature\r
813     * of the previous implementation which allowed gamma processing to be\r
814     * disabled in background handling.  There is no evidence (so far) that this\r
815     * was being used; however, png_set_background itself accepted and must still\r
816     * accept '0' for the gamma value it takes, because it isn't always used.\r
817     *\r
818     * Since this is an API change (albeit a very minor one that removes an\r
819     * undocumented API feature) the following checks were only enabled in\r
820     * libpng-1.6.0.\r
821     */\r
822    if (file_gamma <= 0)\r
823       png_error(png_ptr, "invalid file gamma in png_set_gamma");\r
824 \r
825    if (scrn_gamma <= 0)\r
826       png_error(png_ptr, "invalid screen gamma in png_set_gamma");\r
827 \r
828    /* Set the gamma values unconditionally - this overrides the value in the PNG\r
829     * file if a gAMA chunk was present.  png_set_alpha_mode provides a\r
830     * different, easier, way to default the file gamma.\r
831     */\r
832    png_ptr->colorspace.gamma = file_gamma;\r
833    png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;\r
834    png_ptr->screen_gamma = scrn_gamma;\r
835 }\r
836 \r
837 #  ifdef PNG_FLOATING_POINT_SUPPORTED\r
838 void PNGAPI\r
839 png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)\r
840 {\r
841    png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),\r
842       convert_gamma_value(png_ptr, file_gamma));\r
843 }\r
844 #  endif /* FLOATING_POINT_SUPPORTED */\r
845 #endif /* READ_GAMMA */\r
846 \r
847 #ifdef PNG_READ_EXPAND_SUPPORTED\r
848 /* Expand paletted images to RGB, expand grayscale images of\r
849  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks\r
850  * to alpha channels.\r
851  */\r
852 void PNGAPI\r
853 png_set_expand(png_structrp png_ptr)\r
854 {\r
855    png_debug(1, "in png_set_expand");\r
856 \r
857    if (!png_rtran_ok(png_ptr, 0))\r
858       return;\r
859 \r
860    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);\r
861 }\r
862 \r
863 /* GRR 19990627:  the following three functions currently are identical\r
864  *  to png_set_expand().  However, it is entirely reasonable that someone\r
865  *  might wish to expand an indexed image to RGB but *not* expand a single,\r
866  *  fully transparent palette entry to a full alpha channel--perhaps instead\r
867  *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace\r
868  *  the transparent color with a particular RGB value, or drop tRNS entirely.\r
869  *  IOW, a future version of the library may make the transformations flag\r
870  *  a bit more fine-grained, with separate bits for each of these three\r
871  *  functions.\r
872  *\r
873  *  More to the point, these functions make it obvious what libpng will be\r
874  *  doing, whereas "expand" can (and does) mean any number of things.\r
875  *\r
876  *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified\r
877  *  to expand only the sample depth but not to expand the tRNS to alpha\r
878  *  and its name was changed to png_set_expand_gray_1_2_4_to_8().\r
879  */\r
880 \r
881 /* Expand paletted images to RGB. */\r
882 void PNGAPI\r
883 png_set_palette_to_rgb(png_structrp png_ptr)\r
884 {\r
885    png_debug(1, "in png_set_palette_to_rgb");\r
886 \r
887    if (!png_rtran_ok(png_ptr, 0))\r
888       return;\r
889 \r
890    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);\r
891 }\r
892 \r
893 /* Expand grayscale images of less than 8-bit depth to 8 bits. */\r
894 void PNGAPI\r
895 png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)\r
896 {\r
897    png_debug(1, "in png_set_expand_gray_1_2_4_to_8");\r
898 \r
899    if (!png_rtran_ok(png_ptr, 0))\r
900       return;\r
901 \r
902    png_ptr->transformations |= PNG_EXPAND;\r
903 }\r
904 \r
905 /* Expand tRNS chunks to alpha channels. */\r
906 void PNGAPI\r
907 png_set_tRNS_to_alpha(png_structrp png_ptr)\r
908 {\r
909    png_debug(1, "in png_set_tRNS_to_alpha");\r
910 \r
911    if (!png_rtran_ok(png_ptr, 0))\r
912       return;\r
913 \r
914    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);\r
915 }\r
916 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */\r
917 \r
918 #ifdef PNG_READ_EXPAND_16_SUPPORTED\r
919 /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise\r
920  * it may not work correctly.)\r
921  */\r
922 void PNGAPI\r
923 png_set_expand_16(png_structrp png_ptr)\r
924 {\r
925    png_debug(1, "in png_set_expand_16");\r
926 \r
927    if (!png_rtran_ok(png_ptr, 0))\r
928       return;\r
929 \r
930    png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);\r
931 }\r
932 #endif\r
933 \r
934 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED\r
935 void PNGAPI\r
936 png_set_gray_to_rgb(png_structrp png_ptr)\r
937 {\r
938    png_debug(1, "in png_set_gray_to_rgb");\r
939 \r
940    if (!png_rtran_ok(png_ptr, 0))\r
941       return;\r
942 \r
943    /* Because rgb must be 8 bits or more: */\r
944    png_set_expand_gray_1_2_4_to_8(png_ptr);\r
945    png_ptr->transformations |= PNG_GRAY_TO_RGB;\r
946 }\r
947 #endif\r
948 \r
949 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
950 void PNGFAPI\r
951 png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,\r
952     png_fixed_point red, png_fixed_point green)\r
953 {\r
954    png_debug(1, "in png_set_rgb_to_gray");\r
955 \r
956    /* Need the IHDR here because of the check on color_type below. */\r
957    /* TODO: fix this */\r
958    if (!png_rtran_ok(png_ptr, 1))\r
959       return;\r
960 \r
961    switch(error_action)\r
962    {\r
963       case PNG_ERROR_ACTION_NONE:\r
964          png_ptr->transformations |= PNG_RGB_TO_GRAY;\r
965          break;\r
966 \r
967       case PNG_ERROR_ACTION_WARN:\r
968          png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;\r
969          break;\r
970 \r
971       case PNG_ERROR_ACTION_ERROR:\r
972          png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;\r
973          break;\r
974 \r
975       default:\r
976          png_error(png_ptr, "invalid error action to rgb_to_gray");\r
977          break;\r
978    }\r
979 \r
980    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
981 #ifdef PNG_READ_EXPAND_SUPPORTED\r
982       png_ptr->transformations |= PNG_EXPAND;\r
983 #else\r
984    {\r
985       /* Make this an error in 1.6 because otherwise the application may assume\r
986        * that it just worked and get a memory overwrite.\r
987        */\r
988       png_error(png_ptr,\r
989         "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");\r
990 \r
991       /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */\r
992    }\r
993 #endif\r
994    {\r
995       if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)\r
996       {\r
997          png_uint_16 red_int, green_int;\r
998 \r
999          /* NOTE: this calculation does not round, but this behavior is retained\r
1000           * for consistency, the inaccuracy is very small.  The code here always\r
1001           * overwrites the coefficients, regardless of whether they have been\r
1002           * defaulted or set already.\r
1003           */\r
1004          red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);\r
1005          green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);\r
1006 \r
1007          png_ptr->rgb_to_gray_red_coeff   = red_int;\r
1008          png_ptr->rgb_to_gray_green_coeff = green_int;\r
1009          png_ptr->rgb_to_gray_coefficients_set = 1;\r
1010       }\r
1011 \r
1012       else\r
1013       {\r
1014          if (red >= 0 && green >= 0)\r
1015             png_app_warning(png_ptr,\r
1016                "ignoring out of range rgb_to_gray coefficients");\r
1017 \r
1018          /* Use the defaults, from the cHRM chunk if set, else the historical\r
1019           * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See\r
1020           * png_do_rgb_to_gray for more discussion of the values.  In this case\r
1021           * the coefficients are not marked as 'set' and are not overwritten if\r
1022           * something has already provided a default.\r
1023           */\r
1024          if (png_ptr->rgb_to_gray_red_coeff == 0 &&\r
1025             png_ptr->rgb_to_gray_green_coeff == 0)\r
1026          {\r
1027             png_ptr->rgb_to_gray_red_coeff   = 6968;\r
1028             png_ptr->rgb_to_gray_green_coeff = 23434;\r
1029             /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */\r
1030          }\r
1031       }\r
1032    }\r
1033 }\r
1034 \r
1035 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
1036 /* Convert a RGB image to a grayscale of the same width.  This allows us,\r
1037  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.\r
1038  */\r
1039 \r
1040 void PNGAPI\r
1041 png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,\r
1042    double green)\r
1043 {\r
1044    png_set_rgb_to_gray_fixed(png_ptr, error_action,\r
1045       png_fixed(png_ptr, red, "rgb to gray red coefficient"),\r
1046       png_fixed(png_ptr, green, "rgb to gray green coefficient"));\r
1047 }\r
1048 #endif /* FLOATING POINT */\r
1049 \r
1050 #endif /* RGB_TO_GRAY */\r
1051 \r
1052 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \\r
1053     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)\r
1054 void PNGAPI\r
1055 png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr\r
1056     read_user_transform_fn)\r
1057 {\r
1058    png_debug(1, "in png_set_read_user_transform_fn");\r
1059 \r
1060 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED\r
1061    png_ptr->transformations |= PNG_USER_TRANSFORM;\r
1062    png_ptr->read_user_transform_fn = read_user_transform_fn;\r
1063 #endif\r
1064 }\r
1065 #endif\r
1066 \r
1067 #ifdef PNG_READ_TRANSFORMS_SUPPORTED\r
1068 #ifdef PNG_READ_GAMMA_SUPPORTED\r
1069 /* In the case of gamma transformations only do transformations on images where\r
1070  * the [file] gamma and screen_gamma are not close reciprocals, otherwise it\r
1071  * slows things down slightly, and also needlessly introduces small errors.\r
1072  */\r
1073 static int /* PRIVATE */\r
1074 png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)\r
1075 {\r
1076    /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma\r
1077     * correction as a difference of the overall transform from 1.0\r
1078     *\r
1079     * We want to compare the threshold with s*f - 1, if we get\r
1080     * overflow here it is because of wacky gamma values so we\r
1081     * turn on processing anyway.\r
1082     */\r
1083    png_fixed_point gtest;\r
1084    return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||\r
1085        png_gamma_significant(gtest);\r
1086 }\r
1087 #endif\r
1088 \r
1089 /* Initialize everything needed for the read.  This includes modifying\r
1090  * the palette.\r
1091  */\r
1092 \r
1093 /*For the moment 'png_init_palette_transformations' and\r
1094  * 'png_init_rgb_transformations' only do some flag canceling optimizations.\r
1095  * The intent is that these two routines should have palette or rgb operations\r
1096  * extracted from 'png_init_read_transformations'.\r
1097  */\r
1098 static void /* PRIVATE */\r
1099 png_init_palette_transformations(png_structrp png_ptr)\r
1100 {\r
1101    /* Called to handle the (input) palette case.  In png_do_read_transformations\r
1102     * the first step is to expand the palette if requested, so this code must\r
1103     * take care to only make changes that are invariant with respect to the\r
1104     * palette expansion, or only do them if there is no expansion.\r
1105     *\r
1106     * STRIP_ALPHA has already been handled in the caller (by setting num_trans\r
1107     * to 0.)\r
1108     */\r
1109    int input_has_alpha = 0;\r
1110    int input_has_transparency = 0;\r
1111 \r
1112    if (png_ptr->num_trans > 0)\r
1113    {\r
1114       int i;\r
1115 \r
1116       /* Ignore if all the entries are opaque (unlikely!) */\r
1117       for (i=0; i<png_ptr->num_trans; ++i)\r
1118          if (png_ptr->trans_alpha[i] == 255)\r
1119             continue;\r
1120          else if (png_ptr->trans_alpha[i] == 0)\r
1121             input_has_transparency = 1;\r
1122          else\r
1123             input_has_alpha = 1;\r
1124    }\r
1125 \r
1126    /* If no alpha we can optimize. */\r
1127    if (!input_has_alpha)\r
1128    {\r
1129       /* Any alpha means background and associative alpha processing is\r
1130        * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA\r
1131        * and ENCODE_ALPHA are irrelevant.\r
1132        */\r
1133       png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
1134       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
1135 \r
1136       if (!input_has_transparency)\r
1137          png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);\r
1138    }\r
1139 \r
1140 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)\r
1141    /* png_set_background handling - deals with the complexity of whether the\r
1142     * background color is in the file format or the screen format in the case\r
1143     * where an 'expand' will happen.\r
1144     */\r
1145 \r
1146    /* The following code cannot be entered in the alpha pre-multiplication case\r
1147     * because PNG_BACKGROUND_EXPAND is cancelled below.\r
1148     */\r
1149    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&\r
1150        (png_ptr->transformations & PNG_EXPAND))\r
1151    {\r
1152       {\r
1153          png_ptr->background.red   =\r
1154              png_ptr->palette[png_ptr->background.index].red;\r
1155          png_ptr->background.green =\r
1156              png_ptr->palette[png_ptr->background.index].green;\r
1157          png_ptr->background.blue  =\r
1158              png_ptr->palette[png_ptr->background.index].blue;\r
1159 \r
1160 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED\r
1161         if (png_ptr->transformations & PNG_INVERT_ALPHA)\r
1162         {\r
1163            if (!(png_ptr->transformations & PNG_EXPAND_tRNS))\r
1164            {\r
1165               /* Invert the alpha channel (in tRNS) unless the pixels are\r
1166                * going to be expanded, in which case leave it for later\r
1167                */\r
1168               int i, istop = png_ptr->num_trans;\r
1169 \r
1170               for (i=0; i<istop; i++)\r
1171                  png_ptr->trans_alpha[i] = (png_byte)(255 -\r
1172                     png_ptr->trans_alpha[i]);\r
1173            }\r
1174         }\r
1175 #endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */\r
1176       }\r
1177    } /* background expand and (therefore) no alpha association. */\r
1178 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */\r
1179 }\r
1180 \r
1181 static void /* PRIVATE */\r
1182 png_init_rgb_transformations(png_structrp png_ptr)\r
1183 {\r
1184    /* Added to libpng-1.5.4: check the color type to determine whether there\r
1185     * is any alpha or transparency in the image and simply cancel the\r
1186     * background and alpha mode stuff if there isn't.\r
1187     */\r
1188    int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;\r
1189    int input_has_transparency = png_ptr->num_trans > 0;\r
1190 \r
1191    /* If no alpha we can optimize. */\r
1192    if (!input_has_alpha)\r
1193    {\r
1194       /* Any alpha means background and associative alpha processing is\r
1195        * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA\r
1196        * and ENCODE_ALPHA are irrelevant.\r
1197        */\r
1198 #     ifdef PNG_READ_ALPHA_MODE_SUPPORTED\r
1199          png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
1200          png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
1201 #     endif\r
1202 \r
1203       if (!input_has_transparency)\r
1204          png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);\r
1205    }\r
1206 \r
1207 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)\r
1208    /* png_set_background handling - deals with the complexity of whether the\r
1209     * background color is in the file format or the screen format in the case\r
1210     * where an 'expand' will happen.\r
1211     */\r
1212 \r
1213    /* The following code cannot be entered in the alpha pre-multiplication case\r
1214     * because PNG_BACKGROUND_EXPAND is cancelled below.\r
1215     */\r
1216    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&\r
1217        (png_ptr->transformations & PNG_EXPAND) &&\r
1218        !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))\r
1219        /* i.e., GRAY or GRAY_ALPHA */\r
1220    {\r
1221       {\r
1222          /* Expand background and tRNS chunks */\r
1223          int gray = png_ptr->background.gray;\r
1224          int trans_gray = png_ptr->trans_color.gray;\r
1225 \r
1226          switch (png_ptr->bit_depth)\r
1227          {\r
1228             case 1:\r
1229                gray *= 0xff;\r
1230                trans_gray *= 0xff;\r
1231                break;\r
1232 \r
1233             case 2:\r
1234                gray *= 0x55;\r
1235                trans_gray *= 0x55;\r
1236                break;\r
1237 \r
1238             case 4:\r
1239                gray *= 0x11;\r
1240                trans_gray *= 0x11;\r
1241                break;\r
1242 \r
1243             default:\r
1244 \r
1245             case 8:\r
1246                /* FALL THROUGH (Already 8 bits) */\r
1247 \r
1248             case 16:\r
1249                /* Already a full 16 bits */\r
1250                break;\r
1251          }\r
1252 \r
1253          png_ptr->background.red = png_ptr->background.green =\r
1254             png_ptr->background.blue = (png_uint_16)gray;\r
1255 \r
1256          if (!(png_ptr->transformations & PNG_EXPAND_tRNS))\r
1257          {\r
1258             png_ptr->trans_color.red = png_ptr->trans_color.green =\r
1259                png_ptr->trans_color.blue = (png_uint_16)trans_gray;\r
1260          }\r
1261       }\r
1262    } /* background expand and (therefore) no alpha association. */\r
1263 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */\r
1264 }\r
1265 \r
1266 void /* PRIVATE */\r
1267 png_init_read_transformations(png_structrp png_ptr)\r
1268 {\r
1269    png_debug(1, "in png_init_read_transformations");\r
1270 \r
1271    /* This internal function is called from png_read_start_row in pngrutil.c\r
1272     * and it is called before the 'rowbytes' calculation is done, so the code\r
1273     * in here can change or update the transformations flags.\r
1274     *\r
1275     * First do updates that do not depend on the details of the PNG image data\r
1276     * being processed.\r
1277     */\r
1278 \r
1279 #ifdef PNG_READ_GAMMA_SUPPORTED\r
1280    /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds\r
1281     * png_set_alpha_mode and this is another source for a default file gamma so\r
1282     * the test needs to be performed later - here.  In addition prior to 1.5.4\r
1283     * the tests were repeated for the PALETTE color type here - this is no\r
1284     * longer necessary (and doesn't seem to have been necessary before.)\r
1285     */\r
1286    {\r
1287       /* The following temporary indicates if overall gamma correction is\r
1288        * required.\r
1289        */\r
1290       int gamma_correction = 0;\r
1291 \r
1292       if (png_ptr->colorspace.gamma != 0) /* has been set */\r
1293       {\r
1294          if (png_ptr->screen_gamma != 0) /* screen set too */\r
1295             gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,\r
1296                png_ptr->screen_gamma);\r
1297 \r
1298          else\r
1299             /* Assume the output matches the input; a long time default behavior\r
1300              * of libpng, although the standard has nothing to say about this.\r
1301              */\r
1302             png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);\r
1303       }\r
1304 \r
1305       else if (png_ptr->screen_gamma != 0)\r
1306          /* The converse - assume the file matches the screen, note that this\r
1307           * perhaps undesireable default can (from 1.5.4) be changed by calling\r
1308           * png_set_alpha_mode (even if the alpha handling mode isn't required\r
1309           * or isn't changed from the default.)\r
1310           */\r
1311          png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);\r
1312 \r
1313       else /* neither are set */\r
1314          /* Just in case the following prevents any processing - file and screen\r
1315           * are both assumed to be linear and there is no way to introduce a\r
1316           * third gamma value other than png_set_background with 'UNIQUE', and,\r
1317           * prior to 1.5.4\r
1318           */\r
1319          png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;\r
1320 \r
1321       /* We have a gamma value now. */\r
1322       png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;\r
1323 \r
1324       /* Now turn the gamma transformation on or off as appropriate.  Notice\r
1325        * that PNG_GAMMA just refers to the file->screen correction.  Alpha\r
1326        * composition may independently cause gamma correction because it needs\r
1327        * linear data (e.g. if the file has a gAMA chunk but the screen gamma\r
1328        * hasn't been specified.)  In any case this flag may get turned off in\r
1329        * the code immediately below if the transform can be handled outside the\r
1330        * row loop.\r
1331        */\r
1332       if (gamma_correction)\r
1333          png_ptr->transformations |= PNG_GAMMA;\r
1334 \r
1335       else\r
1336          png_ptr->transformations &= ~PNG_GAMMA;\r
1337    }\r
1338 #endif\r
1339 \r
1340    /* Certain transformations have the effect of preventing other\r
1341     * transformations that happen afterward in png_do_read_transformations,\r
1342     * resolve the interdependencies here.  From the code of\r
1343     * png_do_read_transformations the order is:\r
1344     *\r
1345     *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)\r
1346     *  2) PNG_STRIP_ALPHA (if no compose)\r
1347     *  3) PNG_RGB_TO_GRAY\r
1348     *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY\r
1349     *  5) PNG_COMPOSE\r
1350     *  6) PNG_GAMMA\r
1351     *  7) PNG_STRIP_ALPHA (if compose)\r
1352     *  8) PNG_ENCODE_ALPHA\r
1353     *  9) PNG_SCALE_16_TO_8\r
1354     * 10) PNG_16_TO_8\r
1355     * 11) PNG_QUANTIZE (converts to palette)\r
1356     * 12) PNG_EXPAND_16\r
1357     * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY\r
1358     * 14) PNG_INVERT_MONO\r
1359     * 15) PNG_SHIFT\r
1360     * 16) PNG_PACK\r
1361     * 17) PNG_BGR\r
1362     * 18) PNG_PACKSWAP\r
1363     * 19) PNG_FILLER (includes PNG_ADD_ALPHA)\r
1364     * 20) PNG_INVERT_ALPHA\r
1365     * 21) PNG_SWAP_ALPHA\r
1366     * 22) PNG_SWAP_BYTES\r
1367     * 23) PNG_USER_TRANSFORM [must be last]\r
1368     */\r
1369 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED\r
1370    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&\r
1371       !(png_ptr->transformations & PNG_COMPOSE))\r
1372    {\r
1373       /* Stripping the alpha channel happens immediately after the 'expand'\r
1374        * transformations, before all other transformation, so it cancels out\r
1375        * the alpha handling.  It has the side effect negating the effect of\r
1376        * PNG_EXPAND_tRNS too:\r
1377        */\r
1378       png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |\r
1379          PNG_EXPAND_tRNS);\r
1380       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
1381 \r
1382       /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen\r
1383        * so transparency information would remain just so long as it wasn't\r
1384        * expanded.  This produces unexpected API changes if the set of things\r
1385        * that do PNG_EXPAND_tRNS changes (perfectly possible given the\r
1386        * documentation - which says ask for what you want, accept what you\r
1387        * get.)  This makes the behavior consistent from 1.5.4:\r
1388        */\r
1389       png_ptr->num_trans = 0;\r
1390    }\r
1391 #endif /* STRIP_ALPHA supported, no COMPOSE */\r
1392 \r
1393 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED\r
1394    /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA\r
1395     * settings will have no effect.\r
1396     */\r
1397    if (!png_gamma_significant(png_ptr->screen_gamma))\r
1398    {\r
1399       png_ptr->transformations &= ~PNG_ENCODE_ALPHA;\r
1400       png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;\r
1401    }\r
1402 #endif\r
1403 \r
1404 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
1405    /* Make sure the coefficients for the rgb to gray conversion are set\r
1406     * appropriately.\r
1407     */\r
1408    if (png_ptr->transformations & PNG_RGB_TO_GRAY)\r
1409       png_colorspace_set_rgb_coefficients(png_ptr);\r
1410 #endif\r
1411 \r
1412 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED\r
1413 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)\r
1414    /* Detect gray background and attempt to enable optimization for\r
1415     * gray --> RGB case.\r
1416     *\r
1417     * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or\r
1418     * RGB_ALPHA (in which case need_expand is superfluous anyway), the\r
1419     * background color might actually be gray yet not be flagged as such.\r
1420     * This is not a problem for the current code, which uses\r
1421     * PNG_BACKGROUND_IS_GRAY only to decide when to do the\r
1422     * png_do_gray_to_rgb() transformation.\r
1423     *\r
1424     * TODO: this code needs to be revised to avoid the complexity and\r
1425     * interdependencies.  The color type of the background should be recorded in\r
1426     * png_set_background, along with the bit depth, then the code has a record\r
1427     * of exactly what color space the background is currently in.\r
1428     */\r
1429    if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)\r
1430    {\r
1431       /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if\r
1432        * the file was grayscale the background value is gray.\r
1433        */\r
1434       if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))\r
1435          png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;\r
1436    }\r
1437 \r
1438    else if (png_ptr->transformations & PNG_COMPOSE)\r
1439    {\r
1440       /* PNG_COMPOSE: png_set_background was called with need_expand false,\r
1441        * so the color is in the color space of the output or png_set_alpha_mode\r
1442        * was called and the color is black.  Ignore RGB_TO_GRAY because that\r
1443        * happens before GRAY_TO_RGB.\r
1444        */\r
1445       if (png_ptr->transformations & PNG_GRAY_TO_RGB)\r
1446       {\r
1447          if (png_ptr->background.red == png_ptr->background.green &&\r
1448              png_ptr->background.red == png_ptr->background.blue)\r
1449          {\r
1450             png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;\r
1451             png_ptr->background.gray = png_ptr->background.red;\r
1452          }\r
1453       }\r
1454    }\r
1455 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */\r
1456 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */\r
1457 \r
1458    /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations\r
1459     * can be performed directly on the palette, and some (such as rgb to gray)\r
1460     * can be optimized inside the palette.  This is particularly true of the\r
1461     * composite (background and alpha) stuff, which can be pretty much all done\r
1462     * in the palette even if the result is expanded to RGB or gray afterward.\r
1463     *\r
1464     * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and\r
1465     * earlier and the palette stuff is actually handled on the first row.  This\r
1466     * leads to the reported bug that the palette returned by png_get_PLTE is not\r
1467     * updated.\r
1468     */\r
1469    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1470       png_init_palette_transformations(png_ptr);\r
1471 \r
1472    else\r
1473       png_init_rgb_transformations(png_ptr);\r
1474 \r
1475 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \\r
1476    defined(PNG_READ_EXPAND_16_SUPPORTED)\r
1477    if ((png_ptr->transformations & PNG_EXPAND_16) &&\r
1478       (png_ptr->transformations & PNG_COMPOSE) &&\r
1479       !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&\r
1480       png_ptr->bit_depth != 16)\r
1481    {\r
1482       /* TODO: fix this.  Because the expand_16 operation is after the compose\r
1483        * handling the background color must be 8, not 16, bits deep, but the\r
1484        * application will supply a 16-bit value so reduce it here.\r
1485        *\r
1486        * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at\r
1487        * present, so that case is ok (until do_expand_16 is moved.)\r
1488        *\r
1489        * NOTE: this discards the low 16 bits of the user supplied background\r
1490        * color, but until expand_16 works properly there is no choice!\r
1491        */\r
1492 #     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))\r
1493       CHOP(png_ptr->background.red);\r
1494       CHOP(png_ptr->background.green);\r
1495       CHOP(png_ptr->background.blue);\r
1496       CHOP(png_ptr->background.gray);\r
1497 #     undef CHOP\r
1498    }\r
1499 #endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */\r
1500 \r
1501 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \\r
1502    (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \\r
1503    defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))\r
1504    if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&\r
1505       (png_ptr->transformations & PNG_COMPOSE) &&\r
1506       !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&\r
1507       png_ptr->bit_depth == 16)\r
1508    {\r
1509       /* On the other hand, if a 16-bit file is to be reduced to 8-bits per\r
1510        * component this will also happen after PNG_COMPOSE and so the background\r
1511        * color must be pre-expanded here.\r
1512        *\r
1513        * TODO: fix this too.\r
1514        */\r
1515       png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);\r
1516       png_ptr->background.green =\r
1517          (png_uint_16)(png_ptr->background.green * 257);\r
1518       png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);\r
1519       png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);\r
1520    }\r
1521 #endif\r
1522 \r
1523    /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the\r
1524     * background support (see the comments in scripts/pnglibconf.dfa), this\r
1525     * allows pre-multiplication of the alpha channel to be implemented as\r
1526     * compositing on black.  This is probably sub-optimal and has been done in\r
1527     * 1.5.4 betas simply to enable external critique and testing (i.e. to\r
1528     * implement the new API quickly, without lots of internal changes.)\r
1529     */\r
1530 \r
1531 #ifdef PNG_READ_GAMMA_SUPPORTED\r
1532 #  ifdef PNG_READ_BACKGROUND_SUPPORTED\r
1533       /* Includes ALPHA_MODE */\r
1534       png_ptr->background_1 = png_ptr->background;\r
1535 #  endif\r
1536 \r
1537    /* This needs to change - in the palette image case a whole set of tables are\r
1538     * built when it would be quicker to just calculate the correct value for\r
1539     * each palette entry directly.  Also, the test is too tricky - why check\r
1540     * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that\r
1541     * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the\r
1542     * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction\r
1543     * the gamma tables will not be built even if composition is required on a\r
1544     * gamma encoded value.\r
1545     *\r
1546     * In 1.5.4 this is addressed below by an additional check on the individual\r
1547     * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the\r
1548     * tables.\r
1549     */\r
1550    if ((png_ptr->transformations & PNG_GAMMA)\r
1551       || ((png_ptr->transformations & PNG_RGB_TO_GRAY)\r
1552          && (png_gamma_significant(png_ptr->colorspace.gamma) ||\r
1553             png_gamma_significant(png_ptr->screen_gamma)))\r
1554       || ((png_ptr->transformations & PNG_COMPOSE)\r
1555          && (png_gamma_significant(png_ptr->colorspace.gamma)\r
1556             || png_gamma_significant(png_ptr->screen_gamma)\r
1557 #  ifdef PNG_READ_BACKGROUND_SUPPORTED\r
1558             || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE\r
1559                && png_gamma_significant(png_ptr->background_gamma))\r
1560 #  endif\r
1561       )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)\r
1562          && png_gamma_significant(png_ptr->screen_gamma))\r
1563       )\r
1564    {\r
1565       png_build_gamma_table(png_ptr, png_ptr->bit_depth);\r
1566 \r
1567 #ifdef PNG_READ_BACKGROUND_SUPPORTED\r
1568       if (png_ptr->transformations & PNG_COMPOSE)\r
1569       {\r
1570          /* Issue a warning about this combination: because RGB_TO_GRAY is\r
1571           * optimized to do the gamma transform if present yet do_background has\r
1572           * to do the same thing if both options are set a\r
1573           * double-gamma-correction happens.  This is true in all versions of\r
1574           * libpng to date.\r
1575           */\r
1576          if (png_ptr->transformations & PNG_RGB_TO_GRAY)\r
1577             png_warning(png_ptr,\r
1578                "libpng does not support gamma+background+rgb_to_gray");\r
1579 \r
1580          if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1581          {\r
1582             /* We don't get to here unless there is a tRNS chunk with non-opaque\r
1583              * entries - see the checking code at the start of this function.\r
1584              */\r
1585             png_color back, back_1;\r
1586             png_colorp palette = png_ptr->palette;\r
1587             int num_palette = png_ptr->num_palette;\r
1588             int i;\r
1589             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)\r
1590             {\r
1591 \r
1592                back.red = png_ptr->gamma_table[png_ptr->background.red];\r
1593                back.green = png_ptr->gamma_table[png_ptr->background.green];\r
1594                back.blue = png_ptr->gamma_table[png_ptr->background.blue];\r
1595 \r
1596                back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];\r
1597                back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];\r
1598                back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];\r
1599             }\r
1600             else\r
1601             {\r
1602                png_fixed_point g, gs;\r
1603 \r
1604                switch (png_ptr->background_gamma_type)\r
1605                {\r
1606                   case PNG_BACKGROUND_GAMMA_SCREEN:\r
1607                      g = (png_ptr->screen_gamma);\r
1608                      gs = PNG_FP_1;\r
1609                      break;\r
1610 \r
1611                   case PNG_BACKGROUND_GAMMA_FILE:\r
1612                      g = png_reciprocal(png_ptr->colorspace.gamma);\r
1613                      gs = png_reciprocal2(png_ptr->colorspace.gamma,\r
1614                         png_ptr->screen_gamma);\r
1615                      break;\r
1616 \r
1617                   case PNG_BACKGROUND_GAMMA_UNIQUE:\r
1618                      g = png_reciprocal(png_ptr->background_gamma);\r
1619                      gs = png_reciprocal2(png_ptr->background_gamma,\r
1620                         png_ptr->screen_gamma);\r
1621                      break;\r
1622                   default:\r
1623                      g = PNG_FP_1;    /* back_1 */\r
1624                      gs = PNG_FP_1;   /* back */\r
1625                      break;\r
1626                }\r
1627 \r
1628                if (png_gamma_significant(gs))\r
1629                {\r
1630                   back.red = png_gamma_8bit_correct(png_ptr->background.red,\r
1631                       gs);\r
1632                   back.green = png_gamma_8bit_correct(png_ptr->background.green,\r
1633                       gs);\r
1634                   back.blue = png_gamma_8bit_correct(png_ptr->background.blue,\r
1635                       gs);\r
1636                }\r
1637 \r
1638                else\r
1639                {\r
1640                   back.red   = (png_byte)png_ptr->background.red;\r
1641                   back.green = (png_byte)png_ptr->background.green;\r
1642                   back.blue  = (png_byte)png_ptr->background.blue;\r
1643                }\r
1644 \r
1645                if (png_gamma_significant(g))\r
1646                {\r
1647                   back_1.red = png_gamma_8bit_correct(png_ptr->background.red,\r
1648                      g);\r
1649                   back_1.green = png_gamma_8bit_correct(\r
1650                      png_ptr->background.green, g);\r
1651                   back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,\r
1652                      g);\r
1653                }\r
1654 \r
1655                else\r
1656                {\r
1657                   back_1.red   = (png_byte)png_ptr->background.red;\r
1658                   back_1.green = (png_byte)png_ptr->background.green;\r
1659                   back_1.blue  = (png_byte)png_ptr->background.blue;\r
1660                }\r
1661             }\r
1662 \r
1663             for (i = 0; i < num_palette; i++)\r
1664             {\r
1665                if (i < (int)png_ptr->num_trans &&\r
1666                    png_ptr->trans_alpha[i] != 0xff)\r
1667                {\r
1668                   if (png_ptr->trans_alpha[i] == 0)\r
1669                   {\r
1670                      palette[i] = back;\r
1671                   }\r
1672                   else /* if (png_ptr->trans_alpha[i] != 0xff) */\r
1673                   {\r
1674                      png_byte v, w;\r
1675 \r
1676                      v = png_ptr->gamma_to_1[palette[i].red];\r
1677                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);\r
1678                      palette[i].red = png_ptr->gamma_from_1[w];\r
1679 \r
1680                      v = png_ptr->gamma_to_1[palette[i].green];\r
1681                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);\r
1682                      palette[i].green = png_ptr->gamma_from_1[w];\r
1683 \r
1684                      v = png_ptr->gamma_to_1[palette[i].blue];\r
1685                      png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);\r
1686                      palette[i].blue = png_ptr->gamma_from_1[w];\r
1687                   }\r
1688                }\r
1689                else\r
1690                {\r
1691                   palette[i].red = png_ptr->gamma_table[palette[i].red];\r
1692                   palette[i].green = png_ptr->gamma_table[palette[i].green];\r
1693                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];\r
1694                }\r
1695             }\r
1696 \r
1697             /* Prevent the transformations being done again.\r
1698              *\r
1699              * NOTE: this is highly dubious; it removes the transformations in\r
1700              * place.  This seems inconsistent with the general treatment of the\r
1701              * transformations elsewhere.\r
1702              */\r
1703             png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);\r
1704          } /* color_type == PNG_COLOR_TYPE_PALETTE */\r
1705 \r
1706          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */\r
1707          else /* color_type != PNG_COLOR_TYPE_PALETTE */\r
1708          {\r
1709             int gs_sig, g_sig;\r
1710             png_fixed_point g = PNG_FP_1;  /* Correction to linear */\r
1711             png_fixed_point gs = PNG_FP_1; /* Correction to screen */\r
1712 \r
1713             switch (png_ptr->background_gamma_type)\r
1714             {\r
1715                case PNG_BACKGROUND_GAMMA_SCREEN:\r
1716                   g = png_ptr->screen_gamma;\r
1717                   /* gs = PNG_FP_1; */\r
1718                   break;\r
1719 \r
1720                case PNG_BACKGROUND_GAMMA_FILE:\r
1721                   g = png_reciprocal(png_ptr->colorspace.gamma);\r
1722                   gs = png_reciprocal2(png_ptr->colorspace.gamma,\r
1723                      png_ptr->screen_gamma);\r
1724                   break;\r
1725 \r
1726                case PNG_BACKGROUND_GAMMA_UNIQUE:\r
1727                   g = png_reciprocal(png_ptr->background_gamma);\r
1728                   gs = png_reciprocal2(png_ptr->background_gamma,\r
1729                       png_ptr->screen_gamma);\r
1730                   break;\r
1731 \r
1732                default:\r
1733                   png_error(png_ptr, "invalid background gamma type");\r
1734             }\r
1735 \r
1736             g_sig = png_gamma_significant(g);\r
1737             gs_sig = png_gamma_significant(gs);\r
1738 \r
1739             if (g_sig)\r
1740                png_ptr->background_1.gray = png_gamma_correct(png_ptr,\r
1741                    png_ptr->background.gray, g);\r
1742 \r
1743             if (gs_sig)\r
1744                png_ptr->background.gray = png_gamma_correct(png_ptr,\r
1745                    png_ptr->background.gray, gs);\r
1746 \r
1747             if ((png_ptr->background.red != png_ptr->background.green) ||\r
1748                 (png_ptr->background.red != png_ptr->background.blue) ||\r
1749                 (png_ptr->background.red != png_ptr->background.gray))\r
1750             {\r
1751                /* RGB or RGBA with color background */\r
1752                if (g_sig)\r
1753                {\r
1754                   png_ptr->background_1.red = png_gamma_correct(png_ptr,\r
1755                       png_ptr->background.red, g);\r
1756 \r
1757                   png_ptr->background_1.green = png_gamma_correct(png_ptr,\r
1758                       png_ptr->background.green, g);\r
1759 \r
1760                   png_ptr->background_1.blue = png_gamma_correct(png_ptr,\r
1761                       png_ptr->background.blue, g);\r
1762                }\r
1763 \r
1764                if (gs_sig)\r
1765                {\r
1766                   png_ptr->background.red = png_gamma_correct(png_ptr,\r
1767                       png_ptr->background.red, gs);\r
1768 \r
1769                   png_ptr->background.green = png_gamma_correct(png_ptr,\r
1770                       png_ptr->background.green, gs);\r
1771 \r
1772                   png_ptr->background.blue = png_gamma_correct(png_ptr,\r
1773                       png_ptr->background.blue, gs);\r
1774                }\r
1775             }\r
1776 \r
1777             else\r
1778             {\r
1779                /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */\r
1780                png_ptr->background_1.red = png_ptr->background_1.green\r
1781                    = png_ptr->background_1.blue = png_ptr->background_1.gray;\r
1782 \r
1783                png_ptr->background.red = png_ptr->background.green\r
1784                    = png_ptr->background.blue = png_ptr->background.gray;\r
1785             }\r
1786 \r
1787             /* The background is now in screen gamma: */\r
1788             png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;\r
1789          } /* color_type != PNG_COLOR_TYPE_PALETTE */\r
1790       }/* png_ptr->transformations & PNG_BACKGROUND */\r
1791 \r
1792       else\r
1793       /* Transformation does not include PNG_BACKGROUND */\r
1794 #endif /* PNG_READ_BACKGROUND_SUPPORTED */\r
1795       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE\r
1796 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
1797          /* RGB_TO_GRAY needs to have non-gamma-corrected values! */\r
1798          && ((png_ptr->transformations & PNG_EXPAND) == 0 ||\r
1799          (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)\r
1800 #endif\r
1801          )\r
1802       {\r
1803          png_colorp palette = png_ptr->palette;\r
1804          int num_palette = png_ptr->num_palette;\r
1805          int i;\r
1806 \r
1807          /* NOTE: there are other transformations that should probably be in\r
1808           * here too.\r
1809           */\r
1810          for (i = 0; i < num_palette; i++)\r
1811          {\r
1812             palette[i].red = png_ptr->gamma_table[palette[i].red];\r
1813             palette[i].green = png_ptr->gamma_table[palette[i].green];\r
1814             palette[i].blue = png_ptr->gamma_table[palette[i].blue];\r
1815          }\r
1816 \r
1817          /* Done the gamma correction. */\r
1818          png_ptr->transformations &= ~PNG_GAMMA;\r
1819       } /* color_type == PALETTE && !PNG_BACKGROUND transformation */\r
1820    }\r
1821 #ifdef PNG_READ_BACKGROUND_SUPPORTED\r
1822    else\r
1823 #endif\r
1824 #endif /* PNG_READ_GAMMA_SUPPORTED */\r
1825 \r
1826 #ifdef PNG_READ_BACKGROUND_SUPPORTED\r
1827    /* No GAMMA transformation (see the hanging else 4 lines above) */\r
1828    if ((png_ptr->transformations & PNG_COMPOSE) &&\r
1829        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))\r
1830    {\r
1831       int i;\r
1832       int istop = (int)png_ptr->num_trans;\r
1833       png_color back;\r
1834       png_colorp palette = png_ptr->palette;\r
1835 \r
1836       back.red   = (png_byte)png_ptr->background.red;\r
1837       back.green = (png_byte)png_ptr->background.green;\r
1838       back.blue  = (png_byte)png_ptr->background.blue;\r
1839 \r
1840       for (i = 0; i < istop; i++)\r
1841       {\r
1842          if (png_ptr->trans_alpha[i] == 0)\r
1843          {\r
1844             palette[i] = back;\r
1845          }\r
1846 \r
1847          else if (png_ptr->trans_alpha[i] != 0xff)\r
1848          {\r
1849             /* The png_composite() macro is defined in png.h */\r
1850             png_composite(palette[i].red, palette[i].red,\r
1851                 png_ptr->trans_alpha[i], back.red);\r
1852 \r
1853             png_composite(palette[i].green, palette[i].green,\r
1854                 png_ptr->trans_alpha[i], back.green);\r
1855 \r
1856             png_composite(palette[i].blue, palette[i].blue,\r
1857                 png_ptr->trans_alpha[i], back.blue);\r
1858          }\r
1859       }\r
1860 \r
1861       png_ptr->transformations &= ~PNG_COMPOSE;\r
1862           \r
1863           //png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; /* Add by Sunliang.Liu */\r
1864    }\r
1865 #endif /* PNG_READ_BACKGROUND_SUPPORTED */\r
1866 \r
1867 #ifdef PNG_READ_SHIFT_SUPPORTED\r
1868    if ((png_ptr->transformations & PNG_SHIFT) &&\r
1869       !(png_ptr->transformations & PNG_EXPAND) &&\r
1870        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))\r
1871    {\r
1872       int i;\r
1873       int istop = png_ptr->num_palette;\r
1874       int shift = 8 - png_ptr->sig_bit.red;\r
1875 \r
1876       png_ptr->transformations &= ~PNG_SHIFT;\r
1877 \r
1878       /* significant bits can be in the range 1 to 7 for a meaninful result, if\r
1879        * the number of significant bits is 0 then no shift is done (this is an\r
1880        * error condition which is silently ignored.)\r
1881        */\r
1882       if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)\r
1883       {\r
1884          int component = png_ptr->palette[i].red;\r
1885 \r
1886          component >>= shift;\r
1887          png_ptr->palette[i].red = (png_byte)component;\r
1888       }\r
1889 \r
1890       shift = 8 - png_ptr->sig_bit.green;\r
1891       if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)\r
1892       {\r
1893          int component = png_ptr->palette[i].green;\r
1894 \r
1895          component >>= shift;\r
1896          png_ptr->palette[i].green = (png_byte)component;\r
1897       }\r
1898 \r
1899       shift = 8 - png_ptr->sig_bit.blue;\r
1900       if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)\r
1901       {\r
1902          int component = png_ptr->palette[i].blue;\r
1903 \r
1904          component >>= shift;\r
1905          png_ptr->palette[i].blue = (png_byte)component;\r
1906       }\r
1907    }\r
1908 #endif  /* PNG_READ_SHIFT_SUPPORTED */\r
1909 }\r
1910 \r
1911 /* Modify the info structure to reflect the transformations.  The\r
1912  * info should be updated so a PNG file could be written with it,\r
1913  * assuming the transformations result in valid PNG data.\r
1914  */\r
1915 void /* PRIVATE */\r
1916 png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)\r
1917 {\r
1918    png_debug(1, "in png_read_transform_info");\r
1919 \r
1920 #ifdef PNG_READ_EXPAND_SUPPORTED\r
1921    if (png_ptr->transformations & PNG_EXPAND)\r
1922    {\r
1923       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1924       {\r
1925          /* This check must match what actually happens in\r
1926           * png_do_expand_palette; if it ever checks the tRNS chunk to see if\r
1927           * it is all opaque we must do the same (at present it does not.)\r
1928           */\r
1929          if (png_ptr->num_trans > 0)\r
1930             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;\r
1931 \r
1932          else\r
1933             info_ptr->color_type = PNG_COLOR_TYPE_RGB;\r
1934 \r
1935          info_ptr->bit_depth = 8;\r
1936          info_ptr->num_trans = 0;\r
1937       }\r
1938       else\r
1939       {\r
1940          if (png_ptr->num_trans)\r
1941          {\r
1942             if (png_ptr->transformations & PNG_EXPAND_tRNS)\r
1943                info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;\r
1944          }\r
1945          if (info_ptr->bit_depth < 8)\r
1946             info_ptr->bit_depth = 8;\r
1947 \r
1948          info_ptr->num_trans = 0;\r
1949       }\r
1950    }\r
1951 #endif\r
1952 \r
1953 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\\r
1954    defined(PNG_READ_ALPHA_MODE_SUPPORTED)\r
1955    /* The following is almost certainly wrong unless the background value is in\r
1956     * the screen space!\r
1957     */\r
1958    if (png_ptr->transformations & PNG_COMPOSE)\r
1959       info_ptr->background = png_ptr->background;\r
1960 #endif\r
1961 \r
1962 #ifdef PNG_READ_GAMMA_SUPPORTED\r
1963    /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),\r
1964     * however it seems that the code in png_init_read_transformations, which has\r
1965     * been called before this from png_read_update_info->png_read_start_row\r
1966     * sometimes does the gamma transform and cancels the flag.\r
1967     *\r
1968     * TODO: this looks wrong; the info_ptr should end up with a gamma equal to\r
1969     * the screen_gamma value.  The following probably results in weirdness if\r
1970     * the info_ptr is used by the app after the rows have been read.\r
1971     */\r
1972    info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;\r
1973 #endif\r
1974 \r
1975    if (info_ptr->bit_depth == 16)\r
1976    {\r
1977 #  ifdef PNG_READ_16BIT_SUPPORTED\r
1978 #     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED\r
1979          if (png_ptr->transformations & PNG_SCALE_16_TO_8)\r
1980             info_ptr->bit_depth = 8;\r
1981 #     endif\r
1982 \r
1983 #     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED\r
1984          if (png_ptr->transformations & PNG_16_TO_8)\r
1985             info_ptr->bit_depth = 8;\r
1986 #     endif\r
1987 \r
1988 #  else\r
1989       /* No 16 bit support: force chopping 16-bit input down to 8, in this case\r
1990        * the app program can chose if both APIs are available by setting the\r
1991        * correct scaling to use.\r
1992        */\r
1993 #     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED\r
1994          /* For compatibility with previous versions use the strip method by\r
1995           * default.  This code works because if PNG_SCALE_16_TO_8 is already\r
1996           * set the code below will do that in preference to the chop.\r
1997           */\r
1998          png_ptr->transformations |= PNG_16_TO_8;\r
1999          info_ptr->bit_depth = 8;\r
2000 #     else\r
2001 \r
2002 #        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED\r
2003             png_ptr->transformations |= PNG_SCALE_16_TO_8;\r
2004             info_ptr->bit_depth = 8;\r
2005 #        else\r
2006 \r
2007             CONFIGURATION ERROR: you must enable at least one 16 to 8 method\r
2008 #        endif\r
2009 #    endif\r
2010 #endif /* !READ_16BIT_SUPPORTED */\r
2011    }\r
2012 \r
2013 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED\r
2014    if (png_ptr->transformations & PNG_GRAY_TO_RGB)\r
2015       info_ptr->color_type = (png_byte)(info_ptr->color_type |\r
2016          PNG_COLOR_MASK_COLOR);\r
2017 #endif\r
2018 \r
2019 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
2020    if (png_ptr->transformations & PNG_RGB_TO_GRAY)\r
2021       info_ptr->color_type = (png_byte)(info_ptr->color_type &\r
2022          ~PNG_COLOR_MASK_COLOR);\r
2023 #endif\r
2024 \r
2025 #ifdef PNG_READ_QUANTIZE_SUPPORTED\r
2026    if (png_ptr->transformations & PNG_QUANTIZE)\r
2027    {\r
2028       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||\r
2029           (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&\r
2030           png_ptr->palette_lookup && info_ptr->bit_depth == 8)\r
2031       {\r
2032          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;\r
2033       }\r
2034    }\r
2035 #endif\r
2036 \r
2037 #ifdef PNG_READ_EXPAND_16_SUPPORTED\r
2038    if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&\r
2039       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)\r
2040    {\r
2041       info_ptr->bit_depth = 16;\r
2042    }\r
2043 #endif\r
2044 \r
2045 #ifdef PNG_READ_PACK_SUPPORTED\r
2046    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))\r
2047       info_ptr->bit_depth = 8;\r
2048 #endif\r
2049 \r
2050    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
2051       info_ptr->channels = 1;\r
2052 \r
2053    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)\r
2054       info_ptr->channels = 3;\r
2055 \r
2056    else\r
2057       info_ptr->channels = 1;\r
2058 \r
2059 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED\r
2060    if (png_ptr->transformations & PNG_STRIP_ALPHA)\r
2061    {\r
2062       info_ptr->color_type = (png_byte)(info_ptr->color_type &\r
2063          ~PNG_COLOR_MASK_ALPHA);\r
2064       info_ptr->num_trans = 0;\r
2065    }\r
2066 #endif\r
2067 \r
2068    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)\r
2069       info_ptr->channels++;\r
2070 \r
2071 #ifdef PNG_READ_FILLER_SUPPORTED\r
2072    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */\r
2073    if ((png_ptr->transformations & PNG_FILLER) &&\r
2074        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||\r
2075        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))\r
2076    {\r
2077       info_ptr->channels++;\r
2078       /* If adding a true alpha channel not just filler */\r
2079       if (png_ptr->transformations & PNG_ADD_ALPHA)\r
2080          info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;\r
2081    }\r
2082 #endif\r
2083 \r
2084 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \\r
2085 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)\r
2086    if (png_ptr->transformations & PNG_USER_TRANSFORM)\r
2087    {\r
2088       if (info_ptr->bit_depth < png_ptr->user_transform_depth)\r
2089          info_ptr->bit_depth = png_ptr->user_transform_depth;\r
2090 \r
2091       if (info_ptr->channels < png_ptr->user_transform_channels)\r
2092          info_ptr->channels = png_ptr->user_transform_channels;\r
2093    }\r
2094 #endif\r
2095 \r
2096    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *\r
2097        info_ptr->bit_depth);\r
2098 \r
2099    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);\r
2100 \r
2101    /* Adding in 1.5.4: cache the above value in png_struct so that we can later\r
2102     * check in png_rowbytes that the user buffer won't get overwritten.  Note\r
2103     * that the field is not always set - if png_read_update_info isn't called\r
2104     * the application has to either not do any transforms or get the calculation\r
2105     * right itself.\r
2106     */\r
2107    png_ptr->info_rowbytes = info_ptr->rowbytes;\r
2108 \r
2109 #ifndef PNG_READ_EXPAND_SUPPORTED\r
2110    if (png_ptr)\r
2111       return;\r
2112 #endif\r
2113 }\r
2114 \r
2115 /* Transform the row.  The order of transformations is significant,\r
2116  * and is very touchy.  If you add a transformation, take care to\r
2117  * decide how it fits in with the other transformations here.\r
2118  */\r
2119 void /* PRIVATE */\r
2120 png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)\r
2121 {\r
2122    png_debug(1, "in png_do_read_transformations");\r
2123 \r
2124    if (png_ptr->row_buf == NULL)\r
2125    {\r
2126       /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this\r
2127        * error is incredibly rare and incredibly easy to debug without this\r
2128        * information.\r
2129        */\r
2130       png_error(png_ptr, "NULL row buffer");\r
2131    }\r
2132 \r
2133    /* The following is debugging; prior to 1.5.4 the code was never compiled in;\r
2134     * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro\r
2135     * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for\r
2136     * all transformations, however in practice the ROW_INIT always gets done on\r
2137     * demand, if necessary.\r
2138     */\r
2139    if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&\r
2140       !(png_ptr->flags & PNG_FLAG_ROW_INIT))\r
2141    {\r
2142       /* Application has failed to call either png_read_start_image() or\r
2143        * png_read_update_info() after setting transforms that expand pixels.\r
2144        * This check added to libpng-1.2.19 (but not enabled until 1.5.4).\r
2145        */\r
2146       png_error(png_ptr, "Uninitialized row");\r
2147    }\r
2148 \r
2149 #ifdef PNG_READ_EXPAND_SUPPORTED\r
2150    if (png_ptr->transformations & PNG_EXPAND)\r
2151    {\r
2152       if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)\r
2153       {\r
2154          png_do_expand_palette(row_info, png_ptr->row_buf + 1,\r
2155              png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);\r
2156       }\r
2157 \r
2158       else\r
2159       {\r
2160          if (png_ptr->num_trans &&\r
2161              (png_ptr->transformations & PNG_EXPAND_tRNS))\r
2162             png_do_expand(row_info, png_ptr->row_buf + 1,\r
2163                 &(png_ptr->trans_color));\r
2164 \r
2165          else\r
2166             png_do_expand(row_info, png_ptr->row_buf + 1,\r
2167                 NULL);\r
2168       }\r
2169    }\r
2170 #endif\r
2171 \r
2172 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED\r
2173    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&\r
2174       !(png_ptr->transformations & PNG_COMPOSE) &&\r
2175       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||\r
2176       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))\r
2177       png_do_strip_channel(row_info, png_ptr->row_buf + 1,\r
2178          0 /* at_start == false, because SWAP_ALPHA happens later */);\r
2179 #endif\r
2180 \r
2181 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
2182    if (png_ptr->transformations & PNG_RGB_TO_GRAY)\r
2183    {\r
2184       int rgb_error =\r
2185           png_do_rgb_to_gray(png_ptr, row_info,\r
2186               png_ptr->row_buf + 1);\r
2187 \r
2188       if (rgb_error)\r
2189       {\r
2190          png_ptr->rgb_to_gray_status=1;\r
2191          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==\r
2192              PNG_RGB_TO_GRAY_WARN)\r
2193             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");\r
2194 \r
2195          if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==\r
2196              PNG_RGB_TO_GRAY_ERR)\r
2197             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");\r
2198       }\r
2199    }\r
2200 #endif\r
2201 \r
2202 /* From Andreas Dilger e-mail to png-implement, 26 March 1998:\r
2203  *\r
2204  *   In most cases, the "simple transparency" should be done prior to doing\r
2205  *   gray-to-RGB, or you will have to test 3x as many bytes to check if a\r
2206  *   pixel is transparent.  You would also need to make sure that the\r
2207  *   transparency information is upgraded to RGB.\r
2208  *\r
2209  *   To summarize, the current flow is:\r
2210  *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite\r
2211  *                                   with background "in place" if transparent,\r
2212  *                                   convert to RGB if necessary\r
2213  *   - Gray + alpha -> composite with gray background and remove alpha bytes,\r
2214  *                                   convert to RGB if necessary\r
2215  *\r
2216  *   To support RGB backgrounds for gray images we need:\r
2217  *   - Gray + simple transparency -> convert to RGB + simple transparency,\r
2218  *                                   compare 3 or 6 bytes and composite with\r
2219  *                                   background "in place" if transparent\r
2220  *                                   (3x compare/pixel compared to doing\r
2221  *                                   composite with gray bkgrnd)\r
2222  *   - Gray + alpha -> convert to RGB + alpha, composite with background and\r
2223  *                                   remove alpha bytes (3x float\r
2224  *                                   operations/pixel compared with composite\r
2225  *                                   on gray background)\r
2226  *\r
2227  *  Greg's change will do this.  The reason it wasn't done before is for\r
2228  *  performance, as this increases the per-pixel operations.  If we would check\r
2229  *  in advance if the background was gray or RGB, and position the gray-to-RGB\r
2230  *  transform appropriately, then it would save a lot of work/time.\r
2231  */\r
2232 \r
2233 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED\r
2234    /* If gray -> RGB, do so now only if background is non-gray; else do later\r
2235     * for performance reasons\r
2236     */\r
2237    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&\r
2238        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))\r
2239       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);\r
2240 #endif\r
2241 \r
2242 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\\r
2243    defined(PNG_READ_ALPHA_MODE_SUPPORTED)\r
2244    if (png_ptr->transformations & PNG_COMPOSE)\r
2245       png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);\r
2246 #endif\r
2247 \r
2248 #ifdef PNG_READ_GAMMA_SUPPORTED\r
2249    if ((png_ptr->transformations & PNG_GAMMA) &&\r
2250 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
2251       /* Because RGB_TO_GRAY does the gamma transform. */\r
2252       !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&\r
2253 #endif\r
2254 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\\r
2255    defined(PNG_READ_ALPHA_MODE_SUPPORTED)\r
2256       /* Because PNG_COMPOSE does the gamma transform if there is something to\r
2257        * do (if there is an alpha channel or transparency.)\r
2258        */\r
2259        !((png_ptr->transformations & PNG_COMPOSE) &&\r
2260        ((png_ptr->num_trans != 0) ||\r
2261        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&\r
2262 #endif\r
2263       /* Because png_init_read_transformations transforms the palette, unless\r
2264        * RGB_TO_GRAY will do the transform.\r
2265        */\r
2266        (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))\r
2267       png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);\r
2268 #endif\r
2269 \r
2270 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED\r
2271    if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&\r
2272       (png_ptr->transformations & PNG_COMPOSE) &&\r
2273       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||\r
2274       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))\r
2275       png_do_strip_channel(row_info, png_ptr->row_buf + 1,\r
2276          0 /* at_start == false, because SWAP_ALPHA happens later */);\r
2277 #endif\r
2278 \r
2279 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED\r
2280    if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&\r
2281       (row_info->color_type & PNG_COLOR_MASK_ALPHA))\r
2282       png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);\r
2283 #endif\r
2284 \r
2285 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED\r
2286    if (png_ptr->transformations & PNG_SCALE_16_TO_8)\r
2287       png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);\r
2288 #endif\r
2289 \r
2290 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED\r
2291    /* There is no harm in doing both of these because only one has any effect,\r
2292     * by putting the 'scale' option first if the app asks for scale (either by\r
2293     * calling the API or in a TRANSFORM flag) this is what happens.\r
2294     */\r
2295    if (png_ptr->transformations & PNG_16_TO_8)\r
2296       png_do_chop(row_info, png_ptr->row_buf + 1);\r
2297 #endif\r
2298 \r
2299 #ifdef PNG_READ_QUANTIZE_SUPPORTED\r
2300    if (png_ptr->transformations & PNG_QUANTIZE)\r
2301    {\r
2302       png_do_quantize(row_info, png_ptr->row_buf + 1,\r
2303           png_ptr->palette_lookup, png_ptr->quantize_index);\r
2304 \r
2305       if (row_info->rowbytes == 0)\r
2306          png_error(png_ptr, "png_do_quantize returned rowbytes=0");\r
2307    }\r
2308 #endif /* PNG_READ_QUANTIZE_SUPPORTED */\r
2309 \r
2310 #ifdef PNG_READ_EXPAND_16_SUPPORTED\r
2311    /* Do the expansion now, after all the arithmetic has been done.  Notice\r
2312     * that previous transformations can handle the PNG_EXPAND_16 flag if this\r
2313     * is efficient (particularly true in the case of gamma correction, where\r
2314     * better accuracy results faster!)\r
2315     */\r
2316    if (png_ptr->transformations & PNG_EXPAND_16)\r
2317       png_do_expand_16(row_info, png_ptr->row_buf + 1);\r
2318 #endif\r
2319 \r
2320 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED\r
2321    /* NOTE: moved here in 1.5.4 (from much later in this list.) */\r
2322    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&\r
2323        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))\r
2324       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);\r
2325 #endif\r
2326 \r
2327 #ifdef PNG_READ_INVERT_SUPPORTED\r
2328    if (png_ptr->transformations & PNG_INVERT_MONO)\r
2329       png_do_invert(row_info, png_ptr->row_buf + 1);\r
2330 #endif\r
2331 \r
2332 #ifdef PNG_READ_SHIFT_SUPPORTED\r
2333    if (png_ptr->transformations & PNG_SHIFT)\r
2334       png_do_unshift(row_info, png_ptr->row_buf + 1,\r
2335           &(png_ptr->shift));\r
2336 #endif\r
2337 \r
2338 #ifdef PNG_READ_PACK_SUPPORTED\r
2339    if (png_ptr->transformations & PNG_PACK)\r
2340       png_do_unpack(row_info, png_ptr->row_buf + 1);\r
2341 #endif\r
2342 \r
2343 #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED\r
2344    /* Added at libpng-1.5.10 */\r
2345    if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&\r
2346        png_ptr->num_palette_max >= 0)\r
2347       png_do_check_palette_indexes(png_ptr, row_info);\r
2348 #endif\r
2349 \r
2350 #ifdef PNG_READ_BGR_SUPPORTED\r
2351    if (png_ptr->transformations & PNG_BGR)\r
2352       png_do_bgr(row_info, png_ptr->row_buf + 1);\r
2353 #endif\r
2354 \r
2355 #ifdef PNG_READ_PACKSWAP_SUPPORTED\r
2356    if (png_ptr->transformations & PNG_PACKSWAP)\r
2357       png_do_packswap(row_info, png_ptr->row_buf + 1);\r
2358 #endif\r
2359 \r
2360 #ifdef PNG_READ_FILLER_SUPPORTED\r
2361    if (png_ptr->transformations & PNG_FILLER)\r
2362       png_do_read_filler(row_info, png_ptr->row_buf + 1,\r
2363           (png_uint_32)png_ptr->filler, png_ptr->flags);\r
2364 #endif\r
2365 \r
2366 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED\r
2367    if (png_ptr->transformations & PNG_INVERT_ALPHA)\r
2368       png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);\r
2369 #endif\r
2370 \r
2371 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED\r
2372    if (png_ptr->transformations & PNG_SWAP_ALPHA)\r
2373       png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);\r
2374 #endif\r
2375 \r
2376 #ifdef PNG_READ_16BIT_SUPPORTED\r
2377 #ifdef PNG_READ_SWAP_SUPPORTED\r
2378    if (png_ptr->transformations & PNG_SWAP_BYTES)\r
2379       png_do_swap(row_info, png_ptr->row_buf + 1);\r
2380 #endif\r
2381 #endif\r
2382 \r
2383 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED\r
2384    if (png_ptr->transformations & PNG_USER_TRANSFORM)\r
2385     {\r
2386       if (png_ptr->read_user_transform_fn != NULL)\r
2387          (*(png_ptr->read_user_transform_fn)) /* User read transform function */\r
2388              (png_ptr,     /* png_ptr */\r
2389              row_info,     /* row_info: */\r
2390                 /*  png_uint_32 width;       width of row */\r
2391                 /*  png_size_t rowbytes;     number of bytes in row */\r
2392                 /*  png_byte color_type;     color type of pixels */\r
2393                 /*  png_byte bit_depth;      bit depth of samples */\r
2394                 /*  png_byte channels;       number of channels (1-4) */\r
2395                 /*  png_byte pixel_depth;    bits per pixel (depth*channels) */\r
2396              png_ptr->row_buf + 1);    /* start of pixel data for row */\r
2397 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED\r
2398       if (png_ptr->user_transform_depth)\r
2399          row_info->bit_depth = png_ptr->user_transform_depth;\r
2400 \r
2401       if (png_ptr->user_transform_channels)\r
2402          row_info->channels = png_ptr->user_transform_channels;\r
2403 #endif\r
2404       row_info->pixel_depth = (png_byte)(row_info->bit_depth *\r
2405           row_info->channels);\r
2406 \r
2407       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);\r
2408    }\r
2409 #endif\r
2410 }\r
2411 \r
2412 #ifdef PNG_READ_PACK_SUPPORTED\r
2413 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,\r
2414  * without changing the actual values.  Thus, if you had a row with\r
2415  * a bit depth of 1, you would end up with bytes that only contained\r
2416  * the numbers 0 or 1.  If you would rather they contain 0 and 255, use\r
2417  * png_do_shift() after this.\r
2418  */\r
2419 void /* PRIVATE */\r
2420 png_do_unpack(png_row_infop row_info, png_bytep row)\r
2421 {\r
2422    png_debug(1, "in png_do_unpack");\r
2423 \r
2424    if (row_info->bit_depth < 8)\r
2425    {\r
2426       png_uint_32 i;\r
2427       png_uint_32 row_width=row_info->width;\r
2428 \r
2429       switch (row_info->bit_depth)\r
2430       {\r
2431          case 1:\r
2432          {\r
2433             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);\r
2434             png_bytep dp = row + (png_size_t)row_width - 1;\r
2435             png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);\r
2436             for (i = 0; i < row_width; i++)\r
2437             {\r
2438                *dp = (png_byte)((*sp >> shift) & 0x01);\r
2439 \r
2440                if (shift == 7)\r
2441                {\r
2442                   shift = 0;\r
2443                   sp--;\r
2444                }\r
2445 \r
2446                else\r
2447                   shift++;\r
2448 \r
2449                dp--;\r
2450             }\r
2451             break;\r
2452          }\r
2453 \r
2454          case 2:\r
2455          {\r
2456 \r
2457             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);\r
2458             png_bytep dp = row + (png_size_t)row_width - 1;\r
2459             png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);\r
2460             for (i = 0; i < row_width; i++)\r
2461             {\r
2462                *dp = (png_byte)((*sp >> shift) & 0x03);\r
2463 \r
2464                if (shift == 6)\r
2465                {\r
2466                   shift = 0;\r
2467                   sp--;\r
2468                }\r
2469 \r
2470                else\r
2471                   shift += 2;\r
2472 \r
2473                dp--;\r
2474             }\r
2475             break;\r
2476          }\r
2477 \r
2478          case 4:\r
2479          {\r
2480             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);\r
2481             png_bytep dp = row + (png_size_t)row_width - 1;\r
2482             png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);\r
2483             for (i = 0; i < row_width; i++)\r
2484             {\r
2485                *dp = (png_byte)((*sp >> shift) & 0x0f);\r
2486 \r
2487                if (shift == 4)\r
2488                {\r
2489                   shift = 0;\r
2490                   sp--;\r
2491                }\r
2492 \r
2493                else\r
2494                   shift = 4;\r
2495 \r
2496                dp--;\r
2497             }\r
2498             break;\r
2499          }\r
2500 \r
2501          default:\r
2502             break;\r
2503       }\r
2504       row_info->bit_depth = 8;\r
2505       row_info->pixel_depth = (png_byte)(8 * row_info->channels);\r
2506       row_info->rowbytes = row_width * row_info->channels;\r
2507    }\r
2508 }\r
2509 #endif\r
2510 \r
2511 #ifdef PNG_READ_SHIFT_SUPPORTED\r
2512 /* Reverse the effects of png_do_shift.  This routine merely shifts the\r
2513  * pixels back to their significant bits values.  Thus, if you have\r
2514  * a row of bit depth 8, but only 5 are significant, this will shift\r
2515  * the values back to 0 through 31.\r
2516  */\r
2517 void /* PRIVATE */\r
2518 png_do_unshift(png_row_infop row_info, png_bytep row,\r
2519     png_const_color_8p sig_bits)\r
2520 {\r
2521    int color_type;\r
2522 \r
2523    png_debug(1, "in png_do_unshift");\r
2524 \r
2525    /* The palette case has already been handled in the _init routine. */\r
2526    color_type = row_info->color_type;\r
2527 \r
2528    if (color_type != PNG_COLOR_TYPE_PALETTE)\r
2529    {\r
2530       int shift[4];\r
2531       int channels = 0;\r
2532       int bit_depth = row_info->bit_depth;\r
2533 \r
2534       if (color_type & PNG_COLOR_MASK_COLOR)\r
2535       {\r
2536          shift[channels++] = bit_depth - sig_bits->red;\r
2537          shift[channels++] = bit_depth - sig_bits->green;\r
2538          shift[channels++] = bit_depth - sig_bits->blue;\r
2539       }\r
2540 \r
2541       else\r
2542       {\r
2543          shift[channels++] = bit_depth - sig_bits->gray;\r
2544       }\r
2545 \r
2546       if (color_type & PNG_COLOR_MASK_ALPHA)\r
2547       {\r
2548          shift[channels++] = bit_depth - sig_bits->alpha;\r
2549       }\r
2550 \r
2551       {\r
2552          int c, have_shift;\r
2553 \r
2554          for (c = have_shift = 0; c < channels; ++c)\r
2555          {\r
2556             /* A shift of more than the bit depth is an error condition but it\r
2557              * gets ignored here.\r
2558              */\r
2559             if (shift[c] <= 0 || shift[c] >= bit_depth)\r
2560                shift[c] = 0;\r
2561 \r
2562             else\r
2563                have_shift = 1;\r
2564          }\r
2565 \r
2566          if (!have_shift)\r
2567             return;\r
2568       }\r
2569 \r
2570       switch (bit_depth)\r
2571       {\r
2572          default:\r
2573          /* Must be 1bpp gray: should not be here! */\r
2574             /* NOTREACHED */\r
2575             break;\r
2576 \r
2577          case 2:\r
2578          /* Must be 2bpp gray */\r
2579          /* assert(channels == 1 && shift[0] == 1) */\r
2580          {\r
2581             png_bytep bp = row;\r
2582             png_bytep bp_end = bp + row_info->rowbytes;\r
2583 \r
2584             while (bp < bp_end)\r
2585             {\r
2586                int b = (*bp >> 1) & 0x55;\r
2587                *bp++ = (png_byte)b;\r
2588             }\r
2589             break;\r
2590          }\r
2591 \r
2592          case 4:\r
2593          /* Must be 4bpp gray */\r
2594          /* assert(channels == 1) */\r
2595          {\r
2596             png_bytep bp = row;\r
2597             png_bytep bp_end = bp + row_info->rowbytes;\r
2598             int gray_shift = shift[0];\r
2599             int mask =  0xf >> gray_shift;\r
2600 \r
2601             mask |= mask << 4;\r
2602 \r
2603             while (bp < bp_end)\r
2604             {\r
2605                int b = (*bp >> gray_shift) & mask;\r
2606                *bp++ = (png_byte)b;\r
2607             }\r
2608             break;\r
2609          }\r
2610 \r
2611          case 8:\r
2612          /* Single byte components, G, GA, RGB, RGBA */\r
2613          {\r
2614             png_bytep bp = row;\r
2615             png_bytep bp_end = bp + row_info->rowbytes;\r
2616             int channel = 0;\r
2617 \r
2618             while (bp < bp_end)\r
2619             {\r
2620                int b = *bp >> shift[channel];\r
2621                if (++channel >= channels)\r
2622                   channel = 0;\r
2623                *bp++ = (png_byte)b;\r
2624             }\r
2625             break;\r
2626          }\r
2627 \r
2628 #ifdef PNG_READ_16BIT_SUPPORTED\r
2629          case 16:\r
2630          /* Double byte components, G, GA, RGB, RGBA */\r
2631          {\r
2632             png_bytep bp = row;\r
2633             png_bytep bp_end = bp + row_info->rowbytes;\r
2634             int channel = 0;\r
2635 \r
2636             while (bp < bp_end)\r
2637             {\r
2638                int value = (bp[0] << 8) + bp[1];\r
2639 \r
2640                value >>= shift[channel];\r
2641                if (++channel >= channels)\r
2642                   channel = 0;\r
2643                *bp++ = (png_byte)(value >> 8);\r
2644                *bp++ = (png_byte)(value & 0xff);\r
2645             }\r
2646             break;\r
2647          }\r
2648 #endif\r
2649       }\r
2650    }\r
2651 }\r
2652 #endif\r
2653 \r
2654 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED\r
2655 /* Scale rows of bit depth 16 down to 8 accurately */\r
2656 void /* PRIVATE */\r
2657 png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)\r
2658 {\r
2659    png_debug(1, "in png_do_scale_16_to_8");\r
2660 \r
2661    if (row_info->bit_depth == 16)\r
2662    {\r
2663       png_bytep sp = row; /* source */\r
2664       png_bytep dp = row; /* destination */\r
2665       png_bytep ep = sp + row_info->rowbytes; /* end+1 */\r
2666 \r
2667       while (sp < ep)\r
2668       {\r
2669          /* The input is an array of 16 bit components, these must be scaled to\r
2670           * 8 bits each.  For a 16 bit value V the required value (from the PNG\r
2671           * specification) is:\r
2672           *\r
2673           *    (V * 255) / 65535\r
2674           *\r
2675           * This reduces to round(V / 257), or floor((V + 128.5)/257)\r
2676           *\r
2677           * Represent V as the two byte value vhi.vlo.  Make a guess that the\r
2678           * result is the top byte of V, vhi, then the correction to this value\r
2679           * is:\r
2680           *\r
2681           *    error = floor(((V-vhi.vhi) + 128.5) / 257)\r
2682           *          = floor(((vlo-vhi) + 128.5) / 257)\r
2683           *\r
2684           * This can be approximated using integer arithmetic (and a signed\r
2685           * shift):\r
2686           *\r
2687           *    error = (vlo-vhi+128) >> 8;\r
2688           *\r
2689           * The approximate differs from the exact answer only when (vlo-vhi) is\r
2690           * 128; it then gives a correction of +1 when the exact correction is\r
2691           * 0.  This gives 128 errors.  The exact answer (correct for all 16 bit\r
2692           * input values) is:\r
2693           *\r
2694           *    error = (vlo-vhi+128)*65535 >> 24;\r
2695           *\r
2696           * An alternative arithmetic calculation which also gives no errors is:\r
2697           *\r
2698           *    (V * 255 + 32895) >> 16\r
2699           */\r
2700 \r
2701          png_int_32 tmp = *sp++; /* must be signed! */\r
2702          tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;\r
2703          *dp++ = (png_byte)tmp;\r
2704       }\r
2705 \r
2706       row_info->bit_depth = 8;\r
2707       row_info->pixel_depth = (png_byte)(8 * row_info->channels);\r
2708       row_info->rowbytes = row_info->width * row_info->channels;\r
2709    }\r
2710 }\r
2711 #endif\r
2712 \r
2713 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED\r
2714 void /* PRIVATE */\r
2715 /* Simply discard the low byte.  This was the default behavior prior\r
2716  * to libpng-1.5.4.\r
2717  */\r
2718 png_do_chop(png_row_infop row_info, png_bytep row)\r
2719 {\r
2720    png_debug(1, "in png_do_chop");\r
2721 \r
2722    if (row_info->bit_depth == 16)\r
2723    {\r
2724       png_bytep sp = row; /* source */\r
2725       png_bytep dp = row; /* destination */\r
2726       png_bytep ep = sp + row_info->rowbytes; /* end+1 */\r
2727 \r
2728       while (sp < ep)\r
2729       {\r
2730          *dp++ = *sp;\r
2731          sp += 2; /* skip low byte */\r
2732       }\r
2733 \r
2734       row_info->bit_depth = 8;\r
2735       row_info->pixel_depth = (png_byte)(8 * row_info->channels);\r
2736       row_info->rowbytes = row_info->width * row_info->channels;\r
2737    }\r
2738 }\r
2739 #endif\r
2740 \r
2741 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED\r
2742 void /* PRIVATE */\r
2743 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)\r
2744 {\r
2745    png_debug(1, "in png_do_read_swap_alpha");\r
2746 \r
2747    {\r
2748       png_uint_32 row_width = row_info->width;\r
2749       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)\r
2750       {\r
2751          /* This converts from RGBA to ARGB */\r
2752          if (row_info->bit_depth == 8)\r
2753          {\r
2754             png_bytep sp = row + row_info->rowbytes;\r
2755             png_bytep dp = sp;\r
2756             png_byte save;\r
2757             png_uint_32 i;\r
2758 \r
2759             for (i = 0; i < row_width; i++)\r
2760             {\r
2761                save = *(--sp);\r
2762                *(--dp) = *(--sp);\r
2763                *(--dp) = *(--sp);\r
2764                *(--dp) = *(--sp);\r
2765                *(--dp) = save;\r
2766             }\r
2767          }\r
2768 \r
2769 #ifdef PNG_READ_16BIT_SUPPORTED\r
2770          /* This converts from RRGGBBAA to AARRGGBB */\r
2771          else\r
2772          {\r
2773             png_bytep sp = row + row_info->rowbytes;\r
2774             png_bytep dp = sp;\r
2775             png_byte save[2];\r
2776             png_uint_32 i;\r
2777 \r
2778             for (i = 0; i < row_width; i++)\r
2779             {\r
2780                save[0] = *(--sp);\r
2781                save[1] = *(--sp);\r
2782                *(--dp) = *(--sp);\r
2783                *(--dp) = *(--sp);\r
2784                *(--dp) = *(--sp);\r
2785                *(--dp) = *(--sp);\r
2786                *(--dp) = *(--sp);\r
2787                *(--dp) = *(--sp);\r
2788                *(--dp) = save[0];\r
2789                *(--dp) = save[1];\r
2790             }\r
2791          }\r
2792 #endif\r
2793       }\r
2794 \r
2795       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)\r
2796       {\r
2797          /* This converts from GA to AG */\r
2798          if (row_info->bit_depth == 8)\r
2799          {\r
2800             png_bytep sp = row + row_info->rowbytes;\r
2801             png_bytep dp = sp;\r
2802             png_byte save;\r
2803             png_uint_32 i;\r
2804 \r
2805             for (i = 0; i < row_width; i++)\r
2806             {\r
2807                save = *(--sp);\r
2808                *(--dp) = *(--sp);\r
2809                *(--dp) = save;\r
2810             }\r
2811          }\r
2812 \r
2813 #ifdef PNG_READ_16BIT_SUPPORTED\r
2814          /* This converts from GGAA to AAGG */\r
2815          else\r
2816          {\r
2817             png_bytep sp = row + row_info->rowbytes;\r
2818             png_bytep dp = sp;\r
2819             png_byte save[2];\r
2820             png_uint_32 i;\r
2821 \r
2822             for (i = 0; i < row_width; i++)\r
2823             {\r
2824                save[0] = *(--sp);\r
2825                save[1] = *(--sp);\r
2826                *(--dp) = *(--sp);\r
2827                *(--dp) = *(--sp);\r
2828                *(--dp) = save[0];\r
2829                *(--dp) = save[1];\r
2830             }\r
2831          }\r
2832 #endif\r
2833       }\r
2834    }\r
2835 }\r
2836 #endif\r
2837 \r
2838 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED\r
2839 void /* PRIVATE */\r
2840 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)\r
2841 {\r
2842    png_uint_32 row_width;\r
2843    png_debug(1, "in png_do_read_invert_alpha");\r
2844 \r
2845    row_width = row_info->width;\r
2846    if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)\r
2847    {\r
2848       if (row_info->bit_depth == 8)\r
2849       {\r
2850          /* This inverts the alpha channel in RGBA */\r
2851          png_bytep sp = row + row_info->rowbytes;\r
2852          png_bytep dp = sp;\r
2853          png_uint_32 i;\r
2854 \r
2855          for (i = 0; i < row_width; i++)\r
2856          {\r
2857             *(--dp) = (png_byte)(255 - *(--sp));\r
2858 \r
2859 /*          This does nothing:\r
2860             *(--dp) = *(--sp);\r
2861             *(--dp) = *(--sp);\r
2862             *(--dp) = *(--sp);\r
2863             We can replace it with:\r
2864 */\r
2865             sp-=3;\r
2866             dp=sp;\r
2867          }\r
2868       }\r
2869 \r
2870 #ifdef PNG_READ_16BIT_SUPPORTED\r
2871       /* This inverts the alpha channel in RRGGBBAA */\r
2872       else\r
2873       {\r
2874          png_bytep sp = row + row_info->rowbytes;\r
2875          png_bytep dp = sp;\r
2876          png_uint_32 i;\r
2877 \r
2878          for (i = 0; i < row_width; i++)\r
2879          {\r
2880             *(--dp) = (png_byte)(255 - *(--sp));\r
2881             *(--dp) = (png_byte)(255 - *(--sp));\r
2882 \r
2883 /*          This does nothing:\r
2884             *(--dp) = *(--sp);\r
2885             *(--dp) = *(--sp);\r
2886             *(--dp) = *(--sp);\r
2887             *(--dp) = *(--sp);\r
2888             *(--dp) = *(--sp);\r
2889             *(--dp) = *(--sp);\r
2890             We can replace it with:\r
2891 */\r
2892             sp-=6;\r
2893             dp=sp;\r
2894          }\r
2895       }\r
2896 #endif\r
2897    }\r
2898    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)\r
2899    {\r
2900       if (row_info->bit_depth == 8)\r
2901       {\r
2902          /* This inverts the alpha channel in GA */\r
2903          png_bytep sp = row + row_info->rowbytes;\r
2904          png_bytep dp = sp;\r
2905          png_uint_32 i;\r
2906 \r
2907          for (i = 0; i < row_width; i++)\r
2908          {\r
2909             *(--dp) = (png_byte)(255 - *(--sp));\r
2910             *(--dp) = *(--sp);\r
2911          }\r
2912       }\r
2913 \r
2914 #ifdef PNG_READ_16BIT_SUPPORTED\r
2915       else\r
2916       {\r
2917          /* This inverts the alpha channel in GGAA */\r
2918          png_bytep sp  = row + row_info->rowbytes;\r
2919          png_bytep dp = sp;\r
2920          png_uint_32 i;\r
2921 \r
2922          for (i = 0; i < row_width; i++)\r
2923          {\r
2924             *(--dp) = (png_byte)(255 - *(--sp));\r
2925             *(--dp) = (png_byte)(255 - *(--sp));\r
2926 /*\r
2927             *(--dp) = *(--sp);\r
2928             *(--dp) = *(--sp);\r
2929 */\r
2930             sp-=2;\r
2931             dp=sp;\r
2932          }\r
2933       }\r
2934 #endif\r
2935    }\r
2936 }\r
2937 #endif\r
2938 \r
2939 #ifdef PNG_READ_FILLER_SUPPORTED\r
2940 /* Add filler channel if we have RGB color */\r
2941 void /* PRIVATE */\r
2942 png_do_read_filler(png_row_infop row_info, png_bytep row,\r
2943     png_uint_32 filler, png_uint_32 flags)\r
2944 {\r
2945    png_uint_32 i;\r
2946    png_uint_32 row_width = row_info->width;\r
2947 \r
2948 #ifdef PNG_READ_16BIT_SUPPORTED\r
2949    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);\r
2950 #endif\r
2951    png_byte lo_filler = (png_byte)(filler & 0xff);\r
2952 \r
2953    png_debug(1, "in png_do_read_filler");\r
2954 \r
2955    if (\r
2956        row_info->color_type == PNG_COLOR_TYPE_GRAY)\r
2957    {\r
2958       if (row_info->bit_depth == 8)\r
2959       {\r
2960          if (flags & PNG_FLAG_FILLER_AFTER)\r
2961          {\r
2962             /* This changes the data from G to GX */\r
2963             png_bytep sp = row + (png_size_t)row_width;\r
2964             png_bytep dp =  sp + (png_size_t)row_width;\r
2965             for (i = 1; i < row_width; i++)\r
2966             {\r
2967                *(--dp) = lo_filler;\r
2968                *(--dp) = *(--sp);\r
2969             }\r
2970             *(--dp) = lo_filler;\r
2971             row_info->channels = 2;\r
2972             row_info->pixel_depth = 16;\r
2973             row_info->rowbytes = row_width * 2;\r
2974          }\r
2975 \r
2976          else\r
2977          {\r
2978             /* This changes the data from G to XG */\r
2979             png_bytep sp = row + (png_size_t)row_width;\r
2980             png_bytep dp = sp  + (png_size_t)row_width;\r
2981             for (i = 0; i < row_width; i++)\r
2982             {\r
2983                *(--dp) = *(--sp);\r
2984                *(--dp) = lo_filler;\r
2985             }\r
2986             row_info->channels = 2;\r
2987             row_info->pixel_depth = 16;\r
2988             row_info->rowbytes = row_width * 2;\r
2989          }\r
2990       }\r
2991 \r
2992 #ifdef PNG_READ_16BIT_SUPPORTED\r
2993       else if (row_info->bit_depth == 16)\r
2994       {\r
2995          if (flags & PNG_FLAG_FILLER_AFTER)\r
2996          {\r
2997             /* This changes the data from GG to GGXX */\r
2998             png_bytep sp = row + (png_size_t)row_width * 2;\r
2999             png_bytep dp = sp  + (png_size_t)row_width * 2;\r
3000             for (i = 1; i < row_width; i++)\r
3001             {\r
3002                *(--dp) = hi_filler;\r
3003                *(--dp) = lo_filler;\r
3004                *(--dp) = *(--sp);\r
3005                *(--dp) = *(--sp);\r
3006             }\r
3007             *(--dp) = hi_filler;\r
3008             *(--dp) = lo_filler;\r
3009             row_info->channels = 2;\r
3010             row_info->pixel_depth = 32;\r
3011             row_info->rowbytes = row_width * 4;\r
3012          }\r
3013 \r
3014          else\r
3015          {\r
3016             /* This changes the data from GG to XXGG */\r
3017             png_bytep sp = row + (png_size_t)row_width * 2;\r
3018             png_bytep dp = sp  + (png_size_t)row_width * 2;\r
3019             for (i = 0; i < row_width; i++)\r
3020             {\r
3021                *(--dp) = *(--sp);\r
3022                *(--dp) = *(--sp);\r
3023                *(--dp) = hi_filler;\r
3024                *(--dp) = lo_filler;\r
3025             }\r
3026             row_info->channels = 2;\r
3027             row_info->pixel_depth = 32;\r
3028             row_info->rowbytes = row_width * 4;\r
3029          }\r
3030       }\r
3031 #endif\r
3032    } /* COLOR_TYPE == GRAY */\r
3033    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)\r
3034    {\r
3035       if (row_info->bit_depth == 8)\r
3036       {\r
3037          if (flags & PNG_FLAG_FILLER_AFTER)\r
3038          {\r
3039             /* This changes the data from RGB to RGBX */\r
3040             png_bytep sp = row + (png_size_t)row_width * 3;\r
3041             png_bytep dp = sp  + (png_size_t)row_width;\r
3042             for (i = 1; i < row_width; i++)\r
3043             {\r
3044                *(--dp) = lo_filler;\r
3045                *(--dp) = *(--sp);\r
3046                *(--dp) = *(--sp);\r
3047                *(--dp) = *(--sp);\r
3048             }\r
3049             *(--dp) = lo_filler;\r
3050             row_info->channels = 4;\r
3051             row_info->pixel_depth = 32;\r
3052             row_info->rowbytes = row_width * 4;\r
3053          }\r
3054 \r
3055          else\r
3056          {\r
3057             /* This changes the data from RGB to XRGB */\r
3058             png_bytep sp = row + (png_size_t)row_width * 3;\r
3059             png_bytep dp = sp + (png_size_t)row_width;\r
3060             for (i = 0; i < row_width; i++)\r
3061             {\r
3062                *(--dp) = *(--sp);\r
3063                *(--dp) = *(--sp);\r
3064                *(--dp) = *(--sp);\r
3065                *(--dp) = lo_filler;\r
3066             }\r
3067             row_info->channels = 4;\r