NAME

Image::PNG::Libpng - Perl interface to the C library "libpng".

SYNOPSIS

use Image::PNG::Libpng ':all';
my $png = create_read_struct ();
open my $file, '<:raw', 'nice.png';
$png->init_io ($file);
$png->read_png ();
close $file;

DESCRIPTION

This is a low-level library for accessing the contents of PNG graphics. PNG means Portable Network Graphics and it is a common standard for graphics.

Image::PNG::Libpng enables Perl to use the "libpng" library for reading and writing files in the PNG format. Image::PNG::Libpng does not contain "libpng". "libpng" must be installed on the computer prior to installing Image::PNG::Libpng.

Image::PNG::Libpng consists of Perl subroutines which mirror the C functions in libpng, plus helper subroutines to make it easier to read and write PNG data in Perl.

For those familiar with libpng, to know what the differences between this module and libpng are, please go to the section "Differences from libpng". For those not familiar with libpng, the module basically mirrors the C interface of libpng. An extension of this module, Image::PNG, is intended to give a more intuitive interface to the library.

FUNCTIONS

Most of these functions can also be used as methods, with the return value of "create_read_struct" and "create_write_struct" as arguments.

Simple input and output

These are convenience functions which combine common operations. They don't have equivalents in libpng.

read_png_file

my $png = read_png_file ('nice.png');

Open a file nice.png and read its contents into $png.

This combines "create_read_struct", open, "init_io", and "read_png". The return value is the same as that of "create_read_struct" with the entire PNG image already read in.

write_png_file

$png->write_png_file ('nice.png');

This combines open, "init_io", and "write_png" to write an entire PNG image out to a file. $png must be the object created by "create_write_struct", so "read_png_file" followed by a call to this does not work.

read_from_scalar

my $png = read_from_scalar ($string);

This creates an image structure $png from the contents of a Perl scalar variable $string containing a PNG image. The first argument, $png, is a PNG structure created with "create_read_struct". It reads in all the data from the structure on being called.

This is useful when image data is stored in a Perl scalar. For example

use Image::PNG::Libpng 'read_from_scalar';
use LWP::Simple;
my $image_data = get 'http://libpng.org/pub/png/img_png/libpng-88x31.png';
# Now $image_data contains the PNG file
my $png = read_from_scalar ($image_data);
# Now $png contains the PNG information from the image.
# Get the header.
my $header = $png->get_IHDR ();
printf "Your PNG has width %d and height %d\n", $header->{width}, $header->{height};

See also "Input/output manipulation functions".

write_to_scalar

my $image_data = $png->write_to_scalar ();

This writes the PNG image data in $png into a Perl scalar. So, for example,

# This CGI script prints a PNG in a random colour.

use Image::PNG::Libpng ':all';
use Image::PNG::Const ':all';
my $png = create_write_struct ();
my $size = 100;
$png->set_IHDR ({height => $size, width => $size, bit_depth => 8,
                 color_type => PNG_COLOR_TYPE_RGB});
my $bytes = pack "CCC", randcol (), randcol (), randcol ();
my @rows = ($bytes x $size) x $size;
$png->set_rows (\@rows);
my $img = $png->write_to_scalar ();
binmode STDOUT;
print "Content-Type:image/png\r\n\r\n$img";
exit;
sub randcol
{
    return int (rand () * 0x100);
}

The first argument, $png, is a writeable PNG structure created with "create_write_struct". The return value of the subroutine is the Perl scalar containing the image data.

See also "Input/output manipulation functions".

New-like functions

There are two different "new"-like functions, depending on whether you want to read or write a PNG.

create_read_struct

my $png = create_read_struct ();

Create a structure for reading a PNG. The return value can be used as an object with the other functions as methods.

Correspondence to libpng:

This function corresponds to png_create_read_struct plus create_info_struct (see "No info structure") with the error and warning handler variables set up to use Perl's error reporting.

create_write_struct

my $png = create_write_struct ();

Create a structure for writing a PNG. This can be used as an object with the other functions as methods.

Correspondence to libpng:

This function corresponds to png_create_write_struct plus create_info_struct (see "No info structure") with the error and warning handler variables set up to use Perl's error reporting.

Input and output libpng style

These functions mirror libpng's functions.

init_io

open my $file, "<", 'nice.png';
$png->init_io ($file);

Set the file which $png reads or writes to $file. $file must be an already-opened Perl file handle. If $png was created with create_write_struct, $file must be opened for writing. If $png was created with create_read_struct, $file must be open for reading.

Since PNG files are binary files, it is safest to specify the "raw" pragma or use "binmode" with the file to override any default text file encoding which Perl might be using:

open my $file, ">:raw", 'output.png';

or

open my $file, ">", 'output.png';
binmode $file;

Correspondence to libpng:

This function corresponds to png_init_io, with a Perl file handle substituting for the C FILE *.

read_png

$png->read_png ();

Read the entire PNG file into memory.

You can provide an argument containing transformations to apply to the image:

use Image::PNG::Const qw/PNG_TRANSFORM_STRIP_ALPHA/;
$png->read_png (PNG_TRANSFORM_STRIP_ALPHA);

If the argument is omitted, the default value of PNG_TRANSFORM_IDENTITY (the "do nothing" value) is applied. The possible transformations which can be applied are

PNG_TRANSFORM_IDENTITY

