[devel] Documented png_set_alpha_mode(), other changes in libpng.3 and

libpng-manual.txt.
  The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative
    parameters are supplied by the caller), while in the absence of cHRM
    sRGB/Rec 709 values are still used.
  The bKGD chunk no longer overwrites the background value set by
    png_set_background(), allowing the latter to be used before the file
    header is read. It never performed any useful function to override
    the default anyway.

Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
(subscription required; visit
This commit is contained in:
John Bowler 2011-05-12 21:48:29 -05:00 committed by Glenn Randers-Pehrson
parent ed4d32baa4
commit cb0b29631f
7 changed files with 718 additions and 269 deletions

View File

@ -1,5 +1,5 @@
Libpng 1.5.3beta08 - May 12, 2011
Libpng 1.5.3beta08 - May 13, 2011
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.
@ -112,8 +112,16 @@ Version 1.5.3beta07 [May 11, 2011]
Check for up->location !PNG_AFTER_IDAT when writing unknown chunks
before IDAT.
Version 1.5.3beta08 [May 12, 2011]
Improve "pngvalid --speed" to exclude more of pngvalid from the time.
Version 1.5.3beta08 [May 13, 2011]
Improved "pngvalid --speed" to exclude more of pngvalid from the time.
Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt
The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative
parameters are supplied by the caller), while in the absence of cHRM
sRGB/Rec 709 values are still used.
The bKGD chunk no longer overwrites the background value set by
png_set_background(), allowing the latter to be used before the file
header is read. It never performed any useful function to override
the default anyway.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
(subscription required; visit

12
CHANGES
View File

@ -3371,8 +3371,16 @@ Version 1.5.3beta07 [May 11, 2011]
Check for up->location !PNG_AFTER_IDAT when writing unknown chunks
before IDAT.
Version 1.5.3beta08 [May 12, 2011]
Improve "pngvalid --speed" to exclude more of pngvalid from the time.
Version 1.5.3beta08 [May 13, 2011]
Improved "pngvalid --speed" to exclude more of pngvalid from the time.
Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt
The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative
parameters are supplied by the caller), while in the absence of cHRM
sRGB/Rec 709 values are still used.
The bKGD chunk no longer overwrites the background value set by
png_set_background(), allowing the latter to be used before the file
header is read. It never performed any useful function to override
the default anyway.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit

View File

