[devel] Implement expansion to 16 bits

This commit is contained in:
John Bowler 2011-02-12 09:01:20 -06:00 committed by Glenn Randers-Pehrson
parent 9b872f4cf9
commit 4d56296443
8 changed files with 155 additions and 5 deletions

9
png.h
View File

@ -1060,6 +1060,13 @@ PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr));
PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr));
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16 bit channels, forces conversion of palette to RGB and expansion
* of a tRNS chunk if present.
*/
PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr));
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Use blue, green, red order for pixels. */
PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr));
@ -2271,7 +2278,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
* scripts/symbols.def as well.
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
PNG_EXPORT_LAST_ORDINAL(220);
PNG_EXPORT_LAST_ORDINAL(221);
#endif
#ifdef __cplusplus

View File

@ -286,7 +286,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_QUANTIZE 0x0040
#define PNG_BACKGROUND 0x0080
#define PNG_BACKGROUND_EXPAND 0x0100
/* 0x0200 unused */
#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */
#define PNG_16_TO_8 0x0400
#define PNG_RGBA 0x0800
#define PNG_EXPAND 0x1000
@ -875,6 +875,11 @@ PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
png_bytep row, png_const_color_16p trans_color));
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info,
png_bytep row));
#endif
/* The following decodes the appropriate chunks, and does error correction,
* then calls the appropriate callback for the chunk if it is valid.
*/

View File