No transformation

PNG_TRANSFORM_STRIP_16

Strip 16-bit samples to 8 bits

PNG_TRANSFORM_STRIP_ALPHA

Discard the alpha channel

PNG_TRANSFORM_PACKING

Expand 1, 2 and 4-bit samples to bytes

PNG_TRANSFORM_PACKSWAP

Change order of packed pixels to LSB first

PNG_TRANSFORM_EXPAND

Expand paletted images to RGB, grayscale to 8-bit images and tRNS chunks to alpha channels

PNG_TRANSFORM_INVERT_MONO

Invert monochrome images

PNG_TRANSFORM_SHIFT

Normalize pixels to the sBIT depth

PNG_TRANSFORM_BGR

Flip RGB to BGR, RGBA to BGRA

PNG_TRANSFORM_SWAP_ALPHA

Flip RGBA to ARGB or GA to AG

PNG_TRANSFORM_INVERT_ALPHA

Change alpha from opacity to transparency

PNG_TRANSFORM_SWAP_ENDIAN

Byte-swap 16-bit samples

Correspondence to libpng:

This function corresponds to png_read_png with a default value for the third argument. The fourth, unused, argument to png_read_png does not need to be supplied. See "Unused arguments omitted".

It does not take a second "info" argument. See "No info structure".

write_png

$png->write_png ();

This writes the PNG to the file stream which was associated with it using "init_io". For example,

open my $output, ">:raw", 'out.png';
$png->init_io ($output);
$png->write_png ();
close $output;

An optional argument consists of transformations to apply to the PNG image before writing it:

use Image::PNG::Const qw/PNG_TRANSFORM_STRIP_ALPHA/;
$png->write_png (PNG_TRANSFORM_STRIP_ALPHA);

The transformations which can be applied are as follows:

PNG_TRANSFORM_IDENTITY

No transformation

PNG_TRANSFORM_STRIP_16

Strip 16-bit samples to 8 bits

PNG_TRANSFORM_STRIP_ALPHA

Discard the alpha channel

PNG_TRANSFORM_PACKING

Expand 1, 2 and 4-bit samples to bytes

PNG_TRANSFORM_PACKSWAP

Change order of packed pixels to LSB first

PNG_TRANSFORM_EXPAND

Expand paletted images to RGB, grayscale to 8-bit images and tRNS chunks to alpha channels

PNG_TRANSFORM_INVERT_MONO

Invert monochrome images

PNG_TRANSFORM_SHIFT

Normalize pixels to the sBIT depth

PNG_TRANSFORM_BGR

Flip RGB to BGR, RGBA to BGRA

PNG_TRANSFORM_SWAP_ALPHA

Flip RGBA to ARGB or GA to AG

PNG_TRANSFORM_INVERT_ALPHA

Change alpha from opacity to transparency

PNG_TRANSFORM_SWAP_ENDIAN

Byte-swap 16-bit samples

(NOTE: this list might be wrong, it is just copied from the linux lib pages & the linux lib pages have different transformations for the read and write png functions.)

Correspondence to libpng:

This function corresponds to png_write_png.

The image header

See http://www.w3.org/TR/PNG/#11IHDR for information on the PNG standards for the image header.

sig_cmp

if (sig_cmp ($should_be_png)) {
    print "Your data does not have a PNG signature.\n";
}

This subroutine looks at $should_be_png and checks whether its first bytes correspond to a valid PNG signature. It returns a true value if they do not.

It can also take two further arguments consisting of a byte offset and a number of bytes to check respectively:

sig_cmp ($should_be_png, 0, 8);

If these arguments are not supplied, the byte offset is assumed to be zero, and the number of bytes to check is assumed to be eight.

Correspondence to libpng:

This function corresponds to png_sig_cmp, with default arguments of 0 and 8 if second and third arguments are not supplied.

get_valid

my $valid = $png->get_valid ();
if ($valid->{oFFs}) {
    print "The PNG has valid screen offsets.\n";
}

This function returns a hash with a key for each possible chunk which may or may not be valid. The chunks which you can test for are

bKGD
cHRM
gAMA
hIST
hIST
iCCP
IDAT
IHDR
iTXt
oFFs
pCAL
pHYs
PLTE
sBIT
sCAL
sPLT
sRGB
tEXt
tIME
tRNS
zTXt

The first argument, $png, is a PNG structure created with "create_read_struct".

Correspondence to libpng:

This function corresponds to png_get_valid, with the difference being that the return value is a hash containing a key for each possible chunk.

get_IHDR

my $IHDR = $png->get_IHDR ();

Read the IHDR information from the PNG file. The return value is a reference to a hash.

The hash reference contains the following fields:

width

The width of the image in pixels. This cannot be zero, negative, or omitted.

height

The height of the image in pixels. This cannot be zero, negative, or omitted.

bit_depth

The bit depth of the image (the number of bits used for each colour in a pixel). This cannot be omitted. This can take the values 1, 2, 4, 8, 16.

color_type

The colour type. This cannot be omitted. This can take the values PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA.

interlace_method

The method of interlacing. If this is omitted, it's set to PNG_INTERLACE_NONE. This can take the values PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7.

So, for example, to get the width and height of an image,

my $ihdr = $png->get_IHDR ();
printf "Your image is %d x %d\n", $ihdr->{width}, $ihdr->{height};