@ -1,6 +1,6 @@
libpng-manual.txt - A description on how to use and modify libpng
libpng version 1.5.3beta08 - May 11, 2011
libpng version 1.5.3beta08 - May 13, 2011
Updated and distributed by Glenn Randers-Pehrson
<glennrp at users.sourceforge.net>
Copyright (c) 1998-2011 Glenn Randers-Pehrson
@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on:
libpng versions 0.97, January 1998, through 1.5.3beta08 - May 11, 2011
libpng versions 0.97, January 1998, through 1.5.3beta08 - May 13, 2011
Updated and distributed by Glenn Randers-Pehrson
Copyright (c) 1998-2011 Glenn Randers-Pehrson
@ -637,6 +637,223 @@ and you can retrieve the limit with
Any chunks that would cause either of these limits to be exceeded will
be ignored.
Information about your system
If you intend to display the PNG or to incorporate it in other image data you
need to tell libpng information about your display or drawing surface so that
libpng can convert the values in the image to match the display.
From libpng-1.5.3 this information can be set before reading the PNG file
header. In earlier versions png_set_gamma() existed but behaved incorrectly if
called before the PNG file header had been read and png_set_alpha_mode() did not
exist.
If you need to support versions prior to libpng-1.5.3 test the version number
and follow the procedures described in the appropriate manual page.
You give libpng the encoding expected by your system expressed as a 'gamma'
value. You can also specify a default encoding for the PNG file in
case the required information is missing from the file. By default libpng
assumes that the PNG data matches your system, to keep this default call:
png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/);
or you can use the fixed point equivalent:
png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma);
If you don't know the gamma for you system it is probably 2.2 - a good
approximation to the IEC standard for display systems (sRGB). If images are
too contrasty or washed out you got the value wrong - check your system
documentation!
Many systems permit the system gamma to be changed via a lookup table in the
display driver, a few systems, including older Macs, change the response by
default. As of 1.5.3 three special values are available to handle common
situations:
PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1
standard. This matches almost all systems.
PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6)
Apple Macintosh system with the default settings.
PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the
system expects data with no gamma encoding.
You would use the linear (unencoded) value if you need to process the pixel
values further because this avoids the need to decode and reencode each
component value whenever arithmetic is performed. A lot of graphics software
uses linear values for this reason, often with higher precision component values
to preserve overall accuracy.
The second thing you may need to tell libpng about is how your system handles
alpha channel information. Some, but not all, PNG files contain an alpha
channel. To display these files correctly you need to compose the data onto a
suitable background, as described in the PNG specification.
Libpng only supports composing onto a single color (using png_set_background;
see below.) Otherwise you must do the composition yourself and, in this case,
you may need to call png_set_alpha_mode:
png_set_alpha_mode(png_ptr, mode, screen_gamma);
The screen_gamma value is the same as the argument to png_set_gamma, however how
it effects the output depends on the mode. png_set_alpha_mode sets the file
gamma default to 1/screen_gamma, so normally you don't need to call
png_set_gamma. If you need different defaults call png_set_gamma before
png_set_alpha_mode - if you call it after it will override the settings made by
png_set_alpha_mode.
The mode is as follows:
PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red,
green and blue, or gray, components are gamma encoded color
values and are not premultiplied by the alpha value. The
alpha value is a linear measure of the contribution of the
pixel to the corresponding final output pixel.
You should normally use this format if you intend to perform
color correction on the color values; most, maybe all, color
correction software has no handling for the alpha channel and,
anyway, the math to handle pre-multiplied component values is
unnecessarily complex.
Before you do any arithmetic on the component values you need
to remove the gamma encoding and multiply out the alpha
channel. See the PNG specification for more detail. It is
important to note that when an image with an alpha channel is
scaled linear encoded, pre-multiplied, component values must
be used!
The remaining modes assume you don't need to do any further color correction or
that if you do your color correction software knows all about alpha (it
probably doesn't!)
PNG_ALPHA_STANDARD: The data libpng produces is encoded in the standard way
assumed by most correctly written graphics software.
The gamma encodiing will be removed by libpng and the
linear component values will be pre-multiplied by the
alpha channel.
With this format the final image must be re-encoded to
match the display gamma before the image is displayed.
If your system doesn't do that, yet still seems to
perform arithmetic on the pixels without decoding them,
it is broken - check out the modes below.
With PNG_ALPHA_STANDARD libpng always produces linear
component values, whatever screen_gamma you supply. The
screen_gamma value is, however, used as a default for
the file gamma if the PNG file has no gamma information.
If you call png_set_gamma after png_set_alpha_mode you
will override the linear encoding. Instead the
pre-multiplied pixel values will be gamma encoded but
the alpha channel will still be linear. This may
actually match the requirements of some broken software,
but it is unlikely.
While linear 8 bit data is often used it has
insufficient precision for any image with a reasonable
dynamic range. To avoid problems, and if your software
supports it, use png_set_expand_16() to force all
components to 16 bits.
PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD except that
completely opaque pixels are gamma encoded according to
the screen_gamma value. Pixels with alpha less than 1.0
will still have linear components.
Use this format if you have control over your
compositing software and do don't do other arithmetic
(such as scaling) on the data you get from libpng. Your
compositing software can simply copy opaque pixels to
the output but still has linear values for the
non-opaque pixels.
In normal compositing, where the alpha channel encodes
partial pixel coverage (as opposed to broad area
translucency), the inaccuracies of the 8 bit
representation of non-opaque pixels are irrelevant.
You can also try this format if your software is broken;
it might look better.
PNG_ALPHA_BROKEN This is PNG_ALPHA_STANDARD however all component values,
including the alpha channel are gamma encoded. This is
an appropriate format to try if your software, or more
likely hardware, is totally broken: if it performs
linear arithmetic directly on gamma encoded values.
In most cases of broken software or hardware the bug in the final display
manifests as a subtle halo around composited parts of the image. You may not
even perceive this as a halo; the composited part of the image may simply appear
separate from the background, as though it had been cut out of paper and pasted
on afterward.
If you don't have to deal with bugs in software or hardware, or if you can fix
them, there are three recommended ways of using png_set_alpha_mode:
png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, screen_gamma);
You can do color correction on the result (libpng does not currently
support color correction internally.) When you handle the alpha channel
you need to undo the gamma encoding and multipy out the alpha.
png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, screen_gamma);
png_set_expand_16(png_ptr);
If you are using the high level interface don't call png_set_expand_16,
instead pass PNG_TRANSFORM_EXPAND_16 to the interface.
With this mode you can't do color corrrection, but you can do arithmetic,
including composition and scaling, on the data without further processing.
png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMZED, screen_gamma);
You can avoid the expansion to 16 bit components with this mode, but you
lose the ability to scale the image or perform other linear arithmetic.
All you can do is compose the result onto a matching output. Since this
mode is libpng specific you also need to write your own composition
software.
If you don't need, or can't handle, the alpha channel you can call
png_set_background to remove it by compositing against a fixed color. Don't
call png_set_strip_alpha to do this - it will leave spurious pixel values in
transparent parts of this image.
png_set_background(png_ptr, &background_color, PNG_BACKGROUND_GAMMA_SCREEN,
0, 1);
The background_color is an RGB or grayscale value according to the data format
libpng will produce for you. Because you don't yet know the format of the PNG
file if you call png_set_background at this point you must arrange for the
format produced by libpng to always have 8-bit or 16-bit components and then
store the color as an 8-bit or 16-bit color as appropriate. The color contains
separate gray and RGB component values, so you can let libpng produce gray or
RGB output according to the input format, but low bit depth grayscale images
must always be converted to at least 8-bit format. (Even low low bit depth
grayscale images can't have an alpha channel they can have a transparent
color!)
You set the transforms you need later, either as flags to the high level
interface or libpng API calls for the low level interface. For reference the
settings required are:
8-bit values:
PNG_TRANSFORM_STRIP_16 | PNG_EXPAND
png_set_expand(png_ptr); png_set_strip_16(png_ptr);
16-bit values:
PNG_TRANSFORM_EXPAND_16
png_set_expand_16(png_ptr);
In either case palette image data will be expanded to RGB. If you just want
color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr)
to the list.
Calling png_set_background before the PNG file header is read will not work
prior to libpng-1.5.3. Because the failure may result in unexpected warnings or
errors it is therefore much safer to call png_set_background after the head has
been read. Unfortunately this means that prior to libpng-1.5.3 it cannot be
used with the high level interface.
The high-level read interface
At this point there are two ways to proceed; through the high-level
@ -735,6 +952,22 @@ call to png_read_info().
This will process all chunks up to but not including the image data.
This also copies some of the data from the PNG file into the decode structure
for use in later transformations. Important information copied in is:
1) The PNG file gamma from the gAMA chunk. This overwrites the default value
provided by an earlier call to png_set_gamma or png_set_alpha_mode.
2) Prior to libpng-1.5.3 the background color from a bKGd chunk. This
damages the information provided by an earlier call to png_set_background
resulting in expected behavior. Libpng-1.5.3 no longer does this.
3) The number of significant bits in each component value. Libpng uses this to
optimize gamma handling by reducing the internal lookup table sizes.
4) The transparent color information from a tRNS chunk. This can be modified by
a later call to png_set_tRNS.
Querying the info structure
Functions are used to get the information from the info_ptr once it
@ -1098,7 +1331,7 @@ forms:
converted to microns and back without some loss
of precision.
For more information, see the png_info definition in png.h and the
For more information, see the
PNG specification for chunk contents. Be careful with trusting
rowbytes, as some of the transformations could increase the space
needed to hold a row (expand, filler, gray_to_rgb, etc.).
@ -1133,17 +1366,20 @@ to handle any special transformations of the image data. The various
ways to transform the data will be described in the order that they
should occur. This is important, as some of these change the color
type and/or bit depth of the data, and some others only work on
certain color types and bit depths. Even though each transformation
checks to see if it has data that it can do something with, you should
make sure to only enable a transformation if it will be valid for the
data. For example, don't swap red and blue on grayscale data.
certain color types and bit depths.
The colors used for the background and transparency values should be
supplied in the same format/depth as the current image data. They
are stored in the same format/depth as the image data in a bKGD or tRNS
chunk, so this is what libpng expects for this data. The colors are
transformed to keep in sync with the image data when an application
calls the png_read_update_info() routine (see below).
Transformations you request are ignored if they don't have any meaning for a
particular input data format. However some transformations can have an effect
as a result of a previous transformation. If you specify a contradictory set of
transformations, for example both adding and removing the alpha channel, you
cannot predict the final result.
The color used for the transparency values should be supplied in the same
format/depth as the current image data. It is stored in the same format/depth
as the image data in a tRNS chunk, so this is what libpng expects for this data.
The color used for the background value depends on the need_expand argument as
described below.
Data will be decoded into the supplied row buffers packed into bytes
unless the library has been told to transform it into another format.
@ -1197,18 +1433,16 @@ PNG can have files with 16 bits per channel. If you only can handle
if (bit_depth == 16)
png_set_strip_16(png_ptr);
If, for some reason, you don't need the alpha channel on an image,
and you want to remove it rather than combining it with the background
(but the image author certainly had in mind that you *would* combine
it with the background, so that's what you should probably do):
If you need to process the alpha channel on the image separately from the image
data (for example if you convert it to a bitmap mask) it is possible to have
libpng strip the channel leaving just RGB or gray data:
if (color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
See below for png_set_background(), which does the correct composition on a
single opaque color. This is probably what you should do in all cases rather
than use png_set_strip_alpha() - unless you know for sure that it is the wrong
thing to do.
If you strip the alpha channel you need to find some other way of dealing with
the information. If, instead, you want to convert the image to an opaque
version with no alpha channel use png_set_background; see below.
As of libpng version 1.5.2, almost all useful expansions are supported, the
major ommissions are convertion of grayscale to indexed images (which can be
@ -1342,8 +1576,8 @@ with alpha.
if (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_rgb_to_gray_fixed(png_ptr, error_action,
int red_weight, int green_weight);
png_set_rgb_to_gray(png_ptr, error_action, double red_weight,
double green_weight);
error_action = 1: silently do the conversion
@ -1356,122 +1590,83 @@ with alpha.
image has any pixel where
red != green or red != blue
red_weight: weight of red component times 100000
red_weight: weight of red component
green_weight: weight of green component times 100000
green_weight: weight of green component
If either weight is negative, default
weights (21268, 71514) are used.
weights are used.
In the corresponding fixed point API the red_weight and green_weight values are
simply scaled by 100,000:
png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight,
png_fixed_point green_weight);
If you have set error_action = 1 or 2, you can
later check whether the image really was gray, after processing
the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
It will return a png_byte that is zero if the image was gray or
1 if there were any non-gray pixels. bKGD and sBIT data
1 if there were any non-gray pixels. Background and sBIT data
will be silently converted to grayscale, using the green channel
data, regardless of the error_action setting.
data for sBIT, regardless of the error_action setting.
With red_weight+green_weight<=100000,
the normalized graylevel is computed:
The default values come from the PNG file cHRM chunk if present, otherwise the
defaults correspond to the ITU-R recommendation 709, and also the sRGB color
space, as recommended in the Charles Poynton's Colour FAQ,
<http://www.poynton.com/>, in section 9:
int rw = red_weight * 65536;
int gw = green_weight * 65536;
int bw = 65536 - (rw + gw);
gray = (rw*red + gw*green + bw*blue)/65536;
The default values approximate those recommended in the Charles
Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net>
<http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9>
Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
Libpng approximates this with integers scaled by 32768:
Y = (6968 * R + 23434 * G + 2366 * B)/32768
The calculation is done in a linear colorspace, if the image gamma
can be determined.
If you have a grayscale and you are using png_set_expand_gray_1_2_4_to_8(),
png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to
a higher bit-depth, you must either supply the background color as a gray
value at the original file bit-depth (need_expand = 1) or else supply the
background color as an RGB triplet at the final, expanded bit depth
(need_expand = 0). Similarly, if you are reading a paletted image, you
must either supply the background color as a palette index (need_expand = 1)
or as an RGB triplet that may or may not be in the palette (need_expand = 0).
The png_set_background() function has been described already, it tells libpng to
composite images with alpha or simple transparency against the supplied
background color. For compatibility with versions of libpng earlier than
libpng-1.5.3 it is recommended that you call the function after reading the file
header, even if you don't want to use the color in a bKGD chunk, if one exists.
If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
you may use this color, or supply another color more suitable for
the current display (e.g., the background color from a web page). You
need to tell libpng how the color is represented, both the format of the
component values in the color (the number of bits) and the gamme encoding of the
color. The function takes two arguments, background_gamma_mode and need_expand
to convey this information, however only two combinations are like to be useful:
png_color_16 my_background;
png_color_16p image_background;
if (png_get_bKGD(png_ptr, info_ptr, &image_background))
png_set_background(png_ptr, image_background,
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
PNG_BACKGROUND_GAMMA_FILE, 1/*needs to be expanded*/, 1);
else
png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1);
The png_set_background() function tells libpng to composite images
with alpha or simple transparency against the supplied background
color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
you may use this color, or supply another color more suitable for
the current display (e.g., the background color from a web page). You
need to tell libpng whether the color is in the gamma space of the
display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
know why anyone would use this, but it's here).
To properly display PNG images on any kind of system, the application needs
to know what the display gamma is. Ideally, the user will know this, and
the application will allow them to set it. One method of allowing the user
to set the display gamma separately for each system is to check for a
SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
correctly set.
The second call was described above - my_background is in the format of the
final, display, output produced by libpng. Because you now know the format of
the PNG it is possible to avoid the need to choose either 8 or 16 bit output and
to retain palette images (the palette colors will be modified appropriately and
the tRNS chunk removed.) However, if you are doing this, take great care not to
ask for transformations without checking first that they apply!
Note that display_gamma is the overall gamma correction required to produce
pleasing results, which depends on the lighting conditions in the surrounding
environment. In a dim or brightly lit room, no compensation other than
the physical gamma exponent of the monitor is needed, while in a dark room
a slightly smaller exponent is better.
In the first call the background color has the original bit depth and color type
of the PNG file. So, for palette images the color is supplied as a palette
index and for low bit greyscale images the color is a reduced bit value in
image_background->gray.
double gamma, screen_gamma;
If you didn't call png_set_gamma() before reading the file header, for example
if you need your code to remain compatible with older versions of libpng prior
to libpng-1.5.3, this is the place to call it.
if (/* We have a user-defined screen
gamma value */)
{
screen_gamma = user_defined_screen_gamma;
}
/* One way that applications can share the same
screen gamma value */
else if ((gamma_str = getenv("SCREEN_GAMMA"))
!= NULL)
{
screen_gamma = (double)atof(gamma_str);
}
/* If we don't have another value */
else
{
screen_gamma = 2.2; /* A good guess for a
PC monitor in a bright office or a dim room */
screen_gamma = 2.0; /* A good guess for a
PC monitor in a dark room */
screen_gamma = 1.7 or 1.0; /* A good
guess for Mac systems */
}
The functions png_set_gamma() and its fixed point equivalent
png_set_gamma_fixed() handle gamma transformations of the data.
Pass both the file gamma and the current screen_gamma. If the file does
not have a gamma value, you can pass one anyway if you have an idea what
it is (usually 0.45455 is a good guess for GIF images on PCs). Note
that file gammas are inverted from screen gammas. See the discussions
on gamma in the PNG specification for an excellent description of what
gamma is, and why all applications should support it. It is strongly
recommended that PNG viewers support gamma correction.
Do not call it if you called png_set_alpha_mode(); doing so will damage the
settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is
supported then you can certainly do png_set_gamma() before reading the PNG
header.)
This API unconditionally sets the screen and file gamma values, so it will
override the value in the PNG file unless it is called before the PNG file
@ -4199,7 +4394,7 @@ Other rules can be inferred by inspecting the libpng source.
XIV. Y2K Compliance in libpng
May 11, 2011
May 13, 2011
Since the PNG Development group is an ad-hoc body, we can't make
an official declaration.

425
libpng.3
View File

@ -1,4 +1,4 @@
.TH LIBPNG 3 "May 11, 2011"
.TH LIBPNG 3 "May 13, 2011"
.SH NAME
libpng \- Portable Network Graphics (PNG) Reference Library 1.5.3beta08
.SH SYNOPSIS
@ -951,7 +951,7 @@ Following is a copy of the libpng-manual.txt file that accompanies libpng.
.SH LIBPNG.TXT
libpng-manual.txt - A description on how to use and modify libpng
libpng version 1.5.3beta08 - May 11, 2011
libpng version 1.5.3beta08 - May 13, 2011
Updated and distributed by Glenn Randers-Pehrson
<glennrp at users.sourceforge.net>
Copyright (c) 1998-2011 Glenn Randers-Pehrson
@ -962,7 +962,7 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on:
libpng versions 0.97, January 1998, through 1.5.3beta08 - May 11, 2011
libpng versions 0.97, January 1998, through 1.5.3beta08 - May 13, 2011
Updated and distributed by Glenn Randers-Pehrson
Copyright (c) 1998-2011 Glenn Randers-Pehrson
@ -1588,6 +1588,223 @@ and you can retrieve the limit with
Any chunks that would cause either of these limits to be exceeded will
be ignored.
.SS Information about your system
If you intend to display the PNG or to incorporate it in other image data you
need to tell libpng information about your display or drawing surface so that
libpng can convert the values in the image to match the display.
From libpng-1.5.3 this information can be set before reading the PNG file
header. In earlier versions png_set_gamma() existed but behaved incorrectly if
called before the PNG file header had been read and png_set_alpha_mode() did not
exist.
If you need to support versions prior to libpng-1.5.3 test the version number
and follow the procedures described in the appropriate manual page.
You give libpng the encoding expected by your system expressed as a 'gamma'
value. You can also specify a default encoding for the PNG file in
case the required information is missing from the file. By default libpng
assumes that the PNG data matches your system, to keep this default call:
png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/);
or you can use the fixed point equivalent:
png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma);
If you don't know the gamma for you system it is probably 2.2 - a good
approximation to the IEC standard for display systems (sRGB). If images are
too contrasty or washed out you got the value wrong - check your system
documentation!
Many systems permit the system gamma to be changed via a lookup table in the
display driver, a few systems, including older Macs, change the response by
default. As of 1.5.3 three special values are available to handle common
situations:
PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1
standard. This matches almost all systems.
PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6)
Apple Macintosh system with the default settings.
PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the
system expects data with no gamma encoding.
You would use the linear (unencoded) value if you need to process the pixel
values further because this avoids the need to decode and reencode each
component value whenever arithmetic is performed. A lot of graphics software
uses linear values for this reason, often with higher precision component values
to preserve overall accuracy.
The second thing you may need to tell libpng about is how your system handles
alpha channel information. Some, but not all, PNG files contain an alpha
channel. To display these files correctly you need to compose the data onto a
suitable background, as described in the PNG specification.
Libpng only supports composing onto a single color (using png_set_background;
see below.) Otherwise you must do the composition yourself and, in this case,
you may need to call png_set_alpha_mode:
png_set_alpha_mode(png_ptr, mode, screen_gamma);
The screen_gamma value is the same as the argument to png_set_gamma, however how
it effects the output depends on the mode. png_set_alpha_mode sets the file
gamma default to 1/screen_gamma, so normally you don't need to call
png_set_gamma. If you need different defaults call png_set_gamma before
png_set_alpha_mode - if you call it after it will override the settings made by
png_set_alpha_mode.
The mode is as follows:
PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red,
green and blue, or gray, components are gamma encoded color
values and are not premultiplied by the alpha value. The
alpha value is a linear measure of the contribution of the
pixel to the corresponding final output pixel.
You should normally use this format if you intend to perform
color correction on the color values; most, maybe all, color
correction software has no handling for the alpha channel and,
anyway, the math to handle pre-multiplied component values is
unnecessarily complex.
Before you do any arithmetic on the component values you need
to remove the gamma encoding and multiply out the alpha
channel. See the PNG specification for more detail. It is
important to note that when an image with an alpha channel is
scaled linear encoded, pre-multiplied, component values must
be used!
The remaining modes assume you don't need to do any further color correction or
that if you do your color correction software knows all about alpha (it
probably doesn't!)
PNG_ALPHA_STANDARD: The data libpng produces is encoded in the standard way
assumed by most correctly written graphics software.
The gamma encodiing will be removed by libpng and the
linear component values will be pre-multiplied by the
alpha channel.
With this format the final image must be re-encoded to
match the display gamma before the image is displayed.
If your system doesn't do that, yet still seems to
perform arithmetic on the pixels without decoding them,
it is broken - check out the modes below.
With PNG_ALPHA_STANDARD libpng always produces linear
component values, whatever screen_gamma you supply. The
screen_gamma value is, however, used as a default for
the file gamma if the PNG file has no gamma information.
If you call png_set_gamma after png_set_alpha_mode you
will override the linear encoding. Instead the
pre-multiplied pixel values will be gamma encoded but
the alpha channel will still be linear. This may
actually match the requirements of some broken software,
but it is unlikely.
While linear 8 bit data is often used it has
insufficient precision for any image with a reasonable
dynamic range. To avoid problems, and if your software
supports it, use png_set_expand_16() to force all
components to 16 bits.
PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD except that
completely opaque pixels are gamma encoded according to
the screen_gamma value. Pixels with alpha less than 1.0
will still have linear components.
Use this format if you have control over your
compositing software and do don't do other arithmetic
(such as scaling) on the data you get from libpng. Your
compositing software can simply copy opaque pixels to
the output but still has linear values for the
non-opaque pixels.
In normal compositing, where the alpha channel encodes
partial pixel coverage (as opposed to broad area
translucency), the inaccuracies of the 8 bit
representation of non-opaque pixels are irrelevant.
You can also try this format if your software is broken;
it might look better.
PNG_ALPHA_BROKEN This is PNG_ALPHA_STANDARD however all component values,
including the alpha channel are gamma encoded. This is
an appropriate format to try if your software, or more
likely hardware, is totally broken: if it performs
linear arithmetic directly on gamma encoded values.
In most cases of broken software or hardware the bug in the final display
manifests as a subtle halo around composited parts of the image. You may not
even perceive this as a halo; the composited part of the image may simply appear
separate from the background, as though it had been cut out of paper and pasted
on afterward.
If you don't have to deal with bugs in software or hardware, or if you can fix
them, there are three recommended ways of using png_set_alpha_mode:
png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, screen_gamma);
You can do color correction on the result (libpng does not currently
support color correction internally.) When you handle the alpha channel
you need to undo the gamma encoding and multipy out the alpha.
png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, screen_gamma);
png_set_expand_16(png_ptr);
If you are using the high level interface don't call png_set_expand_16,
instead pass PNG_TRANSFORM_EXPAND_16 to the interface.
With this mode you can't do color corrrection, but you can do arithmetic,
including composition and scaling, on the data without further processing.
png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMZED, screen_gamma);
You can avoid the expansion to 16 bit components with this mode, but you
lose the ability to scale the image or perform other linear arithmetic.
All you can do is compose the result onto a matching output. Since this
mode is libpng specific you also need to write your own composition
software.
If you don't need, or can't handle, the alpha channel you can call
png_set_background to remove it by compositing against a fixed color. Don't
call png_set_strip_alpha to do this - it will leave spurious pixel values in
transparent parts of this image.
png_set_background(png_ptr, &background_color, PNG_BACKGROUND_GAMMA_SCREEN,
0, 1);
The background_color is an RGB or grayscale value according to the data format
libpng will produce for you. Because you don't yet know the format of the PNG
file if you call png_set_background at this point you must arrange for the
format produced by libpng to always have 8-bit or 16-bit components and then
store the color as an 8-bit or 16-bit color as appropriate. The color contains
separate gray and RGB component values, so you can let libpng produce gray or
RGB output according to the input format, but low bit depth grayscale images
must always be converted to at least 8-bit format. (Even low low bit depth
grayscale images can't have an alpha channel they can have a transparent
color!)
You set the transforms you need later, either as flags to the high level
interface or libpng API calls for the low level interface. For reference the
settings required are:
8-bit values:
PNG_TRANSFORM_STRIP_16 | PNG_EXPAND
png_set_expand(png_ptr); png_set_strip_16(png_ptr);
16-bit values:
PNG_TRANSFORM_EXPAND_16
png_set_expand_16(png_ptr);
In either case palette image data will be expanded to RGB. If you just want
color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr)
to the list.
Calling png_set_background before the PNG file header is read will not work
prior to libpng-1.5.3. Because the failure may result in unexpected warnings or
errors it is therefore much safer to call png_set_background after the head has
been read. Unfortunately this means that prior to libpng-1.5.3 it cannot be
used with the high level interface.
.SS The high-level read interface
At this point there are two ways to proceed; through the high-level
@ -1686,6 +1903,22 @@ call to png_read_info().
This will process all chunks up to but not including the image data.
This also copies some of the data from the PNG file into the decode structure
for use in later transformations. Important information copied in is:
1) The PNG file gamma from the gAMA chunk. This overwrites the default value
provided by an earlier call to png_set_gamma or png_set_alpha_mode.
2) Prior to libpng-1.5.3 the background color from a bKGd chunk. This
damages the information provided by an earlier call to png_set_background
resulting in expected behavior. Libpng-1.5.3 no longer does this.
3) The number of significant bits in each component value. Libpng uses this to
optimize gamma handling by reducing the internal lookup table sizes.
4) The transparent color information from a tRNS chunk. This can be modified by
a later call to png_set_tRNS.
.SS Querying the info structure
Functions are used to get the information from the info_ptr once it
@ -2049,7 +2282,7 @@ forms:
converted to microns and back without some loss
of precision.
For more information, see the png_info definition in png.h and the
For more information, see the
PNG specification for chunk contents. Be careful with trusting
rowbytes, as some of the transformations could increase the space
needed to hold a row (expand, filler, gray_to_rgb, etc.).
@ -2084,17 +2317,20 @@ to handle any special transformations of the image data. The various
ways to transform the data will be described in the order that they
should occur. This is important, as some of these change the color
type and/or bit depth of the data, and some others only work on
certain color types and bit depths. Even though each transformation
checks to see if it has data that it can do something with, you should
make sure to only enable a transformation if it will be valid for the
data. For example, don't swap red and blue on grayscale data.
certain color types and bit depths.
The colors used for the background and transparency values should be
supplied in the same format/depth as the current image data. They
are stored in the same format/depth as the image data in a bKGD or tRNS
chunk, so this is what libpng expects for this data. The colors are
transformed to keep in sync with the image data when an application
calls the png_read_update_info() routine (see below).
Transformations you request are ignored if they don't have any meaning for a
particular input data format. However some transformations can have an effect
as a result of a previous transformation. If you specify a contradictory set of
transformations, for example both adding and removing the alpha channel, you
cannot predict the final result.
The color used for the transparency values should be supplied in the same
format/depth as the current image data. It is stored in the same format/depth
as the image data in a tRNS chunk, so this is what libpng expects for this data.
The color used for the background value depends on the need_expand argument as
described below.
Data will be decoded into the supplied row buffers packed into bytes
unless the library has been told to transform it into another format.
@ -2148,18 +2384,16 @@ PNG can have files with 16 bits per channel. If you only can handle
if (bit_depth == 16)
png_set_strip_16(png_ptr);
If, for some reason, you don't need the alpha channel on an image,
and you want to remove it rather than combining it with the background
(but the image author certainly had in mind that you *would* combine
it with the background, so that's what you should probably do):
If you need to process the alpha channel on the image separately from the image
data (for example if you convert it to a bitmap mask) it is possible to have
libpng strip the channel leaving just RGB or gray data:
if (color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
See below for png_set_background(), which does the correct composition on a
single opaque color. This is probably what you should do in all cases rather
than use png_set_strip_alpha() - unless you know for sure that it is the wrong
thing to do.
If you strip the alpha channel you need to find some other way of dealing with
the information. If, instead, you want to convert the image to an opaque
version with no alpha channel use png_set_background; see below.
As of libpng version 1.5.2, almost all useful expansions are supported, the
major ommissions are convertion of grayscale to indexed images (which can be
@ -2293,8 +2527,8 @@ with alpha.
if (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_rgb_to_gray_fixed(png_ptr, error_action,
int red_weight, int green_weight);
png_set_rgb_to_gray(png_ptr, error_action, double red_weight,
double green_weight);
error_action = 1: silently do the conversion
@ -2307,122 +2541,83 @@ with alpha.
image has any pixel where
red != green or red != blue
red_weight: weight of red component times 100000
red_weight: weight of red component
green_weight: weight of green component times 100000
green_weight: weight of green component
If either weight is negative, default
weights (21268, 71514) are used.
weights are used.
In the corresponding fixed point API the red_weight and green_weight values are
simply scaled by 100,000:
png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight,
png_fixed_point green_weight);
If you have set error_action = 1 or 2, you can
later check whether the image really was gray, after processing
the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
It will return a png_byte that is zero if the image was gray or
1 if there were any non-gray pixels. bKGD and sBIT data
1 if there were any non-gray pixels. Background and sBIT data
will be silently converted to grayscale, using the green channel
data, regardless of the error_action setting.
data for sBIT, regardless of the error_action setting.
With red_weight+green_weight<=100000,
the normalized graylevel is computed:
The default values come from the PNG file cHRM chunk if present, otherwise the
defaults correspond to the ITU-R recommendation 709, and also the sRGB color
space, as recommended in the Charles Poynton's Colour FAQ,
<http://www.poynton.com/>, in section 9:
int rw = red_weight * 65536;
int gw = green_weight * 65536;
int bw = 65536 - (rw + gw);
gray = (rw*red + gw*green + bw*blue)/65536;
The default values approximate those recommended in the Charles
Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net>
<http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9>
Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
Libpng approximates this with integers scaled by 32768:
Y = (6968 * R + 23434 * G + 2366 * B)/32768
The calculation is done in a linear colorspace, if the image gamma
can be determined.
If you have a grayscale and you are using png_set_expand_gray_1_2_4_to_8(),
png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to
a higher bit-depth, you must either supply the background color as a gray
value at the original file bit-depth (need_expand = 1) or else supply the
background color as an RGB triplet at the final, expanded bit depth
(need_expand = 0). Similarly, if you are reading a paletted image, you
must either supply the background color as a palette index (need_expand = 1)
or as an RGB triplet that may or may not be in the palette (need_expand = 0).
The png_set_background() function has been described already, it tells libpng to
composite images with alpha or simple transparency against the supplied
background color. For compatibility with versions of libpng earlier than
libpng-1.5.3 it is recommended that you call the function after reading the file
header, even if you don't want to use the color in a bKGD chunk, if one exists.
If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
you may use this color, or supply another color more suitable for
the current display (e.g., the background color from a web page). You
need to tell libpng how the color is represented, both the format of the
component values in the color (the number of bits) and the gamme encoding of the
color. The function takes two arguments, background_gamma_mode and need_expand
to convey this information, however only two combinations are like to be useful:
png_color_16 my_background;
png_color_16p image_background;
if (png_get_bKGD(png_ptr, info_ptr, &image_background))
png_set_background(png_ptr, image_background,
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
PNG_BACKGROUND_GAMMA_FILE, 1/*needs to be expanded*/, 1);
else
png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1);
The png_set_background() function tells libpng to composite images
with alpha or simple transparency against the supplied background
color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
you may use this color, or supply another color more suitable for
the current display (e.g., the background color from a web page). You
need to tell libpng whether the color is in the gamma space of the
display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
know why anyone would use this, but it's here).
To properly display PNG images on any kind of system, the application needs
to know what the display gamma is. Ideally, the user will know this, and
the application will allow them to set it. One method of allowing the user
to set the display gamma separately for each system is to check for a
SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
correctly set.
The second call was described above - my_background is in the format of the
final, display, output produced by libpng. Because you now know the format of
the PNG it is possible to avoid the need to choose either 8 or 16 bit output and
to retain palette images (the palette colors will be modified appropriately and
the tRNS chunk removed.) However, if you are doing this, take great care not to
ask for transformations without checking first that they apply!
Note that display_gamma is the overall gamma correction required to produce
pleasing results, which depends on the lighting conditions in the surrounding
environment. In a dim or brightly lit room, no compensation other than
the physical gamma exponent of the monitor is needed, while in a dark room
a slightly smaller exponent is better.
In the first call the background color has the original bit depth and color type
of the PNG file. So, for palette images the color is supplied as a palette
index and for low bit greyscale images the color is a reduced bit value in
image_background->gray.
double gamma, screen_gamma;
If you didn't call png_set_gamma() before reading the file header, for example
if you need your code to remain compatible with older versions of libpng prior
to libpng-1.5.3, this is the place to call it.
if (/* We have a user-defined screen
gamma value */)
{
screen_gamma = user_defined_screen_gamma;
}
/* One way that applications can share the same
screen gamma value */
else if ((gamma_str = getenv("SCREEN_GAMMA"))
!= NULL)
{
screen_gamma = (double)atof(gamma_str);
}
/* If we don't have another value */
else
{
screen_gamma = 2.2; /* A good guess for a
PC monitor in a bright office or a dim room */
screen_gamma = 2.0; /* A good guess for a
PC monitor in a dark room */
screen_gamma = 1.7 or 1.0; /* A good
guess for Mac systems */
}
The functions png_set_gamma() and its fixed point equivalent
png_set_gamma_fixed() handle gamma transformations of the data.
Pass both the file gamma and the current screen_gamma. If the file does
not have a gamma value, you can pass one anyway if you have an idea what
it is (usually 0.45455 is a good guess for GIF images on PCs). Note
that file gammas are inverted from screen gammas. See the discussions
on gamma in the PNG specification for an excellent description of what
gamma is, and why all applications should support it. It is strongly
recommended that PNG viewers support gamma correction.
Do not call it if you called png_set_alpha_mode(); doing so will damage the
settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is
supported then you can certainly do png_set_gamma() before reading the PNG
header.)
This API unconditionally sets the screen and file gamma values, so it will
override the value in the PNG file unless it is called before the PNG file
@ -5150,7 +5345,7 @@ Other rules can be inferred by inspecting the libpng source.
.SH XIV. Y2K Compliance in libpng
May 11, 2011
May 13, 2011
Since the PNG Development group is an ad-hoc body, we can't make
an official declaration.
@ -5402,7 +5597,7 @@ possible without all of you.
Thanks to Frank J. T. Wojcik for helping with the documentation.
Libpng version 1.5.3beta08 - May 11, 2011:
Libpng version 1.5.3beta08 - May 13, 2011:
Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
@ -5425,7 +5620,7 @@ this sentence.
This code is released under the libpng license.
libpng versions 1.2.6, August 15, 2004, through 1.5.3beta08, May 11, 2011, are
libpng versions 1.2.6, August 15, 2004, through 1.5.3beta08, May 13, 2011, are
Copyright (c) 2004,2006-2007 Glenn Randers-Pehrson, and are
distributed according to the same disclaimer and license as libpng-1.2.5
with the following individual added to the list of Contributing Authors
@ -5524,7 +5719,7 @@ certification mark of the Open Source Initiative.
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
May 11, 2011
May 13, 2011
.\" end of man page

16
png.h
View File

@ -1,7 +1,7 @@
/* png.h - header file for PNG reference library
*
* libpng version 1.5.3beta08 - May 11, 2011
* libpng version 1.5.3beta08 - May 13, 2011
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@ -11,7 +11,7 @@
* Authors and maintainers:
* 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.97, January 1998, through 1.5.3beta08 - May 11, 2011: Glenn
* libpng versions 0.97, January 1998, through 1.5.3beta08 - May 13, 2011: Glenn
* See also "Contributing Authors", below.
*
* Note about libpng version numbers:
@ -182,7 +182,7 @@
*
* This code is released under the libpng license.
*
* libpng versions 1.2.6, August 15, 2004, through 1.5.3beta08, May 11, 2011, are
* libpng versions 1.2.6, August 15, 2004, through 1.5.3beta08, May 13, 2011, are
* Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
* distributed according to the same disclaimer and license as libpng-1.2.5
* with the following individual added to the list of Contributing Authors:
@ -294,7 +294,7 @@
* Y2K compliance in libpng:
* =========================
*
* May 11, 2011
* May 13, 2011
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
@ -357,7 +357,7 @@
/* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.5.3beta08"
#define PNG_HEADER_VERSION_STRING \
" libpng version 1.5.3beta08 - May 11, 2011\n"
" libpng version 1.5.3beta08 - May 13, 2011\n"
#define PNG_LIBPNG_VER_SONUM 15
#define PNG_LIBPNG_VER_DLLNUM 15
@ -1400,7 +1400,11 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr));
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* Handle alpha and tRNS by replacing with a background color. */
/* Handle alpha and tRNS by replacing with a background color. Prior to
* libpng-1.5.3 this API must not be called before the PNG file header has been
* read. Doing so will result in unexpected behavior and possible warnings or
* errors int the PNG file contains a bKGD chunk.
*/
PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
int need_expand, double background_gamma));

