OSDN Git Service

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