Correspondence to libpng:

This function corresponds to png_get_IHDR, with a single Perl hash reference used instead of the several pointers to integers used in libpng.

set_IHDR

my $ihdr = { width => 10, height => 10, bit_depth => 8,
             color_type => PNG_COLOR_TYPE_RGB };
$png->set_IHDR ($ihdr);

Set the IHDR chunk (the image header) of the PNG image.

The first argument, $png, is a writeable PNG structure created with "create_write_struct". The second argument is a hash with the following values:

width

The width of the image in pixels. This cannot be zero, negative, or omitted.

height

The height of the image in pixels. This cannot be zero, negative, or omitted.

bit_depth

The bit depth of the image (the number of bits used for each colour in a pixel). This cannot be omitted. This can have the values 1, 2, 4, 8, 16.

color_type

The colour type. This cannot be omitted. This can have the values PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA.

interlace_method

The method of interlacing. If this is omitted, it's set to PNG_INTERLACE_NONE. This can have the values PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7.

Other fields in the hash are ignored.

Correspondence to libpng:

This function corresponds to png_set_IHDR, with a single Perl hash reference used instead of the seven integers. The variables compression_method, filter_method, in png_set_IHDR can only take one possible value, so the routine ignores them. See "Unused arguments omitted".

get_color_type

my $color_type;
$png->get_color_type (\$color_type);

This returns an integer value. If you want to get a name for the colour type, use "color_type_name".

Correspondence to libpng:

This function corresponds to png_get_color_type.

color_type_name

$name = color_type_name ($color_type);

Given a numerical colour type in $color_type, return the equivalent name. The name is in upper case, with words separated by underscores, as in RGB_ALPHA.

use Image::PNG::Libpng ':all';
my $png = read_png_file ('tantei-san.png');
my $name = color_type_name ($png->get_IHDR->{color_type});
print "Your PNG has colour type $name.\n";

Correspondence to libpng:

This function does not correspond to anything in libpng. The names of the colour types are taken from those defined in the libpng header file, png.h.

Image data

These functions deal with accessing the image data itself.

get_rows

my $rows = $png->get_rows ();
my $pixel = substr ($rows->[10], 20, 1);

This returns the rows of the PNG image, after uncompressing and unfiltering, as binary data. The return value, $rows in the example, is an array reference with a number of rows equal to the height of the PNG image. Each row consists of the actual binary data, which you will need to cut out using a routine like substr or unpack to access pixel values. This binary data is likely to contain bytes equal to zero.

You can get the number of bytes in each row using "get_rowbytes".

Each row is a Perl string. Perl terminates each row of data with an extra zero byte at the end.

Correspondence to libpng:

This function corresponds to png_get_rows.

set_rows

$png->set_rows (\@rows);

Set the rows of data to be written in to the PNG to @rows. @rows needs to contain at least the same number of rows of data as the height of the PNG image, and the length of each entry needs to be at least the width of the entry times the number of bytes required for each pixel.

set_rows does not copy the row data, it just tells libpng where the data is to be found. Thus, if you call this routine as above with an array @rows, then you alter the contents of @rows, then call "write_png", the contents written by write_png will be the contents of @rows at the time you called write_png, rather than the contents at the time you called set_rows. Thus I recommend that you only use this immediately before calling "write_png" to prevent odd problems from occuring. (note to self - this is stupid, should just copy the row data).

Correspondence to libpng:

This function corresponds to png_set_rows.

get_rowbytes

my $bytes_in_a_row = $png->get_rowbytes ();

This returns the number of bytes needed to hold a transformed row of an image.

Correspondence to libpng:

This function corresponds to png_get_rowbytes.

PNG timestamps

See http://www.w3.org/TR/PNG/#11timestampinfo for information on the PNG standards for time stamp information.

get_tIME

my $time = $png->get_tIME ();
if ($time && $time->{year} < 2005) {
    warn "Your PNG is now getting old. Don't forget to oil it to prevent rust.";
}

The return value is either the undefined value, if no tIME chunk exists in the PNG, or a hash reference containing fields "year", "month", "day", "hour", "minute" and "second".

The "modification time value" of the PNG image is a chunk written into the PNG file itself, and may not have the same value as the operating system's modification time for the file. The tIME chunk is not a compulsory requirement for PNG files, and most PNG image files do not contain this chunk. PNG tIME chunks do not contain a time zone. "Universal Time (UTC) should be specified rather than local time."

Correspondence to libpng:

This function corresponds to png_get_tIME, with a Perl hash reference substituted for the C struct png_timep used in libpng.

set_tIME

# Set the time to "now"
$png->set_tIME ();
# Set the time
$png->set_tIME ({year => 1999, month => 12});

Set the modification time of the PNG to the values given by the argument, a hash reference containing the fields year, month, day, hour, minute, and second. If the argument is omitted, the time is set to the current time. If any of year, month, day, hour, minute or second is omitted, these are set to zero. PNG tIME chunks do not contain a time zone. "Universal Time (UTC) should be specified rather than local time."

Correspondence to libpng:

This function corresponds to png_set_tIME, with a Perl hash reference substituted for the C struct png_timep used in libpng.

Text chunks

See http://www.w3.org/TR/PNG/#11textinfo for information on the PNG standards for text information.

get_text

