2 /* pngrtran.c - transforms the data in a row for PNG readers
4 * Last changed in libpng 1.2.15 January 5, 2007
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2007 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
10 * This file contains functions optionally called by an application
11 * in order to tell libpng how to handle data when reading a PNG.
12 * Transformations that are used in both reading and writing are
19 #if defined(PNG_READ_SUPPORTED)
21 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
23 png_set_crc_action(png_structp png_ptr
, int crit_action
, int ancil_action
)
25 png_debug(1, "in png_set_crc_action\n");
26 /* Tell libpng how we react to CRC errors in critical chunks */
27 if(png_ptr
== NULL
) return;
30 case PNG_CRC_NO_CHANGE
: /* leave setting as is */
32 case PNG_CRC_WARN_USE
: /* warn/use data */
33 png_ptr
->flags
&= ~PNG_FLAG_CRC_CRITICAL_MASK
;
34 png_ptr
->flags
|= PNG_FLAG_CRC_CRITICAL_USE
;
36 case PNG_CRC_QUIET_USE
: /* quiet/use data */
37 png_ptr
->flags
&= ~PNG_FLAG_CRC_CRITICAL_MASK
;
38 png_ptr
->flags
|= PNG_FLAG_CRC_CRITICAL_USE
|
39 PNG_FLAG_CRC_CRITICAL_IGNORE
;
41 case PNG_CRC_WARN_DISCARD
: /* not a valid action for critical data */
42 png_warning(png_ptr
, "Can't discard critical data on CRC error.");
43 case PNG_CRC_ERROR_QUIT
: /* error/quit */
46 png_ptr
->flags
&= ~PNG_FLAG_CRC_CRITICAL_MASK
;
52 case PNG_CRC_NO_CHANGE
: /* leave setting as is */
54 case PNG_CRC_WARN_USE
: /* warn/use data */
55 png_ptr
->flags
&= ~PNG_FLAG_CRC_ANCILLARY_MASK
;
56 png_ptr
->flags
|= PNG_FLAG_CRC_ANCILLARY_USE
;
58 case PNG_CRC_QUIET_USE
: /* quiet/use data */
59 png_ptr
->flags
&= ~PNG_FLAG_CRC_ANCILLARY_MASK
;
60 png_ptr
->flags
|= PNG_FLAG_CRC_ANCILLARY_USE
|
61 PNG_FLAG_CRC_ANCILLARY_NOWARN
;
63 case PNG_CRC_ERROR_QUIT
: /* error/quit */
64 png_ptr
->flags
&= ~PNG_FLAG_CRC_ANCILLARY_MASK
;
65 png_ptr
->flags
|= PNG_FLAG_CRC_ANCILLARY_NOWARN
;
67 case PNG_CRC_WARN_DISCARD
: /* warn/discard data */
70 png_ptr
->flags
&= ~PNG_FLAG_CRC_ANCILLARY_MASK
;
75 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
76 defined(PNG_FLOATING_POINT_SUPPORTED)
77 /* handle alpha and tRNS via a background color */
79 png_set_background(png_structp png_ptr
,
80 png_color_16p background_color
, int background_gamma_code
,
81 int need_expand
, double background_gamma
)
83 png_debug(1, "in png_set_background\n");
84 if(png_ptr
== NULL
) return;
85 if (background_gamma_code
== PNG_BACKGROUND_GAMMA_UNKNOWN
)
87 png_warning(png_ptr
, "Application must supply a known background gamma");
91 png_ptr
->transformations
|= PNG_BACKGROUND
;
92 png_memcpy(&(png_ptr
->background
), background_color
,
93 png_sizeof(png_color_16
));
94 png_ptr
->background_gamma
= (float)background_gamma
;
95 png_ptr
->background_gamma_type
= (png_byte
)(background_gamma_code
);
96 png_ptr
->transformations
|= (need_expand
? PNG_BACKGROUND_EXPAND
: 0);
100 #if defined(PNG_READ_16_TO_8_SUPPORTED)
101 /* strip 16 bit depth files to 8 bit depth */
103 png_set_strip_16(png_structp png_ptr
)
105 png_debug(1, "in png_set_strip_16\n");
106 if(png_ptr
== NULL
) return;
107 png_ptr
->transformations
|= PNG_16_TO_8
;
111 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
113 png_set_strip_alpha(png_structp png_ptr
)
115 png_debug(1, "in png_set_strip_alpha\n");
116 if(png_ptr
== NULL
) return;
117 png_ptr
->flags
|= PNG_FLAG_STRIP_ALPHA
;
121 #if defined(PNG_READ_DITHER_SUPPORTED)
122 /* Dither file to 8 bit. Supply a palette, the current number
123 * of elements in the palette, the maximum number of elements
124 * allowed, and a histogram if possible. If the current number
125 * of colors is greater then the maximum number, the palette will be
126 * modified to fit in the maximum number. "full_dither" indicates
127 * whether we need a dithering cube set up for RGB images, or if we
128 * simply are reducing the number of colors in a paletted image.
131 typedef struct png_dsort_struct
133 struct png_dsort_struct FAR
* next
;
137 typedef png_dsort FAR
* png_dsortp
;
138 typedef png_dsort FAR
* FAR
* png_dsortpp
;
141 png_set_dither(png_structp png_ptr
, png_colorp palette
,
142 int num_palette
, int maximum_colors
, png_uint_16p histogram
,
145 png_debug(1, "in png_set_dither\n");
146 if(png_ptr
== NULL
) return;
147 png_ptr
->transformations
|= PNG_DITHER
;
153 png_ptr
->dither_index
= (png_bytep
)png_malloc(png_ptr
,
154 (png_uint_32
)(num_palette
* png_sizeof (png_byte
)));
155 for (i
= 0; i
< num_palette
; i
++)
156 png_ptr
->dither_index
[i
] = (png_byte
)i
;
159 if (num_palette
> maximum_colors
)
161 if (histogram
!= NULL
)
163 /* This is easy enough, just throw out the least used colors.
164 Perhaps not the best solution, but good enough. */
168 /* initialize an array to sort colors */
169 png_ptr
->dither_sort
= (png_bytep
)png_malloc(png_ptr
,
170 (png_uint_32
)(num_palette
* png_sizeof (png_byte
)));
172 /* initialize the dither_sort array */
173 for (i
= 0; i
< num_palette
; i
++)
174 png_ptr
->dither_sort
[i
] = (png_byte
)i
;
176 /* Find the least used palette entries by starting a
177 bubble sort, and running it until we have sorted
178 out enough colors. Note that we don't care about
179 sorting all the colors, just finding which are
182 for (i
= num_palette
- 1; i
>= maximum_colors
; i
--)
184 int done
; /* to stop early if the list is pre-sorted */
188 for (j
= 0; j
< i
; j
++)
190 if (histogram
[png_ptr
->dither_sort
[j
]]
191 < histogram
[png_ptr
->dither_sort
[j
+ 1]])
195 t
= png_ptr
->dither_sort
[j
];
196 png_ptr
->dither_sort
[j
] = png_ptr
->dither_sort
[j
+ 1];
197 png_ptr
->dither_sort
[j
+ 1] = t
;
205 /* swap the palette around, and set up a table, if necessary */
210 /* put all the useful colors within the max, but don't
212 for (i
= 0; i
< maximum_colors
; i
++)
214 if ((int)png_ptr
->dither_sort
[i
] >= maximum_colors
)
218 while ((int)png_ptr
->dither_sort
[j
] >= maximum_colors
);
219 palette
[i
] = palette
[j
];
227 /* move all the used colors inside the max limit, and
228 develop a translation table */
229 for (i
= 0; i
< maximum_colors
; i
++)
231 /* only move the colors we need to */
232 if ((int)png_ptr
->dither_sort
[i
] >= maximum_colors
)
238 while ((int)png_ptr
->dither_sort
[j
] >= maximum_colors
);
240 tmp_color
= palette
[j
];
241 palette
[j
] = palette
[i
];
242 palette
[i
] = tmp_color
;
243 /* indicate where the color went */
244 png_ptr
->dither_index
[j
] = (png_byte
)i
;
245 png_ptr
->dither_index
[i
] = (png_byte
)j
;
249 /* find closest color for those colors we are not using */
250 for (i
= 0; i
< num_palette
; i
++)
252 if ((int)png_ptr
->dither_index
[i
] >= maximum_colors
)
254 int min_d
, k
, min_k
, d_index
;
256 /* find the closest color to one we threw out */
257 d_index
= png_ptr
->dither_index
[i
];
258 min_d
= PNG_COLOR_DIST(palette
[d_index
], palette
[0]);
259 for (k
= 1, min_k
= 0; k
< maximum_colors
; k
++)
263 d
= PNG_COLOR_DIST(palette
[d_index
], palette
[k
]);
271 /* point to closest color */
272 png_ptr
->dither_index
[i
] = (png_byte
)min_k
;
276 png_free(png_ptr
, png_ptr
->dither_sort
);
277 png_ptr
->dither_sort
=NULL
;
281 /* This is much harder to do simply (and quickly). Perhaps
282 we need to go through a median cut routine, but those
283 don't always behave themselves with only a few colors
284 as input. So we will just find the closest two colors,
285 and throw out one of them (chosen somewhat randomly).
286 [We don't understand this at all, so if someone wants to
287 work on improving it, be our guest - AED, GRP]
297 /* initialize palette index arrays */
298 png_ptr
->index_to_palette
= (png_bytep
)png_malloc(png_ptr
,
299 (png_uint_32
)(num_palette
* png_sizeof (png_byte
)));
300 png_ptr
->palette_to_index
= (png_bytep
)png_malloc(png_ptr
,
301 (png_uint_32
)(num_palette
* png_sizeof (png_byte
)));
303 /* initialize the sort array */
304 for (i
= 0; i
< num_palette
; i
++)
306 png_ptr
->index_to_palette
[i
] = (png_byte
)i
;
307 png_ptr
->palette_to_index
[i
] = (png_byte
)i
;
310 hash
= (png_dsortpp
)png_malloc(png_ptr
, (png_uint_32
)(769 *
311 png_sizeof (png_dsortp
)));
312 for (i
= 0; i
< 769; i
++)
314 /* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
316 num_new_palette
= num_palette
;
318 /* initial wild guess at how far apart the farthest pixel
319 pair we will be eliminating will be. Larger
320 numbers mean more areas will be allocated, Smaller
321 numbers run the risk of not saving enough data, and
322 having to do this all over again.
324 I have not done extensive checking on this number.
328 while (num_new_palette
> maximum_colors
)
330 for (i
= 0; i
< num_new_palette
- 1; i
++)
334 for (j
= i
+ 1; j
< num_new_palette
; j
++)
338 d
= PNG_COLOR_DIST(palette
[i
], palette
[j
]);
343 t
= (png_dsortp
)png_malloc_warn(png_ptr
,
344 (png_uint_32
)(png_sizeof(png_dsort
)));
348 t
->left
= (png_byte
)i
;
349 t
->right
= (png_byte
)j
;
358 for (i
= 0; i
<= max_d
; i
++)
364 for (p
= hash
[i
]; p
; p
= p
->next
)
366 if ((int)png_ptr
->index_to_palette
[p
->left
]
368 (int)png_ptr
->index_to_palette
[p
->right
]
373 if (num_new_palette
& 0x01)
385 palette
[png_ptr
->index_to_palette
[j
]]
386 = palette
[num_new_palette
];
391 for (k
= 0; k
< num_palette
; k
++)
393 if (png_ptr
->dither_index
[k
] ==
394 png_ptr
->index_to_palette
[j
])
395 png_ptr
->dither_index
[k
] =
396 png_ptr
->index_to_palette
[next_j
];
397 if ((int)png_ptr
->dither_index
[k
] ==
399 png_ptr
->dither_index
[k
] =
400 png_ptr
->index_to_palette
[j
];
404 png_ptr
->index_to_palette
[png_ptr
->palette_to_index
405 [num_new_palette
]] = png_ptr
->index_to_palette
[j
];
406 png_ptr
->palette_to_index
[png_ptr
->index_to_palette
[j
]]
407 = png_ptr
->palette_to_index
[num_new_palette
];
409 png_ptr
->index_to_palette
[j
] = (png_byte
)num_new_palette
;
410 png_ptr
->palette_to_index
[num_new_palette
] = (png_byte
)j
;
412 if (num_new_palette
<= maximum_colors
)
415 if (num_new_palette
<= maximum_colors
)
420 for (i
= 0; i
< 769; i
++)
424 png_dsortp p
= hash
[i
];
428 png_free(png_ptr
, p
);
436 png_free(png_ptr
, hash
);
437 png_free(png_ptr
, png_ptr
->palette_to_index
);
438 png_free(png_ptr
, png_ptr
->index_to_palette
);
439 png_ptr
->palette_to_index
=NULL
;
440 png_ptr
->index_to_palette
=NULL
;
442 num_palette
= maximum_colors
;
444 if (png_ptr
->palette
== NULL
)
446 png_ptr
->palette
= palette
;
448 png_ptr
->num_palette
= (png_uint_16
)num_palette
;
454 int total_bits
= PNG_DITHER_RED_BITS
+ PNG_DITHER_GREEN_BITS
+
455 PNG_DITHER_BLUE_BITS
;
456 int num_red
= (1 << PNG_DITHER_RED_BITS
);
457 int num_green
= (1 << PNG_DITHER_GREEN_BITS
);
458 int num_blue
= (1 << PNG_DITHER_BLUE_BITS
);
459 png_size_t num_entries
= ((png_size_t
)1 << total_bits
);
461 png_ptr
->palette_lookup
= (png_bytep
)png_malloc(png_ptr
,
462 (png_uint_32
)(num_entries
* png_sizeof (png_byte
)));
464 png_memset(png_ptr
->palette_lookup
, 0, num_entries
*
465 png_sizeof (png_byte
));
467 distance
= (png_bytep
)png_malloc(png_ptr
, (png_uint_32
)(num_entries
*
468 png_sizeof(png_byte
)));
470 png_memset(distance
, 0xff, num_entries
* png_sizeof(png_byte
));
472 for (i
= 0; i
< num_palette
; i
++)
475 int r
= (palette
[i
].red
>> (8 - PNG_DITHER_RED_BITS
));
476 int g
= (palette
[i
].green
>> (8 - PNG_DITHER_GREEN_BITS
));
477 int b
= (palette
[i
].blue
>> (8 - PNG_DITHER_BLUE_BITS
));
479 for (ir
= 0; ir
< num_red
; ir
++)
481 /* int dr = abs(ir - r); */
482 int dr
= ((ir
> r
) ? ir
- r
: r
- ir
);
483 int index_r
= (ir
<< (PNG_DITHER_BLUE_BITS
+ PNG_DITHER_GREEN_BITS
));
485 for (ig
= 0; ig
< num_green
; ig
++)
487 /* int dg = abs(ig - g); */
488 int dg
= ((ig
> g
) ? ig
- g
: g
- ig
);
490 int dm
= ((dr
> dg
) ? dr
: dg
);
491 int index_g
= index_r
| (ig
<< PNG_DITHER_BLUE_BITS
);
493 for (ib
= 0; ib
< num_blue
; ib
++)
495 int d_index
= index_g
| ib
;
496 /* int db = abs(ib - b); */
497 int db
= ((ib
> b
) ? ib
- b
: b
- ib
);
498 int dmax
= ((dm
> db
) ? dm
: db
);
499 int d
= dmax
+ dt
+ db
;
501 if (d
< (int)distance
[d_index
])
503 distance
[d_index
] = (png_byte
)d
;
504 png_ptr
->palette_lookup
[d_index
] = (png_byte
)i
;
511 png_free(png_ptr
, distance
);
516 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
517 /* Transform the image from the file_gamma to the screen_gamma. We
518 * only do transformations on images where the file_gamma and screen_gamma
519 * are not close reciprocals, otherwise it slows things down slightly, and
520 * also needlessly introduces small errors.
522 * We will turn off gamma transformation later if no semitransparent entries
523 * are present in the tRNS array for palette images. We can't do it here
524 * because we don't necessarily have the tRNS chunk yet.
527 png_set_gamma(png_structp png_ptr
, double scrn_gamma
, double file_gamma
)
529 png_debug(1, "in png_set_gamma\n");
530 if(png_ptr
== NULL
) return;
531 if ((fabs(scrn_gamma
* file_gamma
- 1.0) > PNG_GAMMA_THRESHOLD
) ||
532 (png_ptr
->color_type
& PNG_COLOR_MASK_ALPHA
) ||
533 (png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
))
534 png_ptr
->transformations
|= PNG_GAMMA
;
535 png_ptr
->gamma
= (float)file_gamma
;
536 png_ptr
->screen_gamma
= (float)scrn_gamma
;
540 #if defined(PNG_READ_EXPAND_SUPPORTED)
541 /* Expand paletted images to RGB, expand grayscale images of
542 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
546 png_set_expand(png_structp png_ptr
)
548 png_debug(1, "in png_set_expand\n");
549 if(png_ptr
== NULL
) return;
550 png_ptr
->transformations
|= (PNG_EXPAND
| PNG_EXPAND_tRNS
);
553 /* GRR 19990627: the following three functions currently are identical
554 * to png_set_expand(). However, it is entirely reasonable that someone
555 * might wish to expand an indexed image to RGB but *not* expand a single,
556 * fully transparent palette entry to a full alpha channel--perhaps instead
557 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
558 * the transparent color with a particular RGB value, or drop tRNS entirely.
559 * IOW, a future version of the library may make the transformations flag
560 * a bit more fine-grained, with separate bits for each of these three
563 * More to the point, these functions make it obvious what libpng will be
564 * doing, whereas "expand" can (and does) mean any number of things.
566 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
567 * to expand only the sample depth but not to expand the tRNS to alpha.
570 /* Expand paletted images to RGB. */
572 png_set_palette_to_rgb(png_structp png_ptr
)
574 png_debug(1, "in png_set_palette_to_rgb\n");
575 if(png_ptr
== NULL
) return;
576 png_ptr
->transformations
|= (PNG_EXPAND
| PNG_EXPAND_tRNS
);
579 #if !defined(PNG_1_0_X)
580 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
582 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr
)
584 png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n");
585 if(png_ptr
== NULL
) return;
586 png_ptr
->transformations
|= PNG_EXPAND
;
590 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
591 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
592 /* Deprecated as of libpng-1.2.9 */
594 png_set_gray_1_2_4_to_8(png_structp png_ptr
)
596 png_debug(1, "in png_set_gray_1_2_4_to_8\n");
597 if(png_ptr
== NULL
) return;
598 png_ptr
->transformations
|= (PNG_EXPAND
| PNG_EXPAND_tRNS
);
603 /* Expand tRNS chunks to alpha channels. */
605 png_set_tRNS_to_alpha(png_structp png_ptr
)
607 png_debug(1, "in png_set_expand\n");
608 png_ptr
->transformations
|= (PNG_EXPAND
| PNG_EXPAND_tRNS
);
610 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
612 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
614 png_set_gray_to_rgb(png_structp png_ptr
)
616 png_debug(1, "in png_set_gray_to_rgb\n");
617 png_ptr
->transformations
|= PNG_GRAY_TO_RGB
;
621 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
622 #if defined(PNG_FLOATING_POINT_SUPPORTED)
623 /* Convert a RGB image to a grayscale of the same width. This allows us,
624 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
628 png_set_rgb_to_gray(png_structp png_ptr
, int error_action
, double red
,
631 int red_fixed
= (int)((float)red
*100000.0 + 0.5);
632 int green_fixed
= (int)((float)green
*100000.0 + 0.5);
633 if(png_ptr
== NULL
) return;
634 png_set_rgb_to_gray_fixed(png_ptr
, error_action
, red_fixed
, green_fixed
);
639 png_set_rgb_to_gray_fixed(png_structp png_ptr
, int error_action
,
640 png_fixed_point red
, png_fixed_point green
)
642 png_debug(1, "in png_set_rgb_to_gray\n");
643 if(png_ptr
== NULL
) return;
646 case 1: png_ptr
->transformations
|= PNG_RGB_TO_GRAY
;
648 case 2: png_ptr
->transformations
|= PNG_RGB_TO_GRAY_WARN
;
650 case 3: png_ptr
->transformations
|= PNG_RGB_TO_GRAY_ERR
;
652 if (png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
653 #if defined(PNG_READ_EXPAND_SUPPORTED)
654 png_ptr
->transformations
|= PNG_EXPAND
;
657 png_warning(png_ptr
, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
658 png_ptr
->transformations
&= ~PNG_RGB_TO_GRAY
;
662 png_uint_16 red_int
, green_int
;
663 if(red
< 0 || green
< 0)
665 red_int
= 6968; /* .212671 * 32768 + .5 */
666 green_int
= 23434; /* .715160 * 32768 + .5 */
668 else if(red
+ green
< 100000L)
670 red_int
= (png_uint_16
)(((png_uint_32
)red
*32768L)/100000L);
671 green_int
= (png_uint_16
)(((png_uint_32
)green
*32768L)/100000L);
675 png_warning(png_ptr
, "ignoring out of range rgb_to_gray coefficients");
679 png_ptr
->rgb_to_gray_red_coeff
= red_int
;
680 png_ptr
->rgb_to_gray_green_coeff
= green_int
;
681 png_ptr
->rgb_to_gray_blue_coeff
= (png_uint_16
)(32768-red_int
-green_int
);
686 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
687 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
688 defined(PNG_LEGACY_SUPPORTED)
690 png_set_read_user_transform_fn(png_structp png_ptr
, png_user_transform_ptr
691 read_user_transform_fn
)
693 png_debug(1, "in png_set_read_user_transform_fn\n");
694 if(png_ptr
== NULL
) return;
695 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
696 png_ptr
->transformations
|= PNG_USER_TRANSFORM
;
697 png_ptr
->read_user_transform_fn
= read_user_transform_fn
;
699 #ifdef PNG_LEGACY_SUPPORTED
700 if(read_user_transform_fn
)
702 "This version of libpng does not support user transforms");
707 /* Initialize everything needed for the read. This includes modifying
711 png_init_read_transformations(png_structp png_ptr
)
713 png_debug(1, "in png_init_read_transformations\n");
714 #if defined(PNG_USELESS_TESTS_SUPPORTED)
718 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
719 || defined(PNG_READ_GAMMA_SUPPORTED)
720 int color_type
= png_ptr
->color_type
;
723 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
725 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
726 /* Detect gray background and attempt to enable optimization
727 * for gray --> RGB case */
728 /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
729 * RGB_ALPHA (in which case need_expand is superfluous anyway), the
730 * background color might actually be gray yet not be flagged as such.
731 * This is not a problem for the current code, which uses
732 * PNG_BACKGROUND_IS_GRAY only to decide when to do the
733 * png_do_gray_to_rgb() transformation.
735 if ((png_ptr
->transformations
& PNG_BACKGROUND_EXPAND
) &&
736 !(color_type
& PNG_COLOR_MASK_COLOR
))
738 png_ptr
->mode
|= PNG_BACKGROUND_IS_GRAY
;
739 } else if ((png_ptr
->transformations
& PNG_BACKGROUND
) &&
740 !(png_ptr
->transformations
& PNG_BACKGROUND_EXPAND
) &&
741 (png_ptr
->transformations
& PNG_GRAY_TO_RGB
) &&
742 png_ptr
->background
.red
== png_ptr
->background
.green
&&
743 png_ptr
->background
.red
== png_ptr
->background
.blue
)
745 png_ptr
->mode
|= PNG_BACKGROUND_IS_GRAY
;
746 png_ptr
->background
.gray
= png_ptr
->background
.red
;
750 if ((png_ptr
->transformations
& PNG_BACKGROUND_EXPAND
) &&
751 (png_ptr
->transformations
& PNG_EXPAND
))
753 if (!(color_type
& PNG_COLOR_MASK_COLOR
)) /* i.e., GRAY or GRAY_ALPHA */
755 /* expand background and tRNS chunks */
756 switch (png_ptr
->bit_depth
)
759 png_ptr
->background
.gray
*= (png_uint_16
)0xff;
760 png_ptr
->background
.red
= png_ptr
->background
.green
761 = png_ptr
->background
.blue
= png_ptr
->background
.gray
;
762 if (!(png_ptr
->transformations
& PNG_EXPAND_tRNS
))
764 png_ptr
->trans_values
.gray
*= (png_uint_16
)0xff;
765 png_ptr
->trans_values
.red
= png_ptr
->trans_values
.green
766 = png_ptr
->trans_values
.blue
= png_ptr
->trans_values
.gray
;
770 png_ptr
->background
.gray
*= (png_uint_16
)0x55;
771 png_ptr
->background
.red
= png_ptr
->background
.green
772 = png_ptr
->background
.blue
= png_ptr
->background
.gray
;
773 if (!(png_ptr
->transformations
& PNG_EXPAND_tRNS
))
775 png_ptr
->trans_values
.gray
*= (png_uint_16
)0x55;
776 png_ptr
->trans_values
.red
= png_ptr
->trans_values
.green
777 = png_ptr
->trans_values
.blue
= png_ptr
->trans_values
.gray
;
781 png_ptr
->background
.gray
*= (png_uint_16
)0x11;
782 png_ptr
->background
.red
= png_ptr
->background
.green
783 = png_ptr
->background
.blue
= png_ptr
->background
.gray
;
784 if (!(png_ptr
->transformations
& PNG_EXPAND_tRNS
))
786 png_ptr
->trans_values
.gray
*= (png_uint_16
)0x11;
787 png_ptr
->trans_values
.red
= png_ptr
->trans_values
.green
788 = png_ptr
->trans_values
.blue
= png_ptr
->trans_values
.gray
;
793 png_ptr
->background
.red
= png_ptr
->background
.green
794 = png_ptr
->background
.blue
= png_ptr
->background
.gray
;
798 else if (color_type
== PNG_COLOR_TYPE_PALETTE
)
800 png_ptr
->background
.red
=
801 png_ptr
->palette
[png_ptr
->background
.index
].red
;
802 png_ptr
->background
.green
=
803 png_ptr
->palette
[png_ptr
->background
.index
].green
;
804 png_ptr
->background
.blue
=
805 png_ptr
->palette
[png_ptr
->background
.index
].blue
;
807 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
808 if (png_ptr
->transformations
& PNG_INVERT_ALPHA
)
810 #if defined(PNG_READ_EXPAND_SUPPORTED)
811 if (!(png_ptr
->transformations
& PNG_EXPAND_tRNS
))
814 /* invert the alpha channel (in tRNS) unless the pixels are
815 going to be expanded, in which case leave it for later */
817 istop
=(int)png_ptr
->num_trans
;
818 for (i
=0; i
<istop
; i
++)
819 png_ptr
->trans
[i
] = (png_byte
)(255 - png_ptr
->trans
[i
]);
828 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
829 png_ptr
->background_1
= png_ptr
->background
;
831 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
833 if ((color_type
== PNG_COLOR_TYPE_PALETTE
&& png_ptr
->num_trans
!= 0)
834 && (fabs(png_ptr
->screen_gamma
* png_ptr
->gamma
- 1.0)
835 < PNG_GAMMA_THRESHOLD
))
839 for (i
=0; i
<png_ptr
->num_trans
; i
++)
841 if (png_ptr
->trans
[i
] != 0 && png_ptr
->trans
[i
] != 0xff)
842 k
=1; /* partial transparency is present */
845 png_ptr
->transformations
&= (~PNG_GAMMA
);
848 if ((png_ptr
->transformations
& (PNG_GAMMA
| PNG_RGB_TO_GRAY
)) &&
849 png_ptr
->gamma
!= 0.0)
851 png_build_gamma_table(png_ptr
);
852 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
853 if (png_ptr
->transformations
& PNG_BACKGROUND
)
855 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
857 /* could skip if no transparency and
859 png_color back
, back_1
;
860 png_colorp palette
= png_ptr
->palette
;
861 int num_palette
= png_ptr
->num_palette
;
863 if (png_ptr
->background_gamma_type
== PNG_BACKGROUND_GAMMA_FILE
)
865 back
.red
= png_ptr
->gamma_table
[png_ptr
->background
.red
];
866 back
.green
= png_ptr
->gamma_table
[png_ptr
->background
.green
];
867 back
.blue
= png_ptr
->gamma_table
[png_ptr
->background
.blue
];
869 back_1
.red
= png_ptr
->gamma_to_1
[png_ptr
->background
.red
];
870 back_1
.green
= png_ptr
->gamma_to_1
[png_ptr
->background
.green
];
871 back_1
.blue
= png_ptr
->gamma_to_1
[png_ptr
->background
.blue
];
877 switch (png_ptr
->background_gamma_type
)
879 case PNG_BACKGROUND_GAMMA_SCREEN
:
880 g
= (png_ptr
->screen_gamma
);
883 case PNG_BACKGROUND_GAMMA_FILE
:
884 g
= 1.0 / (png_ptr
->gamma
);
885 gs
= 1.0 / (png_ptr
->gamma
* png_ptr
->screen_gamma
);
887 case PNG_BACKGROUND_GAMMA_UNIQUE
:
888 g
= 1.0 / (png_ptr
->background_gamma
);
889 gs
= 1.0 / (png_ptr
->background_gamma
*
890 png_ptr
->screen_gamma
);
893 g
= 1.0; /* back_1 */
897 if ( fabs(gs
- 1.0) < PNG_GAMMA_THRESHOLD
)
899 back
.red
= (png_byte
)png_ptr
->background
.red
;
900 back
.green
= (png_byte
)png_ptr
->background
.green
;
901 back
.blue
= (png_byte
)png_ptr
->background
.blue
;
905 back
.red
= (png_byte
)(pow(
906 (double)png_ptr
->background
.red
/255, gs
) * 255.0 + .5);
907 back
.green
= (png_byte
)(pow(
908 (double)png_ptr
->background
.green
/255, gs
) * 255.0 + .5);
909 back
.blue
= (png_byte
)(pow(
910 (double)png_ptr
->background
.blue
/255, gs
) * 255.0 + .5);
913 back_1
.red
= (png_byte
)(pow(
914 (double)png_ptr
->background
.red
/255, g
) * 255.0 + .5);
915 back_1
.green
= (png_byte
)(pow(
916 (double)png_ptr
->background
.green
/255, g
) * 255.0 + .5);
917 back_1
.blue
= (png_byte
)(pow(
918 (double)png_ptr
->background
.blue
/255, g
) * 255.0 + .5);
920 for (i
= 0; i
< num_palette
; i
++)
922 if (i
< (int)png_ptr
->num_trans
&& png_ptr
->trans
[i
] != 0xff)
924 if (png_ptr
->trans
[i
] == 0)
928 else /* if (png_ptr->trans[i] != 0xff) */
932 v
= png_ptr
->gamma_to_1
[palette
[i
].red
];
933 png_composite(w
, v
, png_ptr
->trans
[i
], back_1
.red
);
934 palette
[i
].red
= png_ptr
->gamma_from_1
[w
];
936 v
= png_ptr
->gamma_to_1
[palette
[i
].green
];
937 png_composite(w
, v
, png_ptr
->trans
[i
], back_1
.green
);
938 palette
[i
].green
= png_ptr
->gamma_from_1
[w
];
940 v
= png_ptr
->gamma_to_1
[palette
[i
].blue
];
941 png_composite(w
, v
, png_ptr
->trans
[i
], back_1
.blue
);
942 palette
[i
].blue
= png_ptr
->gamma_from_1
[w
];
947 palette
[i
].red
= png_ptr
->gamma_table
[palette
[i
].red
];
948 palette
[i
].green
= png_ptr
->gamma_table
[palette
[i
].green
];
949 palette
[i
].blue
= png_ptr
->gamma_table
[palette
[i
].blue
];
953 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
955 /* color_type != PNG_COLOR_TYPE_PALETTE */
957 double m
= (double)(((png_uint_32
)1 << png_ptr
->bit_depth
) - 1);
961 switch (png_ptr
->background_gamma_type
)
963 case PNG_BACKGROUND_GAMMA_SCREEN
:
964 g
= (png_ptr
->screen_gamma
);
967 case PNG_BACKGROUND_GAMMA_FILE
:
968 g
= 1.0 / (png_ptr
->gamma
);
969 gs
= 1.0 / (png_ptr
->gamma
* png_ptr
->screen_gamma
);
971 case PNG_BACKGROUND_GAMMA_UNIQUE
:
972 g
= 1.0 / (png_ptr
->background_gamma
);
973 gs
= 1.0 / (png_ptr
->background_gamma
*
974 png_ptr
->screen_gamma
);
978 png_ptr
->background_1
.gray
= (png_uint_16
)(pow(
979 (double)png_ptr
->background
.gray
/ m
, g
) * m
+ .5);
980 png_ptr
->background
.gray
= (png_uint_16
)(pow(
981 (double)png_ptr
->background
.gray
/ m
, gs
) * m
+ .5);
983 if ((png_ptr
->background
.red
!= png_ptr
->background
.green
) ||
984 (png_ptr
->background
.red
!= png_ptr
->background
.blue
) ||
985 (png_ptr
->background
.red
!= png_ptr
->background
.gray
))
987 /* RGB or RGBA with color background */
988 png_ptr
->background_1
.red
= (png_uint_16
)(pow(
989 (double)png_ptr
->background
.red
/ m
, g
) * m
+ .5);
990 png_ptr
->background_1
.green
= (png_uint_16
)(pow(
991 (double)png_ptr
->background
.green
/ m
, g
) * m
+ .5);
992 png_ptr
->background_1
.blue
= (png_uint_16
)(pow(
993 (double)png_ptr
->background
.blue
/ m
, g
) * m
+ .5);
994 png_ptr
->background
.red
= (png_uint_16
)(pow(
995 (double)png_ptr
->background
.red
/ m
, gs
) * m
+ .5);
996 png_ptr
->background
.green
= (png_uint_16
)(pow(
997 (double)png_ptr
->background
.green
/ m
, gs
) * m
+ .5);
998 png_ptr
->background
.blue
= (png_uint_16
)(pow(
999 (double)png_ptr
->background
.blue
/ m
, gs
) * m
+ .5);
1003 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1004 png_ptr
->background_1
.red
= png_ptr
->background_1
.green
1005 = png_ptr
->background_1
.blue
= png_ptr
->background_1
.gray
;
1006 png_ptr
->background
.red
= png_ptr
->background
.green
1007 = png_ptr
->background
.blue
= png_ptr
->background
.gray
;
1012 /* transformation does not include PNG_BACKGROUND */
1013 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1014 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
1016 png_colorp palette
= png_ptr
->palette
;
1017 int num_palette
= png_ptr
->num_palette
;
1020 for (i
= 0; i
< num_palette
; i
++)
1022 palette
[i
].red
= png_ptr
->gamma_table
[palette
[i
].red
];
1023 palette
[i
].green
= png_ptr
->gamma_table
[palette
[i
].green
];
1024 palette
[i
].blue
= png_ptr
->gamma_table
[palette
[i
].blue
];
1028 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1031 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1032 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1033 /* No GAMMA transformation */
1034 if ((png_ptr
->transformations
& PNG_BACKGROUND
) &&
1035 (color_type
== PNG_COLOR_TYPE_PALETTE
))
1038 int istop
= (int)png_ptr
->num_trans
;
1040 png_colorp palette
= png_ptr
->palette
;
1042 back
.red
= (png_byte
)png_ptr
->background
.red
;
1043 back
.green
= (png_byte
)png_ptr
->background
.green
;
1044 back
.blue
= (png_byte
)png_ptr
->background
.blue
;
1046 for (i
= 0; i
< istop
; i
++)
1048 if (png_ptr
->trans
[i
] == 0)
1052 else if (png_ptr
->trans
[i
] != 0xff)
1054 /* The png_composite() macro is defined in png.h */
1055 png_composite(palette
[i
].red
, palette
[i
].red
,
1056 png_ptr
->trans
[i
], back
.red
);
1057 png_composite(palette
[i
].green
, palette
[i
].green
,
1058 png_ptr
->trans
[i
], back
.green
);
1059 png_composite(palette
[i
].blue
, palette
[i
].blue
,
1060 png_ptr
->trans
[i
], back
.blue
);
1064 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1066 #if defined(PNG_READ_SHIFT_SUPPORTED)
1067 if ((png_ptr
->transformations
& PNG_SHIFT
) &&
1068 (color_type
== PNG_COLOR_TYPE_PALETTE
))
1071 png_uint_16 istop
= png_ptr
->num_palette
;
1072 int sr
= 8 - png_ptr
->sig_bit
.red
;
1073 int sg
= 8 - png_ptr
->sig_bit
.green
;
1074 int sb
= 8 - png_ptr
->sig_bit
.blue
;
1076 if (sr
< 0 || sr
> 8)
1078 if (sg
< 0 || sg
> 8)
1080 if (sb
< 0 || sb
> 8)
1082 for (i
= 0; i
< istop
; i
++)
1084 png_ptr
->palette
[i
].red
>>= sr
;
1085 png_ptr
->palette
[i
].green
>>= sg
;
1086 png_ptr
->palette
[i
].blue
>>= sb
;
1089 #endif /* PNG_READ_SHIFT_SUPPORTED */
1091 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1092 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1098 /* Modify the info structure to reflect the transformations. The
1099 * info should be updated so a PNG file could be written with it,
1100 * assuming the transformations result in valid PNG data.
1103 png_read_transform_info(png_structp png_ptr
, png_infop info_ptr
)
1105 png_debug(1, "in png_read_transform_info\n");
1106 #if defined(PNG_READ_EXPAND_SUPPORTED)
1107 if (png_ptr
->transformations
& PNG_EXPAND
)
1109 if (info_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
1111 if (png_ptr
->num_trans
&& (png_ptr
->transformations
& PNG_EXPAND_tRNS
))
1112 info_ptr
->color_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
1114 info_ptr
->color_type
= PNG_COLOR_TYPE_RGB
;
1115 info_ptr
->bit_depth
= 8;
1116 info_ptr
->num_trans
= 0;
1120 if (png_ptr
->num_trans
)
1122 if (png_ptr
->transformations
& PNG_EXPAND_tRNS
)
1123 info_ptr
->color_type
|= PNG_COLOR_MASK_ALPHA
;
1125 info_ptr
->color_type
|= PNG_COLOR_MASK_COLOR
;
1127 if (info_ptr
->bit_depth
< 8)
1128 info_ptr
->bit_depth
= 8;
1129 info_ptr
->num_trans
= 0;
1134 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1135 if (png_ptr
->transformations
& PNG_BACKGROUND
)
1137 info_ptr
->color_type
&= ~PNG_COLOR_MASK_ALPHA
;
1138 info_ptr
->num_trans
= 0;
1139 info_ptr
->background
= png_ptr
->background
;
1143 #if defined(PNG_READ_GAMMA_SUPPORTED)
1144 if (png_ptr
->transformations
& PNG_GAMMA
)
1146 #ifdef PNG_FLOATING_POINT_SUPPORTED
1147 info_ptr
->gamma
= png_ptr
->gamma
;
1149 #ifdef PNG_FIXED_POINT_SUPPORTED
1150 info_ptr
->int_gamma
= png_ptr
->int_gamma
;
1155 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1156 if ((png_ptr
->transformations
& PNG_16_TO_8
) && (info_ptr
->bit_depth
== 16))
1157 info_ptr
->bit_depth
= 8;
1160 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1161 if (png_ptr
->transformations
& PNG_GRAY_TO_RGB
)
1162 info_ptr
->color_type
|= PNG_COLOR_MASK_COLOR
;
1165 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1166 if (png_ptr
->transformations
& PNG_RGB_TO_GRAY
)
1167 info_ptr
->color_type
&= ~PNG_COLOR_MASK_COLOR
;
1170 #if defined(PNG_READ_DITHER_SUPPORTED)
1171 if (png_ptr
->transformations
& PNG_DITHER
)
1173 if (((info_ptr
->color_type
== PNG_COLOR_TYPE_RGB
) ||
1174 (info_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)) &&
1175 png_ptr
->palette_lookup
&& info_ptr
->bit_depth
== 8)
1177 info_ptr
->color_type
= PNG_COLOR_TYPE_PALETTE
;
1182 #if defined(PNG_READ_PACK_SUPPORTED)
1183 if ((png_ptr
->transformations
& PNG_PACK
) && (info_ptr
->bit_depth
< 8))
1184 info_ptr
->bit_depth
= 8;
1187 if (info_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
1188 info_ptr
->channels
= 1;
1189 else if (info_ptr
->color_type
& PNG_COLOR_MASK_COLOR
)
1190 info_ptr
->channels
= 3;
1192 info_ptr
->channels
= 1;
1194 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1195 if (png_ptr
->flags
& PNG_FLAG_STRIP_ALPHA
)
1196 info_ptr
->color_type
&= ~PNG_COLOR_MASK_ALPHA
;
1199 if (info_ptr
->color_type
& PNG_COLOR_MASK_ALPHA
)
1200 info_ptr
->channels
++;
1202 #if defined(PNG_READ_FILLER_SUPPORTED)
1203 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1204 if ((png_ptr
->transformations
& PNG_FILLER
) &&
1205 ((info_ptr
->color_type
== PNG_COLOR_TYPE_RGB
) ||
1206 (info_ptr
->color_type
== PNG_COLOR_TYPE_GRAY
)))
1208 info_ptr
->channels
++;
1209 /* if adding a true alpha channel not just filler */
1210 #if !defined(PNG_1_0_X)
1211 if (png_ptr
->transformations
& PNG_ADD_ALPHA
)
1212 info_ptr
->color_type
|= PNG_COLOR_MASK_ALPHA
;
1217 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1218 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1219 if(png_ptr
->transformations
& PNG_USER_TRANSFORM
)
1221 if(info_ptr
->bit_depth
< png_ptr
->user_transform_depth
)
1222 info_ptr
->bit_depth
= png_ptr
->user_transform_depth
;
1223 if(info_ptr
->channels
< png_ptr
->user_transform_channels
)
1224 info_ptr
->channels
= png_ptr
->user_transform_channels
;
1228 info_ptr
->pixel_depth
= (png_byte
)(info_ptr
->channels
*
1229 info_ptr
->bit_depth
);
1231 info_ptr
->rowbytes
= PNG_ROWBYTES(info_ptr
->pixel_depth
,info_ptr
->width
);
1233 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1239 /* Transform the row. The order of transformations is significant,
1240 * and is very touchy. If you add a transformation, take care to
1241 * decide how it fits in with the other transformations here.
1244 png_do_read_transformations(png_structp png_ptr
)
1246 png_debug(1, "in png_do_read_transformations\n");
1247 #if !defined(PNG_USELESS_TESTS_SUPPORTED)
1248 if (png_ptr
->row_buf
== NULL
)
1250 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1253 sprintf(msg
, "NULL row buffer for row %ld, pass %d", png_ptr
->row_number
,
1255 png_error(png_ptr
, msg
);
1257 png_error(png_ptr
, "NULL row buffer");
1262 #if defined(PNG_READ_EXPAND_SUPPORTED)
1263 if (png_ptr
->transformations
& PNG_EXPAND
)
1265 if (png_ptr
->row_info
.color_type
== PNG_COLOR_TYPE_PALETTE
)
1267 png_do_expand_palette(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1268 png_ptr
->palette
, png_ptr
->trans
, png_ptr
->num_trans
);
1272 if (png_ptr
->num_trans
&& (png_ptr
->transformations
& PNG_EXPAND_tRNS
))
1273 png_do_expand(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1274 &(png_ptr
->trans_values
));
1276 png_do_expand(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1282 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1283 if (png_ptr
->flags
& PNG_FLAG_STRIP_ALPHA
)
1284 png_do_strip_filler(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1285 PNG_FLAG_FILLER_AFTER
| (png_ptr
->flags
& PNG_FLAG_STRIP_ALPHA
));
1288 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1289 if (png_ptr
->transformations
& PNG_RGB_TO_GRAY
)
1292 png_do_rgb_to_gray(png_ptr
, &(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1295 png_ptr
->rgb_to_gray_status
=1;
1296 if(png_ptr
->transformations
& PNG_RGB_TO_GRAY_WARN
)
1297 png_warning(png_ptr
, "png_do_rgb_to_gray found nongray pixel");
1298 if(png_ptr
->transformations
& PNG_RGB_TO_GRAY_ERR
)
1299 png_error(png_ptr
, "png_do_rgb_to_gray found nongray pixel");
1305 From Andreas Dilger e-mail to png-implement, 26 March 1998:
1307 In most cases, the "simple transparency" should be done prior to doing
1308 gray-to-RGB, or you will have to test 3x as many bytes to check if a
1309 pixel is transparent. You would also need to make sure that the
1310 transparency information is upgraded to RGB.
1312 To summarize, the current flow is:
1313 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1314 with background "in place" if transparent,
1315 convert to RGB if necessary
1316 - Gray + alpha -> composite with gray background and remove alpha bytes,
1317 convert to RGB if necessary
1319 To support RGB backgrounds for gray images we need:
1320 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1321 3 or 6 bytes and composite with background
1322 "in place" if transparent (3x compare/pixel
1323 compared to doing composite with gray bkgrnd)
1324 - Gray + alpha -> convert to RGB + alpha, composite with background and
1325 remove alpha bytes (3x float operations/pixel
1326 compared with composite on gray background)
1328 Greg's change will do this. The reason it wasn't done before is for
1329 performance, as this increases the per-pixel operations. If we would check
1330 in advance if the background was gray or RGB, and position the gray-to-RGB
1331 transform appropriately, then it would save a lot of work/time.
1334 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1335 /* if gray -> RGB, do so now only if background is non-gray; else do later
1336 * for performance reasons */
1337 if ((png_ptr
->transformations
& PNG_GRAY_TO_RGB
) &&
1338 !(png_ptr
->mode
& PNG_BACKGROUND_IS_GRAY
))
1339 png_do_gray_to_rgb(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1342 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1343 if ((png_ptr
->transformations
& PNG_BACKGROUND
) &&
1344 ((png_ptr
->num_trans
!= 0 ) ||
1345 (png_ptr
->color_type
& PNG_COLOR_MASK_ALPHA
)))
1346 png_do_background(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1347 &(png_ptr
->trans_values
), &(png_ptr
->background
)
1348 #if defined(PNG_READ_GAMMA_SUPPORTED)
1349 , &(png_ptr
->background_1
),
1350 png_ptr
->gamma_table
, png_ptr
->gamma_from_1
,
1351 png_ptr
->gamma_to_1
, png_ptr
->gamma_16_table
,
1352 png_ptr
->gamma_16_from_1
, png_ptr
->gamma_16_to_1
,
1353 png_ptr
->gamma_shift
1358 #if defined(PNG_READ_GAMMA_SUPPORTED)
1359 if ((png_ptr
->transformations
& PNG_GAMMA
) &&
1360 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1361 !((png_ptr
->transformations
& PNG_BACKGROUND
) &&
1362 ((png_ptr
->num_trans
!= 0) ||
1363 (png_ptr
->color_type
& PNG_COLOR_MASK_ALPHA
))) &&
1365 (png_ptr
->color_type
!= PNG_COLOR_TYPE_PALETTE
))
1366 png_do_gamma(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1367 png_ptr
->gamma_table
, png_ptr
->gamma_16_table
,
1368 png_ptr
->gamma_shift
);
1371 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1372 if (png_ptr
->transformations
& PNG_16_TO_8
)
1373 png_do_chop(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1376 #if defined(PNG_READ_DITHER_SUPPORTED)
1377 if (png_ptr
->transformations
& PNG_DITHER
)
1379 png_do_dither((png_row_infop
)&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1380 png_ptr
->palette_lookup
, png_ptr
->dither_index
);
1381 if(png_ptr
->row_info
.rowbytes
== (png_uint_32
)0)
1382 png_error(png_ptr
, "png_do_dither returned rowbytes=0");
1386 #if defined(PNG_READ_INVERT_SUPPORTED)
1387 if (png_ptr
->transformations
& PNG_INVERT_MONO
)
1388 png_do_invert(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1391 #if defined(PNG_READ_SHIFT_SUPPORTED)
1392 if (png_ptr
->transformations
& PNG_SHIFT
)
1393 png_do_unshift(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1397 #if defined(PNG_READ_PACK_SUPPORTED)
1398 if (png_ptr
->transformations
& PNG_PACK
)
1399 png_do_unpack(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1402 #if defined(PNG_READ_BGR_SUPPORTED)
1403 if (png_ptr
->transformations
& PNG_BGR
)
1404 png_do_bgr(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1407 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1408 if (png_ptr
->transformations
& PNG_PACKSWAP
)
1409 png_do_packswap(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1412 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1413 /* if gray -> RGB, do so now only if we did not do so above */
1414 if ((png_ptr
->transformations
& PNG_GRAY_TO_RGB
) &&
1415 (png_ptr
->mode
& PNG_BACKGROUND_IS_GRAY
))
1416 png_do_gray_to_rgb(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1419 #if defined(PNG_READ_FILLER_SUPPORTED)
1420 if (png_ptr
->transformations
& PNG_FILLER
)
1421 png_do_read_filler(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
1422 (png_uint_32
)png_ptr
->filler
, png_ptr
->flags
);
1425 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1426 if (png_ptr
->transformations
& PNG_INVERT_ALPHA
)
1427 png_do_read_invert_alpha(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1430 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1431 if (png_ptr
->transformations
& PNG_SWAP_ALPHA
)
1432 png_do_read_swap_alpha(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1435 #if defined(PNG_READ_SWAP_SUPPORTED)
1436 if (png_ptr
->transformations
& PNG_SWAP_BYTES
)
1437 png_do_swap(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
1440 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1441 if (png_ptr
->transformations
& PNG_USER_TRANSFORM
)
1443 if(png_ptr
->read_user_transform_fn
!= NULL
)
1444 (*(png_ptr
->read_user_transform_fn
)) /* user read transform function */
1445 (png_ptr
, /* png_ptr */
1446 &(png_ptr
->row_info
), /* row_info: */
1447 /* png_uint_32 width; width of row */
1448 /* png_uint_32 rowbytes; number of bytes in row */
1449 /* png_byte color_type; color type of pixels */
1450 /* png_byte bit_depth; bit depth of samples */
1451 /* png_byte channels; number of channels (1-4) */
1452 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1453 png_ptr
->row_buf
+ 1); /* start of pixel data for row */
1454 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1455 if(png_ptr
->user_transform_depth
)
1456 png_ptr
->row_info
.bit_depth
= png_ptr
->user_transform_depth
;
1457 if(png_ptr
->user_transform_channels
)
1458 png_ptr
->row_info
.channels
= png_ptr
->user_transform_channels
;
1460 png_ptr
->row_info
.pixel_depth
= (png_byte
)(png_ptr
->row_info
.bit_depth
*
1461 png_ptr
->row_info
.channels
);
1462 png_ptr
->row_info
.rowbytes
= PNG_ROWBYTES(png_ptr
->row_info
.pixel_depth
,
1463 png_ptr
->row_info
.width
);
1469 #if defined(PNG_READ_PACK_SUPPORTED)
1470 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1471 * without changing the actual values. Thus, if you had a row with
1472 * a bit depth of 1, you would end up with bytes that only contained
1473 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1474 * png_do_shift() after this.
1477 png_do_unpack(png_row_infop row_info
, png_bytep row
)
1479 png_debug(1, "in png_do_unpack\n");
1480 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1481 if (row
!= NULL
&& row_info
!= NULL
&& row_info
->bit_depth
< 8)
1483 if (row_info
->bit_depth
< 8)
1487 png_uint_32 row_width
=row_info
->width
;
1489 switch (row_info
->bit_depth
)
1493 png_bytep sp
= row
+ (png_size_t
)((row_width
- 1) >> 3);
1494 png_bytep dp
= row
+ (png_size_t
)row_width
- 1;
1495 png_uint_32 shift
= 7 - (int)((row_width
+ 7) & 0x07);
1496 for (i
= 0; i
< row_width
; i
++)
1498 *dp
= (png_byte
)((*sp
>> shift
) & 0x01);
1514 png_bytep sp
= row
+ (png_size_t
)((row_width
- 1) >> 2);
1515 png_bytep dp
= row
+ (png_size_t
)row_width
- 1;
1516 png_uint_32 shift
= (int)((3 - ((row_width
+ 3) & 0x03)) << 1);
1517 for (i
= 0; i
< row_width
; i
++)
1519 *dp
= (png_byte
)((*sp
>> shift
) & 0x03);
1534 png_bytep sp
= row
+ (png_size_t
)((row_width
- 1) >> 1);
1535 png_bytep dp
= row
+ (png_size_t
)row_width
- 1;
1536 png_uint_32 shift
= (int)((1 - ((row_width
+ 1) & 0x01)) << 2);
1537 for (i
= 0; i
< row_width
; i
++)
1539 *dp
= (png_byte
)((*sp
>> shift
) & 0x0f);
1553 row_info
->bit_depth
= 8;
1554 row_info
->pixel_depth
= (png_byte
)(8 * row_info
->channels
);
1555 row_info
->rowbytes
= row_width
* row_info
->channels
;
1560 #if defined(PNG_READ_SHIFT_SUPPORTED)
1561 /* Reverse the effects of png_do_shift. This routine merely shifts the
1562 * pixels back to their significant bits values. Thus, if you have
1563 * a row of bit depth 8, but only 5 are significant, this will shift
1564 * the values back to 0 through 31.
1567 png_do_unshift(png_row_infop row_info
, png_bytep row
, png_color_8p sig_bits
)
1569 png_debug(1, "in png_do_unshift\n");
1571 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1572 row
!= NULL
&& row_info
!= NULL
&& sig_bits
!= NULL
&&
1574 row_info
->color_type
!= PNG_COLOR_TYPE_PALETTE
)
1579 png_uint_16 value
= 0;
1580 png_uint_32 row_width
= row_info
->width
;
1582 if (row_info
->color_type
& PNG_COLOR_MASK_COLOR
)
1584 shift
[channels
++] = row_info
->bit_depth
- sig_bits
->red
;
1585 shift
[channels
++] = row_info
->bit_depth
- sig_bits
->green
;
1586 shift
[channels
++] = row_info
->bit_depth
- sig_bits
->blue
;
1590 shift
[channels
++] = row_info
->bit_depth
- sig_bits
->gray
;
1592 if (row_info
->color_type
& PNG_COLOR_MASK_ALPHA
)
1594 shift
[channels
++] = row_info
->bit_depth
- sig_bits
->alpha
;
1597 for (c
= 0; c
< channels
; c
++)
1608 switch (row_info
->bit_depth
)
1614 png_uint_32 istop
= row_info
->rowbytes
;
1616 for (bp
= row
, i
= 0; i
< istop
; i
++)
1627 png_uint_32 istop
= row_info
->rowbytes
;
1628 png_byte mask
= (png_byte
)((((int)0xf0 >> shift
[0]) & (int)0xf0) |
1629 (png_byte
)((int)0xf >> shift
[0]));
1631 for (i
= 0; i
< istop
; i
++)
1642 png_uint_32 istop
= row_width
* channels
;
1644 for (i
= 0; i
< istop
; i
++)
1646 *bp
++ >>= shift
[i
%channels
];
1654 png_uint_32 istop
= channels
* row_width
;
1656 for (i
= 0; i
< istop
; i
++)
1658 value
= (png_uint_16
)((*bp
<< 8) + *(bp
+ 1));
1659 value
>>= shift
[i
%channels
];
1660 *bp
++ = (png_byte
)(value
>> 8);
1661 *bp
++ = (png_byte
)(value
& 0xff);
1670 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1671 /* chop rows of bit depth 16 down to 8 */
1673 png_do_chop(png_row_infop row_info
, png_bytep row
)
1675 png_debug(1, "in png_do_chop\n");
1676 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1677 if (row
!= NULL
&& row_info
!= NULL
&& row_info
->bit_depth
== 16)
1679 if (row_info
->bit_depth
== 16)
1685 png_uint_32 istop
= row_info
->width
* row_info
->channels
;
1687 for (i
= 0; i
<istop
; i
++, sp
+= 2, dp
++)
1689 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1690 /* This does a more accurate scaling of the 16-bit color
1691 * value, rather than a simple low-byte truncation.
1693 * What the ideal calculation should be:
1694 * *dp = (((((png_uint_32)(*sp) << 8) |
1695 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1697 * GRR: no, I think this is what it really should be:
1698 * *dp = (((((png_uint_32)(*sp) << 8) |
1699 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1701 * GRR: here's the exact calculation with shifts:
1702 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1703 * *dp = (temp - (temp >> 8)) >> 8;
1705 * Approximate calculation with shift/add instead of multiply/divide:
1706 * *dp = ((((png_uint_32)(*sp) << 8) |
1707 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1709 * What we actually do to avoid extra shifting and conversion:
1712 *dp
= *sp
+ ((((int)(*(sp
+ 1)) - *sp
) > 128) ? 1 : 0);
1714 /* Simply discard the low order byte */
1718 row_info
->bit_depth
= 8;
1719 row_info
->pixel_depth
= (png_byte
)(8 * row_info
->channels
);
1720 row_info
->rowbytes
= row_info
->width
* row_info
->channels
;
1725 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1727 png_do_read_swap_alpha(png_row_infop row_info
, png_bytep row
)
1729 png_debug(1, "in png_do_read_swap_alpha\n");
1730 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1731 if (row
!= NULL
&& row_info
!= NULL
)
1734 png_uint_32 row_width
= row_info
->width
;
1735 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
1737 /* This converts from RGBA to ARGB */
1738 if (row_info
->bit_depth
== 8)
1740 png_bytep sp
= row
+ row_info
->rowbytes
;
1745 for (i
= 0; i
< row_width
; i
++)
1754 /* This converts from RRGGBBAA to AARRGGBB */
1757 png_bytep sp
= row
+ row_info
->rowbytes
;
1762 for (i
= 0; i
< row_width
; i
++)
1777 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
1779 /* This converts from GA to AG */
1780 if (row_info
->bit_depth
== 8)
1782 png_bytep sp
= row
+ row_info
->rowbytes
;
1787 for (i
= 0; i
< row_width
; i
++)
1794 /* This converts from GGAA to AAGG */
1797 png_bytep sp
= row
+ row_info
->rowbytes
;
1802 for (i
= 0; i
< row_width
; i
++)
1817 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1819 png_do_read_invert_alpha(png_row_infop row_info
, png_bytep row
)
1821 png_debug(1, "in png_do_read_invert_alpha\n");
1822 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1823 if (row
!= NULL
&& row_info
!= NULL
)
1826 png_uint_32 row_width
= row_info
->width
;
1827 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
1829 /* This inverts the alpha channel in RGBA */
1830 if (row_info
->bit_depth
== 8)
1832 png_bytep sp
= row
+ row_info
->rowbytes
;
1836 for (i
= 0; i
< row_width
; i
++)
1838 *(--dp
) = (png_byte
)(255 - *(--sp
));
1840 /* This does nothing:
1844 We can replace it with:
1850 /* This inverts the alpha channel in RRGGBBAA */
1853 png_bytep sp
= row
+ row_info
->rowbytes
;
1857 for (i
= 0; i
< row_width
; i
++)
1859 *(--dp
) = (png_byte
)(255 - *(--sp
));
1860 *(--dp
) = (png_byte
)(255 - *(--sp
));
1862 /* This does nothing:
1869 We can replace it with:
1876 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
1878 /* This inverts the alpha channel in GA */
1879 if (row_info
->bit_depth
== 8)
1881 png_bytep sp
= row
+ row_info
->rowbytes
;
1885 for (i
= 0; i
< row_width
; i
++)
1887 *(--dp
) = (png_byte
)(255 - *(--sp
));
1891 /* This inverts the alpha channel in GGAA */
1894 png_bytep sp
= row
+ row_info
->rowbytes
;
1898 for (i
= 0; i
< row_width
; i
++)
1900 *(--dp
) = (png_byte
)(255 - *(--sp
));
1901 *(--dp
) = (png_byte
)(255 - *(--sp
));
1915 #if defined(PNG_READ_FILLER_SUPPORTED)
1916 /* Add filler channel if we have RGB color */
1918 png_do_read_filler(png_row_infop row_info
, png_bytep row
,
1919 png_uint_32 filler
, png_uint_32 flags
)
1922 png_uint_32 row_width
= row_info
->width
;
1924 png_byte hi_filler
= (png_byte
)((filler
>>8) & 0xff);
1925 png_byte lo_filler
= (png_byte
)(filler
& 0xff);
1927 png_debug(1, "in png_do_read_filler\n");
1929 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1930 row
!= NULL
&& row_info
!= NULL
&&
1932 row_info
->color_type
== PNG_COLOR_TYPE_GRAY
)
1934 if(row_info
->bit_depth
== 8)
1936 /* This changes the data from G to GX */
1937 if (flags
& PNG_FLAG_FILLER_AFTER
)
1939 png_bytep sp
= row
+ (png_size_t
)row_width
;
1940 png_bytep dp
= sp
+ (png_size_t
)row_width
;
1941 for (i
= 1; i
< row_width
; i
++)
1943 *(--dp
) = lo_filler
;
1946 *(--dp
) = lo_filler
;
1947 row_info
->channels
= 2;
1948 row_info
->pixel_depth
= 16;
1949 row_info
->rowbytes
= row_width
* 2;
1951 /* This changes the data from G to XG */
1954 png_bytep sp
= row
+ (png_size_t
)row_width
;
1955 png_bytep dp
= sp
+ (png_size_t
)row_width
;
1956 for (i
= 0; i
< row_width
; i
++)
1959 *(--dp
) = lo_filler
;
1961 row_info
->channels
= 2;
1962 row_info
->pixel_depth
= 16;
1963 row_info
->rowbytes
= row_width
* 2;
1966 else if(row_info
->bit_depth
== 16)
1968 /* This changes the data from GG to GGXX */
1969 if (flags
& PNG_FLAG_FILLER_AFTER
)
1971 png_bytep sp
= row
+ (png_size_t
)row_width
* 2;
1972 png_bytep dp
= sp
+ (png_size_t
)row_width
* 2;
1973 for (i
= 1; i
< row_width
; i
++)
1975 *(--dp
) = hi_filler
;
1976 *(--dp
) = lo_filler
;
1980 *(--dp
) = hi_filler
;
1981 *(--dp
) = lo_filler
;
1982 row_info
->channels
= 2;
1983 row_info
->pixel_depth
= 32;
1984 row_info
->rowbytes
= row_width
* 4;
1986 /* This changes the data from GG to XXGG */
1989 png_bytep sp
= row
+ (png_size_t
)row_width
* 2;
1990 png_bytep dp
= sp
+ (png_size_t
)row_width
* 2;
1991 for (i
= 0; i
< row_width
; i
++)
1995 *(--dp
) = hi_filler
;
1996 *(--dp
) = lo_filler
;
1998 row_info
->channels
= 2;
1999 row_info
->pixel_depth
= 32;
2000 row_info
->rowbytes
= row_width
* 4;
2003 } /* COLOR_TYPE == GRAY */
2004 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
2006 if(row_info
->bit_depth
== 8)
2008 /* This changes the data from RGB to RGBX */
2009 if (flags
& PNG_FLAG_FILLER_AFTER
)
2011 png_bytep sp
= row
+ (png_size_t
)row_width
* 3;
2012 png_bytep dp
= sp
+ (png_size_t
)row_width
;
2013 for (i
= 1; i
< row_width
; i
++)
2015 *(--dp
) = lo_filler
;
2020 *(--dp
) = lo_filler
;
2021 row_info
->channels
= 4;
2022 row_info
->pixel_depth
= 32;
2023 row_info
->rowbytes
= row_width
* 4;
2025 /* This changes the data from RGB to XRGB */
2028 png_bytep sp
= row
+ (png_size_t
)row_width
* 3;
2029 png_bytep dp
= sp
+ (png_size_t
)row_width
;
2030 for (i
= 0; i
< row_width
; i
++)
2035 *(--dp
) = lo_filler
;
2037 row_info
->channels
= 4;
2038 row_info
->pixel_depth
= 32;
2039 row_info
->rowbytes
= row_width
* 4;
2042 else if(row_info
->bit_depth
== 16)
2044 /* This changes the data from RRGGBB to RRGGBBXX */
2045 if (flags
& PNG_FLAG_FILLER_AFTER
)
2047 png_bytep sp
= row
+ (png_size_t
)row_width
* 6;
2048 png_bytep dp
= sp
+ (png_size_t
)row_width
* 2;
2049 for (i
= 1; i
< row_width
; i
++)
2051 *(--dp
) = hi_filler
;
2052 *(--dp
) = lo_filler
;
2060 *(--dp
) = hi_filler
;
2061 *(--dp
) = lo_filler
;
2062 row_info
->channels
= 4;
2063 row_info
->pixel_depth
= 64;
2064 row_info
->rowbytes
= row_width
* 8;
2066 /* This changes the data from RRGGBB to XXRRGGBB */
2069 png_bytep sp
= row
+ (png_size_t
)row_width
* 6;
2070 png_bytep dp
= sp
+ (png_size_t
)row_width
* 2;
2071 for (i
= 0; i
< row_width
; i
++)
2079 *(--dp
) = hi_filler
;
2080 *(--dp
) = lo_filler
;
2082 row_info
->channels
= 4;
2083 row_info
->pixel_depth
= 64;
2084 row_info
->rowbytes
= row_width
* 8;
2087 } /* COLOR_TYPE == RGB */
2091 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2092 /* expand grayscale files to RGB, with or without alpha */
2094 png_do_gray_to_rgb(png_row_infop row_info
, png_bytep row
)
2097 png_uint_32 row_width
= row_info
->width
;
2099 png_debug(1, "in png_do_gray_to_rgb\n");
2100 if (row_info
->bit_depth
>= 8 &&
2101 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2102 row
!= NULL
&& row_info
!= NULL
&&
2104 !(row_info
->color_type
& PNG_COLOR_MASK_COLOR
))
2106 if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY
)
2108 if (row_info
->bit_depth
== 8)
2110 png_bytep sp
= row
+ (png_size_t
)row_width
- 1;
2111 png_bytep dp
= sp
+ (png_size_t
)row_width
* 2;
2112 for (i
= 0; i
< row_width
; i
++)
2121 png_bytep sp
= row
+ (png_size_t
)row_width
* 2 - 1;
2122 png_bytep dp
= sp
+ (png_size_t
)row_width
* 4;
2123 for (i
= 0; i
< row_width
; i
++)
2126 *(dp
--) = *(sp
- 1);
2128 *(dp
--) = *(sp
- 1);
2134 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
2136 if (row_info
->bit_depth
== 8)
2138 png_bytep sp
= row
+ (png_size_t
)row_width
* 2 - 1;
2139 png_bytep dp
= sp
+ (png_size_t
)row_width
* 2;
2140 for (i
= 0; i
< row_width
; i
++)
2150 png_bytep sp
= row
+ (png_size_t
)row_width
* 4 - 1;
2151 png_bytep dp
= sp
+ (png_size_t
)row_width
* 4;
2152 for (i
= 0; i
< row_width
; i
++)
2157 *(dp
--) = *(sp
- 1);
2159 *(dp
--) = *(sp
- 1);
2165 row_info
->channels
+= (png_byte
)2;
2166 row_info
->color_type
|= PNG_COLOR_MASK_COLOR
;
2167 row_info
->pixel_depth
= (png_byte
)(row_info
->channels
*
2168 row_info
->bit_depth
);
2169 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,row_width
);
2174 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2175 /* reduce RGB files to grayscale, with or without alpha
2176 * using the equation given in Poynton's ColorFAQ at
2177 * <http://www.inforamp.net/~poynton/>
2178 * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
2180 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2182 * We approximate this with
2184 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2186 * which can be expressed with integers as
2188 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2190 * The calculation is to be done in a linear colorspace.
2192 * Other integer coefficents can be used via png_set_rgb_to_gray().
2195 png_do_rgb_to_gray(png_structp png_ptr
, png_row_infop row_info
, png_bytep row
)
2200 png_uint_32 row_width
= row_info
->width
;
2203 png_debug(1, "in png_do_rgb_to_gray\n");
2205 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2206 row
!= NULL
&& row_info
!= NULL
&&
2208 (row_info
->color_type
& PNG_COLOR_MASK_COLOR
))
2210 png_uint_32 rc
= png_ptr
->rgb_to_gray_red_coeff
;
2211 png_uint_32 gc
= png_ptr
->rgb_to_gray_green_coeff
;
2212 png_uint_32 bc
= png_ptr
->rgb_to_gray_blue_coeff
;
2214 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
2216 if (row_info
->bit_depth
== 8)
2218 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2219 if (png_ptr
->gamma_from_1
!= NULL
&& png_ptr
->gamma_to_1
!= NULL
)
2224 for (i
= 0; i
< row_width
; i
++)
2226 png_byte red
= png_ptr
->gamma_to_1
[*(sp
++)];
2227 png_byte green
= png_ptr
->gamma_to_1
[*(sp
++)];
2228 png_byte blue
= png_ptr
->gamma_to_1
[*(sp
++)];
2229 if(red
!= green
|| red
!= blue
)
2232 *(dp
++) = png_ptr
->gamma_from_1
[
2233 (rc
*red
+gc
*green
+bc
*blue
)>>15];
2244 for (i
= 0; i
< row_width
; i
++)
2246 png_byte red
= *(sp
++);
2247 png_byte green
= *(sp
++);
2248 png_byte blue
= *(sp
++);
2249 if(red
!= green
|| red
!= blue
)
2252 *(dp
++) = (png_byte
)((rc
*red
+gc
*green
+bc
*blue
)>>15);
2260 else /* RGB bit_depth == 16 */
2262 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2263 if (png_ptr
->gamma_16_to_1
!= NULL
&&
2264 png_ptr
->gamma_16_from_1
!= NULL
)
2268 for (i
= 0; i
< row_width
; i
++)
2270 png_uint_16 red
, green
, blue
, w
;
2272 red
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2273 green
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2274 blue
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2276 if(red
== green
&& red
== blue
)
2280 png_uint_16 red_1
= png_ptr
->gamma_16_to_1
[(red
&0xff) >>
2281 png_ptr
->gamma_shift
][red
>>8];
2282 png_uint_16 green_1
= png_ptr
->gamma_16_to_1
[(green
&0xff) >>
2283 png_ptr
->gamma_shift
][green
>>8];
2284 png_uint_16 blue_1
= png_ptr
->gamma_16_to_1
[(blue
&0xff) >>
2285 png_ptr
->gamma_shift
][blue
>>8];
2286 png_uint_16 gray16
= (png_uint_16
)((rc
*red_1
+ gc
*green_1
2288 w
= png_ptr
->gamma_16_from_1
[(gray16
&0xff) >>
2289 png_ptr
->gamma_shift
][gray16
>> 8];
2293 *(dp
++) = (png_byte
)((w
>>8) & 0xff);
2294 *(dp
++) = (png_byte
)(w
& 0xff);
2302 for (i
= 0; i
< row_width
; i
++)
2304 png_uint_16 red
, green
, blue
, gray16
;
2306 red
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2307 green
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2308 blue
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2310 if(red
!= green
|| red
!= blue
)
2312 gray16
= (png_uint_16
)((rc
*red
+ gc
*green
+ bc
*blue
)>>15);
2313 *(dp
++) = (png_byte
)((gray16
>>8) & 0xff);
2314 *(dp
++) = (png_byte
)(gray16
& 0xff);
2319 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
2321 if (row_info
->bit_depth
== 8)
2323 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2324 if (png_ptr
->gamma_from_1
!= NULL
&& png_ptr
->gamma_to_1
!= NULL
)
2328 for (i
= 0; i
< row_width
; i
++)
2330 png_byte red
= png_ptr
->gamma_to_1
[*(sp
++)];
2331 png_byte green
= png_ptr
->gamma_to_1
[*(sp
++)];
2332 png_byte blue
= png_ptr
->gamma_to_1
[*(sp
++)];
2333 if(red
!= green
|| red
!= blue
)
2335 *(dp
++) = png_ptr
->gamma_from_1
2336 [(rc
*red
+ gc
*green
+ bc
*blue
)>>15];
2337 *(dp
++) = *(sp
++); /* alpha */
2345 for (i
= 0; i
< row_width
; i
++)
2347 png_byte red
= *(sp
++);
2348 png_byte green
= *(sp
++);
2349 png_byte blue
= *(sp
++);
2350 if(red
!= green
|| red
!= blue
)
2352 *(dp
++) = (png_byte
)((rc
*red
+ gc
*green
+ bc
*blue
)>>15);
2353 *(dp
++) = *(sp
++); /* alpha */
2357 else /* RGBA bit_depth == 16 */
2359 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2360 if (png_ptr
->gamma_16_to_1
!= NULL
&&
2361 png_ptr
->gamma_16_from_1
!= NULL
)
2365 for (i
= 0; i
< row_width
; i
++)
2367 png_uint_16 red
, green
, blue
, w
;
2369 red
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2370 green
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2371 blue
= (png_uint_16
)(((*(sp
))<<8) | *(sp
+1)); sp
+=2;
2373 if(red
== green
&& red
== blue
)
2377 png_uint_16 red_1
= png_ptr
->gamma_16_to_1
[(red
&0xff) >>
2378 png_ptr
->gamma_shift
][red
>>8];
2379 png_uint_16 green_1
= png_ptr
->gamma_16_to_1
[(green
&0xff) >>
2380 png_ptr
->gamma_shift
][green
>>8];
2381 png_uint_16 blue_1
= png_ptr
->gamma_16_to_1
[(blue
&0xff) >>
2382 png_ptr
->gamma_shift
][blue
>>8];
2383 png_uint_16 gray16
= (png_uint_16
)((rc
* red_1
2384 + gc
* green_1
+ bc
* blue_1
)>>15);
2385 w
= png_ptr
->gamma_16_from_1
[(gray16
&0xff) >>
2386 png_ptr
->gamma_shift
][gray16
>> 8];
2390 *(dp
++) = (png_byte
)((w
>>8) & 0xff);
2391 *(dp
++) = (png_byte
)(w
& 0xff);
2392 *(dp
++) = *(sp
++); /* alpha */
2401 for (i
= 0; i
< row_width
; i
++)
2403 png_uint_16 red
, green
, blue
, gray16
;
2404 red
= (png_uint_16
)((*(sp
)<<8) | *(sp
+1)); sp
+=2;
2405 green
= (png_uint_16
)((*(sp
)<<8) | *(sp
+1)); sp
+=2;
2406 blue
= (png_uint_16
)((*(sp
)<<8) | *(sp
+1)); sp
+=2;
2407 if(red
!= green
|| red
!= blue
)
2409 gray16
= (png_uint_16
)((rc
*red
+ gc
*green
+ bc
*blue
)>>15);
2410 *(dp
++) = (png_byte
)((gray16
>>8) & 0xff);
2411 *(dp
++) = (png_byte
)(gray16
& 0xff);
2412 *(dp
++) = *(sp
++); /* alpha */
2418 row_info
->channels
-= (png_byte
)2;
2419 row_info
->color_type
&= ~PNG_COLOR_MASK_COLOR
;
2420 row_info
->pixel_depth
= (png_byte
)(row_info
->channels
*
2421 row_info
->bit_depth
);
2422 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,row_width
);
2428 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2429 * large of png_color. This lets grayscale images be treated as
2430 * paletted. Most useful for gamma correction and simplification
2434 png_build_grayscale_palette(int bit_depth
, png_colorp palette
)
2441 png_debug(1, "in png_do_build_grayscale_palette\n");
2442 if (palette
== NULL
)
2469 for (i
= 0, v
= 0; i
< num_palette
; i
++, v
+= color_inc
)
2471 palette
[i
].red
= (png_byte
)v
;
2472 palette
[i
].green
= (png_byte
)v
;
2473 palette
[i
].blue
= (png_byte
)v
;
2477 /* This function is currently unused. Do we really need it? */
2478 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2480 png_correct_palette(png_structp png_ptr
, png_colorp palette
,
2483 png_debug(1, "in png_correct_palette\n");
2484 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2485 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2486 if (png_ptr
->transformations
& (PNG_GAMMA
| PNG_BACKGROUND
))
2488 png_color back
, back_1
;
2490 if (png_ptr
->background_gamma_type
== PNG_BACKGROUND_GAMMA_FILE
)
2492 back
.red
= png_ptr
->gamma_table
[png_ptr
->background
.red
];
2493 back
.green
= png_ptr
->gamma_table
[png_ptr
->background
.green
];
2494 back
.blue
= png_ptr
->gamma_table
[png_ptr
->background
.blue
];
2496 back_1
.red
= png_ptr
->gamma_to_1
[png_ptr
->background
.red
];
2497 back_1
.green
= png_ptr
->gamma_to_1
[png_ptr
->background
.green
];
2498 back_1
.blue
= png_ptr
->gamma_to_1
[png_ptr
->background
.blue
];
2504 g
= 1.0 / (png_ptr
->background_gamma
* png_ptr
->screen_gamma
);
2506 if (png_ptr
->background_gamma_type
== PNG_BACKGROUND_GAMMA_SCREEN
||
2507 fabs(g
- 1.0) < PNG_GAMMA_THRESHOLD
)
2509 back
.red
= png_ptr
->background
.red
;
2510 back
.green
= png_ptr
->background
.green
;
2511 back
.blue
= png_ptr
->background
.blue
;
2516 (png_byte
)(pow((double)png_ptr
->background
.red
/255, g
) *
2519 (png_byte
)(pow((double)png_ptr
->background
.green
/255, g
) *
2522 (png_byte
)(pow((double)png_ptr
->background
.blue
/255, g
) *
2526 g
= 1.0 / png_ptr
->background_gamma
;
2529 (png_byte
)(pow((double)png_ptr
->background
.red
/255, g
) *
2532 (png_byte
)(pow((double)png_ptr
->background
.green
/255, g
) *
2535 (png_byte
)(pow((double)png_ptr
->background
.blue
/255, g
) *
2539 if (png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
2543 for (i
= 0; i
< (png_uint_32
)num_palette
; i
++)
2545 if (i
< png_ptr
->num_trans
&& png_ptr
->trans
[i
] == 0)
2549 else if (i
< png_ptr
->num_trans
&& png_ptr
->trans
[i
] != 0xff)
2553 v
= png_ptr
->gamma_to_1
[png_ptr
->palette
[i
].red
];
2554 png_composite(w
, v
, png_ptr
->trans
[i
], back_1
.red
);
2555 palette
[i
].red
= png_ptr
->gamma_from_1
[w
];
2557 v
= png_ptr
->gamma_to_1
[png_ptr
->palette
[i
].green
];
2558 png_composite(w
, v
, png_ptr
->trans
[i
], back_1
.green
);
2559 palette
[i
].green
= png_ptr
->gamma_from_1
[w
];
2561 v
= png_ptr
->gamma_to_1
[png_ptr
->palette
[i
].blue
];
2562 png_composite(w
, v
, png_ptr
->trans
[i
], back_1
.blue
);
2563 palette
[i
].blue
= png_ptr
->gamma_from_1
[w
];
2567 palette
[i
].red
= png_ptr
->gamma_table
[palette
[i
].red
];
2568 palette
[i
].green
= png_ptr
->gamma_table
[palette
[i
].green
];
2569 palette
[i
].blue
= png_ptr
->gamma_table
[palette
[i
].blue
];
2577 for (i
= 0; i
< num_palette
; i
++)
2579 if (palette
[i
].red
== (png_byte
)png_ptr
->trans_values
.gray
)
2585 palette
[i
].red
= png_ptr
->gamma_table
[palette
[i
].red
];
2586 palette
[i
].green
= png_ptr
->gamma_table
[palette
[i
].green
];
2587 palette
[i
].blue
= png_ptr
->gamma_table
[palette
[i
].blue
];
2594 #if defined(PNG_READ_GAMMA_SUPPORTED)
2595 if (png_ptr
->transformations
& PNG_GAMMA
)
2599 for (i
= 0; i
< num_palette
; i
++)
2601 palette
[i
].red
= png_ptr
->gamma_table
[palette
[i
].red
];
2602 palette
[i
].green
= png_ptr
->gamma_table
[palette
[i
].green
];
2603 palette
[i
].blue
= png_ptr
->gamma_table
[palette
[i
].blue
];
2606 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2610 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2611 if (png_ptr
->transformations
& PNG_BACKGROUND
)
2613 if (png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
2617 back
.red
= (png_byte
)png_ptr
->background
.red
;
2618 back
.green
= (png_byte
)png_ptr
->background
.green
;
2619 back
.blue
= (png_byte
)png_ptr
->background
.blue
;
2621 for (i
= 0; i
< (int)png_ptr
->num_trans
; i
++)
2623 if (png_ptr
->trans
[i
] == 0)
2625 palette
[i
].red
= back
.red
;
2626 palette
[i
].green
= back
.green
;
2627 palette
[i
].blue
= back
.blue
;
2629 else if (png_ptr
->trans
[i
] != 0xff)
2631 png_composite(palette
[i
].red
, png_ptr
->palette
[i
].red
,
2632 png_ptr
->trans
[i
], back
.red
);
2633 png_composite(palette
[i
].green
, png_ptr
->palette
[i
].green
,
2634 png_ptr
->trans
[i
], back
.green
);
2635 png_composite(palette
[i
].blue
, png_ptr
->palette
[i
].blue
,
2636 png_ptr
->trans
[i
], back
.blue
);
2640 else /* assume grayscale palette (what else could it be?) */
2644 for (i
= 0; i
< num_palette
; i
++)
2646 if (i
== (png_byte
)png_ptr
->trans_values
.gray
)
2648 palette
[i
].red
= (png_byte
)png_ptr
->background
.red
;
2649 palette
[i
].green
= (png_byte
)png_ptr
->background
.green
;
2650 palette
[i
].blue
= (png_byte
)png_ptr
->background
.blue
;
2659 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2660 /* Replace any alpha or transparency with the supplied background color.
2661 * "background" is already in the screen gamma, while "background_1" is
2662 * at a gamma of 1.0. Paletted files have already been taken care of.
2665 png_do_background(png_row_infop row_info
, png_bytep row
,
2666 png_color_16p trans_values
, png_color_16p background
2667 #if defined(PNG_READ_GAMMA_SUPPORTED)
2668 , png_color_16p background_1
,
2669 png_bytep gamma_table
, png_bytep gamma_from_1
, png_bytep gamma_to_1
,
2670 png_uint_16pp gamma_16
, png_uint_16pp gamma_16_from_1
,
2671 png_uint_16pp gamma_16_to_1
, int gamma_shift
2677 png_uint_32 row_width
=row_info
->width
;
2680 png_debug(1, "in png_do_background\n");
2681 if (background
!= NULL
&&
2682 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2683 row
!= NULL
&& row_info
!= NULL
&&
2685 (!(row_info
->color_type
& PNG_COLOR_MASK_ALPHA
) ||
2686 (row_info
->color_type
!= PNG_COLOR_TYPE_PALETTE
&& trans_values
)))
2688 switch (row_info
->color_type
)
2690 case PNG_COLOR_TYPE_GRAY
:
2692 switch (row_info
->bit_depth
)
2698 for (i
= 0; i
< row_width
; i
++)
2700 if ((png_uint_16
)((*sp
>> shift
) & 0x01)
2701 == trans_values
->gray
)
2703 *sp
&= (png_byte
)((0x7f7f >> (7 - shift
)) & 0xff);
2704 *sp
|= (png_byte
)(background
->gray
<< shift
);
2718 #if defined(PNG_READ_GAMMA_SUPPORTED)
2719 if (gamma_table
!= NULL
)
2723 for (i
= 0; i
< row_width
; i
++)
2725 if ((png_uint_16
)((*sp
>> shift
) & 0x03)
2726 == trans_values
->gray
)
2728 *sp
&= (png_byte
)((0x3f3f >> (6 - shift
)) & 0xff);
2729 *sp
|= (png_byte
)(background
->gray
<< shift
);
2733 png_byte p
= (png_byte
)((*sp
>> shift
) & 0x03);
2734 png_byte g
= (png_byte
)((gamma_table
[p
| (p
<< 2) |
2735 (p
<< 4) | (p
<< 6)] >> 6) & 0x03);
2736 *sp
&= (png_byte
)((0x3f3f >> (6 - shift
)) & 0xff);
2737 *sp
|= (png_byte
)(g
<< shift
);
2753 for (i
= 0; i
< row_width
; i
++)
2755 if ((png_uint_16
)((*sp
>> shift
) & 0x03)
2756 == trans_values
->gray
)
2758 *sp
&= (png_byte
)((0x3f3f >> (6 - shift
)) & 0xff);
2759 *sp
|= (png_byte
)(background
->gray
<< shift
);
2774 #if defined(PNG_READ_GAMMA_SUPPORTED)
2775 if (gamma_table
!= NULL
)
2779 for (i
= 0; i
< row_width
; i
++)
2781 if ((png_uint_16
)((*sp
>> shift
) & 0x0f)
2782 == trans_values
->gray
)
2784 *sp
&= (png_byte
)((0xf0f >> (4 - shift
)) & 0xff);
2785 *sp
|= (png_byte
)(background
->gray
<< shift
);
2789 png_byte p
= (png_byte
)((*sp
>> shift
) & 0x0f);
2790 png_byte g
= (png_byte
)((gamma_table
[p
|
2791 (p
<< 4)] >> 4) & 0x0f);
2792 *sp
&= (png_byte
)((0xf0f >> (4 - shift
)) & 0xff);
2793 *sp
|= (png_byte
)(g
<< shift
);
2809 for (i
= 0; i
< row_width
; i
++)
2811 if ((png_uint_16
)((*sp
>> shift
) & 0x0f)
2812 == trans_values
->gray
)
2814 *sp
&= (png_byte
)((0xf0f >> (4 - shift
)) & 0xff);
2815 *sp
|= (png_byte
)(background
->gray
<< shift
);
2830 #if defined(PNG_READ_GAMMA_SUPPORTED)
2831 if (gamma_table
!= NULL
)
2834 for (i
= 0; i
< row_width
; i
++, sp
++)
2836 if (*sp
== trans_values
->gray
)
2838 *sp
= (png_byte
)background
->gray
;
2842 *sp
= gamma_table
[*sp
];
2850 for (i
= 0; i
< row_width
; i
++, sp
++)
2852 if (*sp
== trans_values
->gray
)
2854 *sp
= (png_byte
)background
->gray
;
2862 #if defined(PNG_READ_GAMMA_SUPPORTED)
2863 if (gamma_16
!= NULL
)
2866 for (i
= 0; i
< row_width
; i
++, sp
+= 2)
2870 v
= (png_uint_16
)(((*sp
) << 8) + *(sp
+ 1));
2871 if (v
== trans_values
->gray
)
2873 /* background is already in screen gamma */
2874 *sp
= (png_byte
)((background
->gray
>> 8) & 0xff);
2875 *(sp
+ 1) = (png_byte
)(background
->gray
& 0xff);
2879 v
= gamma_16
[*(sp
+ 1) >> gamma_shift
][*sp
];
2880 *sp
= (png_byte
)((v
>> 8) & 0xff);
2881 *(sp
+ 1) = (png_byte
)(v
& 0xff);
2889 for (i
= 0; i
< row_width
; i
++, sp
+= 2)
2893 v
= (png_uint_16
)(((*sp
) << 8) + *(sp
+ 1));
2894 if (v
== trans_values
->gray
)
2896 *sp
= (png_byte
)((background
->gray
>> 8) & 0xff);
2897 *(sp
+ 1) = (png_byte
)(background
->gray
& 0xff);
2906 case PNG_COLOR_TYPE_RGB
:
2908 if (row_info
->bit_depth
== 8)
2910 #if defined(PNG_READ_GAMMA_SUPPORTED)
2911 if (gamma_table
!= NULL
)
2914 for (i
= 0; i
< row_width
; i
++, sp
+= 3)
2916 if (*sp
== trans_values
->red
&&
2917 *(sp
+ 1) == trans_values
->green
&&
2918 *(sp
+ 2) == trans_values
->blue
)
2920 *sp
= (png_byte
)background
->red
;
2921 *(sp
+ 1) = (png_byte
)background
->green
;
2922 *(sp
+ 2) = (png_byte
)background
->blue
;
2926 *sp
= gamma_table
[*sp
];
2927 *(sp
+ 1) = gamma_table
[*(sp
+ 1)];
2928 *(sp
+ 2) = gamma_table
[*(sp
+ 2)];
2936 for (i
= 0; i
< row_width
; i
++, sp
+= 3)
2938 if (*sp
== trans_values
->red
&&
2939 *(sp
+ 1) == trans_values
->green
&&
2940 *(sp
+ 2) == trans_values
->blue
)
2942 *sp
= (png_byte
)background
->red
;
2943 *(sp
+ 1) = (png_byte
)background
->green
;
2944 *(sp
+ 2) = (png_byte
)background
->blue
;
2949 else /* if (row_info->bit_depth == 16) */
2951 #if defined(PNG_READ_GAMMA_SUPPORTED)
2952 if (gamma_16
!= NULL
)
2955 for (i
= 0; i
< row_width
; i
++, sp
+= 6)
2957 png_uint_16 r
= (png_uint_16
)(((*sp
) << 8) + *(sp
+ 1));
2958 png_uint_16 g
= (png_uint_16
)(((*(sp
+2)) << 8) + *(sp
+3));
2959 png_uint_16 b
= (png_uint_16
)(((*(sp
+4)) << 8) + *(sp
+5));
2960 if (r
== trans_values
->red
&& g
== trans_values
->green
&&
2961 b
== trans_values
->blue
)
2963 /* background is already in screen gamma */
2964 *sp
= (png_byte
)((background
->red
>> 8) & 0xff);
2965 *(sp
+ 1) = (png_byte
)(background
->red
& 0xff);
2966 *(sp
+ 2) = (png_byte
)((background
->green
>> 8) & 0xff);
2967 *(sp
+ 3) = (png_byte
)(background
->green
& 0xff);
2968 *(sp
+ 4) = (png_byte
)((background
->blue
>> 8) & 0xff);
2969 *(sp
+ 5) = (png_byte
)(background
->blue
& 0xff);
2973 png_uint_16 v
= gamma_16
[*(sp
+ 1) >> gamma_shift
][*sp
];
2974 *sp
= (png_byte
)((v
>> 8) & 0xff);
2975 *(sp
+ 1) = (png_byte
)(v
& 0xff);
2976 v
= gamma_16
[*(sp
+ 3) >> gamma_shift
][*(sp
+ 2)];
2977 *(sp
+ 2) = (png_byte
)((v
>> 8) & 0xff);
2978 *(sp
+ 3) = (png_byte
)(v
& 0xff);
2979 v
= gamma_16
[*(sp
+ 5) >> gamma_shift
][*(sp
+ 4)];
2980 *(sp
+ 4) = (png_byte
)((v
>> 8) & 0xff);
2981 *(sp
+ 5) = (png_byte
)(v
& 0xff);
2989 for (i
= 0; i
< row_width
; i
++, sp
+= 6)
2991 png_uint_16 r
= (png_uint_16
)(((*sp
) << 8) + *(sp
+1));
2992 png_uint_16 g
= (png_uint_16
)(((*(sp
+2)) << 8) + *(sp
+3));
2993 png_uint_16 b
= (png_uint_16
)(((*(sp
+4)) << 8) + *(sp
+5));
2995 if (r
== trans_values
->red
&& g
== trans_values
->green
&&
2996 b
== trans_values
->blue
)
2998 *sp
= (png_byte
)((background
->red
>> 8) & 0xff);
2999 *(sp
+ 1) = (png_byte
)(background
->red
& 0xff);
3000 *(sp
+ 2) = (png_byte
)((background
->green
>> 8) & 0xff);
3001 *(sp
+ 3) = (png_byte
)(background
->green
& 0xff);
3002 *(sp
+ 4) = (png_byte
)((background
->blue
>> 8) & 0xff);
3003 *(sp
+ 5) = (png_byte
)(background
->blue
& 0xff);
3010 case PNG_COLOR_TYPE_GRAY_ALPHA
:
3012 if (row_info
->bit_depth
== 8)
3014 #if defined(PNG_READ_GAMMA_SUPPORTED)
3015 if (gamma_to_1
!= NULL
&& gamma_from_1
!= NULL
&&
3016 gamma_table
!= NULL
)
3020 for (i
= 0; i
< row_width
; i
++, sp
+= 2, dp
++)
3022 png_uint_16 a
= *(sp
+ 1);
3026 *dp
= gamma_table
[*sp
];
3030 /* background is already in screen gamma */
3031 *dp
= (png_byte
)background
->gray
;
3037 v
= gamma_to_1
[*sp
];
3038 png_composite(w
, v
, a
, background_1
->gray
);
3039 *dp
= gamma_from_1
[w
];
3048 for (i
= 0; i
< row_width
; i
++, sp
+= 2, dp
++)
3050 png_byte a
= *(sp
+ 1);
3056 #if defined(PNG_READ_GAMMA_SUPPORTED)
3059 *dp
= (png_byte
)background
->gray
;
3063 png_composite(*dp
, *sp
, a
, background_1
->gray
);
3066 *dp
= (png_byte
)background
->gray
;
3071 else /* if (png_ptr->bit_depth == 16) */
3073 #if defined(PNG_READ_GAMMA_SUPPORTED)
3074 if (gamma_16
!= NULL
&& gamma_16_from_1
!= NULL
&&
3075 gamma_16_to_1
!= NULL
)
3079 for (i
= 0; i
< row_width
; i
++, sp
+= 4, dp
+= 2)
3081 png_uint_16 a
= (png_uint_16
)(((*(sp
+2)) << 8) + *(sp
+3));
3083 if (a
== (png_uint_16
)0xffff)
3087 v
= gamma_16
[*(sp
+ 1) >> gamma_shift
][*sp
];
3088 *dp
= (png_byte
)((v
>> 8) & 0xff);
3089 *(dp
+ 1) = (png_byte
)(v
& 0xff);
3091 #if defined(PNG_READ_GAMMA_SUPPORTED)
3097 /* background is already in screen gamma */
3098 *dp
= (png_byte
)((background
->gray
>> 8) & 0xff);
3099 *(dp
+ 1) = (png_byte
)(background
->gray
& 0xff);
3101 #if defined(PNG_READ_GAMMA_SUPPORTED)
3104 png_uint_16 g
, v
, w
;
3106 g
= gamma_16_to_1
[*(sp
+ 1) >> gamma_shift
][*sp
];
3107 png_composite_16(v
, g
, a
, background_1
->gray
);
3108 w
= gamma_16_from_1
[(v
&0xff) >> gamma_shift
][v
>> 8];
3109 *dp
= (png_byte
)((w
>> 8) & 0xff);
3110 *(dp
+ 1) = (png_byte
)(w
& 0xff);
3120 for (i
= 0; i
< row_width
; i
++, sp
+= 4, dp
+= 2)
3122 png_uint_16 a
= (png_uint_16
)(((*(sp
+2)) << 8) + *(sp
+3));
3123 if (a
== (png_uint_16
)0xffff)
3125 png_memcpy(dp
, sp
, 2);
3127 #if defined(PNG_READ_GAMMA_SUPPORTED)
3133 *dp
= (png_byte
)((background
->gray
>> 8) & 0xff);
3134 *(dp
+ 1) = (png_byte
)(background
->gray
& 0xff);
3136 #if defined(PNG_READ_GAMMA_SUPPORTED)
3141 g
= (png_uint_16
)(((*sp
) << 8) + *(sp
+ 1));
3142 png_composite_16(v
, g
, a
, background_1
->gray
);
3143 *dp
= (png_byte
)((v
>> 8) & 0xff);
3144 *(dp
+ 1) = (png_byte
)(v
& 0xff);
3152 case PNG_COLOR_TYPE_RGB_ALPHA
:
3154 if (row_info
->bit_depth
== 8)
3156 #if defined(PNG_READ_GAMMA_SUPPORTED)
3157 if (gamma_to_1
!= NULL
&& gamma_from_1
!= NULL
&&
3158 gamma_table
!= NULL
)
3162 for (i
= 0; i
< row_width
; i
++, sp
+= 4, dp
+= 3)
3164 png_byte a
= *(sp
+ 3);
3168 *dp
= gamma_table
[*sp
];
3169 *(dp
+ 1) = gamma_table
[*(sp
+ 1)];
3170 *(dp
+ 2) = gamma_table
[*(sp
+ 2)];
3174 /* background is already in screen gamma */
3175 *dp
= (png_byte
)background
->red
;
3176 *(dp
+ 1) = (png_byte
)background
->green
;
3177 *(dp
+ 2) = (png_byte
)background
->blue
;
3183 v
= gamma_to_1
[*sp
];
3184 png_composite(w
, v
, a
, background_1
->red
);
3185 *dp
= gamma_from_1
[w
];
3186 v
= gamma_to_1
[*(sp
+ 1)];
3187 png_composite(w
, v
, a
, background_1
->green
);
3188 *(dp
+ 1) = gamma_from_1
[w
];
3189 v
= gamma_to_1
[*(sp
+ 2)];
3190 png_composite(w
, v
, a
, background_1
->blue
);
3191 *(dp
+ 2) = gamma_from_1
[w
];
3200 for (i
= 0; i
< row_width
; i
++, sp
+= 4, dp
+= 3)
3202 png_byte a
= *(sp
+ 3);
3207 *(dp
+ 1) = *(sp
+ 1);
3208 *(dp
+ 2) = *(sp
+ 2);
3212 *dp
= (png_byte
)background
->red
;
3213 *(dp
+ 1) = (png_byte
)background
->green
;
3214 *(dp
+ 2) = (png_byte
)background
->blue
;
3218 png_composite(*dp
, *sp
, a
, background
->red
);
3219 png_composite(*(dp
+ 1), *(sp
+ 1), a
,
3221 png_composite(*(dp
+ 2), *(sp
+ 2), a
,
3227 else /* if (row_info->bit_depth == 16) */
3229 #if defined(PNG_READ_GAMMA_SUPPORTED)
3230 if (gamma_16
!= NULL
&& gamma_16_from_1
!= NULL
&&
3231 gamma_16_to_1
!= NULL
)
3235 for (i
= 0; i
< row_width
; i
++, sp
+= 8, dp
+= 6)
3237 png_uint_16 a
= (png_uint_16
)(((png_uint_16
)(*(sp
+ 6))
3238 << 8) + (png_uint_16
)(*(sp
+ 7)));
3239 if (a
== (png_uint_16
)0xffff)
3243 v
= gamma_16
[*(sp
+ 1) >> gamma_shift
][*sp
];
3244 *dp
= (png_byte
)((v
>> 8) & 0xff);
3245 *(dp
+ 1) = (png_byte
)(v
& 0xff);
3246 v
= gamma_16
[*(sp
+ 3) >> gamma_shift
][*(sp
+ 2)];
3247 *(dp
+ 2) = (png_byte
)((v
>> 8) & 0xff);
3248 *(dp
+ 3) = (png_byte
)(v
& 0xff);
3249 v
= gamma_16
[*(sp
+ 5) >> gamma_shift
][*(sp
+ 4)];
3250 *(dp
+ 4) = (png_byte
)((v
>> 8) & 0xff);
3251 *(dp
+ 5) = (png_byte
)(v
& 0xff);
3255 /* background is already in screen gamma */
3256 *dp
= (png_byte
)((background
->red
>> 8) & 0xff);
3257 *(dp
+ 1) = (png_byte
)(background
->red
& 0xff);
3258 *(dp
+ 2) = (png_byte
)((background
->green
>> 8) & 0xff);
3259 *(dp
+ 3) = (png_byte
)(background
->green
& 0xff);
3260 *(dp
+ 4) = (png_byte
)((background
->blue
>> 8) & 0xff);
3261 *(dp
+ 5) = (png_byte
)(background
->blue
& 0xff);
3265 png_uint_16 v
, w
, x
;
3267 v
= gamma_16_to_1
[*(sp
+ 1) >> gamma_shift
][*sp
];
3268 png_composite_16(w
, v
, a
, background_1
->red
);
3269 x
= gamma_16_from_1
[((w
&0xff) >> gamma_shift
)][w
>> 8];
3270 *dp
= (png_byte
)((x
>> 8) & 0xff);
3271 *(dp
+ 1) = (png_byte
)(x
& 0xff);
3272 v
= gamma_16_to_1
[*(sp
+ 3) >> gamma_shift
][*(sp
+ 2)];
3273 png_composite_16(w
, v
, a
, background_1
->green
);
3274 x
= gamma_16_from_1
[((w
&0xff) >> gamma_shift
)][w
>> 8];
3275 *(dp
+ 2) = (png_byte
)((x
>> 8) & 0xff);
3276 *(dp
+ 3) = (png_byte
)(x
& 0xff);
3277 v
= gamma_16_to_1
[*(sp
+ 5) >> gamma_shift
][*(sp
+ 4)];
3278 png_composite_16(w
, v
, a
, background_1
->blue
);
3279 x
= gamma_16_from_1
[(w
& 0xff) >> gamma_shift
][w
>> 8];
3280 *(dp
+ 4) = (png_byte
)((x
>> 8) & 0xff);
3281 *(dp
+ 5) = (png_byte
)(x
& 0xff);
3290 for (i
= 0; i
< row_width
; i
++, sp
+= 8, dp
+= 6)
3292 png_uint_16 a
= (png_uint_16
)(((png_uint_16
)(*(sp
+ 6))
3293 << 8) + (png_uint_16
)(*(sp
+ 7)));
3294 if (a
== (png_uint_16
)0xffff)
3296 png_memcpy(dp
, sp
, 6);
3300 *dp
= (png_byte
)((background
->red
>> 8) & 0xff);
3301 *(dp
+ 1) = (png_byte
)(background
->red
& 0xff);
3302 *(dp
+ 2) = (png_byte
)((background
->green
>> 8) & 0xff);
3303 *(dp
+ 3) = (png_byte
)(background
->green
& 0xff);
3304 *(dp
+ 4) = (png_byte
)((background
->blue
>> 8) & 0xff);
3305 *(dp
+ 5) = (png_byte
)(background
->blue
& 0xff);
3311 png_uint_16 r
= (png_uint_16
)(((*sp
) << 8) + *(sp
+ 1));
3312 png_uint_16 g
= (png_uint_16
)(((*(sp
+ 2)) << 8)
3314 png_uint_16 b
= (png_uint_16
)(((*(sp
+ 4)) << 8)
3317 png_composite_16(v
, r
, a
, background
->red
);
3318 *dp
= (png_byte
)((v
>> 8) & 0xff);
3319 *(dp
+ 1) = (png_byte
)(v
& 0xff);
3320 png_composite_16(v
, g
, a
, background
->green
);
3321 *(dp
+ 2) = (png_byte
)((v
>> 8) & 0xff);
3322 *(dp
+ 3) = (png_byte
)(v
& 0xff);
3323 png_composite_16(v
, b
, a
, background
->blue
);
3324 *(dp
+ 4) = (png_byte
)((v
>> 8) & 0xff);
3325 *(dp
+ 5) = (png_byte
)(v
& 0xff);
3334 if (row_info
->color_type
& PNG_COLOR_MASK_ALPHA
)
3336 row_info
->color_type
&= ~PNG_COLOR_MASK_ALPHA
;
3337 row_info
->channels
--;
3338 row_info
->pixel_depth
= (png_byte
)(row_info
->channels
*
3339 row_info
->bit_depth
);
3340 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,row_width
);
3346 #if defined(PNG_READ_GAMMA_SUPPORTED)
3347 /* Gamma correct the image, avoiding the alpha channel. Make sure
3348 * you do this after you deal with the transparency issue on grayscale
3349 * or RGB images. If your bit depth is 8, use gamma_table, if it
3350 * is 16, use gamma_16_table and gamma_shift. Build these with
3351 * build_gamma_table().
3354 png_do_gamma(png_row_infop row_info
, png_bytep row
,
3355 png_bytep gamma_table
, png_uint_16pp gamma_16_table
,
3360 png_uint_32 row_width
=row_info
->width
;
3362 png_debug(1, "in png_do_gamma\n");
3364 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3365 row
!= NULL
&& row_info
!= NULL
&&
3367 ((row_info
->bit_depth
<= 8 && gamma_table
!= NULL
) ||
3368 (row_info
->bit_depth
== 16 && gamma_16_table
!= NULL
)))
3370 switch (row_info
->color_type
)
3372 case PNG_COLOR_TYPE_RGB
:
3374 if (row_info
->bit_depth
== 8)
3377 for (i
= 0; i
< row_width
; i
++)
3379 *sp
= gamma_table
[*sp
];
3381 *sp
= gamma_table
[*sp
];
3383 *sp
= gamma_table
[*sp
];
3387 else /* if (row_info->bit_depth == 16) */
3390 for (i
= 0; i
< row_width
; i
++)
3394 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3395 *sp
= (png_byte
)((v
>> 8) & 0xff);
3396 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3398 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3399 *sp
= (png_byte
)((v
>> 8) & 0xff);
3400 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3402 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3403 *sp
= (png_byte
)((v
>> 8) & 0xff);
3404 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3410 case PNG_COLOR_TYPE_RGB_ALPHA
:
3412 if (row_info
->bit_depth
== 8)
3415 for (i
= 0; i
< row_width
; i
++)
3417 *sp
= gamma_table
[*sp
];
3419 *sp
= gamma_table
[*sp
];
3421 *sp
= gamma_table
[*sp
];
3426 else /* if (row_info->bit_depth == 16) */
3429 for (i
= 0; i
< row_width
; i
++)
3431 png_uint_16 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3432 *sp
= (png_byte
)((v
>> 8) & 0xff);
3433 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3435 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3436 *sp
= (png_byte
)((v
>> 8) & 0xff);
3437 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3439 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3440 *sp
= (png_byte
)((v
>> 8) & 0xff);
3441 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3447 case PNG_COLOR_TYPE_GRAY_ALPHA
:
3449 if (row_info
->bit_depth
== 8)
3452 for (i
= 0; i
< row_width
; i
++)
3454 *sp
= gamma_table
[*sp
];
3458 else /* if (row_info->bit_depth == 16) */
3461 for (i
= 0; i
< row_width
; i
++)
3463 png_uint_16 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3464 *sp
= (png_byte
)((v
>> 8) & 0xff);
3465 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3471 case PNG_COLOR_TYPE_GRAY
:
3473 if (row_info
->bit_depth
== 2)
3476 for (i
= 0; i
< row_width
; i
+= 4)
3484 ((((int)gamma_table
[a
|(a
>>2)|(a
>>4)|(a
>>6)]) ) & 0xc0)|
3485 ((((int)gamma_table
[(b
<<2)|b
|(b
>>2)|(b
>>4)])>>2) & 0x30)|
3486 ((((int)gamma_table
[(c
<<4)|(c
<<2)|c
|(c
>>2)])>>4) & 0x0c)|
3487 ((((int)gamma_table
[(d
<<6)|(d
<<4)|(d
<<2)|d
])>>6) ));
3491 if (row_info
->bit_depth
== 4)
3494 for (i
= 0; i
< row_width
; i
+= 2)
3496 int msb
= *sp
& 0xf0;
3497 int lsb
= *sp
& 0x0f;
3499 *sp
= (png_byte
)((((int)gamma_table
[msb
| (msb
>> 4)]) & 0xf0)
3500 | (((int)gamma_table
[(lsb
<< 4) | lsb
]) >> 4));
3504 else if (row_info
->bit_depth
== 8)
3507 for (i
= 0; i
< row_width
; i
++)
3509 *sp
= gamma_table
[*sp
];
3513 else if (row_info
->bit_depth
== 16)
3516 for (i
= 0; i
< row_width
; i
++)
3518 png_uint_16 v
= gamma_16_table
[*(sp
+ 1) >> gamma_shift
][*sp
];
3519 *sp
= (png_byte
)((v
>> 8) & 0xff);
3520 *(sp
+ 1) = (png_byte
)(v
& 0xff);
3531 #if defined(PNG_READ_EXPAND_SUPPORTED)
3532 /* Expands a palette row to an RGB or RGBA row depending
3533 * upon whether you supply trans and num_trans.
3536 png_do_expand_palette(png_row_infop row_info
, png_bytep row
,
3537 png_colorp palette
, png_bytep trans
, int num_trans
)
3542 png_uint_32 row_width
=row_info
->width
;
3544 png_debug(1, "in png_do_expand_palette\n");
3546 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3547 row
!= NULL
&& row_info
!= NULL
&&
3549 row_info
->color_type
== PNG_COLOR_TYPE_PALETTE
)
3551 if (row_info
->bit_depth
< 8)
3553 switch (row_info
->bit_depth
)
3557 sp
= row
+ (png_size_t
)((row_width
- 1) >> 3);
3558 dp
= row
+ (png_size_t
)row_width
- 1;
3559 shift
= 7 - (int)((row_width
+ 7) & 0x07);
3560 for (i
= 0; i
< row_width
; i
++)
3562 if ((*sp
>> shift
) & 0x01)
3580 sp
= row
+ (png_size_t
)((row_width
- 1) >> 2);
3581 dp
= row
+ (png_size_t
)row_width
- 1;
3582 shift
= (int)((3 - ((row_width
+ 3) & 0x03)) << 1);
3583 for (i
= 0; i
< row_width
; i
++)
3585 value
= (*sp
>> shift
) & 0x03;
3586 *dp
= (png_byte
)value
;
3601 sp
= row
+ (png_size_t
)((row_width
- 1) >> 1);
3602 dp
= row
+ (png_size_t
)row_width
- 1;
3603 shift
= (int)((row_width
& 0x01) << 2);
3604 for (i
= 0; i
< row_width
; i
++)
3606 value
= (*sp
>> shift
) & 0x0f;
3607 *dp
= (png_byte
)value
;
3621 row_info
->bit_depth
= 8;
3622 row_info
->pixel_depth
= 8;
3623 row_info
->rowbytes
= row_width
;
3625 switch (row_info
->bit_depth
)
3631 sp
= row
+ (png_size_t
)row_width
- 1;
3632 dp
= row
+ (png_size_t
)(row_width
<< 2) - 1;
3634 for (i
= 0; i
< row_width
; i
++)
3636 if ((int)(*sp
) >= num_trans
)
3640 *dp
-- = palette
[*sp
].blue
;
3641 *dp
-- = palette
[*sp
].green
;
3642 *dp
-- = palette
[*sp
].red
;
3645 row_info
->bit_depth
= 8;
3646 row_info
->pixel_depth
= 32;
3647 row_info
->rowbytes
= row_width
* 4;
3648 row_info
->color_type
= 6;
3649 row_info
->channels
= 4;
3653 sp
= row
+ (png_size_t
)row_width
- 1;
3654 dp
= row
+ (png_size_t
)(row_width
* 3) - 1;
3656 for (i
= 0; i
< row_width
; i
++)
3658 *dp
-- = palette
[*sp
].blue
;
3659 *dp
-- = palette
[*sp
].green
;
3660 *dp
-- = palette
[*sp
].red
;
3663 row_info
->bit_depth
= 8;
3664 row_info
->pixel_depth
= 24;
3665 row_info
->rowbytes
= row_width
* 3;
3666 row_info
->color_type
= 2;
3667 row_info
->channels
= 3;
3675 /* If the bit depth < 8, it is expanded to 8. Also, if the already
3676 * expanded transparency value is supplied, an alpha channel is built.
3679 png_do_expand(png_row_infop row_info
, png_bytep row
,
3680 png_color_16p trans_value
)
3685 png_uint_32 row_width
=row_info
->width
;
3687 png_debug(1, "in png_do_expand\n");
3688 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3689 if (row
!= NULL
&& row_info
!= NULL
)
3692 if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY
)
3694 png_uint_16 gray
= (png_uint_16
)(trans_value
? trans_value
->gray
: 0);
3696 if (row_info
->bit_depth
< 8)
3698 switch (row_info
->bit_depth
)
3702 gray
= (png_uint_16
)(gray
*0xff);
3703 sp
= row
+ (png_size_t
)((row_width
- 1) >> 3);
3704 dp
= row
+ (png_size_t
)row_width
- 1;
3705 shift
= 7 - (int)((row_width
+ 7) & 0x07);
3706 for (i
= 0; i
< row_width
; i
++)
3708 if ((*sp
>> shift
) & 0x01)
3726 gray
= (png_uint_16
)(gray
*0x55);
3727 sp
= row
+ (png_size_t
)((row_width
- 1) >> 2);
3728 dp
= row
+ (png_size_t
)row_width
- 1;
3729 shift
= (int)((3 - ((row_width
+ 3) & 0x03)) << 1);
3730 for (i
= 0; i
< row_width
; i
++)
3732 value
= (*sp
>> shift
) & 0x03;
3733 *dp
= (png_byte
)(value
| (value
<< 2) | (value
<< 4) |
3749 gray
= (png_uint_16
)(gray
*0x11);
3750 sp
= row
+ (png_size_t
)((row_width
- 1) >> 1);
3751 dp
= row
+ (png_size_t
)row_width
- 1;
3752 shift
= (int)((1 - ((row_width
+ 1) & 0x01)) << 2);
3753 for (i
= 0; i
< row_width
; i
++)
3755 value
= (*sp
>> shift
) & 0x0f;
3756 *dp
= (png_byte
)(value
| (value
<< 4));
3770 row_info
->bit_depth
= 8;
3771 row_info
->pixel_depth
= 8;
3772 row_info
->rowbytes
= row_width
;
3775 if (trans_value
!= NULL
)
3777 if (row_info
->bit_depth
== 8)
3779 sp
= row
+ (png_size_t
)row_width
- 1;
3780 dp
= row
+ (png_size_t
)(row_width
<< 1) - 1;
3781 for (i
= 0; i
< row_width
; i
++)
3790 else if (row_info
->bit_depth
== 16)
3792 sp
= row
+ row_info
->rowbytes
- 1;
3793 dp
= row
+ (row_info
->rowbytes
<< 1) - 1;
3794 for (i
= 0; i
< row_width
; i
++)
3796 if (((png_uint_16
)*(sp
) |
3797 ((png_uint_16
)*(sp
- 1) << 8)) == gray
)
3811 row_info
->color_type
= PNG_COLOR_TYPE_GRAY_ALPHA
;
3812 row_info
->channels
= 2;
3813 row_info
->pixel_depth
= (png_byte
)(row_info
->bit_depth
<< 1);
3814 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,
3818 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
&& trans_value
)
3820 if (row_info
->bit_depth
== 8)
3822 sp
= row
+ (png_size_t
)row_info
->rowbytes
- 1;
3823 dp
= row
+ (png_size_t
)(row_width
<< 2) - 1;
3824 for (i
= 0; i
< row_width
; i
++)
3826 if (*(sp
- 2) == trans_value
->red
&&
3827 *(sp
- 1) == trans_value
->green
&&
3828 *(sp
- 0) == trans_value
->blue
)
3837 else if (row_info
->bit_depth
== 16)
3839 sp
= row
+ row_info
->rowbytes
- 1;
3840 dp
= row
+ (png_size_t
)(row_width
<< 3) - 1;
3841 for (i
= 0; i
< row_width
; i
++)
3843 if ((((png_uint_16
)*(sp
- 4) |
3844 ((png_uint_16
)*(sp
- 5) << 8)) == trans_value
->red
) &&
3845 (((png_uint_16
)*(sp
- 2) |
3846 ((png_uint_16
)*(sp
- 3) << 8)) == trans_value
->green
) &&
3847 (((png_uint_16
)*(sp
- 0) |
3848 ((png_uint_16
)*(sp
- 1) << 8)) == trans_value
->blue
))
3866 row_info
->color_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
3867 row_info
->channels
= 4;
3868 row_info
->pixel_depth
= (png_byte
)(row_info
->bit_depth
<< 2);
3869 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,row_width
);
3875 #if defined(PNG_READ_DITHER_SUPPORTED)
3877 png_do_dither(png_row_infop row_info
, png_bytep row
,
3878 png_bytep palette_lookup
, png_bytep dither_lookup
)
3882 png_uint_32 row_width
=row_info
->width
;
3884 png_debug(1, "in png_do_dither\n");
3885 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3886 if (row
!= NULL
&& row_info
!= NULL
)
3889 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
&&
3890 palette_lookup
&& row_info
->bit_depth
== 8)
3895 for (i
= 0; i
< row_width
; i
++)
3901 /* this looks real messy, but the compiler will reduce
3902 it down to a reasonable formula. For example, with
3903 5 bits per color, we get:
3904 p = (((r >> 3) & 0x1f) << 10) |
3905 (((g >> 3) & 0x1f) << 5) |
3908 p
= (((r
>> (8 - PNG_DITHER_RED_BITS
)) &
3909 ((1 << PNG_DITHER_RED_BITS
) - 1)) <<
3910 (PNG_DITHER_GREEN_BITS
+ PNG_DITHER_BLUE_BITS
)) |
3911 (((g
>> (8 - PNG_DITHER_GREEN_BITS
)) &
3912 ((1 << PNG_DITHER_GREEN_BITS
) - 1)) <<
3913 (PNG_DITHER_BLUE_BITS
)) |
3914 ((b
>> (8 - PNG_DITHER_BLUE_BITS
)) &
3915 ((1 << PNG_DITHER_BLUE_BITS
) - 1));
3917 *dp
++ = palette_lookup
[p
];
3919 row_info
->color_type
= PNG_COLOR_TYPE_PALETTE
;
3920 row_info
->channels
= 1;
3921 row_info
->pixel_depth
= row_info
->bit_depth
;
3922 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,row_width
);
3924 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
&&
3925 palette_lookup
!= NULL
&& row_info
->bit_depth
== 8)
3930 for (i
= 0; i
< row_width
; i
++)
3937 p
= (((r
>> (8 - PNG_DITHER_RED_BITS
)) &
3938 ((1 << PNG_DITHER_RED_BITS
) - 1)) <<
3939 (PNG_DITHER_GREEN_BITS
+ PNG_DITHER_BLUE_BITS
)) |
3940 (((g
>> (8 - PNG_DITHER_GREEN_BITS
)) &
3941 ((1 << PNG_DITHER_GREEN_BITS
) - 1)) <<
3942 (PNG_DITHER_BLUE_BITS
)) |
3943 ((b
>> (8 - PNG_DITHER_BLUE_BITS
)) &
3944 ((1 << PNG_DITHER_BLUE_BITS
) - 1));
3946 *dp
++ = palette_lookup
[p
];
3948 row_info
->color_type
= PNG_COLOR_TYPE_PALETTE
;
3949 row_info
->channels
= 1;
3950 row_info
->pixel_depth
= row_info
->bit_depth
;
3951 row_info
->rowbytes
= PNG_ROWBYTES(row_info
->pixel_depth
,row_width
);
3953 else if (row_info
->color_type
== PNG_COLOR_TYPE_PALETTE
&&
3954 dither_lookup
&& row_info
->bit_depth
== 8)
3957 for (i
= 0; i
< row_width
; i
++, sp
++)
3959 *sp
= dither_lookup
[*sp
];
3966 #ifdef PNG_FLOATING_POINT_SUPPORTED
3967 #if defined(PNG_READ_GAMMA_SUPPORTED)
3968 const static int png_gamma_shift
[] =
3969 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
3971 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
3972 * tables, we don't make a full table if we are reducing to 8-bit in
3973 * the future. Note also how the gamma_16 tables are segmented so that
3974 * we don't need to allocate > 64K chunks for a full 16-bit table.
3977 png_build_gamma_table(png_structp png_ptr
)
3979 png_debug(1, "in png_build_gamma_table\n");
3981 if (png_ptr
->bit_depth
<= 8)
3986 if (png_ptr
->screen_gamma
> .000001)
3987 g
= 1.0 / (png_ptr
->gamma
* png_ptr
->screen_gamma
);
3991 png_ptr
->gamma_table
= (png_bytep
)png_malloc(png_ptr
,
3994 for (i
= 0; i
< 256; i
++)
3996 png_ptr
->gamma_table
[i
] = (png_byte
)(pow((double)i
/ 255.0,
4000 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4001 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4002 if (png_ptr
->transformations
& ((PNG_BACKGROUND
) | PNG_RGB_TO_GRAY
))
4005 g
= 1.0 / (png_ptr
->gamma
);
4007 png_ptr
->gamma_to_1
= (png_bytep
)png_malloc(png_ptr
,
4010 for (i
= 0; i
< 256; i
++)
4012 png_ptr
->gamma_to_1
[i
] = (png_byte
)(pow((double)i
/ 255.0,
4017 png_ptr
->gamma_from_1
= (png_bytep
)png_malloc(png_ptr
,
4020 if(png_ptr
->screen_gamma
> 0.000001)
4021 g
= 1.0 / png_ptr
->screen_gamma
;
4023 g
= png_ptr
->gamma
; /* probably doing rgb_to_gray */
4025 for (i
= 0; i
< 256; i
++)
4027 png_ptr
->gamma_from_1
[i
] = (png_byte
)(pow((double)i
/ 255.0,
4032 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4037 int i
, j
, shift
, num
;
4041 if (png_ptr
->color_type
& PNG_COLOR_MASK_COLOR
)
4043 sig_bit
= (int)png_ptr
->sig_bit
.red
;
4044 if ((int)png_ptr
->sig_bit
.green
> sig_bit
)
4045 sig_bit
= png_ptr
->sig_bit
.green
;
4046 if ((int)png_ptr
->sig_bit
.blue
> sig_bit
)
4047 sig_bit
= png_ptr
->sig_bit
.blue
;
4051 sig_bit
= (int)png_ptr
->sig_bit
.gray
;
4055 shift
= 16 - sig_bit
;
4059 if (png_ptr
->transformations
& PNG_16_TO_8
)
4061 if (shift
< (16 - PNG_MAX_GAMMA_8
))
4062 shift
= (16 - PNG_MAX_GAMMA_8
);
4070 png_ptr
->gamma_shift
= (png_byte
)shift
;
4072 num
= (1 << (8 - shift
));
4074 if (png_ptr
->screen_gamma
> .000001)
4075 g
= 1.0 / (png_ptr
->gamma
* png_ptr
->screen_gamma
);
4079 png_ptr
->gamma_16_table
= (png_uint_16pp
)png_malloc(png_ptr
,
4080 (png_uint_32
)(num
* png_sizeof (png_uint_16p
)));
4082 if (png_ptr
->transformations
& (PNG_16_TO_8
| PNG_BACKGROUND
))
4085 png_uint_32 last
, max
;
4087 for (i
= 0; i
< num
; i
++)
4089 png_ptr
->gamma_16_table
[i
] = (png_uint_16p
)png_malloc(png_ptr
,
4090 (png_uint_32
)(256 * png_sizeof (png_uint_16
)));
4095 for (i
= 0; i
< 256; i
++)
4097 fout
= ((double)i
+ 0.5) / 256.0;
4099 max
= (png_uint_32
)(fin
* (double)((png_uint_32
)num
<< 8));
4102 png_ptr
->gamma_16_table
[(int)(last
& (0xff >> shift
))]
4103 [(int)(last
>> (8 - shift
))] = (png_uint_16
)(
4104 (png_uint_16
)i
| ((png_uint_16
)i
<< 8));
4108 while (last
< ((png_uint_32
)num
<< 8))
4110 png_ptr
->gamma_16_table
[(int)(last
& (0xff >> shift
))]
4111 [(int)(last
>> (8 - shift
))] = (png_uint_16
)65535L;
4117 for (i
= 0; i
< num
; i
++)
4119 png_ptr
->gamma_16_table
[i
] = (png_uint_16p
)png_malloc(png_ptr
,
4120 (png_uint_32
)(256 * png_sizeof (png_uint_16
)));
4122 ig
= (((png_uint_32
)i
* (png_uint_32
)png_gamma_shift
[shift
]) >> 4);
4123 for (j
= 0; j
< 256; j
++)
4125 png_ptr
->gamma_16_table
[i
][j
] =
4126 (png_uint_16
)(pow((double)(ig
+ ((png_uint_32
)j
<< 8)) /
4127 65535.0, g
) * 65535.0 + .5);
4132 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4133 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4134 if (png_ptr
->transformations
& (PNG_BACKGROUND
| PNG_RGB_TO_GRAY
))
4137 g
= 1.0 / (png_ptr
->gamma
);
4139 png_ptr
->gamma_16_to_1
= (png_uint_16pp
)png_malloc(png_ptr
,
4140 (png_uint_32
)(num
* png_sizeof (png_uint_16p
)));
4142 for (i
= 0; i
< num
; i
++)
4144 png_ptr
->gamma_16_to_1
[i
] = (png_uint_16p
)png_malloc(png_ptr
,
4145 (png_uint_32
)(256 * png_sizeof (png_uint_16
)));
4147 ig
= (((png_uint_32
)i
*
4148 (png_uint_32
)png_gamma_shift
[shift
]) >> 4);
4149 for (j
= 0; j
< 256; j
++)
4151 png_ptr
->gamma_16_to_1
[i
][j
] =
4152 (png_uint_16
)(pow((double)(ig
+ ((png_uint_32
)j
<< 8)) /
4153 65535.0, g
) * 65535.0 + .5);
4157 if(png_ptr
->screen_gamma
> 0.000001)
4158 g
= 1.0 / png_ptr
->screen_gamma
;
4160 g
= png_ptr
->gamma
; /* probably doing rgb_to_gray */
4162 png_ptr
->gamma_16_from_1
= (png_uint_16pp
)png_malloc(png_ptr
,
4163 (png_uint_32
)(num
* png_sizeof (png_uint_16p
)));
4165 for (i
= 0; i
< num
; i
++)
4167 png_ptr
->gamma_16_from_1
[i
] = (png_uint_16p
)png_malloc(png_ptr
,
4168 (png_uint_32
)(256 * png_sizeof (png_uint_16
)));
4170 ig
= (((png_uint_32
)i
*
4171 (png_uint_32
)png_gamma_shift
[shift
]) >> 4);
4172 for (j
= 0; j
< 256; j
++)
4174 png_ptr
->gamma_16_from_1
[i
][j
] =
4175 (png_uint_16
)(pow((double)(ig
+ ((png_uint_32
)j
<< 8)) /
4176 65535.0, g
) * 65535.0 + .5);
4180 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4184 /* To do: install integer version of png_build_gamma_table here */
4187 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4188 /* undoes intrapixel differencing */
4190 png_do_read_intrapixel(png_row_infop row_info
, png_bytep row
)
4192 png_debug(1, "in png_do_read_intrapixel\n");
4194 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4195 row
!= NULL
&& row_info
!= NULL
&&
4197 (row_info
->color_type
& PNG_COLOR_MASK_COLOR
))
4199 int bytes_per_pixel
;
4200 png_uint_32 row_width
= row_info
->width
;
4201 if (row_info
->bit_depth
== 8)
4206 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
4207 bytes_per_pixel
= 3;
4208 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
4209 bytes_per_pixel
= 4;
4213 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= bytes_per_pixel
)
4215 *(rp
) = (png_byte
)((256 + *rp
+ *(rp
+1))&0xff);
4216 *(rp
+2) = (png_byte
)((256 + *(rp
+2) + *(rp
+1))&0xff);
4219 else if (row_info
->bit_depth
== 16)
4224 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
4225 bytes_per_pixel
= 6;
4226 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
4227 bytes_per_pixel
= 8;
4231 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= bytes_per_pixel
)
4233 png_uint_32 s0
= (*(rp
) << 8) | *(rp
+1);
4234 png_uint_32 s1
= (*(rp
+2) << 8) | *(rp
+3);
4235 png_uint_32 s2
= (*(rp
+4) << 8) | *(rp
+5);
4236 png_uint_32 red
= (png_uint_32
)((s0
+s1
+65536L) & 0xffffL
);
4237 png_uint_32 blue
= (png_uint_32
)((s2
+s1
+65536L) & 0xffffL
);
4238 *(rp
) = (png_byte
)((red
>> 8) & 0xff);
4239 *(rp
+1) = (png_byte
)(red
& 0xff);
4240 *(rp
+4) = (png_byte
)((blue
>> 8) & 0xff);
4241 *(rp
+5) = (png_byte
)(blue
& 0xff);
4246 #endif /* PNG_MNG_FEATURES_SUPPORTED */
4247 #endif /* PNG_READ_SUPPORTED */