/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/png/pngrtran.c
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/png/pngrtran.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 5 months ago) by william
File MIME type: text/plain
File size: 147885 byte(s)
committing r3113 initial commit again...
1 william 31
2     /* pngrtran.c - transforms the data in a row for PNG readers
3     *
4     * Last changed in libpng 1.2.38 [July 16, 2009]
5     * Copyright (c) 1998-2009 Glenn Randers-Pehrson
6     * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7     * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8     *
9     * This code is released under the libpng license.
10     * For conditions of distribution and use, see the disclaimer
11     * and license in png.h
12     *
13     * This file contains functions optionally called by an application
14     * in order to tell libpng how to handle data when reading a PNG.
15     * Transformations that are used in both reading and writing are
16     * in pngtrans.c.
17     */
18    
19     #define PNG_INTERNAL
20     #include "png.h"
21     #if defined(PNG_READ_SUPPORTED)
22    
23     /* Set the action on getting a CRC error for an ancillary or critical chunk. */
24     void PNGAPI
25     png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
26     {
27     png_debug(1, "in png_set_crc_action");
28     /* Tell libpng how we react to CRC errors in critical chunks */
29     if (png_ptr == NULL)
30     return;
31     switch (crit_action)
32     {
33     case PNG_CRC_NO_CHANGE: /* Leave setting as is */
34     break;
35    
36     case PNG_CRC_WARN_USE: /* Warn/use data */
37     png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
38     png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
39     break;
40    
41     case PNG_CRC_QUIET_USE: /* Quiet/use data */
42     png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
43     png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
44     PNG_FLAG_CRC_CRITICAL_IGNORE;
45     break;
46    
47     case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
48     png_warning(png_ptr,
49     "Can't discard critical data on CRC error.");
50     case PNG_CRC_ERROR_QUIT: /* Error/quit */
51    
52     case PNG_CRC_DEFAULT:
53     default:
54     png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
55     break;
56     }
57    
58     switch (ancil_action)
59     {
60     case PNG_CRC_NO_CHANGE: /* Leave setting as is */
61     break;
62    
63     case PNG_CRC_WARN_USE: /* Warn/use data */
64     png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
65     png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
66     break;
67    
68     case PNG_CRC_QUIET_USE: /* Quiet/use data */
69     png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
70     png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
71     PNG_FLAG_CRC_ANCILLARY_NOWARN;
72     break;
73    
74     case PNG_CRC_ERROR_QUIT: /* Error/quit */
75     png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
76     png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
77     break;
78    
79     case PNG_CRC_WARN_DISCARD: /* Warn/discard data */
80    
81     case PNG_CRC_DEFAULT:
82     default:
83     png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
84     break;
85     }
86     }
87    
88     #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
89     defined(PNG_FLOATING_POINT_SUPPORTED)
90     /* Handle alpha and tRNS via a background color */
91     void PNGAPI
92     png_set_background(png_structp png_ptr,
93     png_color_16p background_color, int background_gamma_code,
94     int need_expand, double background_gamma)
95     {
96     png_debug(1, "in png_set_background");
97     if (png_ptr == NULL)
98     return;
99     if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
100     {
101     png_warning(png_ptr, "Application must supply a known background gamma");
102     return;
103     }
104    
105     png_ptr->transformations |= PNG_BACKGROUND;
106     png_memcpy(&(png_ptr->background), background_color,
107     png_sizeof(png_color_16));
108     png_ptr->background_gamma = (float)background_gamma;
109     png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
110     png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
111     }
112     #endif
113    
114     #if defined(PNG_READ_16_TO_8_SUPPORTED)
115     /* Strip 16 bit depth files to 8 bit depth */
116     void PNGAPI
117     png_set_strip_16(png_structp png_ptr)
118     {
119     png_debug(1, "in png_set_strip_16");
120     if (png_ptr == NULL)
121     return;
122     png_ptr->transformations |= PNG_16_TO_8;
123     }
124     #endif
125    
126     #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
127     void PNGAPI
128     png_set_strip_alpha(png_structp png_ptr)
129     {
130     png_debug(1, "in png_set_strip_alpha");
131     if (png_ptr == NULL)
132     return;
133     png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
134     }
135     #endif
136    
137     #if defined(PNG_READ_DITHER_SUPPORTED)
138     /* Dither file to 8 bit. Supply a palette, the current number
139     * of elements in the palette, the maximum number of elements
140     * allowed, and a histogram if possible. If the current number
141     * of colors is greater then the maximum number, the palette will be
142     * modified to fit in the maximum number. "full_dither" indicates
143     * whether we need a dithering cube set up for RGB images, or if we
144     * simply are reducing the number of colors in a paletted image.
145     */
146    
147     typedef struct png_dsort_struct
148     {
149     struct png_dsort_struct FAR * next;
150     png_byte left;
151     png_byte right;
152     } png_dsort;
153     typedef png_dsort FAR * png_dsortp;
154     typedef png_dsort FAR * FAR * png_dsortpp;
155    
156     void PNGAPI
157     png_set_dither(png_structp png_ptr, png_colorp palette,
158     int num_palette, int maximum_colors, png_uint_16p histogram,
159     int full_dither)
160     {
161     png_debug(1, "in png_set_dither");
162     if (png_ptr == NULL)
163     return;
164     png_ptr->transformations |= PNG_DITHER;
165    
166     if (!full_dither)
167     {
168     int i;
169    
170     png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
171     (png_uint_32)(num_palette * png_sizeof(png_byte)));
172     for (i = 0; i < num_palette; i++)
173     png_ptr->dither_index[i] = (png_byte)i;
174     }
175    
176     if (num_palette > maximum_colors)
177     {
178     if (histogram != NULL)
179     {
180     /* This is easy enough, just throw out the least used colors.
181     * Perhaps not the best solution, but good enough.
182     */
183    
184     int i;
185    
186     /* Initialize an array to sort colors */
187     png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
188     (png_uint_32)(num_palette * png_sizeof(png_byte)));
189    
190     /* Initialize the dither_sort array */
191     for (i = 0; i < num_palette; i++)
192     png_ptr->dither_sort[i] = (png_byte)i;
193    
194     /* Find the least used palette entries by starting a
195     * bubble sort, and running it until we have sorted
196     * out enough colors. Note that we don't care about
197     * sorting all the colors, just finding which are
198     * least used.
199     */
200    
201     for (i = num_palette - 1; i >= maximum_colors; i--)
202     {
203     int done; /* To stop early if the list is pre-sorted */
204     int j;
205    
206     done = 1;
207     for (j = 0; j < i; j++)
208     {
209     if (histogram[png_ptr->dither_sort[j]]
210     < histogram[png_ptr->dither_sort[j + 1]])
211     {
212     png_byte t;
213    
214     t = png_ptr->dither_sort[j];
215     png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
216     png_ptr->dither_sort[j + 1] = t;
217     done = 0;
218     }
219     }
220     if (done)
221     break;
222     }
223    
224     /* Swap the palette around, and set up a table, if necessary */
225     if (full_dither)
226     {
227     int j = num_palette;
228    
229     /* Put all the useful colors within the max, but don't
230     * move the others.
231     */
232     for (i = 0; i < maximum_colors; i++)
233     {
234     if ((int)png_ptr->dither_sort[i] >= maximum_colors)
235     {
236     do
237     j--;
238     while ((int)png_ptr->dither_sort[j] >= maximum_colors);
239     palette[i] = palette[j];
240     }
241     }
242     }
243     else
244     {
245     int j = num_palette;
246    
247     /* Move all the used colors inside the max limit, and
248     * develop a translation table.
249     */
250     for (i = 0; i < maximum_colors; i++)
251     {
252     /* Only move the colors we need to */
253     if ((int)png_ptr->dither_sort[i] >= maximum_colors)
254     {
255     png_color tmp_color;
256    
257     do
258     j--;
259     while ((int)png_ptr->dither_sort[j] >= maximum_colors);
260    
261     tmp_color = palette[j];
262     palette[j] = palette[i];
263     palette[i] = tmp_color;
264     /* Indicate where the color went */
265     png_ptr->dither_index[j] = (png_byte)i;
266     png_ptr->dither_index[i] = (png_byte)j;
267     }
268     }
269    
270     /* Find closest color for those colors we are not using */
271     for (i = 0; i < num_palette; i++)
272     {
273     if ((int)png_ptr->dither_index[i] >= maximum_colors)
274     {
275     int min_d, k, min_k, d_index;
276    
277     /* Find the closest color to one we threw out */
278     d_index = png_ptr->dither_index[i];
279     min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
280     for (k = 1, min_k = 0; k < maximum_colors; k++)
281     {
282     int d;
283    
284     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
285    
286     if (d < min_d)
287     {
288     min_d = d;
289     min_k = k;
290     }
291     }
292     /* Point to closest color */
293     png_ptr->dither_index[i] = (png_byte)min_k;
294     }
295     }
296     }
297     png_free(png_ptr, png_ptr->dither_sort);
298     png_ptr->dither_sort = NULL;
299     }
300     else
301     {
302     /* This is much harder to do simply (and quickly). Perhaps
303     * we need to go through a median cut routine, but those
304     * don't always behave themselves with only a few colors
305     * as input. So we will just find the closest two colors,
306     * and throw out one of them (chosen somewhat randomly).
307     * [We don't understand this at all, so if someone wants to
308     * work on improving it, be our guest - AED, GRP]
309     */
310     int i;
311     int max_d;
312     int num_new_palette;
313     png_dsortp t;
314     png_dsortpp hash;
315    
316     t = NULL;
317    
318     /* Initialize palette index arrays */
319     png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
320     (png_uint_32)(num_palette * png_sizeof(png_byte)));
321     png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
322     (png_uint_32)(num_palette * png_sizeof(png_byte)));
323    
324     /* Initialize the sort array */
325     for (i = 0; i < num_palette; i++)
326     {
327     png_ptr->index_to_palette[i] = (png_byte)i;
328     png_ptr->palette_to_index[i] = (png_byte)i;
329     }
330    
331     hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
332     png_sizeof(png_dsortp)));
333     png_memset(hash, 0, 769 * png_sizeof(png_dsortp));
334    
335     num_new_palette = num_palette;
336    
337     /* Initial wild guess at how far apart the farthest pixel
338     * pair we will be eliminating will be. Larger
339     * numbers mean more areas will be allocated, Smaller
340     * numbers run the risk of not saving enough data, and
341     * having to do this all over again.
342     *
343     * I have not done extensive checking on this number.
344     */
345     max_d = 96;
346    
347     while (num_new_palette > maximum_colors)
348     {
349     for (i = 0; i < num_new_palette - 1; i++)
350     {
351     int j;
352    
353     for (j = i + 1; j < num_new_palette; j++)
354     {
355     int d;
356    
357     d = PNG_COLOR_DIST(palette[i], palette[j]);
358    
359     if (d <= max_d)
360     {
361    
362     t = (png_dsortp)png_malloc_warn(png_ptr,
363     (png_uint_32)(png_sizeof(png_dsort)));
364     if (t == NULL)
365     break;
366     t->next = hash[d];
367     t->left = (png_byte)i;
368     t->right = (png_byte)j;
369     hash[d] = t;
370     }
371     }
372     if (t == NULL)
373     break;
374     }
375    
376     if (t != NULL)
377     for (i = 0; i <= max_d; i++)
378     {
379     if (hash[i] != NULL)
380     {
381     png_dsortp p;
382    
383     for (p = hash[i]; p; p = p->next)
384     {
385     if ((int)png_ptr->index_to_palette[p->left]
386     < num_new_palette &&
387     (int)png_ptr->index_to_palette[p->right]
388     < num_new_palette)
389     {
390     int j, next_j;
391    
392     if (num_new_palette & 0x01)
393     {
394     j = p->left;
395     next_j = p->right;
396     }
397     else
398     {
399     j = p->right;
400     next_j = p->left;
401     }
402    
403     num_new_palette--;
404     palette[png_ptr->index_to_palette[j]]
405     = palette[num_new_palette];
406     if (!full_dither)
407     {
408     int k;
409    
410     for (k = 0; k < num_palette; k++)
411     {
412     if (png_ptr->dither_index[k] ==
413     png_ptr->index_to_palette[j])
414     png_ptr->dither_index[k] =
415     png_ptr->index_to_palette[next_j];
416     if ((int)png_ptr->dither_index[k] ==
417     num_new_palette)
418     png_ptr->dither_index[k] =
419     png_ptr->index_to_palette[j];
420     }
421     }
422    
423     png_ptr->index_to_palette[png_ptr->palette_to_index
424     [num_new_palette]] = png_ptr->index_to_palette[j];
425     png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
426     = png_ptr->palette_to_index[num_new_palette];
427    
428     png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
429     png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
430     }
431     if (num_new_palette <= maximum_colors)
432     break;
433     }
434     if (num_new_palette <= maximum_colors)
435     break;
436     }
437     }
438    
439     for (i = 0; i < 769; i++)
440     {
441     if (hash[i] != NULL)
442     {
443     png_dsortp p = hash[i];
444     while (p)
445     {
446     t = p->next;
447     png_free(png_ptr, p);
448     p = t;
449     }
450     }
451     hash[i] = 0;
452     }
453     max_d += 96;
454     }
455     png_free(png_ptr, hash);
456     png_free(png_ptr, png_ptr->palette_to_index);
457     png_free(png_ptr, png_ptr->index_to_palette);
458     png_ptr->palette_to_index = NULL;
459     png_ptr->index_to_palette = NULL;
460     }
461     num_palette = maximum_colors;
462     }
463     if (png_ptr->palette == NULL)
464     {
465     png_ptr->palette = palette;
466     }
467     png_ptr->num_palette = (png_uint_16)num_palette;
468    
469     if (full_dither)
470     {
471     int i;
472     png_bytep distance;
473     int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
474     PNG_DITHER_BLUE_BITS;
475     int num_red = (1 << PNG_DITHER_RED_BITS);
476     int num_green = (1 << PNG_DITHER_GREEN_BITS);
477     int num_blue = (1 << PNG_DITHER_BLUE_BITS);
478     png_size_t num_entries = ((png_size_t)1 << total_bits);
479     png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
480     (png_uint_32)(num_entries * png_sizeof(png_byte)));
481     png_memset(png_ptr->palette_lookup, 0, num_entries *
482     png_sizeof(png_byte));
483    
484     distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
485     png_sizeof(png_byte)));
486    
487     png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
488    
489     for (i = 0; i < num_palette; i++)
490     {
491     int ir, ig, ib;
492     int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
493     int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
494     int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
495    
496     for (ir = 0; ir < num_red; ir++)
497     {
498     /* int dr = abs(ir - r); */
499     int dr = ((ir > r) ? ir - r : r - ir);
500     int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
501    
502     for (ig = 0; ig < num_green; ig++)
503     {
504     /* int dg = abs(ig - g); */
505     int dg = ((ig > g) ? ig - g : g - ig);
506     int dt = dr + dg;
507     int dm = ((dr > dg) ? dr : dg);
508     int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
509    
510     for (ib = 0; ib < num_blue; ib++)
511     {
512     int d_index = index_g | ib;
513     /* int db = abs(ib - b); */
514     int db = ((ib > b) ? ib - b : b - ib);
515     int dmax = ((dm > db) ? dm : db);
516     int d = dmax + dt + db;
517    
518     if (d < (int)distance[d_index])
519     {
520     distance[d_index] = (png_byte)d;
521     png_ptr->palette_lookup[d_index] = (png_byte)i;
522     }
523     }
524     }
525     }
526     }
527    
528     png_free(png_ptr, distance);
529     }
530     }
531     #endif
532    
533     #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
534     /* Transform the image from the file_gamma to the screen_gamma. We
535     * only do transformations on images where the file_gamma and screen_gamma
536     * are not close reciprocals, otherwise it slows things down slightly, and
537     * also needlessly introduces small errors.
538     *
539     * We will turn off gamma transformation later if no semitransparent entries
540     * are present in the tRNS array for palette images. We can't do it here
541     * because we don't necessarily have the tRNS chunk yet.
542     */
543     void PNGAPI
544     png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
545     {
546     png_debug(1, "in png_set_gamma");
547     if (png_ptr == NULL)
548     return;
549     if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
550     (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
551     (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
552     png_ptr->transformations |= PNG_GAMMA;
553     png_ptr->gamma = (float)file_gamma;
554     png_ptr->screen_gamma = (float)scrn_gamma;
555     }
556     #endif
557    
558     #if defined(PNG_READ_EXPAND_SUPPORTED)
559     /* Expand paletted images to RGB, expand grayscale images of
560     * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
561     * to alpha channels.
562     */
563     void PNGAPI
564     png_set_expand(png_structp png_ptr)
565     {
566     png_debug(1, "in png_set_expand");
567     if (png_ptr == NULL)
568     return;
569     png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
570     png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
571     }
572    
573     /* GRR 19990627: the following three functions currently are identical
574     * to png_set_expand(). However, it is entirely reasonable that someone
575     * might wish to expand an indexed image to RGB but *not* expand a single,
576     * fully transparent palette entry to a full alpha channel--perhaps instead
577     * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
578     * the transparent color with a particular RGB value, or drop tRNS entirely.
579     * IOW, a future version of the library may make the transformations flag
580     * a bit more fine-grained, with separate bits for each of these three
581     * functions.
582     *
583     * More to the point, these functions make it obvious what libpng will be
584     * doing, whereas "expand" can (and does) mean any number of things.
585     *
586     * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
587     * to expand only the sample depth but not to expand the tRNS to alpha.
588     */
589    
590     /* Expand paletted images to RGB. */
591     void PNGAPI
592     png_set_palette_to_rgb(png_structp png_ptr)
593     {
594     png_debug(1, "in png_set_palette_to_rgb");
595     if (png_ptr == NULL)
596     return;
597     png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
598     png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
599     }
600    
601     #if !defined(PNG_1_0_X)
602     /* Expand grayscale images of less than 8-bit depth to 8 bits. */
603     void PNGAPI
604     png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
605     {
606     png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
607     if (png_ptr == NULL)
608     return;
609     png_ptr->transformations |= PNG_EXPAND;
610     png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
611     }
612     #endif
613    
614     #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
615     /* Expand grayscale images of less than 8-bit depth to 8 bits. */
616     /* Deprecated as of libpng-1.2.9 */
617     void PNGAPI
618     png_set_gray_1_2_4_to_8(png_structp png_ptr)
619     {
620     png_debug(1, "in png_set_gray_1_2_4_to_8");
621     if (png_ptr == NULL)
622     return;
623     png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
624     }
625     #endif
626    
627    
628     /* Expand tRNS chunks to alpha channels. */
629     void PNGAPI
630     png_set_tRNS_to_alpha(png_structp png_ptr)
631     {
632     png_debug(1, "in png_set_tRNS_to_alpha");
633     png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
634     png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
635     }
636     #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
637    
638     #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
639     void PNGAPI
640     png_set_gray_to_rgb(png_structp png_ptr)
641     {
642     png_debug(1, "in png_set_gray_to_rgb");
643     png_ptr->transformations |= PNG_GRAY_TO_RGB;
644     png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
645     }
646     #endif
647    
648     #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
649     #if defined(PNG_FLOATING_POINT_SUPPORTED)
650     /* Convert a RGB image to a grayscale of the same width. This allows us,
651     * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
652     */
653    
654     void PNGAPI
655     png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
656     double green)
657     {
658     int red_fixed = (int)((float)red*100000.0 + 0.5);
659     int green_fixed = (int)((float)green*100000.0 + 0.5);
660     if (png_ptr == NULL)
661     return;
662     png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
663     }
664     #endif
665    
666     void PNGAPI
667     png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
668     png_fixed_point red, png_fixed_point green)
669     {
670     png_debug(1, "in png_set_rgb_to_gray");
671     if (png_ptr == NULL)
672     return;
673     switch(error_action)
674     {
675     case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
676     break;
677    
678     case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
679     break;
680    
681     case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
682     }
683     if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
684     #if defined(PNG_READ_EXPAND_SUPPORTED)
685     png_ptr->transformations |= PNG_EXPAND;
686     #else
687     {
688     png_warning(png_ptr,
689     "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
690     png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
691     }
692     #endif
693     {
694     png_uint_16 red_int, green_int;
695     if (red < 0 || green < 0)
696     {
697     red_int = 6968; /* .212671 * 32768 + .5 */
698     green_int = 23434; /* .715160 * 32768 + .5 */
699     }
700     else if (red + green < 100000L)
701     {
702     red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
703     green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
704     }
705     else
706     {
707     png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
708     red_int = 6968;
709     green_int = 23434;
710     }
711     png_ptr->rgb_to_gray_red_coeff = red_int;
712     png_ptr->rgb_to_gray_green_coeff = green_int;
713     png_ptr->rgb_to_gray_blue_coeff =
714     (png_uint_16)(32768 - red_int - green_int);
715     }
716     }
717     #endif
718    
719     #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
720     defined(PNG_LEGACY_SUPPORTED) || \
721     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
722     void PNGAPI
723     png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
724     read_user_transform_fn)
725     {
726     png_debug(1, "in png_set_read_user_transform_fn");
727     if (png_ptr == NULL)
728     return;
729     #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
730     png_ptr->transformations |= PNG_USER_TRANSFORM;
731     png_ptr->read_user_transform_fn = read_user_transform_fn;
732     #endif
733     #ifdef PNG_LEGACY_SUPPORTED
734     if (read_user_transform_fn)
735     png_warning(png_ptr,
736     "This version of libpng does not support user transforms");
737     #endif
738     }
739     #endif
740    
741     /* Initialize everything needed for the read. This includes modifying
742     * the palette.
743     */
744     void /* PRIVATE */
745     png_init_read_transformations(png_structp png_ptr)
746     {
747     png_debug(1, "in png_init_read_transformations");
748     #if defined(PNG_USELESS_TESTS_SUPPORTED)
749     if (png_ptr != NULL)
750     #endif
751     {
752     #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
753     || defined(PNG_READ_GAMMA_SUPPORTED)
754     int color_type = png_ptr->color_type;
755     #endif
756    
757     #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
758    
759     #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
760     /* Detect gray background and attempt to enable optimization
761     * for gray --> RGB case
762     *
763     * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
764     * RGB_ALPHA (in which case need_expand is superfluous anyway), the
765     * background color might actually be gray yet not be flagged as such.
766     * This is not a problem for the current code, which uses
767     * PNG_BACKGROUND_IS_GRAY only to decide when to do the
768     * png_do_gray_to_rgb() transformation.
769     */
770     if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
771     !(color_type & PNG_COLOR_MASK_COLOR))
772     {
773     png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
774     } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
775     !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
776     (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
777     png_ptr->background.red == png_ptr->background.green &&
778     png_ptr->background.red == png_ptr->background.blue)
779     {
780     png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
781     png_ptr->background.gray = png_ptr->background.red;
782     }
783     #endif
784    
785     if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
786     (png_ptr->transformations & PNG_EXPAND))
787     {
788     if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
789     {
790     /* Expand background and tRNS chunks */
791     switch (png_ptr->bit_depth)
792     {
793     case 1:
794     png_ptr->background.gray *= (png_uint_16)0xff;
795     png_ptr->background.red = png_ptr->background.green
796     = png_ptr->background.blue = png_ptr->background.gray;
797     if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
798     {
799     png_ptr->trans_values.gray *= (png_uint_16)0xff;
800     png_ptr->trans_values.red = png_ptr->trans_values.green
801     = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
802     }
803     break;
804    
805     case 2:
806     png_ptr->background.gray *= (png_uint_16)0x55;
807     png_ptr->background.red = png_ptr->background.green
808     = png_ptr->background.blue = png_ptr->background.gray;
809     if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
810     {
811     png_ptr->trans_values.gray *= (png_uint_16)0x55;
812     png_ptr->trans_values.red = png_ptr->trans_values.green
813     = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
814     }
815     break;
816    
817     case 4:
818     png_ptr->background.gray *= (png_uint_16)0x11;
819     png_ptr->background.red = png_ptr->background.green
820     = png_ptr->background.blue = png_ptr->background.gray;
821     if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
822     {
823     png_ptr->trans_values.gray *= (png_uint_16)0x11;
824     png_ptr->trans_values.red = png_ptr->trans_values.green
825     = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
826     }
827     break;
828    
829     case 8:
830    
831     case 16:
832     png_ptr->background.red = png_ptr->background.green
833     = png_ptr->background.blue = png_ptr->background.gray;
834     break;
835     }
836     }
837     else if (color_type == PNG_COLOR_TYPE_PALETTE)
838     {
839     png_ptr->background.red =
840     png_ptr->palette[png_ptr->background.index].red;
841     png_ptr->background.green =
842     png_ptr->palette[png_ptr->background.index].green;
843     png_ptr->background.blue =
844     png_ptr->palette[png_ptr->background.index].blue;
845    
846     #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
847     if (png_ptr->transformations & PNG_INVERT_ALPHA)
848     {
849     #if defined(PNG_READ_EXPAND_SUPPORTED)
850     if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
851     #endif
852     {
853     /* Invert the alpha channel (in tRNS) unless the pixels are
854     * going to be expanded, in which case leave it for later
855     */
856     int i, istop;
857     istop=(int)png_ptr->num_trans;
858     for (i=0; i<istop; i++)
859     png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
860     }
861     }
862     #endif
863    
864     }
865     }
866     #endif
867    
868     #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
869     png_ptr->background_1 = png_ptr->background;
870     #endif
871     #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
872    
873     if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
874     && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
875     < PNG_GAMMA_THRESHOLD))
876     {
877     int i, k;
878     k=0;
879     for (i=0; i<png_ptr->num_trans; i++)
880     {
881     if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
882     k=1; /* Partial transparency is present */
883     }
884     if (k == 0)
885     png_ptr->transformations &= ~PNG_GAMMA;
886     }
887    
888     if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
889     png_ptr->gamma != 0.0)
890     {
891     png_build_gamma_table(png_ptr);
892     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
893     if (png_ptr->transformations & PNG_BACKGROUND)
894     {
895     if (color_type == PNG_COLOR_TYPE_PALETTE)
896     {
897     /* Could skip if no transparency */
898     png_color back, back_1;
899     png_colorp palette = png_ptr->palette;
900     int num_palette = png_ptr->num_palette;
901     int i;
902     if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
903     {
904     back.red = png_ptr->gamma_table[png_ptr->background.red];
905     back.green = png_ptr->gamma_table[png_ptr->background.green];
906     back.blue = png_ptr->gamma_table[png_ptr->background.blue];
907    
908     back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
909     back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
910     back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
911     }
912     else
913     {
914     double g, gs;
915    
916     switch (png_ptr->background_gamma_type)
917     {
918     case PNG_BACKGROUND_GAMMA_SCREEN:
919     g = (png_ptr->screen_gamma);
920     gs = 1.0;
921     break;
922    
923     case PNG_BACKGROUND_GAMMA_FILE:
924     g = 1.0 / (png_ptr->gamma);
925     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
926     break;
927    
928     case PNG_BACKGROUND_GAMMA_UNIQUE:
929     g = 1.0 / (png_ptr->background_gamma);
930     gs = 1.0 / (png_ptr->background_gamma *
931     png_ptr->screen_gamma);
932     break;
933     default:
934     g = 1.0; /* back_1 */
935     gs = 1.0; /* back */
936     }
937    
938     if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
939     {
940     back.red = (png_byte)png_ptr->background.red;
941     back.green = (png_byte)png_ptr->background.green;
942     back.blue = (png_byte)png_ptr->background.blue;
943     }
944     else
945     {
946     back.red = (png_byte)(pow(
947     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
948     back.green = (png_byte)(pow(
949     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
950     back.blue = (png_byte)(pow(
951     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
952     }
953    
954     back_1.red = (png_byte)(pow(
955     (double)png_ptr->background.red/255, g) * 255.0 + .5);
956     back_1.green = (png_byte)(pow(
957     (double)png_ptr->background.green/255, g) * 255.0 + .5);
958     back_1.blue = (png_byte)(pow(
959     (double)png_ptr->background.blue/255, g) * 255.0 + .5);
960     }
961     for (i = 0; i < num_palette; i++)
962     {
963     if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
964     {
965     if (png_ptr->trans[i] == 0)
966     {
967     palette[i] = back;
968     }
969     else /* if (png_ptr->trans[i] != 0xff) */
970     {
971     png_byte v, w;
972    
973     v = png_ptr->gamma_to_1[palette[i].red];
974     png_composite(w, v, png_ptr->trans[i], back_1.red);
975     palette[i].red = png_ptr->gamma_from_1[w];
976    
977     v = png_ptr->gamma_to_1[palette[i].green];
978     png_composite(w, v, png_ptr->trans[i], back_1.green);
979     palette[i].green = png_ptr->gamma_from_1[w];
980    
981     v = png_ptr->gamma_to_1[palette[i].blue];
982     png_composite(w, v, png_ptr->trans[i], back_1.blue);
983     palette[i].blue = png_ptr->gamma_from_1[w];
984     }
985     }
986     else
987     {
988     palette[i].red = png_ptr->gamma_table[palette[i].red];
989     palette[i].green = png_ptr->gamma_table[palette[i].green];
990     palette[i].blue = png_ptr->gamma_table[palette[i].blue];
991     }
992     }
993     /* Prevent the transformations being done again, and make sure
994     * that the now spurious alpha channel is stripped - the code
995     * has just reduced background composition and gamma correction
996     * to a simple alpha channel strip.
997     */
998     png_ptr->transformations &= ~PNG_BACKGROUND;
999     png_ptr->transformations &= ~PNG_GAMMA;
1000     png_ptr->transformations |= PNG_STRIP_ALPHA;
1001     }
1002     /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1003     else
1004     /* color_type != PNG_COLOR_TYPE_PALETTE */
1005     {
1006     double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
1007     double g = 1.0;
1008     double gs = 1.0;
1009    
1010     switch (png_ptr->background_gamma_type)
1011     {
1012     case PNG_BACKGROUND_GAMMA_SCREEN:
1013     g = (png_ptr->screen_gamma);
1014     gs = 1.0;
1015     break;
1016    
1017     case PNG_BACKGROUND_GAMMA_FILE:
1018     g = 1.0 / (png_ptr->gamma);
1019     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
1020     break;
1021    
1022     case PNG_BACKGROUND_GAMMA_UNIQUE:
1023     g = 1.0 / (png_ptr->background_gamma);
1024     gs = 1.0 / (png_ptr->background_gamma *
1025     png_ptr->screen_gamma);
1026     break;
1027     }
1028    
1029     png_ptr->background_1.gray = (png_uint_16)(pow(
1030     (double)png_ptr->background.gray / m, g) * m + .5);
1031     png_ptr->background.gray = (png_uint_16)(pow(
1032     (double)png_ptr->background.gray / m, gs) * m + .5);
1033    
1034     if ((png_ptr->background.red != png_ptr->background.green) ||
1035     (png_ptr->background.red != png_ptr->background.blue) ||
1036     (png_ptr->background.red != png_ptr->background.gray))
1037     {
1038     /* RGB or RGBA with color background */
1039     png_ptr->background_1.red = (png_uint_16)(pow(
1040     (double)png_ptr->background.red / m, g) * m + .5);
1041     png_ptr->background_1.green = (png_uint_16)(pow(
1042     (double)png_ptr->background.green / m, g) * m + .5);
1043     png_ptr->background_1.blue = (png_uint_16)(pow(
1044     (double)png_ptr->background.blue / m, g) * m + .5);
1045     png_ptr->background.red = (png_uint_16)(pow(
1046     (double)png_ptr->background.red / m, gs) * m + .5);
1047     png_ptr->background.green = (png_uint_16)(pow(
1048     (double)png_ptr->background.green / m, gs) * m + .5);
1049     png_ptr->background.blue = (png_uint_16)(pow(
1050     (double)png_ptr->background.blue / m, gs) * m + .5);
1051     }
1052     else
1053     {
1054     /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1055     png_ptr->background_1.red = png_ptr->background_1.green
1056     = png_ptr->background_1.blue = png_ptr->background_1.gray;
1057     png_ptr->background.red = png_ptr->background.green
1058     = png_ptr->background.blue = png_ptr->background.gray;
1059     }
1060     }
1061     }
1062     else
1063     /* Transformation does not include PNG_BACKGROUND */
1064     #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1065     if (color_type == PNG_COLOR_TYPE_PALETTE)
1066     {
1067     png_colorp palette = png_ptr->palette;
1068     int num_palette = png_ptr->num_palette;
1069     int i;
1070    
1071     for (i = 0; i < num_palette; i++)
1072     {
1073     palette[i].red = png_ptr->gamma_table[palette[i].red];
1074     palette[i].green = png_ptr->gamma_table[palette[i].green];
1075     palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1076     }
1077    
1078     /* Done the gamma correction. */
1079     png_ptr->transformations &= ~PNG_GAMMA;
1080     }
1081     }
1082     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1083     else
1084     #endif
1085     #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1086     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1087     /* No GAMMA transformation */
1088     if ((png_ptr->transformations & PNG_BACKGROUND) &&
1089     (color_type == PNG_COLOR_TYPE_PALETTE))
1090     {
1091     int i;
1092     int istop = (int)png_ptr->num_trans;
1093     png_color back;
1094     png_colorp palette = png_ptr->palette;
1095    
1096     back.red = (png_byte)png_ptr->background.red;
1097     back.green = (png_byte)png_ptr->background.green;
1098     back.blue = (png_byte)png_ptr->background.blue;
1099    
1100     for (i = 0; i < istop; i++)
1101     {
1102     if (png_ptr->trans[i] == 0)
1103     {
1104     palette[i] = back;
1105     }
1106     else if (png_ptr->trans[i] != 0xff)
1107     {
1108     /* The png_composite() macro is defined in png.h */
1109     png_composite(palette[i].red, palette[i].red,
1110     png_ptr->trans[i], back.red);
1111     png_composite(palette[i].green, palette[i].green,
1112     png_ptr->trans[i], back.green);
1113     png_composite(palette[i].blue, palette[i].blue,
1114     png_ptr->trans[i], back.blue);
1115     }
1116     }
1117    
1118     /* Handled alpha, still need to strip the channel. */
1119     png_ptr->transformations &= ~PNG_BACKGROUND;
1120     png_ptr->transformations |= PNG_STRIP_ALPHA;
1121     }
1122     #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1123    
1124     #if defined(PNG_READ_SHIFT_SUPPORTED)
1125     if ((png_ptr->transformations & PNG_SHIFT) &&
1126     (color_type == PNG_COLOR_TYPE_PALETTE))
1127     {
1128     png_uint_16 i;
1129     png_uint_16 istop = png_ptr->num_palette;
1130     int sr = 8 - png_ptr->sig_bit.red;
1131     int sg = 8 - png_ptr->sig_bit.green;
1132     int sb = 8 - png_ptr->sig_bit.blue;
1133    
1134     if (sr < 0 || sr > 8)
1135     sr = 0;
1136     if (sg < 0 || sg > 8)
1137     sg = 0;
1138     if (sb < 0 || sb > 8)
1139     sb = 0;
1140     for (i = 0; i < istop; i++)
1141     {
1142     png_ptr->palette[i].red >>= sr;
1143     png_ptr->palette[i].green >>= sg;
1144     png_ptr->palette[i].blue >>= sb;
1145     }
1146     }
1147     #endif /* PNG_READ_SHIFT_SUPPORTED */
1148     }
1149     #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1150     && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1151     if (png_ptr)
1152     return;
1153     #endif
1154     }
1155    
1156     /* Modify the info structure to reflect the transformations. The
1157     * info should be updated so a PNG file could be written with it,
1158     * assuming the transformations result in valid PNG data.
1159     */
1160     void /* PRIVATE */
1161     png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1162     {
1163     png_debug(1, "in png_read_transform_info");
1164     #if defined(PNG_READ_EXPAND_SUPPORTED)
1165     if (png_ptr->transformations & PNG_EXPAND)
1166     {
1167     if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1168     {
1169     if (png_ptr->num_trans &&
1170     (png_ptr->transformations & PNG_EXPAND_tRNS))
1171     info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1172     else
1173     info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1174     info_ptr->bit_depth = 8;
1175     info_ptr->num_trans = 0;
1176     }
1177     else
1178     {
1179     if (png_ptr->num_trans)
1180     {
1181     if (png_ptr->transformations & PNG_EXPAND_tRNS)
1182     info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1183     }
1184     if (info_ptr->bit_depth < 8)
1185     info_ptr->bit_depth = 8;
1186     info_ptr->num_trans = 0;
1187     }
1188     }
1189     #endif
1190    
1191     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1192     if (png_ptr->transformations & PNG_BACKGROUND)
1193     {
1194     info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1195     info_ptr->num_trans = 0;
1196     info_ptr->background = png_ptr->background;
1197     }
1198     #endif
1199    
1200     #if defined(PNG_READ_GAMMA_SUPPORTED)
1201     if (png_ptr->transformations & PNG_GAMMA)
1202     {
1203     #ifdef PNG_FLOATING_POINT_SUPPORTED
1204     info_ptr->gamma = png_ptr->gamma;
1205     #endif
1206     #ifdef PNG_FIXED_POINT_SUPPORTED
1207     info_ptr->int_gamma = png_ptr->int_gamma;
1208     #endif
1209     }
1210     #endif
1211    
1212     #if defined(PNG_READ_16_TO_8_SUPPORTED)
1213     if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1214     info_ptr->bit_depth = 8;
1215     #endif
1216    
1217     #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1218     if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1219     info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1220     #endif
1221    
1222     #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1223     if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1224     info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1225     #endif
1226    
1227     #if defined(PNG_READ_DITHER_SUPPORTED)
1228     if (png_ptr->transformations & PNG_DITHER)
1229     {
1230     if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1231     (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1232     png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1233     {
1234     info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1235     }
1236     }
1237     #endif
1238    
1239     #if defined(PNG_READ_PACK_SUPPORTED)
1240     if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1241     info_ptr->bit_depth = 8;
1242     #endif
1243    
1244     if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1245     info_ptr->channels = 1;
1246     else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1247     info_ptr->channels = 3;
1248     else
1249     info_ptr->channels = 1;
1250    
1251     #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1252     if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1253     info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1254     #endif
1255    
1256     if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1257     info_ptr->channels++;
1258    
1259     #if defined(PNG_READ_FILLER_SUPPORTED)
1260     /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1261     if ((png_ptr->transformations & PNG_FILLER) &&
1262     ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1263     (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1264     {
1265     info_ptr->channels++;
1266     /* If adding a true alpha channel not just filler */
1267     #if !defined(PNG_1_0_X)
1268     if (png_ptr->transformations & PNG_ADD_ALPHA)
1269     info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1270     #endif
1271     }
1272     #endif
1273    
1274     #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1275     defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1276     if (png_ptr->transformations & PNG_USER_TRANSFORM)
1277     {
1278     if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1279     info_ptr->bit_depth = png_ptr->user_transform_depth;
1280     if (info_ptr->channels < png_ptr->user_transform_channels)
1281     info_ptr->channels = png_ptr->user_transform_channels;
1282     }
1283     #endif
1284    
1285     info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1286     info_ptr->bit_depth);
1287    
1288     info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1289    
1290     #if !defined(PNG_READ_EXPAND_SUPPORTED)
1291     if (png_ptr)
1292     return;
1293     #endif
1294     }
1295    
1296     /* Transform the row. The order of transformations is significant,
1297     * and is very touchy. If you add a transformation, take care to
1298     * decide how it fits in with the other transformations here.
1299     */
1300     void /* PRIVATE */
1301     png_do_read_transformations(png_structp png_ptr)
1302     {
1303     png_debug(1, "in png_do_read_transformations");
1304     if (png_ptr->row_buf == NULL)
1305     {
1306     #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1307     char msg[50];
1308    
1309     png_snprintf2(msg, 50,
1310     "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
1311     png_ptr->pass);
1312     png_error(png_ptr, msg);
1313     #else
1314     png_error(png_ptr, "NULL row buffer");
1315     #endif
1316     }
1317     #ifdef PNG_WARN_UNINITIALIZED_ROW
1318     if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
1319     /* Application has failed to call either png_read_start_image()
1320     * or png_read_update_info() after setting transforms that expand
1321     * pixels. This check added to libpng-1.2.19
1322     */
1323     #if (PNG_WARN_UNINITIALIZED_ROW==1)
1324     png_error(png_ptr, "Uninitialized row");
1325     #else
1326     png_warning(png_ptr, "Uninitialized row");
1327     #endif
1328     #endif
1329    
1330     #if defined(PNG_READ_EXPAND_SUPPORTED)
1331     if (png_ptr->transformations & PNG_EXPAND)
1332     {
1333     if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1334     {
1335     png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1336     png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1337     }
1338     else
1339     {
1340     if (png_ptr->num_trans &&
1341     (png_ptr->transformations & PNG_EXPAND_tRNS))
1342     png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1343     &(png_ptr->trans_values));
1344     else
1345     png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1346     NULL);
1347     }
1348     }
1349     #endif
1350    
1351     #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1352     if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1353     png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1354     PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1355     #endif
1356    
1357     #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1358     if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1359     {
1360     int rgb_error =
1361     png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1362     if (rgb_error)
1363     {
1364     png_ptr->rgb_to_gray_status=1;
1365     if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1366     PNG_RGB_TO_GRAY_WARN)
1367     png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1368     if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1369     PNG_RGB_TO_GRAY_ERR)
1370     png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1371     }
1372     }
1373     #endif
1374    
1375     /* From Andreas Dilger e-mail to png-implement, 26 March 1998:
1376     *
1377     * In most cases, the "simple transparency" should be done prior to doing
1378     * gray-to-RGB, or you will have to test 3x as many bytes to check if a
1379     * pixel is transparent. You would also need to make sure that the
1380     * transparency information is upgraded to RGB.
1381     *
1382     * To summarize, the current flow is:
1383     * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1384     * with background "in place" if transparent,
1385     * convert to RGB if necessary
1386     * - Gray + alpha -> composite with gray background and remove alpha bytes,
1387     * convert to RGB if necessary
1388     *
1389     * To support RGB backgrounds for gray images we need:
1390     * - Gray + simple transparency -> convert to RGB + simple transparency,
1391     * compare 3 or 6 bytes and composite with
1392     * background "in place" if transparent
1393     * (3x compare/pixel compared to doing
1394     * composite with gray bkgrnd)
1395     * - Gray + alpha -> convert to RGB + alpha, composite with background and
1396     * remove alpha bytes (3x float
1397     * operations/pixel compared with composite
1398     * on gray background)
1399     *
1400     * Greg's change will do this. The reason it wasn't done before is for
1401     * performance, as this increases the per-pixel operations. If we would check
1402     * in advance if the background was gray or RGB, and position the gray-to-RGB
1403     * transform appropriately, then it would save a lot of work/time.
1404     */
1405    
1406     #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1407     /* If gray -> RGB, do so now only if background is non-gray; else do later
1408     * for performance reasons
1409     */
1410     if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1411     !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1412     png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1413     #endif
1414    
1415     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1416     if ((png_ptr->transformations & PNG_BACKGROUND) &&
1417     ((png_ptr->num_trans != 0 ) ||
1418     (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1419     png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1420     &(png_ptr->trans_values), &(png_ptr->background)
1421     #if defined(PNG_READ_GAMMA_SUPPORTED)
1422     , &(png_ptr->background_1),
1423     png_ptr->gamma_table, png_ptr->gamma_from_1,
1424     png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1425     png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1426     png_ptr->gamma_shift
1427     #endif
1428     );
1429     #endif
1430    
1431     #if defined(PNG_READ_GAMMA_SUPPORTED)
1432     if ((png_ptr->transformations & PNG_GAMMA) &&
1433     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1434     !((png_ptr->transformations & PNG_BACKGROUND) &&
1435     ((png_ptr->num_trans != 0) ||
1436     (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1437     #endif
1438     (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1439     png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1440     png_ptr->gamma_table, png_ptr->gamma_16_table,
1441     png_ptr->gamma_shift);
1442     #endif
1443    
1444     #if defined(PNG_READ_16_TO_8_SUPPORTED)
1445     if (png_ptr->transformations & PNG_16_TO_8)
1446     png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1447     #endif
1448    
1449     #if defined(PNG_READ_DITHER_SUPPORTED)
1450     if (png_ptr->transformations & PNG_DITHER)
1451     {
1452     png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1453     png_ptr->palette_lookup, png_ptr->dither_index);
1454     if (png_ptr->row_info.rowbytes == (png_uint_32)0)
1455     png_error(png_ptr, "png_do_dither returned rowbytes=0");
1456     }
1457     #endif
1458    
1459     #if defined(PNG_READ_INVERT_SUPPORTED)
1460     if (png_ptr->transformations & PNG_INVERT_MONO)
1461     png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1462     #endif
1463    
1464     #if defined(PNG_READ_SHIFT_SUPPORTED)
1465     if (png_ptr->transformations & PNG_SHIFT)
1466     png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1467     &(png_ptr->shift));
1468     #endif
1469    
1470     #if defined(PNG_READ_PACK_SUPPORTED)
1471     if (png_ptr->transformations & PNG_PACK)
1472     png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1473     #endif
1474    
1475     #if defined(PNG_READ_BGR_SUPPORTED)
1476     if (png_ptr->transformations & PNG_BGR)
1477     png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1478     #endif
1479    
1480     #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1481     if (png_ptr->transformations & PNG_PACKSWAP)
1482     png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1483     #endif
1484    
1485     #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1486     /* If gray -> RGB, do so now only if we did not do so above */
1487     if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1488     (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1489     png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1490     #endif
1491    
1492     #if defined(PNG_READ_FILLER_SUPPORTED)
1493     if (png_ptr->transformations & PNG_FILLER)
1494     png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1495     (png_uint_32)png_ptr->filler, png_ptr->flags);
1496     #endif
1497    
1498     #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1499     if (png_ptr->transformations & PNG_INVERT_ALPHA)
1500     png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1501     #endif
1502    
1503     #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1504     if (png_ptr->transformations & PNG_SWAP_ALPHA)
1505     png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1506     #endif
1507    
1508     #if defined(PNG_READ_SWAP_SUPPORTED)
1509     if (png_ptr->transformations & PNG_SWAP_BYTES)
1510     png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1511     #endif
1512    
1513     #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1514     if (png_ptr->transformations & PNG_USER_TRANSFORM)
1515     {
1516     if (png_ptr->read_user_transform_fn != NULL)
1517     (*(png_ptr->read_user_transform_fn)) /* User read transform function */
1518     (png_ptr, /* png_ptr */
1519     &(png_ptr->row_info), /* row_info: */
1520     /* png_uint_32 width; width of row */
1521     /* png_uint_32 rowbytes; number of bytes in row */
1522     /* png_byte color_type; color type of pixels */
1523     /* png_byte bit_depth; bit depth of samples */
1524     /* png_byte channels; number of channels (1-4) */
1525     /* png_byte pixel_depth; bits per pixel (depth*channels) */
1526     png_ptr->row_buf + 1); /* start of pixel data for row */
1527     #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1528     if (png_ptr->user_transform_depth)
1529     png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1530     if (png_ptr->user_transform_channels)
1531     png_ptr->row_info.channels = png_ptr->user_transform_channels;
1532     #endif
1533     png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1534     png_ptr->row_info.channels);
1535     png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1536     png_ptr->row_info.width);
1537     }
1538     #endif
1539    
1540     }
1541    
1542     #if defined(PNG_READ_PACK_SUPPORTED)
1543     /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1544     * without changing the actual values. Thus, if you had a row with
1545     * a bit depth of 1, you would end up with bytes that only contained
1546     * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1547     * png_do_shift() after this.
1548     */
1549     void /* PRIVATE */
1550     png_do_unpack(png_row_infop row_info, png_bytep row)
1551     {
1552     png_debug(1, "in png_do_unpack");
1553     #if defined(PNG_USELESS_TESTS_SUPPORTED)
1554     if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1555     #else
1556     if (row_info->bit_depth < 8)
1557     #endif
1558     {
1559     png_uint_32 i;
1560     png_uint_32 row_width=row_info->width;
1561    
1562     switch (row_info->bit_depth)
1563     {
1564     case 1:
1565     {
1566     png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1567     png_bytep dp = row + (png_size_t)row_width - 1;
1568     png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1569     for (i = 0; i < row_width; i++)
1570     {
1571     *dp = (png_byte)((*sp >> shift) & 0x01);
1572     if (shift == 7)
1573     {
1574     shift = 0;
1575     sp--;
1576     }
1577     else
1578     shift++;
1579    
1580     dp--;
1581     }
1582     break;
1583     }
1584    
1585     case 2:
1586     {
1587    
1588     png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1589     png_bytep dp = row + (png_size_t)row_width - 1;
1590     png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1591     for (i = 0; i < row_width; i++)
1592     {
1593     *dp = (png_byte)((*sp >> shift) & 0x03);
1594     if (shift == 6)
1595     {
1596     shift = 0;
1597     sp--;
1598     }
1599     else
1600     shift += 2;
1601    
1602     dp--;
1603     }
1604     break;
1605     }
1606    
1607     case 4:
1608     {
1609     png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1610     png_bytep dp = row + (png_size_t)row_width - 1;
1611     png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1612     for (i = 0; i < row_width; i++)
1613     {
1614     *dp = (png_byte)((*sp >> shift) & 0x0f);
1615     if (shift == 4)
1616     {
1617     shift = 0;
1618     sp--;
1619     }
1620     else
1621     shift = 4;
1622    
1623     dp--;
1624     }
1625     break;
1626     }
1627     }
1628     row_info->bit_depth = 8;
1629     row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1630     row_info->rowbytes = row_width * row_info->channels;
1631     }
1632     }
1633     #endif
1634    
1635     #if defined(PNG_READ_SHIFT_SUPPORTED)
1636     /* Reverse the effects of png_do_shift. This routine merely shifts the
1637     * pixels back to their significant bits values. Thus, if you have
1638     * a row of bit depth 8, but only 5 are significant, this will shift
1639     * the values back to 0 through 31.
1640     */
1641     void /* PRIVATE */
1642     png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1643     {
1644     png_debug(1, "in png_do_unshift");
1645     if (
1646     #if defined(PNG_USELESS_TESTS_SUPPORTED)
1647     row != NULL && row_info != NULL && sig_bits != NULL &&
1648     #endif
1649     row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1650     {
1651     int shift[4];
1652     int channels = 0;
1653     int c;
1654     png_uint_16 value = 0;
1655     png_uint_32 row_width = row_info->width;
1656    
1657     if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1658     {
1659     shift[channels++] = row_info->bit_depth - sig_bits->red;
1660     shift[channels++] = row_info->bit_depth - sig_bits->green;
1661     shift[channels++] = row_info->bit_depth - sig_bits->blue;
1662     }
1663     else
1664     {
1665     shift[channels++] = row_info->bit_depth - sig_bits->gray;
1666     }
1667     if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1668     {
1669     shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1670     }
1671    
1672     for (c = 0; c < channels; c++)
1673     {
1674     if (shift[c] <= 0)
1675     shift[c] = 0;
1676     else
1677     value = 1;
1678     }
1679    
1680     if (!value)
1681     return;
1682    
1683     switch (row_info->bit_depth)
1684     {
1685     case 2:
1686     {
1687     png_bytep bp;
1688     png_uint_32 i;
1689     png_uint_32 istop = row_info->rowbytes;
1690    
1691     for (bp = row, i = 0; i < istop; i++)
1692     {
1693     *bp >>= 1;
1694     *bp++ &= 0x55;
1695     }
1696     break;
1697     }
1698    
1699     case 4:
1700     {
1701     png_bytep bp = row;
1702     png_uint_32 i;
1703     png_uint_32 istop = row_info->rowbytes;
1704     png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1705     (png_byte)((int)0xf >> shift[0]));
1706    
1707     for (i = 0; i < istop; i++)
1708     {
1709     *bp >>= shift[0];
1710     *bp++ &= mask;
1711     }
1712     break;
1713     }
1714    
1715     case 8:
1716     {
1717     png_bytep bp = row;
1718     png_uint_32 i;
1719     png_uint_32 istop = row_width * channels;
1720    
1721     for (i = 0; i < istop; i++)
1722     {
1723     *bp++ >>= shift[i%channels];
1724     }
1725     break;
1726     }
1727    
1728     case 16:
1729     {
1730     png_bytep bp = row;
1731     png_uint_32 i;
1732     png_uint_32 istop = channels * row_width;
1733    
1734     for (i = 0; i < istop; i++)
1735     {
1736     value = (png_uint_16)((*bp << 8) + *(bp + 1));
1737     value >>= shift[i%channels];
1738     *bp++ = (png_byte)(value >> 8);
1739     *bp++ = (png_byte)(value & 0xff);
1740     }
1741     break;
1742     }
1743     }
1744     }
1745     }
1746     #endif
1747    
1748     #if defined(PNG_READ_16_TO_8_SUPPORTED)
1749     /* Chop rows of bit depth 16 down to 8 */
1750     void /* PRIVATE */
1751     png_do_chop(png_row_infop row_info, png_bytep row)
1752     {
1753     png_debug(1, "in png_do_chop");
1754     #if defined(PNG_USELESS_TESTS_SUPPORTED)
1755     if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1756     #else
1757     if (row_info->bit_depth == 16)
1758     #endif
1759     {
1760     png_bytep sp = row;
1761     png_bytep dp = row;
1762     png_uint_32 i;
1763     png_uint_32 istop = row_info->width * row_info->channels;
1764    
1765     for (i = 0; i<istop; i++, sp += 2, dp++)
1766     {
1767     #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1768     /* This does a more accurate scaling of the 16-bit color
1769     * value, rather than a simple low-byte truncation.
1770     *
1771     * What the ideal calculation should be:
1772     * *dp = (((((png_uint_32)(*sp) << 8) |
1773     * (png_uint_32)(*(sp + 1))) * 255 + 127)
1774     * / (png_uint_32)65535L;
1775     *
1776     * GRR: no, I think this is what it really should be:
1777     * *dp = (((((png_uint_32)(*sp) << 8) |
1778     * (png_uint_32)(*(sp + 1))) + 128L)
1779     * / (png_uint_32)257L;
1780     *
1781     * GRR: here's the exact calculation with shifts:
1782     * temp = (((png_uint_32)(*sp) << 8) |
1783     * (png_uint_32)(*(sp + 1))) + 128L;
1784     * *dp = (temp - (temp >> 8)) >> 8;
1785     *
1786     * Approximate calculation with shift/add instead of multiply/divide:
1787     * *dp = ((((png_uint_32)(*sp) << 8) |
1788     * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1789     *
1790     * What we actually do to avoid extra shifting and conversion:
1791     */
1792    
1793     *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1794     #else
1795     /* Simply discard the low order byte */
1796     *dp = *sp;
1797     #endif
1798     }
1799     row_info->bit_depth = 8;
1800     row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1801     row_info->rowbytes = row_info->width * row_info->channels;
1802     }
1803     }
1804     #endif
1805    
1806     #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1807     void /* PRIVATE */
1808     png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1809     {
1810     png_debug(1, "in png_do_read_swap_alpha");
1811     #if defined(PNG_USELESS_TESTS_SUPPORTED)
1812     if (row != NULL && row_info != NULL)
1813     #endif
1814     {
1815     png_uint_32 row_width = row_info->width;
1816     if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1817     {
1818     /* This converts from RGBA to ARGB */
1819     if (row_info->bit_depth == 8)
1820     {
1821     png_bytep sp = row + row_info->rowbytes;
1822     png_bytep dp = sp;
1823     png_byte save;
1824     png_uint_32 i;
1825    
1826     for (i = 0; i < row_width; i++)
1827     {
1828     save = *(--sp);
1829     *(--dp) = *(--sp);
1830     *(--dp) = *(--sp);
1831     *(--dp) = *(--sp);
1832     *(--dp) = save;
1833     }
1834     }
1835     /* This converts from RRGGBBAA to AARRGGBB */
1836     else
1837     {
1838     png_bytep sp = row + row_info->rowbytes;
1839     png_bytep dp = sp;
1840     png_byte save[2];
1841     png_uint_32 i;
1842    
1843     for (i = 0; i < row_width; i++)
1844     {
1845     save[0] = *(--sp);
1846     save[1] = *(--sp);
1847     *(--dp) = *(--sp);
1848     *(--dp) = *(--sp);
1849     *(--dp) = *(--sp);
1850     *(--dp) = *(--sp);
1851     *(--dp) = *(--sp);
1852     *(--dp) = *(--sp);
1853     *(--dp) = save[0];
1854     *(--dp) = save[1];
1855     }
1856     }
1857     }
1858     else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1859     {
1860     /* This converts from GA to AG */
1861     if (row_info->bit_depth == 8)
1862     {
1863     png_bytep sp = row + row_info->rowbytes;
1864     png_bytep dp = sp;
1865     png_byte save;
1866     png_uint_32 i;
1867    
1868     for (i = 0; i < row_width; i++)
1869     {
1870     save = *(--sp);
1871     *(--dp) = *(--sp);
1872     *(--dp) = save;
1873     }
1874     }
1875     /* This converts from GGAA to AAGG */
1876     else
1877     {
1878     png_bytep sp = row + row_info->rowbytes;
1879     png_bytep dp = sp;
1880     png_byte save[2];
1881     png_uint_32 i;
1882    
1883     for (i = 0; i < row_width; i++)
1884     {
1885     save[0] = *(--sp);
1886     save[1] = *(--sp);
1887     *(--dp) = *(--sp);
1888     *(--dp) = *(--sp);
1889     *(--dp) = save[0];
1890     *(--dp) = save[1];
1891     }
1892     }
1893     }
1894     }
1895     }
1896     #endif
1897    
1898     #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1899     void /* PRIVATE */
1900     png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1901     {
1902     png_debug(1, "in png_do_read_invert_alpha");
1903     #if defined(PNG_USELESS_TESTS_SUPPORTED)
1904     if (row != NULL && row_info != NULL)
1905     #endif
1906     {
1907     png_uint_32 row_width = row_info->width;
1908     if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1909     {
1910     /* This inverts the alpha channel in RGBA */
1911     if (row_info->bit_depth == 8)
1912     {
1913     png_bytep sp = row + row_info->rowbytes;
1914     png_bytep dp = sp;
1915     png_uint_32 i;
1916    
1917     for (i = 0; i < row_width; i++)
1918     {
1919     *(--dp) = (png_byte)(255 - *(--sp));
1920    
1921     /* This does nothing:
1922     *(--dp) = *(--sp);
1923     *(--dp) = *(--sp);
1924     *(--dp) = *(--sp);
1925     We can replace it with:
1926     */
1927     sp-=3;
1928     dp=sp;
1929     }
1930     }
1931     /* This inverts the alpha channel in RRGGBBAA */
1932     else
1933     {
1934     png_bytep sp = row + row_info->rowbytes;
1935     png_bytep dp = sp;
1936     png_uint_32 i;
1937    
1938     for (i = 0; i < row_width; i++)
1939     {
1940     *(--dp) = (png_byte)(255 - *(--sp));
1941     *(--dp) = (png_byte)(255 - *(--sp));
1942    
1943     /* This does nothing:
1944     *(--dp) = *(--sp);
1945     *(--dp) = *(--sp);
1946     *(--dp) = *(--sp);
1947     *(--dp) = *(--sp);
1948     *(--dp) = *(--sp);
1949     *(--dp) = *(--sp);
1950     We can replace it with:
1951     */
1952     sp-=6;
1953     dp=sp;
1954     }
1955     }
1956     }
1957     else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1958     {
1959     /* This inverts the alpha channel in GA */
1960     if (row_info->bit_depth == 8)
1961     {
1962     png_bytep sp = row + row_info->rowbytes;
1963     png_bytep dp = sp;
1964     png_uint_32 i;
1965    
1966     for (i = 0; i < row_width; i++)
1967     {
1968     *(--dp) = (png_byte)(255 - *(--sp));
1969     *(--dp) = *(--sp);
1970     }
1971     }
1972     /* This inverts the alpha channel in GGAA */
1973     else
1974     {
1975     png_bytep sp = row + row_info->rowbytes;
1976     png_bytep dp = sp;
1977     png_uint_32 i;
1978    
1979     for (i = 0; i < row_width; i++)
1980     {
1981     *(--dp) = (png_byte)(255 - *(--sp));
1982     *(--dp) = (png_byte)(255 - *(--sp));
1983     /*
1984     *(--dp) = *(--sp);
1985     *(--dp) = *(--sp);
1986     */
1987     sp-=2;
1988     dp=sp;
1989     }
1990     }
1991     }
1992     }
1993     }
1994     #endif
1995    
1996     #if defined(PNG_READ_FILLER_SUPPORTED)
1997     /* Add filler channel if we have RGB color */
1998     void /* PRIVATE */
1999     png_do_read_filler(png_row_infop row_info, png_bytep row,
2000     png_uint_32 filler, png_uint_32 flags)
2001     {
2002     png_uint_32 i;
2003     png_uint_32 row_width = row_info->width;
2004    
2005     png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2006     png_byte lo_filler = (png_byte)(filler & 0xff);
2007    
2008     png_debug(1, "in png_do_read_filler");
2009     if (
2010     #if defined(PNG_USELESS_TESTS_SUPPORTED)
2011     row != NULL && row_info != NULL &&
2012     #endif
2013     row_info->color_type == PNG_COLOR_TYPE_GRAY)
2014     {
2015     if (row_info->bit_depth == 8)
2016     {
2017     /* This changes the data from G to GX */
2018     if (flags & PNG_FLAG_FILLER_AFTER)
2019     {
2020     png_bytep sp = row + (png_size_t)row_width;
2021     png_bytep dp = sp + (png_size_t)row_width;
2022     for (i = 1; i < row_width; i++)
2023     {
2024     *(--dp) = lo_filler;
2025     *(--dp) = *(--sp);
2026     }
2027     *(--dp) = lo_filler;
2028     row_info->channels = 2;
2029     row_info->pixel_depth = 16;
2030     row_info->rowbytes = row_width * 2;
2031     }
2032     /* This changes the data from G to XG */
2033     else
2034     {
2035     png_bytep sp = row + (png_size_t)row_width;
2036     png_bytep dp = sp + (png_size_t)row_width;
2037     for (i = 0; i < row_width; i++)
2038     {
2039     *(--dp) = *(--sp);
2040     *(--dp) = lo_filler;
2041     }
2042     row_info->channels = 2;
2043     row_info->pixel_depth = 16;
2044     row_info->rowbytes = row_width * 2;
2045     }
2046     }
2047     else if (row_info->bit_depth == 16)
2048     {
2049     /* This changes the data from GG to GGXX */
2050     if (flags & PNG_FLAG_FILLER_AFTER)
2051     {
2052     png_bytep sp = row + (png_size_t)row_width * 2;
2053     png_bytep dp = sp + (png_size_t)row_width * 2;
2054     for (i = 1; i < row_width; i++)
2055     {
2056     *(--dp) = hi_filler;
2057     *(--dp) = lo_filler;
2058     *(--dp) = *(--sp);
2059     *(--dp) = *(--sp);
2060     }
2061     *(--dp) = hi_filler;
2062     *(--dp) = lo_filler;
2063     row_info->channels = 2;
2064     row_info->pixel_depth = 32;
2065     row_info->rowbytes = row_width * 4;
2066     }
2067     /* This changes the data from GG to XXGG */
2068     else
2069     {
2070     png_bytep sp = row + (png_size_t)row_width * 2;
2071     png_bytep dp = sp + (png_size_t)row_width * 2;
2072     for (i = 0; i < row_width; i++)
2073     {
2074     *(--dp) = *(--sp);
2075     *(--dp) = *(--sp);
2076     *(--dp) = hi_filler;
2077     *(--dp) = lo_filler;
2078     }
2079     row_info->channels = 2;
2080     row_info->pixel_depth = 32;
2081     row_info->rowbytes = row_width * 4;
2082     }
2083     }
2084     } /* COLOR_TYPE == GRAY */
2085     else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2086     {
2087     if (row_info->bit_depth == 8)
2088     {
2089     /* This changes the data from RGB to RGBX */
2090     if (flags & PNG_FLAG_FILLER_AFTER)
2091     {
2092     png_bytep sp = row + (png_size_t)row_width * 3;
2093     png_bytep dp = sp + (png_size_t)row_width;
2094     for (i = 1; i < row_width; i++)
2095     {
2096     *(--dp) = lo_filler;
2097     *(--dp) = *(--sp);
2098     *(--dp) = *(--sp);
2099     *(--dp) = *(--sp);
2100     }
2101     *(--dp) = lo_filler;
2102     row_info->channels = 4;
2103     row_info->pixel_depth = 32;
2104     row_info->rowbytes = row_width * 4;
2105     }
2106     /* This changes the data from RGB to XRGB */
2107     else
2108     {
2109     png_bytep sp = row + (png_size_t)row_width * 3;
2110     png_bytep dp = sp + (png_size_t)row_width;
2111     for (i = 0; i < row_width; i++)
2112     {
2113     *(--dp) = *(--sp);
2114     *(--dp) = *(--sp);
2115     *(--dp) = *(--sp);
2116     *(--dp) = lo_filler;
2117     }
2118     row_info->channels = 4;
2119     row_info->pixel_depth = 32;
2120     row_info->rowbytes = row_width * 4;
2121     }
2122     }
2123     else if (row_info->bit_depth == 16)
2124     {
2125     /* This changes the data from RRGGBB to RRGGBBXX */
2126     if (flags & PNG_FLAG_FILLER_AFTER)
2127     {
2128     png_bytep sp = row + (png_size_t)row_width * 6;
2129     png_bytep dp = sp + (png_size_t)row_width * 2;
2130     for (i = 1; i < row_width; i++)
2131     {
2132     *(--dp) = hi_filler;
2133     *(--dp) = lo_filler;
2134     *(--dp) = *(--sp);
2135     *(--dp) = *(--sp);
2136     *(--dp) = *(--sp);
2137     *(--dp) = *(--sp);
2138     *(--dp) = *(--sp);
2139     *(--dp) = *(--sp);
2140     }
2141     *(--dp) = hi_filler;
2142     *(--dp) = lo_filler;
2143     row_info->channels = 4;
2144     row_info->pixel_depth = 64;
2145     row_info->rowbytes = row_width * 8;
2146     }
2147     /* This changes the data from RRGGBB to XXRRGGBB */
2148     else
2149     {
2150     png_bytep sp = row + (png_size_t)row_width * 6;
2151     png_bytep dp = sp + (png_size_t)row_width * 2;
2152     for (i = 0; i < row_width; i++)
2153     {
2154     *(--dp) = *(--sp);
2155     *(--dp) = *(--sp);
2156     *(--dp) = *(--sp);
2157     *(--dp) = *(--sp);
2158     *(--dp) = *(--sp);
2159     *(--dp) = *(--sp);
2160     *(--dp) = hi_filler;
2161     *(--dp) = lo_filler;
2162     }
2163     row_info->channels = 4;
2164     row_info->pixel_depth = 64;
2165     row_info->rowbytes = row_width * 8;
2166     }
2167     }
2168     } /* COLOR_TYPE == RGB */
2169     }
2170     #endif
2171    
2172     #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2173     /* Expand grayscale files to RGB, with or without alpha */
2174     void /* PRIVATE */
2175     png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2176     {
2177     png_uint_32 i;
2178     png_uint_32 row_width = row_info->width;
2179    
2180     png_debug(1, "in png_do_gray_to_rgb");
2181     if (row_info->bit_depth >= 8 &&
2182     #if defined(PNG_USELESS_TESTS_SUPPORTED)
2183     row != NULL && row_info != NULL &&
2184     #endif
2185     !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2186     {
2187     if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2188     {
2189     if (row_info->bit_depth == 8)
2190     {
2191     png_bytep sp = row + (png_size_t)row_width - 1;
2192     png_bytep dp = sp + (png_size_t)row_width * 2;
2193     for (i = 0; i < row_width; i++)
2194     {
2195     *(dp--) = *sp;
2196     *(dp--) = *sp;
2197     *(dp--) = *(sp--);
2198     }
2199     }
2200     else
2201     {
2202     png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2203     png_bytep dp = sp + (png_size_t)row_width * 4;
2204     for (i = 0; i < row_width; i++)
2205     {
2206     *(dp--) = *sp;
2207     *(dp--) = *(sp - 1);
2208     *(dp--) = *sp;
2209     *(dp--) = *(sp - 1);
2210     *(dp--) = *(sp--);
2211     *(dp--) = *(sp--);
2212     }
2213     }
2214     }
2215     else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2216     {
2217     if (row_info->bit_depth == 8)
2218     {
2219     png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2220     png_bytep dp = sp + (png_size_t)row_width * 2;
2221     for (i = 0; i < row_width; i++)
2222     {
2223     *(dp--) = *(sp--);
2224     *(dp--) = *sp;
2225     *(dp--) = *sp;
2226     *(dp--) = *(sp--);
2227     }
2228     }
2229     else
2230     {
2231     png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2232     png_bytep dp = sp + (png_size_t)row_width * 4;
2233     for (i = 0; i < row_width; i++)
2234     {
2235     *(dp--) = *(sp--);
2236     *(dp--) = *(sp--);
2237     *(dp--) = *sp;
2238     *(dp--) = *(sp - 1);
2239     *(dp--) = *sp;
2240     *(dp--) = *(sp - 1);
2241     *(dp--) = *(sp--);
2242     *(dp--) = *(sp--);
2243     }
2244     }
2245     }
2246     row_info->channels += (png_byte)2;
2247     row_info->color_type |= PNG_COLOR_MASK_COLOR;
2248     row_info->pixel_depth = (png_byte)(row_info->channels *
2249     row_info->bit_depth);
2250     row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2251     }
2252     }
2253     #endif
2254    
2255     #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2256     /* Reduce RGB files to grayscale, with or without alpha
2257     * using the equation given in Poynton's ColorFAQ at
2258     * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
2259     * New link:
2260     * <http://www.poynton.com/notes/colour_and_gamma/>
2261     * Charles Poynton poynton at poynton.com
2262     *
2263     * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2264     *
2265     * We approximate this with
2266     *
2267     * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2268     *
2269     * which can be expressed with integers as
2270     *
2271     * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2272     *
2273     * The calculation is to be done in a linear colorspace.
2274     *
2275     * Other integer coefficents can be used via png_set_rgb_to_gray().
2276     */
2277     int /* PRIVATE */
2278     png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2279    
2280     {
2281     png_uint_32 i;
2282    
2283     png_uint_32 row_width = row_info->width;
2284     int rgb_error = 0;
2285    
2286     png_debug(1, "in png_do_rgb_to_gray");
2287     if (
2288     #if defined(PNG_USELESS_TESTS_SUPPORTED)
2289     row != NULL && row_info != NULL &&
2290     #endif
2291     (row_info->color_type & PNG_COLOR_MASK_COLOR))
2292     {
2293     png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2294     png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2295     png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2296    
2297     if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2298     {
2299     if (row_info->bit_depth == 8)
2300     {
2301     #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2302     if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2303     {
2304     png_bytep sp = row;
2305     png_bytep dp = row;
2306    
2307     for (i = 0; i < row_width; i++)
2308     {
2309     png_byte red = png_ptr->gamma_to_1[*(sp++)];
2310     png_byte green = png_ptr->gamma_to_1[*(sp++)];
2311     png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2312     if (red != green || red != blue)
2313     {
2314     rgb_error |= 1;
2315     *(dp++) = png_ptr->gamma_from_1[
2316     (rc*red + gc*green + bc*blue)>>15];
2317     }
2318     else
2319     *(dp++) = *(sp - 1);
2320     }
2321     }
2322     else
2323     #endif
2324     {
2325     png_bytep sp = row;
2326     png_bytep dp = row;
2327     for (i = 0; i < row_width; i++)
2328     {
2329     png_byte red = *(sp++);
2330     png_byte green = *(sp++);
2331     png_byte blue = *(sp++);
2332     if (red != green || red != blue)
2333     {
2334     rgb_error |= 1;
2335     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2336     }
2337     else
2338     *(dp++) = *(sp - 1);
2339     }
2340     }
2341     }
2342    
2343     else /* RGB bit_depth == 16 */
2344     {
2345     #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2346     if (png_ptr->gamma_16_to_1 != NULL &&
2347     png_ptr->gamma_16_from_1 != NULL)
2348     {
2349     png_bytep sp = row;
2350     png_bytep dp = row;
2351     for (i = 0; i < row_width; i++)
2352     {
2353     png_uint_16 red, green, blue, w;
2354    
2355     red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2356     green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2357     blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2358    
2359     if (red == green && red == blue)
2360     w = red;
2361     else
2362     {
2363     png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2364     png_ptr->gamma_shift][red>>8];
2365     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2366     png_ptr->gamma_shift][green>>8];
2367     png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2368     png_ptr->gamma_shift][blue>>8];
2369     png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2370     + bc*blue_1)>>15);
2371     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2372     png_ptr->gamma_shift][gray16 >> 8];
2373     rgb_error |= 1;
2374     }
2375    
2376     *(dp++) = (png_byte)((w>>8) & 0xff);
2377     *(dp++) = (png_byte)(w & 0xff);
2378     }
2379     }
2380     else
2381     #endif
2382     {
2383     png_bytep sp = row;
2384     png_bytep dp = row;
2385     for (i = 0; i < row_width; i++)
2386     {
2387     png_uint_16 red, green, blue, gray16;
2388    
2389     red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2390     green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2391     blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2392    
2393     if (red != green || red != blue)
2394     rgb_error |= 1;
2395     gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2396     *(dp++) = (png_byte)((gray16>>8) & 0xff);
2397     *(dp++) = (png_byte)(gray16 & 0xff);
2398     }
2399     }
2400     }
2401     }
2402     if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2403     {
2404     if (row_info->bit_depth == 8)
2405     {
2406     #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2407     if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2408     {
2409     png_bytep sp = row;
2410     png_bytep dp = row;
2411     for (i = 0; i < row_width; i++)
2412     {
2413     png_byte red = png_ptr->gamma_to_1[*(sp++)];
2414     png_byte green = png_ptr->gamma_to_1[*(sp++)];
2415     png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2416     if (red != green || red != blue)
2417     rgb_error |= 1;
2418     *(dp++) = png_ptr->gamma_from_1
2419     [(rc*red + gc*green + bc*blue)>>15];
2420     *(dp++) = *(sp++); /* alpha */
2421     }
2422     }
2423     else
2424     #endif
2425     {
2426     png_bytep sp = row;
2427     png_bytep dp = row;
2428     for (i = 0; i < row_width; i++)
2429     {
2430     png_byte red = *(sp++);
2431     png_byte green = *(sp++);
2432     png_byte blue = *(sp++);
2433     if (red != green || red != blue)
2434     rgb_error |= 1;
2435     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2436     *(dp++) = *(sp++); /* alpha */
2437     }
2438     }
2439     }
2440     else /* RGBA bit_depth == 16 */
2441     {
2442     #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2443     if (png_ptr->gamma_16_to_1 != NULL &&
2444     png_ptr->gamma_16_from_1 != NULL)
2445     {
2446     png_bytep sp = row;
2447     png_bytep dp = row;
2448     for (i = 0; i < row_width; i++)
2449     {
2450     png_uint_16 red, green, blue, w;
2451    
2452     red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2453     green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2454     blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2455    
2456     if (red == green && red == blue)
2457     w = red;
2458     else
2459     {
2460     png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2461     png_ptr->gamma_shift][red>>8];
2462     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2463     png_ptr->gamma_shift][green>>8];
2464     png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2465     png_ptr->gamma_shift][blue>>8];
2466     png_uint_16 gray16 = (png_uint_16)((rc * red_1
2467     + gc * green_1 + bc * blue_1)>>15);
2468     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2469     png_ptr->gamma_shift][gray16 >> 8];
2470     rgb_error |= 1;
2471     }
2472    
2473     *(dp++) = (png_byte)((w>>8) & 0xff);
2474     *(dp++) = (png_byte)(w & 0xff);
2475     *(dp++) = *(sp++); /* alpha */
2476     *(dp++) = *(sp++);
2477     }
2478     }
2479     else
2480     #endif
2481     {
2482     png_bytep sp = row;
2483     png_bytep dp = row;
2484     for (i = 0; i < row_width; i++)
2485     {
2486     png_uint_16 red, green, blue, gray16;
2487     red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2488     green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2489     blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2490     if (red != green || red != blue)
2491     rgb_error |= 1;
2492     gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2493     *(dp++) = (png_byte)((gray16>>8) & 0xff);
2494     *(dp++) = (png_byte)(gray16 & 0xff);
2495     *(dp++) = *(sp++); /* alpha */
2496     *(dp++) = *(sp++);
2497     }
2498     }
2499     }
2500     }
2501     row_info->channels -= (png_byte)2;
2502     row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2503     row_info->pixel_depth = (png_byte)(row_info->channels *
2504     row_info->bit_depth);
2505     row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2506     }
2507     return rgb_error;
2508     }
2509     #endif
2510    
2511     /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2512     * large of png_color. This lets grayscale images be treated as
2513     * paletted. Most useful for gamma correction and simplification
2514     * of code.
2515     */
2516     void PNGAPI
2517     png_build_grayscale_palette(int bit_depth, png_colorp palette)
2518     {
2519     int num_palette;
2520     int color_inc;
2521     int i;
2522     int v;
2523    
2524     png_debug(1, "in png_do_build_grayscale_palette");
2525     if (palette == NULL)
2526     return;
2527    
2528     switch (bit_depth)
2529     {
2530     case 1:
2531     num_palette = 2;
2532     color_inc = 0xff;
2533     break;
2534    
2535     case 2:
2536     num_palette = 4;
2537     color_inc = 0x55;
2538     break;
2539    
2540     case 4:
2541     num_palette = 16;
2542     color_inc = 0x11;
2543     break;
2544    
2545     case 8:
2546     num_palette = 256;
2547     color_inc = 1;
2548     break;
2549    
2550     default:
2551     num_palette = 0;
2552     color_inc = 0;
2553     break;
2554     }
2555    
2556     for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2557     {
2558     palette[i].red = (png_byte)v;
2559     palette[i].green = (png_byte)v;
2560     palette[i].blue = (png_byte)v;
2561     }
2562     }
2563    
2564     /* This function is currently unused. Do we really need it? */
2565     #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2566     void /* PRIVATE */
2567     png_correct_palette(png_structp png_ptr, png_colorp palette,
2568     int num_palette)
2569     {
2570     png_debug(1, "in png_correct_palette");
2571     #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2572     defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2573     if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2574     {
2575     png_color back, back_1;
2576    
2577     if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2578     {
2579     back.red = png_ptr->gamma_table[png_ptr->background.red];
2580     back.green = png_ptr->gamma_table[png_ptr->background.green];
2581     back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2582    
2583     back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2584     back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2585     back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2586     }
2587     else
2588     {
2589     double g;
2590    
2591     g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2592    
2593     if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2594     fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2595     {
2596     back.red = png_ptr->background.red;
2597     back.green = png_ptr->background.green;
2598     back.blue = png_ptr->background.blue;
2599     }
2600     else
2601     {
2602     back.red =
2603     (png_byte)(pow((double)png_ptr->background.red/255, g) *
2604     255.0 + 0.5);
2605     back.green =
2606     (png_byte)(pow((double)png_ptr->background.green/255, g) *
2607     255.0 + 0.5);
2608     back.blue =
2609     (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2610     255.0 + 0.5);
2611     }
2612    
2613     g = 1.0 / png_ptr->background_gamma;
2614    
2615     back_1.red =
2616     (png_byte)(pow((double)png_ptr->background.red/255, g) *
2617     255.0 + 0.5);
2618     back_1.green =
2619     (png_byte)(pow((double)png_ptr->background.green/255, g) *
2620     255.0 + 0.5);
2621     back_1.blue =
2622     (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2623     255.0 + 0.5);
2624     }
2625    
2626     if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2627     {
2628     png_uint_32 i;
2629    
2630     for (i = 0; i < (png_uint_32)num_palette; i++)
2631     {
2632     if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2633     {
2634     palette[i] = back;
2635     }
2636     else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2637     {
2638     png_byte v, w;
2639    
2640     v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2641     png_composite(w, v, png_ptr->trans[i], back_1.red);
2642     palette[i].red = png_ptr->gamma_from_1[w];
2643    
2644     v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2645     png_composite(w, v, png_ptr->trans[i], back_1.green);
2646     palette[i].green = png_ptr->gamma_from_1[w];
2647    
2648     v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2649     png_composite(w, v, png_ptr->trans[i], back_1.blue);
2650     palette[i].blue = png_ptr->gamma_from_1[w];
2651     }
2652     else
2653     {
2654     palette[i].red = png_ptr->gamma_table[palette[i].red];
2655     palette[i].green = png_ptr->gamma_table[palette[i].green];
2656     palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2657     }
2658     }
2659     }
2660     else
2661     {
2662     int i;
2663    
2664     for (i = 0; i < num_palette; i++)
2665     {
2666     if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2667     {
2668     palette[i] = back;
2669     }
2670     else
2671     {
2672     palette[i].red = png_ptr->gamma_table[palette[i].red];
2673     palette[i].green = png_ptr->gamma_table[palette[i].green];
2674     palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2675     }
2676     }
2677     }
2678     }
2679     else
2680     #endif
2681     #if defined(PNG_READ_GAMMA_SUPPORTED)
2682     if (png_ptr->transformations & PNG_GAMMA)
2683     {
2684     int i;
2685    
2686     for (i = 0; i < num_palette; i++)
2687     {
2688     palette[i].red = png_ptr->gamma_table[palette[i].red];
2689     palette[i].green = png_ptr->gamma_table[palette[i].green];
2690     palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2691     }
2692     }
2693     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2694     else
2695     #endif
2696     #endif
2697     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2698     if (png_ptr->transformations & PNG_BACKGROUND)
2699     {
2700     if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2701     {
2702     png_color back;
2703    
2704     back.red = (png_byte)png_ptr->background.red;
2705     back.green = (png_byte)png_ptr->background.green;
2706     back.blue = (png_byte)png_ptr->background.blue;
2707    
2708     for (i = 0; i < (int)png_ptr->num_trans; i++)
2709     {
2710     if (png_ptr->trans[i] == 0)
2711     {
2712     palette[i].red = back.red;
2713     palette[i].green = back.green;
2714     palette[i].blue = back.blue;
2715     }
2716     else if (png_ptr->trans[i] != 0xff)
2717     {
2718     png_composite(palette[i].red, png_ptr->palette[i].red,
2719     png_ptr->trans[i], back.red);
2720     png_composite(palette[i].green, png_ptr->palette[i].green,
2721     png_ptr->trans[i], back.green);
2722     png_composite(palette[i].blue, png_ptr->palette[i].blue,
2723     png_ptr->trans[i], back.blue);
2724     }
2725     }
2726     }
2727     else /* Assume grayscale palette (what else could it be?) */
2728     {
2729     int i;
2730    
2731     for (i = 0; i < num_palette; i++)
2732     {
2733     if (i == (png_byte)png_ptr->trans_values.gray)
2734     {
2735     palette[i].red = (png_byte)png_ptr->background.red;
2736     palette[i].green = (png_byte)png_ptr->background.green;
2737     palette[i].blue = (png_byte)png_ptr->background.blue;
2738     }
2739     }
2740     }
2741     }
2742     #endif
2743     }
2744     #endif
2745    
2746     #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2747     /* Replace any alpha or transparency with the supplied background color.
2748     * "background" is already in the screen gamma, while "background_1" is
2749     * at a gamma of 1.0. Paletted files have already been taken care of.
2750     */
2751     void /* PRIVATE */
2752     png_do_background(png_row_infop row_info, png_bytep row,
2753     png_color_16p trans_values, png_color_16p background
2754     #if defined(PNG_READ_GAMMA_SUPPORTED)
2755     , png_color_16p background_1,
2756     png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2757     png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2758     png_uint_16pp gamma_16_to_1, int gamma_shift
2759     #endif
2760     )
2761     {
2762     png_bytep sp, dp;
2763     png_uint_32 i;
2764     png_uint_32 row_width=row_info->width;
2765     int shift;
2766    
2767     png_debug(1, "in png_do_background");
2768     if (background != NULL &&
2769     #if defined(PNG_USELESS_TESTS_SUPPORTED)
2770     row != NULL && row_info != NULL &&
2771     #endif
2772     (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2773     (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2774     {
2775     switch (row_info->color_type)
2776     {
2777     case PNG_COLOR_TYPE_GRAY:
2778     {
2779     switch (row_info->bit_depth)
2780     {
2781     case 1:
2782     {
2783     sp = row;
2784     shift = 7;
2785     for (i = 0; i < row_width; i++)
2786     {
2787     if ((png_uint_16)((*sp >> shift) & 0x01)
2788     == trans_values->gray)
2789     {
2790     *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2791     *sp |= (png_byte)(background->gray << shift);
2792     }
2793     if (!shift)
2794     {
2795     shift = 7;
2796     sp++;
2797     }
2798     else
2799     shift--;
2800     }
2801     break;
2802     }
2803    
2804     case 2:
2805     {
2806     #if defined(PNG_READ_GAMMA_SUPPORTED)
2807     if (gamma_table != NULL)
2808     {
2809     sp = row;
2810     shift = 6;
2811     for (i = 0; i < row_width; i++)
2812     {
2813     if ((png_uint_16)((*sp >> shift) & 0x03)
2814     == trans_values->gray)
2815     {
2816     *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2817     *sp |= (png_byte)(background->gray << shift);
2818     }
2819     else
2820     {
2821     png_byte p = (png_byte)((*sp >> shift) & 0x03);
2822     png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2823     (p << 4) | (p << 6)] >> 6) & 0x03);
2824     *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2825     *sp |= (png_byte)(g << shift);
2826     }
2827     if (!shift)
2828     {
2829     shift = 6;
2830     sp++;
2831     }
2832     else
2833     shift -= 2;
2834     }
2835     }
2836     else
2837     #endif
2838     {
2839     sp = row;
2840     shift = 6;
2841     for (i = 0; i < row_width; i++)
2842     {
2843     if ((png_uint_16)((*sp >> shift) & 0x03)
2844     == trans_values->gray)
2845     {
2846     *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2847     *sp |= (png_byte)(background->gray << shift);
2848     }
2849     if (!shift)
2850     {
2851     shift = 6;
2852     sp++;
2853     }
2854     else
2855     shift -= 2;
2856     }
2857     }
2858     break;
2859     }
2860    
2861     case 4:
2862     {
2863     #if defined(PNG_READ_GAMMA_SUPPORTED)
2864     if (gamma_table != NULL)
2865     {
2866     sp = row;
2867     shift = 4;
2868     for (i = 0; i < row_width; i++)
2869     {
2870     if ((png_uint_16)((*sp >> shift) & 0x0f)
2871     == trans_values->gray)
2872     {
2873     *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2874     *sp |= (png_byte)(background->gray << shift);
2875     }
2876     else
2877     {
2878     png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2879     png_byte g = (png_byte)((gamma_table[p |
2880     (p << 4)] >> 4) & 0x0f);
2881     *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2882     *sp |= (png_byte)(g << shift);
2883     }
2884     if (!shift)
2885     {
2886     shift = 4;
2887     sp++;
2888     }
2889     else
2890     shift -= 4;
2891     }
2892     }
2893     else
2894     #endif
2895     {
2896     sp = row;
2897     shift = 4;
2898     for (i = 0; i < row_width; i++)
2899     {
2900     if ((png_uint_16)((*sp >> shift) & 0x0f)
2901     == trans_values->gray)
2902     {
2903     *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2904     *sp |= (png_byte)(background->gray << shift);
2905     }
2906     if (!shift)
2907     {
2908     shift = 4;
2909     sp++;
2910     }
2911     else
2912     shift -= 4;
2913     }
2914     }
2915     break;
2916     }
2917    
2918     case 8:
2919     {
2920     #if defined(PNG_READ_GAMMA_SUPPORTED)
2921     if (gamma_table != NULL)
2922     {
2923     sp = row;
2924     for (i = 0; i < row_width; i++, sp++)
2925     {
2926     if (*sp == trans_values->gray)
2927     {
2928     *sp = (png_byte)background->gray;
2929     }
2930     else
2931     {
2932     *sp = gamma_table[*sp];
2933     }
2934     }
2935     }
2936     else
2937     #endif
2938     {
2939     sp = row;
2940     for (i = 0; i < row_width; i++, sp++)
2941     {
2942     if (*sp == trans_values->gray)
2943     {
2944     *sp = (png_byte)background->gray;
2945     }
2946     }
2947     }
2948     break;
2949     }
2950    
2951     case 16:
2952     {
2953     #if defined(PNG_READ_GAMMA_SUPPORTED)
2954     if (gamma_16 != NULL)
2955     {
2956     sp = row;
2957     for (i = 0; i < row_width; i++, sp += 2)
2958     {
2959     png_uint_16 v;
2960    
2961     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2962     if (v == trans_values->gray)
2963     {
2964     /* Background is already in screen gamma */
2965     *sp = (png_byte)((background->gray >> 8) & 0xff);
2966     *(sp + 1) = (png_byte)(background->gray & 0xff);
2967     }
2968     else
2969     {
2970     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2971     *sp = (png_byte)((v >> 8) & 0xff);
2972     *(sp + 1) = (png_byte)(v & 0xff);
2973     }
2974     }
2975     }
2976     else
2977     #endif
2978     {
2979     sp = row;
2980     for (i = 0; i < row_width; i++, sp += 2)
2981     {
2982     png_uint_16 v;
2983    
2984     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2985     if (v == trans_values->gray)
2986     {
2987     *sp = (png_byte)((background->gray >> 8) & 0xff);
2988     *(sp + 1) = (png_byte)(background->gray & 0xff);
2989     }
2990     }
2991     }
2992     break;
2993     }
2994     }
2995     break;
2996     }
2997    
2998     case PNG_COLOR_TYPE_RGB:
2999     {
3000     if (row_info->bit_depth == 8)
3001     {
3002     #if defined(PNG_READ_GAMMA_SUPPORTED)
3003     if (gamma_table != NULL)
3004     {
3005     sp = row;
3006     for (i = 0; i < row_width; i++, sp += 3)
3007     {
3008     if (*sp == trans_values->red &&
3009     *(sp + 1) == trans_values->green &&
3010     *(sp + 2) == trans_values->blue)
3011     {
3012     *sp = (png_byte)background->red;
3013     *(sp + 1) = (png_byte)background->green;
3014     *(sp + 2) = (png_byte)background->blue;
3015     }
3016     else
3017     {
3018     *sp = gamma_table[*sp];
3019     *(sp + 1) = gamma_table[*(sp + 1)];
3020     *(sp + 2) = gamma_table[*(sp + 2)];
3021     }
3022     }
3023     }
3024     else
3025     #endif
3026     {
3027     sp = row;
3028     for (i = 0; i < row_width; i++, sp += 3)
3029     {
3030     if (*sp == trans_values->red &&
3031     *(sp + 1) == trans_values->green &&
3032     *(sp + 2) == trans_values->blue)
3033     {
3034     *sp = (png_byte)background->red;
3035     *(sp + 1) = (png_byte)background->green;
3036     *(sp + 2) = (png_byte)background->blue;
3037     }
3038     }
3039     }
3040     }
3041     else /* if (row_info->bit_depth == 16) */
3042     {
3043     #if defined(PNG_READ_GAMMA_SUPPORTED)
3044     if (gamma_16 != NULL)
3045     {
3046     sp = row;
3047     for (i = 0; i < row_width; i++, sp += 6)
3048     {
3049     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3050     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3051     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3052     if (r == trans_values->red && g == trans_values->green &&
3053     b == trans_values->blue)
3054     {
3055     /* Background is already in screen gamma */
3056     *sp = (png_byte)((background->red >> 8) & 0xff);
3057     *(sp + 1) = (png_byte)(background->red & 0xff);
3058     *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3059     *(sp + 3) = (png_byte)(background->green & 0xff);
3060     *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3061     *(sp + 5) = (png_byte)(background->blue & 0xff);
3062     }
3063     else
3064     {
3065     png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3066     *sp = (png_byte)((v >> 8) & 0xff);
3067     *(sp + 1) = (png_byte)(v & 0xff);
3068     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3069     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3070     *(sp + 3) = (png_byte)(v & 0xff);
3071     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3072     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3073     *(sp + 5) = (png_byte)(v & 0xff);
3074     }
3075     }
3076     }
3077     else
3078     #endif
3079     {
3080     sp = row;
3081     for (i = 0; i < row_width; i++, sp += 6)
3082     {
3083     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
3084     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3085     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3086    
3087     if (r == trans_values->red && g == trans_values->green &&
3088     b == trans_values->blue)
3089     {
3090     *sp = (png_byte)((background->red >> 8) & 0xff);
3091     *(sp + 1) = (png_byte)(background->red & 0xff);
3092     *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3093     *(sp + 3) = (png_byte)(background->green & 0xff);
3094     *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3095     *(sp + 5) = (png_byte)(background->blue & 0xff);
3096     }
3097     }
3098     }
3099     }
3100     break;
3101     }
3102    
3103     case PNG_COLOR_TYPE_GRAY_ALPHA:
3104     {
3105     if (row_info->bit_depth == 8)
3106     {
3107     #if defined(PNG_READ_GAMMA_SUPPORTED)
3108     if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3109     gamma_table != NULL)
3110     {
3111     sp = row;
3112     dp = row;
3113     for (i = 0; i < row_width; i++, sp += 2, dp++)
3114     {
3115     png_uint_16 a = *(sp + 1);
3116    
3117     if (a == 0xff)
3118     {
3119     *dp = gamma_table[*sp];
3120     }
3121     else if (a == 0)
3122     {
3123     /* Background is already in screen gamma */
3124     *dp = (png_byte)background->gray;
3125     }
3126     else
3127     {
3128     png_byte v, w;
3129    
3130     v = gamma_to_1[*sp];
3131     png_composite(w, v, a, background_1->gray);
3132     *dp = gamma_from_1[w];
3133     }
3134     }
3135     }
3136     else
3137     #endif
3138     {
3139     sp = row;
3140     dp = row;
3141     for (i = 0; i < row_width; i++, sp += 2, dp++)
3142     {
3143     png_byte a = *(sp + 1);
3144    
3145     if (a == 0xff)
3146     {
3147     *dp = *sp;
3148     }
3149     #if defined(PNG_READ_GAMMA_SUPPORTED)
3150     else if (a == 0)
3151     {
3152     *dp = (png_byte)background->gray;
3153     }
3154     else
3155     {
3156     png_composite(*dp, *sp, a, background_1->gray);
3157     }
3158     #else
3159     *dp = (png_byte)background->gray;
3160     #endif
3161     }
3162     }
3163     }
3164     else /* if (png_ptr->bit_depth == 16) */
3165     {
3166     #if defined(PNG_READ_GAMMA_SUPPORTED)
3167     if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3168     gamma_16_to_1 != NULL)
3169     {
3170     sp = row;
3171     dp = row;
3172     for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3173     {
3174     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3175    
3176     if (a == (png_uint_16)0xffff)
3177     {
3178     png_uint_16 v;
3179    
3180     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3181     *dp = (png_byte)((v >> 8) & 0xff);
3182     *(dp + 1) = (png_byte)(v & 0xff);
3183     }
3184     #if defined(PNG_READ_GAMMA_SUPPORTED)
3185     else if (a == 0)
3186     #else
3187     else
3188     #endif
3189     {
3190     /* Background is already in screen gamma */
3191     *dp = (png_byte)((background->gray >> 8) & 0xff);
3192     *(dp + 1) = (png_byte)(background->gray & 0xff);
3193     }
3194     #if defined(PNG_READ_GAMMA_SUPPORTED)
3195     else
3196     {
3197     png_uint_16 g, v, w;
3198    
3199     g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3200     png_composite_16(v, g, a, background_1->gray);
3201     w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3202     *dp = (png_byte)((w >> 8) & 0xff);
3203     *(dp + 1) = (png_byte)(w & 0xff);
3204     }
3205     #endif
3206     }
3207     }
3208     else
3209     #endif
3210     {
3211     sp = row;
3212     dp = row;
3213     for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3214     {
3215     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3216     if (a == (png_uint_16)0xffff)
3217     {
3218     png_memcpy(dp, sp, 2);
3219     }
3220     #if defined(PNG_READ_GAMMA_SUPPORTED)
3221     else if (a == 0)
3222     #else
3223     else
3224     #endif
3225     {
3226     *dp = (png_byte)((background->gray >> 8) & 0xff);
3227     *(dp + 1) = (png_byte)(background->gray & 0xff);
3228     }
3229     #if defined(PNG_READ_GAMMA_SUPPORTED)
3230     else
3231     {
3232     png_uint_16 g, v;
3233    
3234     g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3235     png_composite_16(v, g, a, background_1->gray);
3236     *dp = (png_byte)((v >> 8) & 0xff);
3237     *(dp + 1) = (png_byte)(v & 0xff);
3238     }
3239     #endif
3240     }
3241     }
3242     }
3243     break;
3244     }
3245    
3246     case PNG_COLOR_TYPE_RGB_ALPHA:
3247     {
3248     if (row_info->bit_depth == 8)
3249     {
3250     #if defined(PNG_READ_GAMMA_SUPPORTED)
3251     if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3252     gamma_table != NULL)
3253     {
3254     sp = row;
3255     dp = row;
3256     for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3257     {
3258     png_byte a = *(sp + 3);
3259    
3260     if (a == 0xff)
3261     {
3262     *dp = gamma_table[*sp];
3263     *(dp + 1) = gamma_table[*(sp + 1)];
3264     *(dp + 2) = gamma_table[*(sp + 2)];
3265     }
3266     else if (a == 0)
3267     {
3268     /* Background is already in screen gamma */
3269     *dp = (png_byte)background->red;
3270     *(dp + 1) = (png_byte)background->green;
3271     *(dp + 2) = (png_byte)background->blue;
3272     }
3273     else
3274     {
3275     png_byte v, w;
3276    
3277     v = gamma_to_1[*sp];
3278     png_composite(w, v, a, background_1->red);
3279     *dp = gamma_from_1[w];
3280     v = gamma_to_1[*(sp + 1)];
3281     png_composite(w, v, a, background_1->green);
3282     *(dp + 1) = gamma_from_1[w];
3283     v = gamma_to_1[*(sp + 2)];
3284     png_composite(w, v, a, background_1->blue);
3285     *(dp + 2) = gamma_from_1[w];
3286     }
3287     }
3288     }
3289     else
3290     #endif
3291     {
3292     sp = row;
3293     dp = row;
3294     for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3295     {
3296     png_byte a = *(sp + 3);
3297    
3298     if (a == 0xff)
3299     {
3300     *dp = *sp;
3301     *(dp + 1) = *(sp + 1);
3302     *(dp + 2) = *(sp + 2);
3303     }
3304     else if (a == 0)
3305     {
3306     *dp = (png_byte)background->red;
3307     *(dp + 1) = (png_byte)background->green;
3308     *(dp + 2) = (png_byte)background->blue;
3309     }
3310     else
3311     {
3312     png_composite(*dp, *sp, a, background->red);
3313     png_composite(*(dp + 1), *(sp + 1), a,
3314     background->green);
3315     png_composite(*(dp + 2), *(sp + 2), a,
3316     background->blue);
3317     }
3318     }
3319     }
3320     }
3321     else /* if (row_info->bit_depth == 16) */
3322     {
3323     #if defined(PNG_READ_GAMMA_SUPPORTED)
3324     if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3325     gamma_16_to_1 != NULL)
3326     {
3327     sp = row;
3328     dp = row;
3329     for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3330     {
3331     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3332     << 8) + (png_uint_16)(*(sp + 7)));
3333     if (a == (png_uint_16)0xffff)
3334     {
3335     png_uint_16 v;
3336    
3337     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3338     *dp = (png_byte)((v >> 8) & 0xff);
3339     *(dp + 1) = (png_byte)(v & 0xff);
3340     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3341     *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3342     *(dp + 3) = (png_byte)(v & 0xff);
3343     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3344     *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3345     *(dp + 5) = (png_byte)(v & 0xff);
3346     }
3347     else if (a == 0)
3348     {
3349     /* Background is already in screen gamma */
3350     *dp = (png_byte)((background->red >> 8) & 0xff);
3351     *(dp + 1) = (png_byte)(background->red & 0xff);
3352     *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3353     *(dp + 3) = (png_byte)(background->green & 0xff);
3354     *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3355     *(dp + 5) = (png_byte)(background->blue & 0xff);
3356     }
3357     else
3358     {
3359     png_uint_16 v, w, x;
3360    
3361     v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3362     png_composite_16(w, v, a, background_1->red);
3363     x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3364     *dp = (png_byte)((x >> 8) & 0xff);
3365     *(dp + 1) = (png_byte)(x & 0xff);
3366     v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3367     png_composite_16(w, v, a, background_1->green);
3368     x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3369     *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3370     *(dp + 3) = (png_byte)(x & 0xff);
3371     v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3372     png_composite_16(w, v, a, background_1->blue);
3373     x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3374     *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3375     *(dp + 5) = (png_byte)(x & 0xff);
3376     }
3377     }
3378     }
3379     else
3380     #endif
3381     {
3382     sp = row;
3383     dp = row;
3384     for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3385     {
3386     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3387     << 8) + (png_uint_16)(*(sp + 7)));
3388     if (a == (png_uint_16)0xffff)
3389     {
3390     png_memcpy(dp, sp, 6);
3391     }
3392     else if (a == 0)
3393     {
3394     *dp = (png_byte)((background->red >> 8) & 0xff);
3395     *(dp + 1) = (png_byte)(background->red & 0xff);
3396     *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3397     *(dp + 3) = (png_byte)(background->green & 0xff);
3398     *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3399     *(dp + 5) = (png_byte)(background->blue & 0xff);
3400     }
3401     else
3402     {
3403     png_uint_16 v;
3404    
3405     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3406     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3407     + *(sp + 3));
3408     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3409     + *(sp + 5));
3410    
3411     png_composite_16(v, r, a, background->red);
3412     *dp = (png_byte)((v >> 8) & 0xff);
3413     *(dp + 1) = (png_byte)(v & 0xff);
3414     png_composite_16(v, g, a, background->green);
3415     *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3416     *(dp + 3) = (png_byte)(v & 0xff);
3417     png_composite_16(v, b, a, background->blue);
3418     *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3419     *(dp + 5) = (png_byte)(v & 0xff);
3420     }
3421     }
3422     }
3423     }
3424     break;
3425     }
3426     }
3427    
3428     if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3429     {
3430     row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3431     row_info->channels--;
3432     row_info->pixel_depth = (png_byte)(row_info->channels *
3433     row_info->bit_depth);
3434     row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3435     }
3436     }
3437     }
3438     #endif
3439    
3440     #if defined(PNG_READ_GAMMA_SUPPORTED)
3441     /* Gamma correct the image, avoiding the alpha channel. Make sure
3442     * you do this after you deal with the transparency issue on grayscale
3443     * or RGB images. If your bit depth is 8, use gamma_table, if it
3444     * is 16, use gamma_16_table and gamma_shift. Build these with
3445     * build_gamma_table().
3446     */
3447     void /* PRIVATE */
3448     png_do_gamma(png_row_infop row_info, png_bytep row,
3449     png_bytep gamma_table, png_uint_16pp gamma_16_table,
3450     int gamma_shift)
3451     {
3452     png_bytep sp;
3453     png_uint_32 i;
3454     png_uint_32 row_width=row_info->width;
3455    
3456     png_debug(1, "in png_do_gamma");
3457     if (
3458     #if defined(PNG_USELESS_TESTS_SUPPORTED)
3459     row != NULL && row_info != NULL &&
3460     #endif
3461     ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3462     (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3463     {
3464     switch (row_info->color_type)
3465     {
3466     case PNG_COLOR_TYPE_RGB:
3467     {
3468     if (row_info->bit_depth == 8)
3469     {
3470     sp = row;
3471     for (i = 0; i < row_width; i++)
3472     {
3473     *sp = gamma_table[*sp];
3474     sp++;
3475     *sp = gamma_table[*sp];
3476     sp++;
3477     *sp = gamma_table[*sp];
3478     sp++;
3479     }
3480     }
3481     else /* if (row_info->bit_depth == 16) */
3482     {
3483     sp = row;
3484     for (i = 0; i < row_width; i++)
3485     {
3486     png_uint_16 v;
3487    
3488     v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3489     *sp = (png_byte)((v >> 8) & 0xff);
3490     *(sp + 1) = (png_byte)(v & 0xff);
3491     sp += 2;
3492     v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3493     *sp = (png_byte)((v >> 8) & 0xff);
3494     *(sp + 1) = (png_byte)(v & 0xff);
3495     sp += 2;
3496     v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3497     *sp = (png_byte)((v >> 8) & 0xff);
3498     *(sp + 1) = (png_byte)(v & 0xff);
3499     sp += 2;
3500     }
3501     }
3502     break;
3503     }
3504    
3505     case PNG_COLOR_TYPE_RGB_ALPHA:
3506     {
3507     if (row_info->bit_depth == 8)
3508     {
3509     sp = row;
3510     for (i = 0; i < row_width; i++)
3511     {
3512     *sp = gamma_table[*sp];
3513     sp++;
3514     *sp = gamma_table[*sp];
3515     sp++;
3516     *sp = gamma_table[*sp];
3517     sp++;
3518     sp++;
3519     }
3520     }
3521     else /* if (row_info->bit_depth == 16) */
3522     {
3523     sp = row;
3524     for (i = 0; i < row_width; i++)
3525     {
3526     png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3527     *sp = (png_byte)((v >> 8) & 0xff);
3528     *(sp + 1) = (png_byte)(v & 0xff);
3529     sp += 2;
3530     v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3531     *sp = (png_byte)((v >> 8) & 0xff);
3532     *(sp + 1) = (png_byte)(v & 0xff);
3533     sp += 2;
3534     v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3535     *sp = (png_byte)((v >> 8) & 0xff);
3536     *(sp + 1) = (png_byte)(v & 0xff);
3537     sp += 4;
3538     }
3539     }
3540     break;
3541     }
3542    
3543     case PNG_COLOR_TYPE_GRAY_ALPHA:
3544     {
3545     if (row_info->bit_depth == 8)
3546     {
3547     sp = row;
3548     for (i = 0; i < row_width; i++)
3549     {
3550     *sp = gamma_table[*sp];
3551     sp += 2;
3552     }
3553     }
3554     else /* if (row_info->bit_depth == 16) */
3555     {
3556     sp = row;
3557     for (i = 0; i < row_width; i++)
3558     {
3559     png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3560     *sp = (png_byte)((v >> 8) & 0xff);
3561     *(sp + 1) = (png_byte)(v & 0xff);
3562     sp += 4;
3563     }
3564     }
3565     break;
3566     }
3567    
3568     case PNG_COLOR_TYPE_GRAY:
3569     {
3570     if (row_info->bit_depth == 2)
3571     {
3572     sp = row;
3573     for (i = 0; i < row_width; i += 4)
3574     {
3575     int a = *sp & 0xc0;
3576     int b = *sp & 0x30;
3577     int c = *sp & 0x0c;
3578     int d = *sp & 0x03;
3579    
3580     *sp = (png_byte)(
3581     ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3582     ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3583     ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3584     ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3585     sp++;
3586     }
3587     }
3588    
3589     if (row_info->bit_depth == 4)
3590     {
3591     sp = row;
3592     for (i = 0; i < row_width; i += 2)
3593     {
3594     int msb = *sp & 0xf0;
3595     int lsb = *sp & 0x0f;
3596    
3597     *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3598     | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3599     sp++;
3600     }
3601     }
3602    
3603     else if (row_info->bit_depth == 8)
3604     {
3605     sp = row;
3606     for (i = 0; i < row_width; i++)
3607     {
3608     *sp = gamma_table[*sp];
3609     sp++;
3610     }
3611     }
3612    
3613     else if (row_info->bit_depth == 16)
3614     {
3615     sp = row;
3616     for (i = 0; i < row_width; i++)
3617     {
3618     png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3619     *sp = (png_byte)((v >> 8) & 0xff);
3620     *(sp + 1) = (png_byte)(v & 0xff);
3621     sp += 2;
3622     }
3623     }
3624     break;
3625     }
3626     }
3627     }
3628     }
3629     #endif
3630    
3631     #if defined(PNG_READ_EXPAND_SUPPORTED)
3632     /* Expands a palette row to an RGB or RGBA row depending
3633     * upon whether you supply trans and num_trans.
3634     */
3635     void /* PRIVATE */
3636     png_do_expand_palette(png_row_infop row_info, png_bytep row,
3637     png_colorp palette, png_bytep trans, int num_trans)
3638     {
3639     int shift, value;
3640     png_bytep sp, dp;
3641     png_uint_32 i;
3642     png_uint_32 row_width=row_info->width;
3643    
3644     png_debug(1, "in png_do_expand_palette");
3645     if (
3646     #if defined(PNG_USELESS_TESTS_SUPPORTED)
3647     row != NULL && row_info != NULL &&
3648     #endif
3649     row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3650     {
3651     if (row_info->bit_depth < 8)
3652     {
3653     switch (row_info->bit_depth)
3654     {
3655     case 1:
3656     {
3657     sp = row + (png_size_t)((row_width - 1) >> 3);
3658     dp = row + (png_size_t)row_width - 1;
3659     shift = 7 - (int)((row_width + 7) & 0x07);
3660     for (i = 0; i < row_width; i++)
3661     {
3662     if ((*sp >> shift) & 0x01)
3663     *dp = 1;
3664     else
3665     *dp = 0;
3666     if (shift == 7)
3667     {
3668     shift = 0;
3669     sp--;
3670     }
3671     else
3672     shift++;
3673    
3674     dp--;
3675     }
3676     break;
3677     }
3678    
3679     case 2:
3680     {
3681     sp = row + (png_size_t)((row_width - 1) >> 2);
3682     dp = row + (png_size_t)row_width - 1;
3683     shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3684     for (i = 0; i < row_width; i++)
3685     {
3686     value = (*sp >> shift) & 0x03;
3687     *dp = (png_byte)value;
3688     if (shift == 6)
3689     {
3690     shift = 0;
3691     sp--;
3692     }
3693     else
3694     shift += 2;
3695    
3696     dp--;
3697     }
3698     break;
3699     }
3700    
3701     case 4:
3702     {
3703     sp = row + (png_size_t)((row_width - 1) >> 1);
3704     dp = row + (png_size_t)row_width - 1;
3705     shift = (int)((row_width & 0x01) << 2);
3706     for (i = 0; i < row_width; i++)
3707     {
3708     value = (*sp >> shift) & 0x0f;
3709     *dp = (png_byte)value;
3710     if (shift == 4)
3711     {
3712     shift = 0;
3713     sp--;
3714     }
3715     else
3716     shift += 4;
3717    
3718     dp--;
3719     }
3720     break;
3721     }
3722     }
3723     row_info->bit_depth = 8;
3724     row_info->pixel_depth = 8;
3725     row_info->rowbytes = row_width;
3726     }
3727     switch (row_info->bit_depth)
3728     {
3729     case 8:
3730     {
3731     if (trans != NULL)
3732     {
3733     sp = row + (png_size_t)row_width - 1;
3734     dp = row + (png_size_t)(row_width << 2) - 1;
3735    
3736     for (i = 0; i < row_width; i++)
3737     {
3738     if ((int)(*sp) >= num_trans)
3739     *dp-- = 0xff;
3740     else
3741     *dp-- = trans[*sp];
3742     *dp-- = palette[*sp].blue;
3743     *dp-- = palette[*sp].green;
3744     *dp-- = palette[*sp].red;
3745     sp--;
3746     }
3747     row_info->bit_depth = 8;
3748     row_info->pixel_depth = 32;
3749     row_info->rowbytes = row_width * 4;
3750     row_info->color_type = 6;
3751     row_info->channels = 4;
3752     }
3753     else
3754     {
3755     sp = row + (png_size_t)row_width - 1;
3756     dp = row + (png_size_t)(row_width * 3) - 1;
3757    
3758     for (i = 0; i < row_width; i++)
3759     {
3760     *dp-- = palette[*sp].blue;
3761     *dp-- = palette[*sp].green;
3762     *dp-- = palette[*sp].red;
3763     sp--;
3764     }
3765    
3766     row_info->bit_depth = 8;
3767     row_info->pixel_depth = 24;
3768     row_info->rowbytes = row_width * 3;
3769     row_info->color_type = 2;
3770     row_info->channels = 3;
3771     }
3772     break;
3773     }
3774     }
3775     }
3776     }
3777    
3778     /* If the bit depth < 8, it is expanded to 8. Also, if the already
3779     * expanded transparency value is supplied, an alpha channel is built.
3780     */
3781     void /* PRIVATE */
3782     png_do_expand(png_row_infop row_info, png_bytep row,
3783     png_color_16p trans_value)
3784     {
3785     int shift, value;
3786     png_bytep sp, dp;
3787     png_uint_32 i;
3788     png_uint_32 row_width=row_info->width;
3789    
3790     png_debug(1, "in png_do_expand");
3791     #if defined(PNG_USELESS_TESTS_SUPPORTED)
3792     if (row != NULL && row_info != NULL)
3793     #endif
3794     {
3795     if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3796     {
3797     png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3798    
3799     if (row_info->bit_depth < 8)
3800     {
3801     switch (row_info->bit_depth)
3802     {
3803     case 1:
3804     {
3805     gray = (png_uint_16)((gray&0x01)*0xff);
3806     sp = row + (png_size_t)((row_width - 1) >> 3);
3807     dp = row + (png_size_t)row_width - 1;
3808     shift = 7 - (int)((row_width + 7) & 0x07);
3809     for (i = 0; i < row_width; i++)
3810     {
3811     if ((*sp >> shift) & 0x01)
3812     *dp = 0xff;
3813     else
3814     *dp = 0;
3815     if (shift == 7)
3816     {
3817     shift = 0;
3818     sp--;
3819     }
3820     else
3821     shift++;
3822    
3823     dp--;
3824     }
3825     break;
3826     }
3827    
3828     case 2:
3829     {
3830     gray = (png_uint_16)((gray&0x03)*0x55);
3831     sp = row + (png_size_t)((row_width - 1) >> 2);
3832     dp = row + (png_size_t)row_width - 1;
3833     shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3834     for (i = 0; i < row_width; i++)
3835     {
3836     value = (*sp >> shift) & 0x03;
3837     *dp = (png_byte)(value | (value << 2) | (value << 4) |
3838     (value << 6));
3839     if (shift == 6)
3840     {
3841     shift = 0;
3842     sp--;
3843     }
3844     else
3845     shift += 2;
3846    
3847     dp--;
3848     }
3849     break;
3850     }
3851    
3852     case 4:
3853     {
3854     gray = (png_uint_16)((gray&0x0f)*0x11);
3855     sp = row + (png_size_t)((row_width - 1) >> 1);
3856     dp = row + (png_size_t)row_width - 1;
3857     shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3858     for (i = 0; i < row_width; i++)
3859     {
3860     value = (*sp >> shift) & 0x0f;
3861     *dp = (png_byte)(value | (value << 4));
3862     if (shift == 4)
3863     {
3864     shift = 0;
3865     sp--;
3866     }
3867     else
3868     shift = 4;
3869    
3870     dp--;
3871     }
3872     break;
3873     }
3874     }
3875    
3876     row_info->bit_depth = 8;
3877     row_info->pixel_depth = 8;
3878     row_info->rowbytes = row_width;
3879     }
3880    
3881     if (trans_value != NULL)
3882     {
3883     if (row_info->bit_depth == 8)
3884     {
3885     gray = gray & 0xff;
3886