my $text_chunks = $png->get_text ();

This subroutine gets all the text chunks in the PNG image and returns them as an array reference. Each element of the array represents one text chunk. The element representing one chunk is a hash reference with the text fields such as "key", "lang_key", "compression" taken from the PNG's information.

The text data is uncompressed by libpng. If it is international text, Image::PNG::Libpng automatically puts it into Perl's internal Unicode encoding (UTF-8).

Note that PNG international text is required to be in the UTF-8 encoding, and non-international text is required to contain whitespace and printable ASCII characters only. See "The PNG specification" for more on the requirements of a PNG text section.

Correspondence to libpng:

This function corresponds to png_get_text, with a Perl array of hash references substituted for the C array of structs used in libpng.

set_text

$png->set_text ($text_chunks);

This sets the text chunks in an array reference $text_chunks. . If it is called more than once, the chunks are not overwritten but appended to the existing ones. (This behaviour is copied from libpng itself.)

$png->set_text ([{compression => PNG_TEXT_COMPRESSION_NONE,
                  key => "Copyright",
                  text => "Copyright (C) 1997 The Dukes of Hazzard",
          }]);

Correspondence to libpng:

This function corresponds to png_set_text.

Private chunks

See http://www.w3.org/TR/PNG/#12Use-of-private-chunks for information on the PNG standards for private chunks.

set_keep_unknown_chunks

use Image::PNG::Const 'PNG_HANDLE_CHUNK_ALWAYS';
$png->set_keep_unknown_chunks (PNG_HANDLE_CHUNK_ALWAYS);

Tell libpng not to discard unknown chunks when reading the file.

get_unknown_chunks

my $private_chunks = $png->get_unknown_chunks ();
# Get some data from a private chunk
my $chunk_three_data = $private_chunks->[3]->{data};
# Get the size of the data
print length $chunk_three_data;

This gets all of the private chunks from the image. The return value is an array reference containing hash references. If there are no private chunks, this returns an undefined value. There is one element of the array for each chunk member. It is necessary to call "set_keep_unknown_chunks" with an appropriate value before reading the file, otherwise libpng discards unknown chunks when reading the file.

Each member hash reference has the following keys:

name

The name of the unknown chunk, in the PNG chunk format (four bytes).

location

The location of the unknown chunk.

data

The data of the unknown chunk

The "size" field of the PNG structure is not stored, because the "data" member of the hash contains information on its length.

Correspondence to libpng:

This function corresponds to png_get_unknown_chunks

set_unknown_chunks

This currently does not fully function.

Correspondence to libpng:

This function corresponds to png_set_unknown_chunks

Helper functions

These helper functions assist the programmer in the transition from libpng, which uses C conventions such as upper case macros standing for numerical constants and C structures, to Perl's string-based conventions.

text_compression_name

my $name = Image::PNG::Libpng::text_compression_name ($text->{compression});

Given a numerical text compression type, return the equivalent name. The name is in upper case. The possible return values are

TEXT_NONE
TEXT_zTXt
ITXT_NONE
ITXT_zTXt
an empty string

if the compression method is unknown.

The compression field is also used to store the information about whether the text is "international text" in UTF-8 or not.

Correspondence to libpng:

This function does not correspond to anything in libpng. The names of the text compression types are based on those in png.h, but without the word "COMPRESSION", so for example the libpng constant PNG_ITXT_COMPRESSION_zTXt corresponds to a return value of ITXT_zTXt.

Library version functions

get_libpng_ver

my $libpng_version = Image::PNG::Libpng::get_libpng_ver ();

This function returns the version of the libpng library which the module is using.

Correspondence to libpng:

This function corresponds to png_get_libpng_ver. However, it doesn't require the png_structp argument of the C function.

access_version_number

my $libpng_version_number = Image::PNG::Libpng::access_version_number ();

This function returns the version of the libpng library which the module is using as an integer number.

Correspondence to libpng:

This function corresponds to png_access_version_number.

Palettes

See http://www.w3.org/TR/PNG/#11PLTE for information on the PNG standards for the palette chunk.

get_PLTE

my $colours = $png->get_PLTE ();
# Get the green value of the twentieth entry in the palette.
my $green = $colours->[20]->{green};

This function gets the palette from the PNG. The return value is an array reference containing the palette. This array contains hash references with the values "green", "blue" and "red" for the colour of each pixel in the palette. If the PNG has no palette, it returns an undefined value.

A PNG image may or may not contain a palette. To check whether the image contains a palette, use something of the following form:

use Image::PNG::Const ':all';
my $color_type = $png->get_color_type ();
if ($color_type == PNG_COLOR_TYPE_PALETTE) {
    # The PNG uses a palette.
}

A PNG image may also contain a palette even when the "color_type" does not indicate that. To check for that case, use "get_valid".

Correspondence to libpng:

This function corresponds to png_get_PLTE.

set_PLTE

$png->set_PLTE ($palette);

Set the palette of $png. The argument is an array reference containing hash references. There is one hash reference for each palette entry. The hash references contain three fields, red, green, and blue, corresponding to the pixel value for that palette entry. Other values in the hash references are ignored. For example,

$png->set_PLTE ([{red => 1, green => 99, blue => 0x10},
                 {red => 0xFF, green => 0xFF, blue => 0xFF}]);

creates a palette with two entries in $png.