View File

@ -947,30 +947,38 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
}
#endif
{
png_uint_16 red_int, green_int;
if (red < 0 || green < 0)
if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
{
red_int = 6968; /* .212671 * 32768 + .5 */
green_int = 23434; /* .715160 * 32768 + .5 */
}
png_uint_16 red_int, green_int;
else if (red + green < 100000L)
{
red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
png_ptr->rgb_to_gray_red_coeff = red_int;
png_ptr->rgb_to_gray_green_coeff = green_int;
png_ptr->rgb_to_gray_blue_coeff =
(png_uint_16)(32768 - red_int - green_int);
}
else
{
png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
red_int = 6968;
green_int = 23434;
}
if (red >= 0 && green >= 0)
png_warning(png_ptr,
"ignoring out of range rgb_to_gray coefficients");
png_ptr->rgb_to_gray_red_coeff = red_int;
png_ptr->rgb_to_gray_green_coeff = green_int;
png_ptr->rgb_to_gray_blue_coeff =
(png_uint_16)(32768 - red_int - green_int);
/* Use the defaults, from the cHRM chunk if set, else the built in Rec
* 709 values (which correspond to sRGB, so we don't have to worry
* about the sRGB chunk!)
*/
if (png_ptr->rgb_to_gray_red_coeff == 0 &&
png_ptr->rgb_to_gray_green_coeff == 0 &&
png_ptr->rgb_to_gray_blue_coeff == 0)
{
png_ptr->rgb_to_gray_red_coeff = 6968; /* .212671 * 32768 + .5 */
png_ptr->rgb_to_gray_green_coeff = 23434; /* .715160 * 32768 + .5 */
png_ptr->rgb_to_gray_blue_coeff = 2366;
}
}
}
}