@ -137,6 +137,7 @@ png_set_strip_16(png_structp png_ptr)
return;
png_ptr->transformations |= PNG_16_TO_8;
png_ptr->transformations &= ~PNG_EXPAND_16;
}
#endif
@ -686,6 +687,25 @@ png_set_tRNS_to_alpha(png_structp png_ptr)
}
#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16 bit channels, expand the tRNS chunk too (because otherwise
* it may not work correctly.)
*/
void PNGAPI
png_set_expand_16(png_structp png_ptr)
{
png_debug(1, "in png_set_expand_16");
if (png_ptr == NULL)
return;
png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
png_ptr->transformations &= ~PNG_16_TO_8;
png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
void PNGAPI
png_set_gray_to_rgb(png_structp png_ptr)
@ -1285,6 +1305,14 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
}
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
info_ptr->bit_depth = 16;
}
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
if (png_ptr->transformations & PNG_BACKGROUND)
{
@ -1445,14 +1473,17 @@ png_do_read_transformations(png_structp png_ptr)
(png_ptr->transformations & PNG_EXPAND_tRNS))
png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
&(png_ptr->trans_color));
else
else
png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
NULL);
}
}
#endif
/* Delay the 'expand 16' step until later for efficiency - so that the
* intermediate steps work with 8 bit data. */
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
(png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
@ -1567,6 +1598,16 @@ png_do_read_transformations(png_structp png_ptr)
}
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Do the expansion now, after all the arithmetic has been done. Notice
* that previous transformations can handle the PNG_EXPAND_16 flag if this
* is efficient (particularly true in the case of gamma correction, where
* better accuracy results faster!)
*/
if (png_ptr->transformations & PNG_EXPAND_16)
png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_INVERT_SUPPORTED
if (png_ptr->transformations & PNG_INVERT_MONO)
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
@ -1594,6 +1635,9 @@ png_do_read_transformations(png_structp png_ptr)
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/*NOTE: this must be in the wrong place - what happens if BGR is set too?
* Need pngvalid to test this combo.
*/
/* If gray -> RGB, do so now only if we did not do so above */
if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
@ -4066,6 +4110,37 @@ png_do_expand(png_row_infop row_info, png_bytep row,
}
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* If the bit depth is 8 and the colour type is not a palette type expand the
* whole row to 16 bits. Has no effect otherwise.
*/
void /* PRIVATE */
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
if (row_info->bit_depth == 8 &&
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
{
/* The row have a sequence of bytes containing [0..255] and we need
* to turn it into another row containing [0..65535], to do this we
* calculate:
*
* (input / 255) * 65535
*
* Which happens to be exactly input * 257 and this can be achieved
* simply by byte replication in place (copying backwards).
*/
png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */
while (dp > sp)
dp[-2] = dp[-1] = *--sp, dp -= 2;
row_info->rowbytes *= 2;
row_info->bit_depth = 16;
row_info->pixel_depth = (png_byte)(row_info->channels * 16);
}
}
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
void /* PRIVATE */
png_do_quantize(png_row_infop row_info, png_bytep row,

View File

@ -3463,6 +3463,24 @@ png_read_start_row(png_structp png_ptr)
}
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
if (png_ptr->transformations & PNG_EXPAND_16)
{
# ifdef PNG_READ_EXPAND_SUPPORTED
/* In fact it is an error if it isn't supported, but checking is
* the safe way.
*/
if (png_ptr->transformations & PNG_EXPAND)
{
if (png_ptr->bit_depth < 16)
max_pixel_depth *= 2;
}
else
# endif
png_ptr->transformations &= ~PNG_EXPAND_16;
}
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
if (png_ptr->transformations & (PNG_FILLER))
{

View File

@ -4465,6 +4465,48 @@ image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this,
}
IT(expand_gray_1_2_4_to_8, expand);
/* png_set_expand_16 */
static void
image_transform_png_set_expand_16_set(PNG_CONST image_transform *this,
transform_display *that, png_structp pp, png_infop pi)
{
png_set_expand_16(pp);
this->next->set(this->next, that, pp, pi);
}
static void
image_transform_png_set_expand_16_mod(PNG_CONST image_transform *this,
image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
{
/* Expect expand_16 to expand everything to 16 bits as a result of also
* causing 'expand' to happen.
*/
if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
image_pixel_convert_PLTE(that, &display->this);
if (that->have_tRNS)
image_pixel_add_alpha(that, &display->this);
if (that->bit_depth < 16)
that->sample_depth = that->bit_depth = 16;
this->next->mod(this->next, that, pp, display);
}
static int
image_transform_png_set_expand_16_add(image_transform *this,
PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
{
UNUSED(colour_type)
this->next = *that;
*that = this;
/* expand_16 does something unless the bit depth is already 16. */
return bit_depth < 16;
}
IT(expand_16, expand_gray_1_2_4_to_8);
/* png_set_strip_16 */
static void
@ -4516,7 +4558,7 @@ image_transform_png_set_strip_16_add(image_transform *this,
return bit_depth > 8;
}
IT(strip_16, expand_gray_1_2_4_to_8);
IT(strip_16, expand_16);
/* png_set_strip_alpha */
static void

View File

@ -304,6 +304,7 @@ option READ_TRANSFORMS requires READ
= NO_READ_TRANSFORMS READ_TRANSFORMS_NOT_SUPPORTED
option READ_EXPAND requires READ_TRANSFORMS
option READ_EXPAND_16 requires READ_TRANSFORMS READ_16BIT enables READ_EXPAND
option READ_SHIFT requires READ_TRANSFORMS
option READ_PACK requires READ_TRANSFORMS
option READ_BGR requires READ_TRANSFORMS

View File

@ -118,7 +118,6 @@
#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_pCAL_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_WRITE_sPLT_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
#define PNG_READ_tIME_SUPPORTED
@ -155,6 +154,7 @@
#define PNG_tRNS_SUPPORTED
#define PNG_WRITE_iTXt_SUPPORTED
#define PNG_oFFs_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
#define PNG_hIST_SUPPORTED
#define PNG_iCCP_SUPPORTED
@ -164,6 +164,7 @@
#define PNG_pCAL_SUPPORTED
#define PNG_CHECK_cHRM_SUPPORTED
#define PNG_tIME_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_pHYs_SUPPORTED
#define PNG_READ_iTXt_SUPPORTED
#define PNG_TEXT_SUPPORTED

View File

@ -226,3 +226,4 @@ EXPORTS
png_get_current_pass_number @218
png_process_data_pause @219
png_process_data_skip @220
png_set_expand_16 @221