Correspondence to libpng:

This function corresponds to png_set_PLTE.

Compression and filtering

set_filter

use Image::PNG::Const 'PNG_FILTER_NONE';
$png->set_filter (PNG_FILTER_NONE);

This sets the filters which are allowed to be used for writing a PNG image. The possible values are

PNG_NO_FILTERS
PNG_FILTER_NONE
PNG_FILTER_SUB
PNG_FILTER_UP
PNG_FILTER_AVG
PNG_FILTER_PAETH
PNG_ALL_FILTERS

These can be combined using | (logical or):

use Image::PNG::Const ':all';
set_filter ($png, PNG_FILTER_UP | PNG_FILTER_AVG);

Please see http://www.w3.org/TR/PNG/#9Filter-types for the meanings of these filter types.

Correspondence to libpng:

This function corresponds to png_set_filter with the second (unused) argument omitted. See "Unused arguments omitted".

Other chunks

These routines deal with the other possible chunks of PNGs.

The getter and setter routines for all other chunks are designed so that the return value of get_wXYZ is able to be used directly as the value for set_wXYZ, so the values of chunks can easily be copied from one PNG to another.

my $values = $png1->get_wXYZ ();
$png2->set_wXYZ ($values);

If the chunk is not present, or if the chunk is not supported by the user's version of libpng, the return value of get_wXYZ is the undefined value.

bKGD

The background colour of the PNG image.

See http://www.w3.org/TR/PNG/#11bKGD for information on the PNG standards for the background chunk.

get_bKGD

my $bkgd = $png->get_bKGD ();

Get the bKGD (background) chunk of the image.

The return value is a hash with the following keys, depending on the colour type of the image:

index

For palette colour types, this is the offset into the palette.

gray

For greyscale colour types.

red
green
blue

Correspondence to libpng:

This function corresponds to png_get_bKGD with a hash function instead of a png_color struct.

set_bKGD

$png->set_bKGD ($bkgd);

Set the bKGD (background) chunk of the image. $bkgd is a hash reference. The keys of the hash reference are as described in "get_bKGD".

Correspondence to libpng:

This function corresponds to png_set_bKGD with a hash function instead of a png_color struct.

cHRM

See http://www.w3.org/TR/PNG/#11cHRM "cHRM Primary chromaticities and white point" of the PNG specification.

get_cHRM

my %cHRM = $png->get_cHRM ();

Get the cHRM chunk as a hash.

The keys of the hash are

white_x
white_y
red_x
red_y
green_x
green_y
blue_x
blue_y

The values of the hash are floating point numbers between 0 and 1.

Correspondence to libpng:

This function corresponds to png_get_cHRM with a hash function instead of the double arguments. The hash key names correspond to the names of the double arguments in libpng.

set_cHRM

$png->set_cHRM (\%cHRM);

Set the cHRM chunk from a hash.

The keys of the hash are

white_x
white_y
red_x
red_y
green_x
green_y
blue_x
blue_y

The values of the hash are floating point numbers between 0 and 1.

Correspondence to libpng:

This function corresponds to png_set_cHRM with a hash function instead of the double arguments.

gAMA

See http://www.w3.org/TR/PNG/#11gAMA of the PNG specification.

get_gAMA

my $gamma = $png->get_gAMA ();

Get the gamma value or gAMA chunk. The return value is a floating-point number.

Correspondence to libpng:

This function corresponds to png_get_gAMA

set_gAMA

$png->set_gAMA (0.2);

Set the gamma value or gAMA chunk.

Correspondence to libpng:

This function corresponds to png_set_gAMA

sRGB

See http://www.w3.org/TR/PNG/#11sRGB of the PNG specification.

get_sRGB

my $sRGB = $png->get_sRGB ();

The return value is an integer number corresponding to one of the following:

PNG_sRGB_INTENT_SATURATION
PNG_sRGB_INTENT_PERCEPTUAL
PNG_sRGB_INTENT_ABSOLUTE
PNG_sRGB_INTENT_RELATIVE

Correspondence to libpng:

This function corresponds to png_get_sRGB

set_sRGB

$png->set_sRGB ($srgb);

$srgb is one of the following (integer numbers).

PNG_sRGB_INTENT_SATURATION
PNG_sRGB_INTENT_PERCEPTUAL
PNG_sRGB_INTENT_ABSOLUTE
PNG_sRGB_INTENT_RELATIVE

Correspondence to libpng:

This function corresponds to png_set_sRGB

pHYs

See http://www.w3.org/TR/PNG/#11pHYs of the PNG specification.

get_pHYs

my $phys = $png->get_pHYs ();

The return value is a hash reference with the keys

res_x
res_y
unit_type

Correspondence to libpng:

This function corresponds to png_get_pHYs

set_pHYs

$png->set_pHYs ({res_x => 1, res_y => 1, unit_type => 99});

Correspondence to libpng:

This function corresponds to png_set_pHYs

oFFs

This is an extension to the PNG specification. See http://www.libpng.org/pub/png/spec/1.1/pngext-1.1.0-pdg.html#C.oFFs.

get_oFFs

my $phys = $png->get_oFFs ();

Get oFFs chunk. Return value is a hash reference

Correspondence to libpng:

This function corresponds to png_get_oFFs

set_oFFs

$png->set_oFFs ({x_offset => 1, y_offset => 1, unit_type => 99});