View File

@ -1020,6 +1020,33 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
#endif /* PNG_READ_sRGB_SUPPORTED */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
/* Store the _white values as default coefficients for the rgb to gray
* operation if it is supported.
*/
if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
{
/* png_set_background has not been called, the coefficients must be in
* range for the following to work without overflow.
*/
if (y_red <= (1<<17) && y_green <= (1<<17) && y_blue <= (1<<17))
{
/* The y values are chromaticities: Y/X+Y+Z, the weights for the gray
* transformation are simply the normalized Y values for red, green and
* blue scaled by 32768.
*/
png_uint_32 w = y_red + y_green + y_blue;
png_ptr->rgb_to_gray_red_coeff = (png_uint_16)(((png_uint_32)y_red *
32768)/w);
png_ptr->rgb_to_gray_green_coeff = (png_uint_16)(((png_uint_32)y_green
* 32768)/w);
png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(((png_uint_32)y_blue *
32768)/w);
}
}
#endif
png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
x_green, y_green, x_blue, y_blue);
}
@ -1544,6 +1571,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
png_size_t truelen;
png_byte buf[6];
png_color_16 background;
png_debug(1, "in png_handle_bKGD");
@ -1600,7 +1628,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
*/
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
png_ptr->background.index = buf[0];
background.index = buf[0];
if (info_ptr && info_ptr->num_palette)
{
@ -1610,33 +1638,36 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
png_ptr->background.red =
(png_uint_16)png_ptr->palette[buf[0]].red;
png_ptr->background.green =
(png_uint_16)png_ptr->palette[buf[0]].green;
png_ptr->background.blue =
(png_uint_16)png_ptr->palette[buf[0]].blue;
background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
}
else
background.red = background.green = background.blue = 0;
background.gray = 0;
}
else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
{
png_ptr->background.red =
png_ptr->background.green =
png_ptr->background.blue =
png_ptr->background.gray = png_get_uint_16(buf);
background.index = 0;
background.red =
background.green =
background.blue =
background.gray = png_get_uint_16(buf);
}
else
{
png_ptr->background.red = png_get_uint_16(buf);
png_ptr->background.green = png_get_uint_16(buf + 2);
png_ptr->background.blue = png_get_uint_16(buf + 4);
background.index = 0;
background.red = png_get_uint_16(buf);
background.green = png_get_uint_16(buf + 2);
background.blue = png_get_uint_16(buf + 4);
background.gray = 0;
}
png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
png_set_bKGD(png_ptr, info_ptr, &background);
}
#endif