[alpha] Implementing premultiplied alpha, work in progress

Always expand pixels to 16-bit samples when premultiplying.
  In pngconf.h, require PNG_GAMMA_SUPPORTED to be defined when defining
    PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
  Eliminated PNG_DIVIDE_BY_255 and PNG_8_BIT_PREMULTIPLY macros
    leaving only PNG_DIVIDE_BY_65535 and PNG_16_BIT_PREMULTIPLY
    because we will always work with 16 bits.
This commit is contained in:
Glenn Randers-Pehrson
2009-11-28 18:33:19 -06:00
parent 85fbf27733
commit 7aa2927db0
5 changed files with 94 additions and 48 deletions

View File

@@ -1,5 +1,5 @@
Libpng 1.4.1alpha02 - November 28, 2009 Libpng 1.4.1alpha02 - November 29, 2009
This is not intended to be a public release. It will be replaced This is not intended to be a public release. It will be replaced
within a few weeks by a public version or by another test version. within a few weeks by a public version or by another test version.
@@ -29,13 +29,19 @@ Changes since the last public release (1.4.0beta107):
version 1.4.1alpha01 [November 27, 2009] version 1.4.1alpha01 [November 27, 2009]
Based on 1.4.0beta107 Based on 1.4.0beta107
version 1.4.1alpha02 [November 28, 2009] version 1.4.1alpha02 [November 29, 2009]
Restored premultiplied alpha feature from version 1.4.0beta105. Restored premultiplied alpha feature from version 1.4.0beta105.
Added "double gamma" to parameters for png_set_premultiply_alpha(). Added "double gamma" to parameters for png_set_premultiply_alpha().
Added "float gamma_premultiply" member to the png_struct. Added "float gamma_premultiply" member to the png_struct.
Moved PNG_DIVIDE_BY_255, PNG_8_BIT_PREMULTIPLY(), etc., from Moved PNG_DIVIDE_BY_255, PNG_8_BIT_PREMULTIPLY(), etc., from
png.h to pngpriv.h png.h to pngpriv.h
Updated documentation about png_set_premultiply_alpha(). Updated documentation about png_set_premultiply_alpha().
Always expand pixels to 16-bit samples when premultiplying.
In pngconf.h, require PNG_GAMMA_SUPPORTED to be defined when defining
PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
Eliminated PNG_DIVIDE_BY_255 and PNG_8_BIT_PREMULTIPLY macros
leaving only PNG_DIVIDE_BY_65535 and PNG_16_BIT_PREMULTIPLY
because we will always work with 16 bits.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@@ -2411,13 +2411,19 @@ version 1.4.0beta107 [November 27, 2009]
version 1.4.1alpha01 [November 27, 2009] version 1.4.1alpha01 [November 27, 2009]
Based on 1.4.0beta107 Based on 1.4.0beta107
version 1.4.1alpha02 [November 28, 2009] version 1.4.1alpha02 [November 29, 2009]
Restored premultiplied alpha feature from version 1.4.0beta105. Restored premultiplied alpha feature from version 1.4.0beta105.
Added "double gamma" to parameters for png_set_premultiply_alpha(). Added "double gamma" to parameters for png_set_premultiply_alpha().
Added "float gamma_premultiply" member to the png_struct. Added "float gamma_premultiply" member to the png_struct.
Moved PNG_DIVIDE_BY_255, PNG_8_BIT_PREMULTIPLY(), etc., from Moved PNG_DIVIDE_BY_255, PNG_8_BIT_PREMULTIPLY(), etc., from
png.h to pngpriv.h png.h to pngpriv.h
Updated documentation about png_set_premultiply_alpha(). Updated documentation about png_set_premultiply_alpha().
Always expand pixels to 16-bit samples when premultiplying.
In pngconf.h, require PNG_GAMMA_SUPPORTED to be defined when defining
PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
Eliminated PNG_DIVIDE_BY_255 and PNG_8_BIT_PREMULTIPLY macros
leaving only PNG_DIVIDE_BY_65535 and PNG_16_BIT_PREMULTIPLY
because we will always work with 16 bits.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

10
png.h
View File