Set oFFs chunk.

Correspondence to libpng:

This function corresponds to png_set_oFFs

sBIT

See http://www.w3.org/TR/PNG/#11sBIT of the PNG specification.

get_sBIT

my $sbit = $png->get_sBIT ();

This is implemented but untested.

Correspondence to libpng:

This function corresponds to png_get_sBIT

set_sBIT

$png->set_sBIT ({red => 1, blue => 2, green => 3});

This is implemented but untested.

Correspondence to libpng:

This function corresponds to png_set_sBIT

iCCP

See http://www.w3.org/TR/PNG/#11iCCP of the PNG specification.

get_iCCP

my $iccp = $png->get_iCCP ();

The return value is a hash with two keys,

name

The name of the profile.

profile

The colour profile.

Correspondence to libpng:

This function corresponds to png_get_sCCP

set_iCCP

$png->set_iCCP ({name => 'name', profile => 'profile'});

Correspondence to libpng:

This function corresponds to png_set_sCCP

pCAL

pCAL is an extension of the PNG specification. See http://www.libpng.org/pub/png/spec/1.1/pngext-1.1.0-pdg.html#C.pCAL.

get_pCAL

my $pcal = $png->get_pCAL ();

Implemented but not tested. Return value is a hash with the following keys:

purpose

The purpose string of the pCAL chunk.

x0

The zero value for the equation.

x1

The max value for the equation.

type

The equation type as a number.

units

The units as a string.

params

If this exists its value is a reference to an array containing the parameter list of the pCAL chunk.

Correspondence to libpng:

This function corresponds to png_get_pCAL

set_pCAL

$png->set_pCAL ($values);

Implemented but not tested. The input is just the same as the output of "get_pCAL".

Correspondence to libpng:

This function corresponds to png_set_pCAL

hIST

See http://www.w3.org/TR/PNG/#11hIST of the PNG specification.

get_hIST

my $hist = $png->get_hIST ();

Return value is array reference. The number of entries in the array reference is the same as in the palette.

Correspondence to libpng:

This function corresponds to png_get_hIST

set_hIST

$png->set_hIST (\@hist);

Set the histogram.

Correspondence to libpng:

This function corresponds to png_set_hIST

UNIMPLEMENTED CHUNKS

These chunks have skeleton routines but the actual reading and writing code is not yet implemented.

sCAL

This is an extension to the PNG specification. See http://www.libpng.org/pub/png/spec/1.1/pngext-1.1.0-pdg.html#C.sCAL.

get_sCAL

Not implemented.

set_sCAL

Not implemented.

tRNS

See http://www.w3.org/TR/PNG/#11tRNS of the PNG specification.

get_tRNS

Not implemented.

set_tRNS

Not implemented.

sPLT

See http://www.w3.org/TR/PNG/#11sPLT of the PNG specification.

get_sPLT

Not implemented.

set_sPLT

Not implemented.

META FUNCTIONS

These functions enable examination of the installed libpng from Perl.

libpng_supports

if (libpng_supports ('iTXt')) {
    print "Your libpng supports international text.\n";
}

This function returns true or false depending on whether the version of libpng which this was compiled with supports or does not support a particular facility.

The possible arguments to libpng_supports are

iTXt

Does the libpng support international text?

tEXt

Does the libpng support text?

zTXt

Does the libpng support compressed text?

ACCESS FUNCTIONS

These functions are used to access parts of the $png object itself.

get_internals

my ($png_struct, $png_info) = get_internals ($png);

This allows writers of XS extensions to Image::PNG::Libpng access to the internal png_structp and png_infop contained in $png. The return value is a list containing the png_structp as the first argument and the png_infop as the second argument, wrapped up as references to objects of type Image::PNG::Libpng::png_struct and Image::PNG::Libpng::png_info.

To access the values of the actual pointers from XS, use something like the following:

    void access_png_internals (png, info)
	SV * png;
	SV * info;
    PREINIT:
	png_struct * cpng;
	png_info * cinfo;
    CODE:
	cpng = INT2PTR (png_struct *, SvIV ((SV *) SvRV (png)));
	cinfo = INT2PTR (png_info *, SvIV ((SV *) SvRV (info)));

An example exists in Image::PNG::Cairo.

set_transforms

$png->set_transforms (PNG_TRANSFORM_BGR);

Set transforms for reading and writing. This is the same as the optional argument to "read_png" or "write_png". If both this and the optional argument are given, the optional argument overrides what is set here.

set_row_pointers

$png->set_row_pointers ($row_pointers);

This is a routine which allows an XS module communicating with Image::PNG::Libpng to directly set the value of the row pointers for the PNG image. This is then freed by Image::PNG::Libpng using Perl's Safefree when $png is destroyed. Because the freeing uses Safefree, it's better to use Newx to allocate the memory rather than malloc.

The Perl scalar $row_pointers should be set up something like the following (where rp is the C pointer):

RETVAL = newSV (0);
xv_setref_pv (RETVAL, "Image::PNG::Libpng::row_pointers", rp);

It's extracted from the Perl scalar using

rp = INT2PTR (png_byte **, (SV *) SvRV (row_pointers));

where row_pointers is the SV * corresponding to $row_pointers in the Perl script.

EXPORTS

Nothing is exported by default, but all the functions in this module can be exported on request. The export tag 'all' exports everything in the module:

use Image::PNG::Libpng ':all';
# Now everything in the module has been imported

Differences from libpng

The functions in Image::PNG::Libpng are closely based on those of libpng, with the following differences.

No info structure

This module, Image::PNG::Libpng does not use the "info" structure of libpng. Almost all libpng functions require two initial arguments, a png_structp and a png_infop. However, in Image::PNG::Libpng, both the "png" and the "info" are contained in the first argument to each function.

Unused arguments omitted

This module eliminates all the unevaluated arguments of libpng. For example, libpng requires the user to pass a pointer to a png_struct before calling the library to ask for its version number (see "get_libpng_ver"), but the library ignores the this structure anyway, so this module does not duplicate this. There are many similar instances of unevaluated arguments, which have all been eliminated from this module.

If you are interested in exactly which libpng arguments are omitted, you can find each instance in the file perl-libpng.c in the top directory of the distribution in the macro UNUSED_ZERO_ARG.

Function return values are used to return values

In libpng, some functions return results using references, and some return results using the function's return value. For example png_get_rows (see "get_rows") uses the return value of the function to return an array of pointers, but png_get_PLTE (see "get_PLTE") uses a pointer reference to return an array of pointers, and the return value to indicate errors.

Image::PNG::Libpng uses only the return value. Errors and non-existence are indicated by a return value of the undefined value.

In libpng, some functions use the return value to indicate errors, and some of the functions don't indicate errors but fail silently. Some of the functions which use the return value to indicate an error use a non-zero value to indicate an error, and some of them use a zero value to indicate an error.

No destructors

Freeing the memory allocated by "create_read_struct" and "create_write_struct" is automatically handled by Perl.

Older versions of this module (pre-0.18) had functions called destroy_read_struct and destroy_write_struct corresponding to the functions with similar names in libpng. From version 0.18, these functions still exist, but they no longer do anything. The memory freeing is now handled by Perl automatically.

Other unimplemented parts of libpng

Memory management functions

This module does not offer an interface to png_malloc and png_free.

Error handling functions

This module does not offer an interface to png_error and png_get_error_ptr. It redirects the error and warning handlers to Perl's error stream.

Input/output manipulation functions

This module does not offer a direct interface to png_set_write_fn and png_set_read_fn. However, it is possible to use their functionality to access Perl data via "read_from_scalar" and "write_to_scalar".

Partial read/write functions

This module does not yet offer an interface to the partial read and write functions of libpng. The reason is because I don't know enough about Perl's internal structures to be able to create a memory-safe interface to these functions. The partial read/write functions would rely on preserving pointers to data structures within the Perl program's data area between calls. So this module doesn't deal with png_write_chunk, png_write_end, png_write_info, png_write_row, or png_write_rows.

Other unsupported functions

All libpng deprecated functions are not supported.

Other unsupported functions include

png_set_crc_action
png_set_sig_bytes
png_get_compression_buffer_size
png_set_compression_buffer_size
png_set_write_status_fn
png_set_unknown_chunk_location
png_set_check_for_invalid_index
png_set_benign_errors
png_benign_error
png_chunk_benign_error
png_get_image_width
png_get_image_height
png_get_bit_depth
png_get_color_type
png_get_interlace_type
png_get_compression_type
png_set_text_compression_strategy
png_get_filter_type
png_get_channels
png_get_signature
png_get_progressive_ptr
png_set_filter_heuristics
png_set_quantize
png_set_tRNS_to_alpha

Unfortunately there are a raft of functions in libpng, many completely undocumented.

DIAGNOSTICS

The module may produce the following error or warning messages. Errors are marked "(F)" and warnings are marked "(W)".

libpng error: %s

(F) An error from libpng sent via Perl's warning handler.

libpng warning: %s

(W) A warning from libpng sent via Perl's warning handler.

%s:%d: Call to calloc for %d '%s' failed: out of memory

(F) A request for more memory was refused. The first two parameters are the file name and line number of where this happened.

Memory leak detected: there are %d allocated pieces of memory which have not been freed.

(W) The module's internal check for memory errors was tripped somehow. This probably indicates a bug in the module.

Attempt to destroy an object of unknown type

(F) There was an attempt to free some corrupted memory.

According to its compression type, a text chunk in the current PNG file claims to be ITXT but Perl's 'is_utf8_string' says that its encoding is invalid.

(W)

A language key 'lang_key' member of a 'png_text' structure in the file failed Perl's 'is_utf8_string' test, which says that its encoding is invalid.

(W)

None of your text chunks was allowed

(W) The user tried to set some text chunks in the image but they were not allowed.

Trying to read from a PNG in memory but there is no PNG in memory

(F) Something went wrong trying to read a PNG from a Perl scalar. This probably indicates a bug in the program.

Request for too many bytes %d on a scalar of length %d at read position %d.

(F) There was an attempt to read some data from a Perl scalar which went beyond the expected end of the scalar in memory.

Attempt to write PNG without calling init_io

(F) write_png was called before a file handle was associated with the PNG.

set_IHDR: Bad values for width (%d), height (%d), or bit depth (%d)

(F) The user tried to set a PNG header with unacceptable values, as indicated.

set_PLTE: Empty array of colours in set_PLTE

(F) The user tried to set an empty palette of colours.