@@ -1,7 +1,7 @@
/* png.h - header file for PNG reference library /* png.h - header file for PNG reference library
* *
* libpng version 1.4.1alpha02 - November 28, 2009 * libpng version 1.4.1alpha02 - November 29, 2009
* Copyright (c) 1998-2009 Glenn Randers-Pehrson * Copyright (c) 1998-2009 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -11,7 +11,7 @@
* Authors and maintainers: * Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.4.1alpha02 - November 28, 2009: Glenn * libpng versions 0.97, January 1998, through 1.4.1alpha02 - November 29, 2009: Glenn
* See also "Contributing Authors", below. * See also "Contributing Authors", below.
* *
* Note about libpng version numbers: * Note about libpng version numbers:
@@ -164,7 +164,7 @@
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* *
* libpng versions 1.2.6, August 15, 2004, through 1.4.1alpha02, November 28, 2009, are * libpng versions 1.2.6, August 15, 2004, through 1.4.1alpha02, November 29, 2009, are
* Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are * Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are
* distributed according to the same disclaimer and license as libpng-1.2.5 * distributed according to the same disclaimer and license as libpng-1.2.5
* with the following individual added to the list of Contributing Authors: * with the following individual added to the list of Contributing Authors:
@@ -340,7 +340,7 @@
/* Version information for png.h - this should match the version in png.c */ /* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.4.1alpha02" #define PNG_LIBPNG_VER_STRING "1.4.1alpha02"
#define PNG_HEADER_VERSION_STRING \ #define PNG_HEADER_VERSION_STRING \
" libpng version 1.4.1alpha02 - November 28, 2009\n" " libpng version 1.4.1alpha02 - November 29, 2009\n"
#define PNG_LIBPNG_VER_SONUM 14 #define PNG_LIBPNG_VER_SONUM 14
#define PNG_LIBPNG_VER_DLLNUM 14 #define PNG_LIBPNG_VER_DLLNUM 14
@@ -1339,7 +1339,7 @@ struct png_struct_def
/* New member added in libpng-1.4.1 */ /* New member added in libpng-1.4.1 */
#ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED #ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
float gamma_premultiply; float gamma_premultiply PNG_DEPSTRUCT;
#endif #endif
}; };

View File

@@ -1,7 +1,7 @@
/* pngconf.h - machine configurable file for libpng /* pngconf.h - machine configurable file for libpng
* *
* libpng version 1.4.1alpha02 - November 28, 2009 * libpng version 1.4.1alpha02 - November 29, 2009
* For conditions of distribution and use, see copyright notice in png.h * For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1998-2009 Glenn Randers-Pehrson * Copyright (c) 1998-2009 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -524,7 +524,7 @@
# define PNG_READ_INVERT_ALPHA_SUPPORTED # define PNG_READ_INVERT_ALPHA_SUPPORTED
# endif # endif
# ifndef PNG_NO_READ_PREMULTIPLY_ALPHA # ifndef PNG_NO_READ_PREMULTIPLY_ALPHA
# define PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED # define PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
# endif # endif
# ifndef PNG_NO_READ_STRIP_ALPHA # ifndef PNG_NO_READ_STRIP_ALPHA
# define PNG_READ_STRIP_ALPHA_SUPPORTED # define PNG_READ_STRIP_ALPHA_SUPPORTED
@@ -861,6 +861,13 @@
# define PNG_TEXT_SUPPORTED # define PNG_TEXT_SUPPORTED
#endif #endif
# /* Premultiply will not work without gamma support. */
# ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
# ifndef PNG_READ_GAMMA_SUPPORTED
# undef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
# endif
# endif
#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ #endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
#ifndef PNG_NO_READ_UNKNOWN_CHUNKS #ifndef PNG_NO_READ_UNKNOWN_CHUNKS

View File

@@ -1,7 +1,7 @@
/* pngrtran.c - transforms the data in a row for PNG readers /* pngrtran.c - transforms the data in a row for PNG readers
* *
* Last changed in libpng 1.4.0 [November 28, 2009] * Last changed in libpng 1.4.0 [November 29, 2009]
* Copyright (c) 1998-2009 Glenn Randers-Pehrson * Copyright (c) 1998-2009 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -151,7 +151,7 @@ png_set_premultiply_alpha(png_structp png_ptr, double gamma)
png_ptr->transformations |= png_ptr->transformations |=
(PNG_PREMULTIPLY_ALPHA | PNG_EXPAND_tRNS); (PNG_PREMULTIPLY_ALPHA | PNG_EXPAND_tRNS);
png_ptr->transformations |= png_ptr->transformations |=
PNG_EXPAND; /* This shouldn't be necessary */ PNG_EXPAND;
png_ptr->flags &= ~PNG_FLAG_ROW_INIT; png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
/* Check for overflow */ /* Check for overflow */
if (gamma == 0 || gamma > 21474.83) if (gamma == 0 || gamma > 21474.83)
@@ -902,8 +902,11 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->transformations &= ~PNG_GAMMA; png_ptr->transformations &= ~PNG_GAMMA;
} }
if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && if ((png_ptr->transformations & (PNG_GAMMA |
png_ptr->gamma != 0.0) #ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
PNG_PREMULTIPLY_ALPHA |
#endif
PNG_RGB_TO_GRAY )) && png_ptr->gamma != 0.0)
{ {
png_build_gamma_table(png_ptr); png_build_gamma_table(png_ptr);
#ifdef PNG_READ_BACKGROUND_SUPPORTED #ifdef PNG_READ_BACKGROUND_SUPPORTED
@@ -1298,6 +1301,11 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
} }
#endif #endif
# ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
if (png_ptr->transformations & PNG_PREMULTIPLY_ALPHA)
info_ptr->bit_depth = 16;
#endif
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
info_ptr->bit_depth); info_ptr->bit_depth);
@@ -1430,8 +1438,17 @@ png_do_read_transformations(png_structp png_ptr)
#endif #endif
#ifdef PNG_READ_16_TO_8_SUPPORTED #ifdef PNG_READ_16_TO_8_SUPPORTED
# ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
/* Do this after the PREMULTIPLY operation */
if (!(png_ptr->transformations & PNG_PREMULTIPLY_ALPHA))
{
if (png_ptr->transformations & PNG_16_TO_8)
png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
}
# else
if (png_ptr->transformations & PNG_16_TO_8) if (png_ptr->transformations & PNG_16_TO_8)
png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
# endif
#endif #endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED #ifdef PNG_READ_BACKGROUND_SUPPORTED
@@ -1513,9 +1530,30 @@ png_do_read_transformations(png_structp png_ptr)
#endif #endif
#ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED #ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
/* TO DO: build 16-bit gamma tables */
/* TO DO: expand pixels to 16 bits either here or (better) inside
* png_do_read_premultiply_alpha
*/
if (png_ptr->transformations & PNG_PREMULTIPLY_ALPHA) if (png_ptr->transformations & PNG_PREMULTIPLY_ALPHA)
png_do_read_premultiply_alpha(&(png_ptr->row_info), png_do_read_premultiply_alpha(&(png_ptr->row_info),
png_ptr->row_buf + 1); png_ptr->row_buf + 1);
# ifdef PNG_READ_16_TO_8_SUPPORTED
if (!(png_ptr->transformations & PNG_PREMULTIPLY_ALPHA))
{
if (png_ptr->transformations & PNG_16_TO_8)
png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
}
# endif
/* TO DO: apply png_ptr->gamma_premultiply to the premultiplied
* samples, using either the 8-bit or 16-bit gamma table as
* appropriate.
*/
#endif #endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
@@ -2008,30 +2046,17 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
void /* PRIVATE */ void /* PRIVATE */
png_do_read_premultiply_alpha(png_row_infop row_info, png_bytep row) png_do_read_premultiply_alpha(png_row_infop row_info, png_bytep row)
{ {
/* TO DO: expand to 16 bits, then apply gamma
* before premultiply
*/
png_debug(1, "in png_do_read_premultiply_alpha"); png_debug(1, "in png_do_read_premultiply_alpha");
{ {
png_uint_32 row_width = row_info->width; png_uint_32 row_width = row_info->width;
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{ {
/* This premultiplies the pixels with the alpha channel in RGBA */
if (row_info->bit_depth == 8)
{
png_bytep sp = row + row_info->rowbytes;
png_bytep dp = sp;
png_uint_16 a = 0;
png_uint_32 i;
for (i = 0; i < row_width; i++)
{
a = *(--sp); --dp;
sp--; *(--dp) = PNG_8_BIT_PREMULTIPLY((*sp), a);
sp--; *(--dp) = PNG_8_BIT_PREMULTIPLY((*sp), a);
sp--; *(--dp) = PNG_8_BIT_PREMULTIPLY((*sp), a);
}
}
/* This premultiplies the pixels with the alpha channel in RRGGBBAA */
else
{ {
png_uint_16p sp = (png_uint_16p)(row + row_info->rowbytes); png_uint_16p sp = (png_uint_16p)(row + row_info->rowbytes);
png_uint_16p dp = sp; png_uint_16p dp = sp;
@@ -2049,22 +2074,6 @@ png_do_read_premultiply_alpha(png_row_infop row_info, png_bytep row)
} }
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{ {
/* This premultiplies the pixels with the alpha channel in GA */
if (row_info->bit_depth == 8)
{
png_bytep sp = row + row_info->rowbytes;
png_bytep dp = sp;
png_uint_16 a = 0;
png_uint_32 i;
for (i = 0; i < row_width; i++)
{
a = *(--sp); --dp;
sp--; *(--dp) = PNG_8_BIT_PREMULTIPLY((*sp), a);
}
}
/* This premultiplies the pixels with the alpha channel in GGAA */
else
{ {
png_uint_16p sp = (png_uint_16p) (row + row_info->rowbytes); png_uint_16p sp = (png_uint_16p) (row + row_info->rowbytes);
png_uint_16p dp = sp; png_uint_16p dp = sp;
@@ -3880,6 +3889,24 @@ png_do_expand(png_row_infop row_info, png_bytep row,
row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
} }
#ifdef PNG_READ_PREMULTIPLY_ALPHA_SUPPORTED
if (row_info->bit_depth == 8)
{
if (row_info->bit_depth == 8)
{
png_bytep sp = row + (png_size_t)row_width;
png_bytep dp = sp + (png_size_t)row_width;
for (i = 1; i < row_width; i++)
{
*(--dp) = *(--sp);
*(--dp) = *(sp);
}
}
row_info->pixel_depth *= 2;
row_info->rowbytes *= 2;
}
#endif
} }
} }
#endif #endif