Too many transparencies %d supplied

(F) The user tried to set more than the maximum possible number of transparencies for a paletted image.

Image has no height

(F) The height of the image is zero.

Image has no rows

(F) The image does not have any rows of image data.

Image rows have zero length

(F) The rows of image data have zero length.

Image has zero height

(F) The image we are trying to read has zero height.

Out of memory allocating %d bytes for image

(F) We were refused the memory we want to read the image into.

Row pointers already allocated

(F) There was an attempt to set the rows of an image after they had already been set.

array has %d rows but PNG image requires %d rows

(F) set_rows was called with an array of the wrong size.

Chunk name '%s' has wrong number of characters: %d required

(F) We tried to set an unknown chunk with a name which doesn't have four characters.

read unknown chunks not supported in this libpng

(W)

Number of unknown chunks is zero

(F) The user tried to set an empty list of unknown chunks.

Non-hash in chunk array

(W)

Illegal PNG chunk name length, chunk names must be %d characters long

(W) The user's name for a private chunk was not a valid length. In this case the chunk is ignored.

write unknown chunks not supported in this libpng

(W)

undefined chunk name at offset %d in chunk list

(F) The chunk name was not defined.

chunk %i has bad length %d: should be %d in chunk list

(F)

set_keep_unknown_chunks is not supported in your libpng

(F) libpng was compiled without this option.

BUGS

This section documents some known deficiencies in the module.

set_rows is unreliable

The method "set_rows" doesn't actually copy or write any information. All it does is set a pointer to the pointers to the rows in the PNG data structure. The actual data is only written when you ask to write it. So if you "set_rows" to some data, then delete or change that data before asking to write the png with "write_png", you will get a memory error.

Conditional compilation

It is possible to compile a version of the libpng library without support for various things. For example, it's possible to have a libpng without support for text chunks by undefining a macro PNG_TEXT_SUPPORTED. The module supports some of the conditional compilation choices which I've found in practice, but it does not support every possible choice. If you encounter problems using this Perl module because of a conditionally-compiled libpng, then please let me know and I'll consider adding that facility to the module.

STANDALONE SCRIPT

A standalone script, pnginspect, is installed with the distribution. It prints out the contents of the chunks of the PNG file on the command line.

SEE ALSO

The PNG specification

The PNG specification (link to W3 consortium) explains the details of the PNG format.

The libpng documentation

"Official" documentation

The starting point is the plain text libpng manual at http://libpng.org/pub/png/libpng-manual.txt and the manual page libpng.3, which you can read using "man 3 libpng".

Be warned that the documentation which comes with libpng is rather sketchy. See "Differences from libpng". It doesn't contain full specifications (prototypes, return values) for all of the functions in the library. If you are considering programming in C using libpng, you will definitely also need to look at the header file "png.h". In some cases you will also need to look at the source code of the library.

Unofficial documentation

There is a collection of function definitions under the title "Interface Definitions for libpng12" at http://refspecs.freestandards.org/LSB_3.1.1/LSB-Desktop-generic/LSB-Desktop-generic/libpng12man.html as part of the "Linux Standard Base Desktop Specification". These contain extensive information on the prototypes and return values for the libpng routines, something which is often only available elsewhere by actually looking at the libpng source code. These pages are usually the first hits on search engines if you search for a function name in libpng.

Other Perl modules on CPAN

These other modules may also be useful.

Image::Size

If you only need to read the sizes of images, Image::Size works with PNG and other image formats.

Image::Info

Image::Info is a module for getting information out of various types of images. It has good support for PNG and is written in pure Perl (doesn't require a C compiler). As well as basics such as height, width, and colour type, it can get text chunks, modification time, palette, gamma (gAMA chunk), resolution (pHYs chunk), and significant bits (sBIT chunk). At the time of writing (version 1.31) it doesn't support other chunks.

Image::ExifTool

Image::ExifTool is a pure Perl (doesn't require a C compiler) solution for accessing the text segments of images. It has extensive support for PNG text segments.

Alien::PNG

Alien::PNG claims to be a way of "building, finding and using PNG binaries". It may help in installing libpng. I didn't use it as a dependency for this module because it seems not to work in batch mode, but stop and prompt the user. I'm interested in hearing feedback from users whether this works or not on various platforms.

Image::PNG::Rewriter

Image::PNG::Rewriter is a utility for unpacking and recompressing the IDAT (image data) part of a PNG image. The main purpose seems to be to recompress the image data with the module author's other module Compress::Deflate7. At the time of writing, that only works with Perl versions 5.12 or later.

Image::Pngslimmer

Image::Pngslimmer reduces the size of dynamically created PNG images. It's very, very slow at reading PNG data, but seems to work OK.

AUTHOR

Ben Bullock, <bkb@cpan.org>

COPYRIGHT & LICENCE

The Image::PNG::Libpng package and associated files are copyright (C) 2014 Ben Bullock.

You can use, copy, modify and redistribute Image::PNG::Libpng and associated files under the Perl Artistic Licence or the GNU General Public Licence.

SUPPORT

Mailing list

There is a mailing list at http://groups.google.com/group/perlimagepng. It is not necessary to be a member of the list to post messages to the list or participate in discussions.

Reporting a bug

There is a bug tracker at https://github.com/benkasminbullock/image-png-libpng/issues.