Image:...Libpng(3pm)
π Image::PNG::Libpng(3pm) β the Perl libpng era π
okay so bestie, buckle up: Image::PNG::Libpng is a Perl module. It's the Perl interface to the C library libpng, and this page is the whole manual for it. Grab a snack, we're going in π
β¨ NAME β¨
Image::PNG::Libpng β Perl interface to the C library libpng. That's it, that's the name, she's iconic and she knows it π
π¦ SYNOPSIS π¦
Two vibes, two flavours. First up, the Libpng-like interface:
use Image::PNG::Libpng ':all';
my $png = create_read_struct ();
open my $file, '<:raw', 'nice.png' or die $!;
$png->init_io ($file);
$png->read_png ();
close $file;
# Get all valid chunks
my $valid = $png->get_valid ();
my @valid_chunks = sort grep {$valid->{$_}} keys %$valid;
print "Valid chunks are ", join (", ", @valid_chunks), "\n";
# Print image information
my $header = $png->get_IHDR ();
for my $k (keys %$header) {
print "$k: $header->{$k}\n";
}
(This example is included as examples/synopsis.pl <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/synopsis.pl> in the distribution.)
Then the Simple interface, for when you literally just wanna get in and get out:
use Image::PNG::Libpng ':all';
my $png = read_png_file ('../t/tantei-san.png');
# Get all valid chunks
my $valid = $png->get_valid ();
my @valid_chunks = sort grep {$valid->{$_}} keys %$valid;
print "Valid chunks are ", join (", ", @valid_chunks), "\n";
# Print image information
my $header = $png->get_IHDR ();
for my $k (keys %$header) {
if ($k eq 'color_type') {
print "$k: " . color_type_name ($header->{$k}) . "\n";
}
else {
print "$k: $header->{$k}\n";
}
}
my $wpng = $png->copy_png ();
$wpng->write_png_file ('new.png');
(This example is included as examples/synopsis-easy.pl <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/synopsis-easy.pl> in the distribution.)
π VERSION π
This document describes Image::PNG::Libpng version 0.60, corresponding to git commit c8b9220ff9731ddfc6ff4b0d5f7bfed775d952fe <https://github.com/benkasminbullock/image-png-libpng/commit/c8b9220ff9731ddfc6ff4b0d5f7bfed775d952fe> at Tue Mar 17 11:06:31 2026 +0900.
Unless otherwise qualified, comments in this document on the libpng source code and documentation refer to libpng version 1.6.45. Libpng is not bundled with this distribution, so your installed version may vary β check yours, no cap π
π DESCRIPTION π
Image::PNG::Libpng is a Perl library for accessing the contents of PNG (Portable Network Graphics) images. It enables Perl to use the libpng library to read and write files in PNG format.
Heads up bestie π βImage::PNG::Libpngdoes not contain the libpng library. Thelibpnglibrary must be installed on your computer prior to installingImage::PNG::Libpng.
So what's inside? 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. She's giving translator, she's giving bridge between worlds π«Ά
And if you already know libpng β like, you've been in those C streets β the section "Differences from libpng" explains the differences with libpng.
π₯ FUNCTIONS π₯
The functions in the module are gathered into the following categories, and yes, we're listing every single one because we don't do half-finished here β¨:
- "Simple input and output" β describes some convenience functions
- "Libpng-style input and output" β describes functions which closely mirror libpng
- "The image header" β describes functions for reading and writing the meta-information about PNG images
- "Image data" β describes functions for accessing the image data itself
- "Text chunks"
- "Private chunks"
- "Library version functions"
- "Compression and filtering"
- "Other chunks"
- "Libpng transformations"
- "Other libpng functions" β functions from libpng which don't fit elsewhere
- "Other functions" β which are functions specific to this module
πΈ Simple input and output πΈ
These convenience functions combine common operations. Real talk: they are not part of the original libpng API. They're the module's own little shortcuts, and honestly? Obsessed.
π copy_png
my $outpng = $png->copy_png ();
Copy a PNG from a read to a write structure. This function bridges two kinds of object β "read a png" objects created by create_read_struct and "write a png" objects created by create_write_struct. It copies all the valid chunks from a read structure to a write structure. Like passing the aux cord, but for chunks π§
The following example demonstrates copying a PNG:
use utf8;
use FindBin '$Bin';
use Image::PNG::Libpng qw(read_png_file write_png_file) ;
my $pngin = read_png_file ("$Bin/../t/tantei-san.png");
my $pngout = $pngin->copy_png ();
$pngout->set_text ([{key => 'Name', text => 'Shunsaku Kudo'}]);
# $pngout->write_png_file ('copy.png');
(This example is included as examples/copy-png.pl <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/copy-png.pl> in the distribution.)
π¦ create_reader
my $png = create_reader ('file.png');
$png->read_png ();
This combines create_read_struct, open, and init_io on the specified file name but does not read the file in. It's for the case that the user wants to apply some kind of transformation first. Like setting up the whole aesthetic before you hit post π
π Setting the background
In the following example, the user sets the background with set_background to replace the alpha channel:
use utf8;
use FindBin '$Bin';
use Image::PNG::Libpng ':all';
use Image::PNG::Const ':all';
my $file = "$Bin/luv.png";
my %color = (red => 0xC0, green => 0xFF, blue => 0xFF);
my $png = create_reader ($file);
$png->set_background (\%color, PNG_BACKGROUND_GAMMA_SCREEN, 0);
$png->read_png ();
my $wpng = copy_png ($png);
$wpng->write_png_file ("$Bin/set-background.png");
(This example is included as examples/set-background.pl <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/set-background.pl> in the distribution.)
examples/luv.png <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/luv.png> is included in the distribution.
examples/set-background.png <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/set-background.png> is included in the distribution.
This function was added to the module in version 0.53.
π§ create_writer
my $png = create_writer ('file.png');
$png->set_IHDR (\%ihdr);
$png->set_rows (\@rows);
$png->write_png ();
This combines create_write_struct, open, and init_io on the specified file name but does not read the file in. It's for the case that the user wants to apply some kind of transformation before writing. Main character energy: prep first, glow-up second β¨
This function was added to the module in version 0.53.
π 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 PNG image data β for example data read from a file, or data obtained from a web page. 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;
use JSON::Create;
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 ();
my $jc = JSON::Create->new (indent => 1, sort => 1);
print $jc->run ($header);
(This example is included as examples/get-www-png.pl <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/get-www-png.pl> in the distribution.)
The output looks like this:
{
"bit_depth":4,
"color_type":3,
"height":31,
"interlace_method":0,
"width":88
}
See also "Input and output manipulation functions".
β read_png_file
my $png = read_png_file ('q.png');
Open q.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. One and done, periodt π
The optional argument to read_png can be specified using an optional transforms argument:
my $png = read_png_file ('file.png', transforms => PNG_TRANSFORM_EXPAND);
croak in Carp is used to signal errors opening or closing the file.
π«Ά 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. (Rude but fair, the inline one wins π)
π 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 the file name specified by the argument.
Careful bestie π β$pngmust be the object created bycreate_write_struct, soread_png_filefollowed by a call to this does not work. Seecopy_pngif you need to do that kind of operation.
The optional argument to write_png can be specified using set_transforms.
croak in Carp is used to signal errors opening or closing the file.
π write_to_scalar
my $image_data = $png->write_to_scalar ();
This writes the PNG image data in $png into a Perl scalar. 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.
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);
}
(This example is included as examples/png-cgi.pl <https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/png-cgi.pl> in the distribution.)
See also "Input and output manipulation functions".
The optional argument to write_png can be specified using set_transforms.
π§ Libpng-style input and output π§
There are two different new-like functions, depending on whether you want to read or write a PNG: create_read_struct and create_write_struct. These are based on the libpng API. Input uses open plus init_io followed by read_png or write_png.
π₯ Examples
A self-pixellating program
β¦and that's exactly where part 1 wraps, bestie β the self-pixellating program is literally about to start in part 2 πΈ
Okay so this next example is literally the whole monochrome-PNG flex: you make a write structure with create_write_struct, open a filehandle to write to, link that filehandle to the PNG structure with init_io, then use write_info, write_image, and write_end to actually push the PNG data into the file. Iconic pipeline, no cap.
use utf8;
use FindBin '$Bin';
use Image::PNG::Libpng ':all';
use Image::PNG::Const ':all';
my $outfile = "$Bin/mono.png";
my ($height, $width, $rows) = pixelate (__FILE__, 5);
my $png = create_write_struct ();
open my $out, ">:raw", $outfile or die $!;
$png->init_io ($out);
$png->set_IHDR ({height => $height, width => $width, bit_depth => 1,
color_type => PNG_COLOR_TYPE_GRAY});
$png->set_text ([{key => 'silly', text => 'finely-tuned breakfast cereal',}]);
$png->set_tIME ({year => 1999});
$png->write_info ();
$png->set_invert_mono ();
# PNG puts the leftmost pixel in the high-order part of the byte.
$png->set_packswap ();
$png->write_image ($rows);
$png->write_end ();
close $out or die $!;
exit;
sub pixelate
{
my ($file, $box) = @_;
open my $in, "<", $file or die "Can't open '$file': $!";
my $width = 0;
my @lines;
while (<$in>) {
chomp;
s/\t/ /g;
push @lines, $_;
if (length ($_) > $width) {
$width = length ($_);
}
}
close $in or die $!;
$width *= $box;
my $height = scalar (@lines) * $box;
my $zero = pack "C", 0;
my $bwidth = int(($width+7)/8);
my @rows = ($zero x $bwidth) x $height;
for my $r (0..$height-1) {
my $y = int ($r/$box);
my $line = $lines[$y];
for my $x (0..length ($line) - 1) {
if (substr ($line, $x, 1) ne ' ') {
for my $c (0..$box - 1) {
my $offset = $x*$box + $c;
my $byte = int ($offset / 8);
my $bit = $offset % 8;
my $octet = ord (substr ($rows[$r], $byte, 1));
substr ($rows[$r], $byte, 1) = chr ($octet | 1<<$bit);
}
}
}
}
return ($height, $width, \@rows);
}
This example is included as examples/libpng-write.pl (https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/libpng-write.pl) in the distribution.
examples/mono.png (https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/mono.png) is included in the distribution too. Cute, right? π
πΈ create_read_struct πΈ
my $png = create_read_struct ();
Make a structure for reading a PNG. The return value can be used as an object with the other functions as methods, and it can be copied to a write structure with copy_png. Bestie, it's giving "read mode main character energy."
This function corresponds to png_create_read_struct in libpng 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 ();
Make a structure for writing a PNG. This can be used as an object with the other functions as methods. Very "I'm the one writing the file" of it.
This function corresponds to png_create_write_struct in libpng plus create_info_struct (see "No info structure") with the error and warning handler variables set up to use Perl's error reporting.
π¦ 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. Match the vibe to the mode, bestie.
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;
This function corresponds to png_init_io in libpng, with a Perl file handle substituting for the C FILE *.
π Caveats when using init_io π
Check the return value of open
On some versions of Perl, init_io may crash in some circumstances with an error like segmentation fault, if you use code like
my $png = create_read_struct ();
open my $file, "<:raw", "some.png";
$png->init_io ($file);
and you do not check whether the call to open was successful, and some.png does not exist. The crash occurs within Perl's conversion of $file into a C FILE * pointer, before this module's code runs. This bug was fixed in Perls after version 5.24.1. To avoid trouble, please check the return value of open. Like, actually check it. Do not just vibe and hope. π
Cannot deal with non-file filehandles
Since init_io is a Perl access to an underlying C function png_init_io, it requires something which can be passed to the underlying C as a FILE *, C's file structure. If, for example, you use IO::String or open a scalar reference as a file handle, since these actions do not create a C file structure, an error of the form scalar's file handle is NULL will occur. Big yikes, but at least it tells you.
If you have a PNG in the form of a Perl scalar, use read_from_scalar instead of init_io, which uses a C function called png_set_read_fn so that the C library can access the data in the Perl scalar. See also "Input and output manipulation functions".
π read_end π
$png->read_end ();
Read the part of the PNG file after the image data. The afterparty part, basically.
This function corresponds to png_read_end in libpng.
β read_image β
my $rows = $png->read_image ();
Read the image data of the PNG file. This is the actual pixels, the main event.
This function corresponds to png_read_image in libpng.
π read_info π
$png->read_info ();
Read the part of the PNG file before the image data. The little pregame info moment.
This function corresponds to png_read_info in libpng.
π read_png π
$png->read_png ();
Read the entire PNG file into memory. All of it. No crumbs left behind.
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_BGRβ Flip RGB to BGR, RGBA to BGRA. See alsoset_bgr.PNG_TRANSFORM_EXPANDβ Performset_expand(). See alsoset_expand.PNG_TRANSFORM_EXPAND_16β Expand samples to 16 bits. See alsoset_expand_16.PNG_TRANSFORM_GRAY_TO_RGBβ Expand grayscale samples to RGB (or GA to RGBA). See alsoset_gray_to_rgb.PNG_TRANSFORM_IDENTITYβ No transformation.PNG_TRANSFORM_INVERT_ALPHAβ Change alpha from opacity to transparency. See alsoset_invert_alpha.PNG_TRANSFORM_INVERT_MONOβ Invert monochrome images. See alsoset_invert_mono.PNG_TRANSFORM_PACKINGβ Expand 1, 2 and 4-bit samples to bytes. See alsoset_packing.PNG_TRANSFORM_PACKSWAPβ Change order of packed pixels to LSB first. See alsoset_packswap.PNG_TRANSFORM_SCALE_16β Strip 16-bit samples to 8-bit accurately. See alsoset_scale_16.PNG_TRANSFORM_SHIFTβ Normalize pixels to the sBIT depth.PNG_TRANSFORM_STRIP_16β Chop 16-bit samples to 8-bit less accurately. See alsoset_strip_16.PNG_TRANSFORM_STRIP_ALPHAβ Discard the alpha channel.PNG_TRANSFORM_SWAP_ALPHAβ Flip RGBA to ARGB or GA to AG. See alsoset_swap_alpha.PNG_TRANSFORM_SWAP_ENDIANβ Byte-swap 16-bit samples. See alsoset_swap.
This function corresponds to png_read_png in libpng 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".
β read_update_info β
$png->read_update_info ();
βπ€ͺβ Inside Image::PNG::Libpng, the libpng function png_read_update_info is called before reading image data. According to "The libpng documentation", this function may only be called once for any particular info structure. So although the above Perl interface exists in the module, it is strongly recommended to not use this unless you know exactly what you are doing, since it will usually cause an error when the image data is read. This is the "do not touch the stove" warning, bestie. Like, the stove is on.
This function corresponds to png_read_update_info in libpng
π write_end π
$png->write_end ();
Write the final part of the PNG file. The outro. The closing credits. The final slay.
This function corresponds to png_write_end in libpng.
π¦ write_image π¦
$png->write_image ($rows);
Write the image of the PNG file. $rows is an array reference as per set_rows. Same shape, same energy.
This function corresponds to png_write_image in libpng.
πΈ write_info πΈ
$png->write_info ();
Write the first part of the PNG file. The intro, the setup, the "let her know what's coming" section.
This function corresponds to png_write_info in libpng.
π 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_BGRβ Flip RGB to BGR, RGBA to BGRA. See alsoset_bgr.PNG_TRANSFORM_INVERT_ALPHAβ Change alpha from opacity to transparency. See alsoset_invert_alpha.PNG_TRANSFORM_INVERT_MONOβ Invert monochrome images. See alsoset_invert_mono.PNG_TRANSFORM_PACKINGβ Expand 1, 2 and 4-bit samples to bytes. See alsoset_packing.PNG_TRANSFORM_PACKSWAPβ Change order of packed pixels to LSB first. See alsoset_packswap.PNG_TRANSFORM_SHIFTβ Normalize pixels to the sBIT depth.PNG_TRANSFORM_STRIP_FILLER_AFTERβ Strip out trailing filler bytes.PNG_TRANSFORM_STRIP_FILLER_BEFOREβ Strip out leading filler bytes.PNG_TRANSFORM_SWAP_ALPHAβ Flip RGBA to ARGB or GA to AG. See alsoset_swap_alpha.PNG_TRANSFORM_SWAP_ENDIANβ Byte-swap 16-bit samples. See alsoset_swap.
This function corresponds to png_write_png in libpng.
πΈ The image header πΈ
Okay bestie, this cluster of functions is all about the header part of PNG image data β the little name tag your PNG wears before it shows you the pixels. If you want the actual spec tea, peep this subsection http://www.w3.org/TR/PNG/#11IHDR of "The PNG specification" for all the PNG standards info on the image header. π
color_type_name
$name = color_type_name ($color_type);
A lil convenience function that hands you back a string matching whatever numerical color type you passed in $color_type. The name comes back in upper case, with words separated by underscores, like "RGB_ALPHA". Slay. β¨
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";
(This example is included as examples/color-type-name.pl β over at https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/color-type-name.pl β in the distribution.)
And ngl, this one's a special little unicorn: it does not correspond to anything in libpng. The names of the color types are straight up taken from those defined in the libpng header file, png.h. π¦
get_bit_depth
my $bit_depth = $png->get_bit_depth ();
Gets the bit depth β aka the number of bits for one channel of one pixel. That's it, that's the whole vibe check. π
This function corresponds to png_get_bit_depth in libpng.
get_channels
my $channels = $png->get_channels ();
Gets the number of channels, from one to four. The channels are the components of pixels β think the red channel, or the alpha (transparency) channel. π
The return value is:
1for color typePNG_COLOR_TYPE_GRAYandPNG_COLOR_TYPE_PALETTE2forPNG_COLOR_TYPE_GRAY_ALPHA3forPNG_COLOR_TYPE_RGB4forPNG_COLOR_TYPE_RGB_ALPHA, orPNG_COLOR_TYPE_RGBwith a filler byte
Lowkey important caveat: the number of channels does not necessarily correspond to the number of bytes, since the bit depth can also be 1, 2, 4, 8, or 16, depending on the color type. Also go check the convenience function color_type_channels while you're at it. π
This function corresponds to png_get_channels in libpng.
get_color_type
my $color_type = $png->get_color_type ();
This returns an integer value. That's giving numbers only, no name tag. If you want an actual name for the color type, use color_type_name. π·οΈ
This function corresponds to png_get_color_type in libpng.
get_IHDR
my $IHDR = $png->get_IHDR ();
Reads the IHDR information from the PNG file. The return value is a hash reference containing these key/value pairs β no cap, this is the whole roster: π
widthβ the width of the image in pixels.heightβ the height of the image in pixels.bit_depthβ the bit depth of the image (the number of bits used for each color in a pixel). This can take the values1,2,4,8,16.color_typeβ the color type. This can take the valuesPNG_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. This can take the valuesPNG_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};
This function corresponds to png_get_IHDR in libpng, with a single Perl hash reference used instead of the several pointers to integers used in libpng. Main character energy fr. π«
Heads up though β it does not return the fields filter_type and compression_type, since these are always 0. See "Unused arguments omitted". β
get_image_height
my $height = $png->get_image_height ();
Gets the image's height from the header. Short king. π
This function corresponds to png_get_image_height in libpng.
get_image_width
my $width = $png->get_image_width ();
Gets the image's width from the header. Also short. π
This function corresponds to png_get_image_width in libpng.
get_interlace_type
my $interlace_type = $png->get_interlace_type ();
Gets the interlace type. This is either PNG_INTERLACE_NONE or PNG_INTERLACE_ADAM7. Two options, pick your fighter. π₯
This function corresponds to png_get_interlace_type in libpng.
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, eXIf, gAMA, hIST, hIST, iCCP, IDAT, IHDR, iTXt, oFFs, pCAL, pHYs, PLTE, sBIT, sCAL, sPLT, sRGB, tEXt, tIME, tRNS, and zTXt. (Yes bestie, hIST is in there twice in the original list β we keep the lore intact. π«Ά)
So like, libpng_supports tells you whether the installed libpng on your system supports various chunks β but this one tells you whether the chunks are actually present in a particular PNG image file. Different questions, both iconic. π
The first argument, $png, is a PNG structure created with create_read_struct.
This function corresponds to png_get_valid in libpng, with the difference being that the return value is a hash containing a key for each possible chunk.
height
my $height = $png->height ();
Alias for get_image_height. Just a nickname. This is not exported β it's intended for use with the object only. π
set_IHDR
my $ihdr = {width => 10, height => 10, bit_depth => 8,
color_type => PNG_COLOR_TYPE_RGB};
$png->set_IHDR ($ihdr);
Sets the IHDR chunk (the image header) of the PNG image. Let's gooo. π₯
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 color in a pixel). This cannot be omitted. This can have the values1,2,4,8,16.color_typeβ the color type. This cannot be omitted. This can have the valuesPNG_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 toPNG_INTERLACE_NONE. This can have the valuesPNG_INTERLACE_NONE,PNG_INTERLACE_ADAM7.
Other fields in the hash are ignored. They're just there, vibing, not contributing. π
This function corresponds to png_set_IHDR in libpng, with a single Perl hash reference used instead of the seven integers.
The values compression_method, filter_method, may be supplied by the user but are ignored since they may only take the value 0. See "Unused arguments omitted". β¨
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. Wild, I know β read it twice. π
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. Defaults, but make it fashion. π
This function corresponds to png_sig_cmp in libpng, with default arguments of 0 and 8 if second and third arguments are not supplied.
width
my $width = $png->width ();
Alias for get_image_width. Not exported β it's intended for use with the object only. Same deal as height. π¦
π§ Image data π§
These functions deal with accessing the image data itself β the actual pixels, the main event. π
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. Byte math, but make it cute. π’
This function corresponds to png_get_rowbytes in libpng.
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 element of the array reference is a string containing the binary data making up a row of the image. You can pull individual pixel values out of it using a function such as substr or unpack. Heads up: this binary data is likely to contain bytes equal to zero. π
get_rowbytes gives you the number of bytes in each row.
Each row is a Perl string. Perl terminates each row of data with an extra zero byte at the end. That's just how Perl does. π
This function corresponds to png_get_rows in libpng.
set_rows
$png->set_rows (\@rows);
Sets the rows of data to be written in to the PNG to @rows.
Okay so the rules: @rows needs to contain at least the same number of rows of data as the height of the PNG image set with set_IHDR, and the length of each entry needs to be at least the width of the image multiplied by the number of bytes required for each pixel. Read that constraint twice, it's important. β οΈ
π₯ Lore drop: this function was changed to copy the data in version 0.46. Noted for the historians.
This function corresponds to png_set_rows in libpng.
πΈ Text chunks πΈ
See this subsection http://www.w3.org/TR/PNG/#11textinfo of "The PNG specification" for information on the PNG standards for text information.
π¦ get_text π¦
my $text_chunks = $png->get_text ();
This gets all of the text chunks in the PNG image and returns them as an array reference. Each element of the array represents one text chunk. This element is a hash reference with keys such as "key", "lang_key", or "compression" taken from the PNG's information.
The text data is uncompressed by libpng. If it is international text ("ITXT"), it is put into Perl's internal Unicode encoding if it is found to be valid UTF-8. (PNG "international text", "ITXT" 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.)
This function corresponds to "png_get_text" in libpng, with a Perl array of hash references substituted for the C array of structs used by libpng. See "set_text" for details of the keys and values which may be returned.
π set_text π
$png->set_text ([\%chunk1, \%chunk2]);
This sets the text chunks in a writeable image. The input value is an array reference containing one or more hash references. Each hash reference must have a "key" value for the text. According to the PNG specification, this should be between one and 79 bytes in length. This module enforces that restriction, so if you supply a key longer than that, the chunk cannot be added. A hash reference may also have the following:
compressionβ The value of"compression"controls the compression of the text. If"compression"is not supplied, a default value ofPNG_TEXT_COMPRESSION_NONEis applied. The"compression"field can take the following values, available fromImage::PNG::Const:PNG_TEXT_COMPRESSION_NONEβTEXT = Printable ASCII and space characters.PNG_TEXT_COMPRESSION_zTXtβTEXT = Printable ASCII and space characters.PNG_ITXT_COMPRESSION_NONEβITXT = International text, should be UTF-8.PNG_ITXT_COMPRESSION_zTXtβITXT = International text, should be UTF-8.
itxt_lengthβ The string length of international text in bytes.
βπ€ͺβ This is ignored by libpng when writing text chunks. When reading text chunks, if the text is marked as international text, libpng adds the length of the string in bytes in this field rather than in "text_length".
langβ This should be set to name of the language of the text, if the text chunk is iTXt. According to the PNG specification, "It is an ISO 646.IRV:1991 [ISO 646] string consisting of hyphen-separated words of 1-8 alphanumeric characters each (for example cn, en-uk, no-bok, x-klingon, x-KlInGoN)."
Support for writing "lang" was added in version 0.49 of this module. (Prior to that undocumented support existed via a differently-named key.)
βπ€ͺβ This module does not attempt to check the supplied value, but merely passes it to libpng. libpng appears not to check the value either, nor to enforce restrictions on its length.
lang_keyβ This corresponds to the"Translated keyword"of the PNG specification. Note that the user needs to supply"key"and"lang"as well as"lang_key".
Support for writing "lang_key" was added in version 0.49 of this module. (Prior to that undocumented support existed via a differently-named key.)
textβ The value of"text"is added to the PNG as the text segment. This can be omitted if you just want to write a key value without any accompanying text.text_lengthβ The string length in bytes. The user may set this, but it is ignored when writing PNG text chunks, instead this module uses the string length obtained from Perl. This key contains the length of the string when reading text chunks via"get_text", but if the text is marked as international text,"itxt_length"is used to return its length in bytes, rather than this.
Whether or not the value of "text" is an ITXT field is decided by the value of "compression".
People who want to fiddle with the text compression applied can do so via "set_text_compression_level" and the other functions described below that.
If "set_text" is called more than once, the chunks are not overwritten but appended to the existing ones. (This behaviour is from libpng itself.)
Prior to version 0.50, "set_text" would fail silently if the user added invalid chunks, for example hash references without a valid "key", or things which were not hash references at all. From version 0.50, all invalid inputs cause fatal errors. However, unknown keys in the hash references do not cause fatal errors.
This function corresponds to "png_set_text" in libpng.
π Example π
use utf8;
use Image::PNG::Const ':all';
use Image::PNG::Libpng ':all';
my $png = create_write_struct ();
$png->set_IHDR ({width => 1, height => 1, bit_depth => 8,
color_type => PNG_COLOR_TYPE_GRAY});
$png->set_rows (['X']);
$png->set_text ([{
compression => PNG_TEXT_COMPRESSION_NONE,
key => "Copyright",
text => "Copyright (C) 2020 Fat Cat",
}, {
compression => PNG_ITXT_COMPRESSION_zTXt,
key => "Copyright",
lang_key => 'θθ
権',
lang => 'ja_JP',
text => '©什εοΌεΉ΄θθγγ£γ³γγΌγ¬γΌγγ',
}]);
$png->write_png_file ('copyright.png');
(This example is included as examples/set-text.pl (https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/set-text.pl) in the distribution.)
π«Ά 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_NONETEXT_zTXtITXT_NONEITXT_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.
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".
π Private chunks π
See this subsection http://www.w3.org/TR/PNG/#12Use-of-private-chunks of "The PNG specification" for information on the PNG standards for private chunks.
To test whether your version of libpng supports "private chunks", use "libpng_supports" with argument 'UNKNOWN_CHUNKS':
if (libpng_supports ('UNKNOWN_CHUNKS')) {
# do something
}
π¦ get_chunk_malloc_max π¦
my $max = $png->get_chunk_malloc_max ();
This gets the maximum amount of memory that a chunk can use.
To test whether your version of libpng supports "get_chunk_malloc_max", use "libpng_supports" with argument "CHUNK_MALLOC_MAX":
if (libpng_supports ('CHUNK_MALLOC_MAX')) {
# do something
}
This function corresponds to "png_get_chunk_malloc_max" in libpng
π set_chunk_malloc_max π
$png->set_chunk_malloc_max ($max);
This sets the maximum amount of memory that a chunk can use. The default value of libpng 1.6.45 is 8 megabytes.
To test whether your version of libpng supports "get_chunk_malloc_max", use "libpng_supports" with argument "CHUNK_MALLOC_MAX":
if (libpng_supports ('CHUNK_MALLOC_MAX')) {
# do something
}
This function corresponds to "png_set_chunk_malloc_max" in libpng
πΈ 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.
This function corresponds to "png_get_unknown_chunks" in libpng
π¦ set_unknown_chunks π¦
$png->set_unknown_chunks (name => 'dUCk', data => 'abcdefg',
location => PNG_AFTER_IDAT);
βπ€ͺβ This currently does not fully function.
This function corresponds to "png_set_unknown_chunks" in libpng
π Library version functions π
β 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.
This function corresponds to "png_access_version_number" in libpng.
π 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.
This function corresponds to "png_get_libpng_ver" in libpng. However, it doesn't require the "png_structp" argument of the C function. See "Unused arguments omitted".
π Compression and filtering π
get_compression_buffer_size
my $size = $png->get_compression_buffer_size ();
Returns the value of the compression buffer size, bestie β and yes, that value may be altered with set_compression_buffer_size. β¨
set_compression_buffer_size
$png->set_compression_buffer_size (100);
Sets the size of the buffer that zlib uses to compress or decompress the image data. It takes one argument, an integer number. This cannot be less than 6. π«Ά
set_compression_level
$png->set_compression_level ($number);
Sets the compression level used to make the PNG. A value of 0 (Z_NO_COMPRESSION) corresponds to no compression at all; otherwise $number may take values of 1 (Z_BEST_SPEED) to 9 (Z_BEST_COMPRESSION), with smaller values giving faster compression, and larger values giving better compression β meaning smaller output. These correspond to the -1, -2, ... -9 options to the gzip utility, or the compression level parameter of zlib. Calling with -1 (Z_DEFAULT_COMPRESSION) reverts to the default compression. Calling with any other number outside the range 0 to 9 results in a fatal error. π
This function was added to the module in version 0.49.
set_compression_mem_level
$png->set_compression_mem_level ($argument);
βπ€ͺβ Untested function corresponding to png_set_compression_mem_level. Takes one integer argument.
Sets the memLevel parameter of deflateInit2 in zlib when writing PNG image data. Argument between 1 for minimum memory and 9 for maximum speed. The default is 8. See "zlib documentation". π
set_compression_window_bits
$png->set_compression_window_bits ($argument);
βπ€ͺβ Untested function corresponding to png_set_compression_window_bits. Takes one integer argument.
Sets the windowBits parameter of deflateInit2 in zlib when writing PNG image data. Argument value must be between 8 and 15 for libpng. The default is 15. See the "zlib documentation". πΈ
set_compression_strategy
$png->set_compression_strategy ($argument);
βπ€ͺβ Untested function corresponding to png_set_compression_strategy. Takes one integer argument.
Sets the strategy parameter of deflateInit2 when writing PNG image data. Setting this with libpng overrides libpng's default behaviour of changing the value depending on the filter in use. For zlib, the argument is either 0 for default behaviour, or 1 to 4. See the "zlib documentation". libpng uses the default strategy 0 (Z_DEFAULT_STRATEGY) for unfiltered image data, and 1 (Z_FILTERED) for filtered image data. π₯
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_FILTERSPNG_FILTER_NONEPNG_FILTER_SUBPNG_FILTER_UPPNG_FILTER_AVGPNG_FILTER_PAETHPNG_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 this subsection at http://www.w3.org/TR/PNG/#9Filter-types of The PNG specification for the meanings of these filter types. π¦
This function corresponds to png_set_filter in libpng with the second (unused) argument omitted. See "Unused arguments omitted".
set_text_compression_level
$png->set_text_compression_level ($argument);
βπ€ͺβ Untested function corresponding to png_set_text_compression_level. Takes one integer argument.
As set_compression_level but for compressed text. β¨
set_text_compression_mem_level
$png->set_text_compression_mem_level ($argument);
βπ€ͺβ Untested function corresponding to png_set_text_compression_mem_level. Takes one integer argument.
As set_compression_mem_level but for compressed text. π
set_text_compression_window_bits
$png->set_text_compression_window_bits ($argument);
βπ€ͺβ Untested function corresponding to png_set_text_compression_window_bits. Takes one integer argument.
As set_compression_window_bits but for compressed text. π
set_text_compression_strategy
$png->set_text_compression_strategy ($argument);
βπ€ͺβ Untested function corresponding to png_set_text_compression_strategy. Takes one integer argument.
As set_compression_strategy but for compressed text. π
π¦ 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 color of the PNG image. π¨
See this subsection at http://www.w3.org/TR/PNG/#11bKGD of The PNG specification 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 color type of the image:
indexβ For palette color types, this is the offset into the palette.grayβ For grayscale color types.redgreenblue
This function corresponds to png_get_bKGD in libpng 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".
This function corresponds to png_set_bKGD in libpng with a hash function instead of a png_color struct.
cHRM
See this subsection at http://www.w3.org/TR/PNG/#11cHRM of The PNG specification "cHRM Primary chromaticities and white point". πΈ
get_cHRM
my $cHRM = $png->get_cHRM ();
Get the cHRM chunk as a hash reference.
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.
This function corresponds to png_get_cHRM in libpng with a hash reference supplying the arguments. The hash's keys correspond to the names of the double arguments in libpng. β¨
get_cHRM_XYZ
my $cHRM = $png->get_cHRM_XYZ ();
Get the cHRM chunk as a hash reference for the XYZ color space.
The keys of the hash are red_x, red_y, red_z, green_x, green_y, green_z, blue_x, blue_y, blue_z.
The values of the hash are floating point numbers between 0 and 1.
This function corresponds to png_get_cHRM_XYZ in libpng with a hash reference supplying the arguments. The hash's keys correspond to the names of the double arguments in libpng. π¦
set_cHRM
$png->set_cHRM (\%cHRM);
Set the cHRM chunk from a hash reference.
The keys of the hash are as for "get_cHRM". The values are floating point numbers between 0 and 1.
This function corresponds to png_set_cHRM in libpng with a hash reference instead of the double arguments. π
set_cHRM_XYZ
$png->set_cHRM_XYZ (\%cHRM);
Set the cHRM chunk from a hash reference for the XYZ color space.
The keys of the hash are as for "get_cHRM_XYZ". The values are floating point numbers between 0 and 1. The Y values red_y, green_y, and blue_y should sum to 1. If you supply values outside the allowed range, libpng corrects them silently on writing rather than producing an error.
This function corresponds to png_set_cHRM_XYZ in libpng with a hash reference instead of the double arguments. π«Ά
eXIf
The eXIf chunk is an extension to the PNG specification. See http://www.simplesystems.org/png-group/proposals/eXIf/. Support for this chunk was added in version 0.50 of this module.
get_eXIf
my $exif = $png->get_eXIf ();
This retrieves the eXIf chunk from $png but does not process the internal information.
set_eXIf
$png->set_eXIf ($exif);
libpng checks whether the chunk's first two bytes are either II for little-endian (from Intel) or MM for big-endian (from Motorola) then adds the entire chunk, including the first two bytes, to the PNG.
βπ€ͺβ As of December 2020, there appears to be a bug in libpng in which theeXIfchunk is added twice, causing a warning of the formlibpng warning: eXIf: duplicateon reading a PNG file back in. Seehttps://github.com/glennrp/libpng/pull/351. π
gAMA
See this subsection at 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.
This function corresponds to png_get_gAMA in libpng. π
set_gAMA
$png->set_gAMA (0.2);
Set the gamma value or gAMA chunk.
This function corresponds to png_set_gAMA in libpng. π
hIST
See this subsection at http://www.w3.org/TR/PNG/#11hIST of The PNG specification.
get_hIST
my $hist = $png->get_hIST ();
If the PNG file contains a histogram, the return value is an array reference; otherwise it is the undefined value. The number of entries in the array reference is the same as in the palette.
This function corresponds to png_get_hIST in libpng. π
set_hIST
$png->set_hIST (\@hist);
Set the histogram of frequencies of the colors of a paletted (PLTE) image. The entries of the histogram are 16 bit unsigned integers, so the maximum value that can be entered is 65535 = 2^16 - 1. Larger numbers and floating point numbers will cause a warning to be printed and the value to be set to zero. The histogram must have exactly the same number of entries as the palette or the call will fail with a warning. A histogram cannot be added to an image without a palette. A call to set_hIST for an image without a palette will cause a warning and return without setting the value. π
(I'm not sure of the best form of error handling for this function so it may change in future versions to have errors for a bad histogram rather than warnings.)
This function corresponds to png_set_hIST in libpng. π
iCCP
See this subsection at 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 color profile.
The compression_type value, which is always 0, is not returned. See "Unused arguments omitted".
This function corresponds to png_get_iCCP in libpng. π
set_iCCP
$png->set_iCCP ({name => 'name', profile => 'profile'});
This one maps to png_set_iCCP in libpng. For the deets on the arguments, go see get_iCCP. Thereβs a compression_type argument that must always be 0 anyway, so itβs literally ignored. See Unused arguments omitted. periodt π
π 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 ();
Grab the oFFs chunk. The return value is a hash reference. slay β¨
This function corresponds to png_get_oFFs in libpng.
set_oFFs
$png->set_oFFs ({x_offset => 1, y_offset => 1, unit_type => 0});
Set the oFFs chunk. See the specification linked above for the meanings of the parameters. If unit_type is not 0 or 1, a warning is produced. heads up, bestie β οΈ
This function corresponds to png_set_oFFs in libpng.
π¦ pCAL π¦
pCAL is an extension of the PNG specification which allows one to associate pixels in the PNG image with non-image data such as a heat map. See http://www.libpng.org/pub/png/spec/1.1/pngext-1.1.0-pdg.html#C.pCAL.
To test whether your version of libpng supports the pCAL extension, use libpng_supports with argument 'pCAL':
if (libpng_supports ('pCAL')) {
# do something
}
get_pCAL
my $pcal = $png->get_pCAL ();
The return value is a hash reference with the following keys:
paramsβ If this exists, its value is a reference to an array containing the parameter list of the pCAL chunk, which are floating point numbers. Within the PNG file chunk, these parameters are stored as strings representing floating point numbers, but you can pass in Perl floating point numbers rather than strings. The number of parameters you should set is fixed by thetypeparameter. Refer to the PNG specification for full details.purposeβ The purpose string of the pCAL chunk.typeβ The equation type as a number, from0to3. See the PNG specification for the meanings. Other numbers cause an error.unitsβ The units as a string. See the PNG specification for details.x0β The zero value for the equation, an integer.x1β The max value for the equation, an integer.
This function corresponds to png_get_pCAL in libpng.
set_pCAL
$png->set_pCAL (\%values);
See get_pCAL for the parameters of %values.
This function corresponds to png_set_pCAL in libpng.
π pHYs π
See this subsection 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_xres_yunit_typeβ Is either0or1.
This function corresponds to png_get_pHYs in libpng.
set_pHYs
$png->set_pHYs ({res_x => 1, res_y => 1, unit_type => 1});
This function corresponds to png_set_pHYs in libpng.
π PLTE π
See this subsection http://www.w3.org/TR/PNG/#11PLTE of The PNG specification for information on the PNG standards for the palette chunk.
get_palette_max
my $pmax = $png->get_palette_max ();
If your libpng supports it, this will return the maximum palette index found in the image, or -1 if the palette was not checked, or 0 if no palette was found.
To test whether your version of libpng supports get_palette_max, use libpng_supports with argument 'GET_PALETTE_MAX':
if (libpng_supports ('GET_PALETTE_MAX')) {
# do something
}
βπ€ͺβ This function is implemented but so far it is not very clear to me what it does, since, for example, it returns zero for the test image t/tantei-san.png which is an image with a fully-used 256-color palette. Iβve asked about it on the libpng mailing list https://sourceforge.net/p/png-mng/mailman/png-mng-implement/?viewmonth=202012&viewday=14, but so far nobody has responded. the suspense is real π
get_PLTE
my $colors = $png->get_PLTE ();
# Get the green value of the twentieth entry in the palette.
my $green = $colors->[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 color 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. iykyk π§
This function corresponds to png_get_PLTE in libpng.
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. iconic behavior π
This function corresponds to png_set_PLTE in libpng.
β sBIT β
See this subsection http://www.w3.org/TR/PNG/#11sBIT of The PNG specification.
get_sBIT
my $sbit = $png->get_sBIT ();
The return value is a hash reference containing integer values for the keys red, blue, green, gray and alpha, depending on the color_type of $png.
βπ€ͺβ Prior to version 0.50 of this module, get_sBIT wrote values of 0 for all of the keys, regardless of the color_type, causing errors in some circumstances. From version 0.50, hash keys are not entered if the color_type of the image makes them invalid. lowkey a glow-up π
This function corresponds to png_get_sBIT in libpng.
set_sBIT
$png->set_sBIT ({red => 1, blue => 2, green => 3});
The argument is a hash reference containing integer values for the keys red, blue, green, gray, and alpha, as required by the color_type of $png.
This function corresponds to png_set_sBIT in libpng.
πΈ 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.
To test whether your version of libpng supports the sCAL chunk, use libpng_supports with argument 'sCAL':
if (libpng_supports ('sCAL')) {
# do something
}
get_sCAL
my $scal = $png->get_sCAL ();
The returned hash value contains the following keys:
unitβ The unit type, which is eitherPNG_SCALE_UNKNOWN,PNG_SCALE_METER, orPNG_SCALE_RADIAN.widthβ The width, as a string.heightβ The height, as a string.
This function corresponds to png_get_sCAL_s in libpng. Note that this uses the sCAL_s function rather than the get_sCAL and the returned values are the strings themselves rather than parsed numbers. no cap, read that twice π«Ά
set_sCAL
$png->set_sCAL ($scal);
$scal is a hash reference containing the keys described in get_sCAL.
This function corresponds to png_set_sCAL_s in libpng. Note that this uses the set_sCAL_s function rather than set_sCAL and the input values are the strings themselves rather than numbers.
π sPLT π
See this subsection http://www.w3.org/TR/PNG/#11sPLT of The PNG specification.
get_sPLT
βπ€ͺβ Provisional. See set_sPLT for documentation, the return value is like the input of that.
set_sPLT
$png->set_sPLT ([{ name => 'palette', depth => 8, entries => [{red => 1, blue => 2},]}]);
Set suggested palettes. The input is an array reference containing hash references with the following fields:
nameβ The name of the suggested palette.depthβ The depth of the suggested palette.entriesβ The entries of the palette. This is an array reference containing hash references with keys as follows:redbluegreenfrequencyalpha
The field nentries which is returned by get_sPLT does not need to be specified, it is calculated from the length of entries. math is mathing π§
π sRGB π
See this subsection 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_SATURATIONPNG_sRGB_INTENT_PERCEPTUALPNG_sRGB_INTENT_ABSOLUTEPNG_sRGB_INTENT_RELATIVE
This function corresponds to png_get_sRGB in libpng.
set_sRGB
$png->set_sRGB ($srgb);
$srgb is one of the values described in get_sRGB.
This function corresponds to png_set_sRGB in libpng.
π tIME π
See this subsection http://www.w3.org/TR/PNG/#11timestampinfo of The PNG specification 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. month and day start from 1 rather than 0.
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. According to this subsection http://www.w3.org/TR/PNG/#11tIME of The PNG specification, Universal Time (UTC) should be specified rather than local time. timezone drama, but make it PNG π°οΈ
This function corresponds to png_get_tIME in libpng, 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 your PNG, bestie β you pass it a hash reference with the fields year, month, day (that's day-of-the-month, not a vibe check), hour, minute and second. And listen: the numbering for month and day starts at 1, not 0, so please don't come at it with zero-index brain π«Ά.
Defaults, because of course there are defaults:
- If any of year, hour, minute or second is omitted from the hash reference, those get set to zero.
- If month or day are omitted, those get set to 1.
PNG tIME chunks do not contain a time zone β literally none, it's giving timezone-less. According to this subsection http://www.w3.org/TR/PNG/#11tIME of The PNG specification: "Universal Time (UTC) should be specified rather than local time." So UTC, not local. Periodt.
And if the entire argument is omitted, or it contains an invalid value? The time gets set to the current time. Iconic little fallback, honestly.
This function corresponds to png_set_tIME in libpng, with a Perl hash reference substituted for the C struct png_timep used in libpng.
π tRNS π
Go peek at this subsection http://www.w3.org/TR/PNG/#11tRNS of The PNG specification first, iykyk.
get_tRNS
my $trns = $png->get_tRNS ();
Grabs the tRNS chunk for you π. If the image is a palette type, what you get back is an array reference. If the image is a non-palette type, you get a hash containing values for the keys red, green, blue, and gray.
set_tRNS
$png->set_tRNS ($trns);
Sets the tRNS chunk. If the image is a palette type, $trns is a reference to an array of positive or zero values between 0 and 255, the same size as the palette β and it must not contain more than 256 values, that's the hard limit, no exceptions π«. If the image is not a palette type, $trns is a hash reference containing values for the keys red, green, blue and gray.
β¨ Libpng transformations β¨
set_bgr
$png->set_bgr ();
βπ€ͺβ Untested. Flips RGB to BGR. See the libpng manual for details.
Wanna know if your version of libpng supports set_bgr? For a read object, hit up libpng_supports with the argument 'READ_BGR':
if (libpng_supports ('READ_BGR')) {
# do something
}
For a write object, use the argument 'WRITE_BGR'.
This function corresponds to png_set_bgr in libpng
set_expand
$png->set_expand ();
Sets a transformation in $png such that paletted images get expanded to RGB, grayscale images of bit-depth less than 8 get expanded to 8-bit images, and tRNS chunks get expanded to alpha channels. A whole little glow-up pipeline πΈ.
To test whether your version of libpng supports set_expand, use libpng_supports with argument 'READ_EXPAND':
if (libpng_supports ('READ_EXPAND')) {
# do something
}
This function corresponds to png_set_expand in libpng
set_expand_16
$png->set_expand_16 ();
βπ€ͺβ Untested.
To test whether your version of libpng supports set_expand_16, use libpng_supports with argument 'READ_EXPAND_16':
if (libpng_supports ('READ_EXPAND_16')) {
# do something
}
This function corresponds to png_set_expand_16 in libpng
set_expand_gray_1_2_4_to_8
$png->set_expand_gray_1_2_4_to_8 ();
βπ€ͺβ Untested.
To test whether your version of libpng supports set_expand_gray_1_2_4_to_8, use libpng_supports with argument 'READ_EXPAND':
if (libpng_supports ('READ_EXPAND')) {
# do something
}
This function corresponds to png_set_expand_gray_1_2_4_to_8 in libpng
set_gray_to_rgb
$png->set_gray_to_rgb ();
Converts a grayscale PNG file into RGB format while reading. Gray era over, RGB era begins π .
To test whether your version of libpng supports set_gray_to_rgb, use libpng_supports with argument 'READ_GRAY_TO_RGB':
if (libpng_supports ('READ_GRAY_TO_RGB')) {
# do something
}
This function corresponds to png_set_gray_to_rgb in libpng
set_invert_alpha
$png->set_invert_alpha ();
βπ€ͺβ Untested. See the libpng manual for details.
To test whether your version of libpng supports set_invert_alpha, use libpng_supports with argument 'READ_INVERT_ALPHA':
if (libpng_supports ('READ_INVERT_ALPHA')) {
# do something
}
This function corresponds to png_set_invert_alpha in libpng
set_invert_mono
$png->set_invert_mono ();
Inverts monochrome images. See the libpng manual for details β the libpng manual is the real main character here, lowkey.
To test whether your version of libpng supports set_invert_mono, use libpng_supports with argument 'READ_INVERT':
if (libpng_supports ('READ_INVERT')) {
# do something
}
This function corresponds to png_set_invert_mono in libpng
set_packing
$png->set_packing ();
When reading a PNG this expands the image to 1 pixel per byte for bit-depths 1, 2 and 4, without changing the order of the pixels. If you don't call this, the pixels of bit_depths 1, 2 and 4 are packed into bytes as small as possible β like, 8 pixels per byte for 1-bit files. See the libpng manual for details. Also see set_packswap π.
To test whether your version of libpng supports set_packing, for a read object, use libpng_supports with argument 'READ_PACK':
if (libpng_supports ('READ_PACK')) {
# do something
}
For a write object, use argument 'WRITE_PACK'.
This function corresponds to png_set_packing in libpng
set_packswap
$png->set_packswap ();
Swaps the bits of 1, 2, or 4 bits/pixel images. The default for a PNG image is to put the left pixel into the highest part of the byte β so for example if the bit depth is 1, the pixels from left to right go into a byte as values 128 for the leftmost, 64, 32, 16, 8, 4, 2, then 1 for the rightmost pixel. This call reverses that behavior so the pixels in a byte go 1 for the leftmost, 2, ..., then 128 for the rightmost. It's giving uno-reverse for bits π¦. See the libpng manual for details.
To test whether your version of libpng supports set_packswap, for a read object, use libpng_supports with argument 'READ_PACKSWAP':
if (libpng_supports ('READ_PACKSWAP')) {
# do something
}
For a write object, use argument 'WRITE_PACKSWAP'.
This function corresponds to png_set_packswap in libpng
set_palette_to_rgb
$png->set_palette_to_rgb ();
βπ€ͺβ Untested. See the libpng manual for details.
To test whether your version of libpng supports set_palette_to_rgb, use libpng_supports with argument 'READ_EXPAND':
if (libpng_supports ('READ_EXPAND')) {
# do something
}
This function corresponds to png_set_palette_to_rgb in libpng
set_scale_16
$png->set_scale_16 ()
βπ€ͺβ Untested.
To test whether your version of libpng supports set_scale_16, use libpng_supports with argument 'READ_SCALE_16_TO_8':
if (libpng_supports ('READ_SCALE_16_TO_8')) {
# do something
}
This function corresponds to png_set_scale_16 in libpng
set_strip_16
$png->set_strip_16 ();
Strips the pixels of a PNG stream with 16 bits per channel down to 8 bits per channel. Trimming the excess, so slay β¨.
To test whether your version of libpng supports set_strip_16, use libpng_supports with argument 'READ_STRIP_16_TO_8':
if (libpng_supports ('READ_STRIP_16_TO_8')) {
# do something
}
This function corresponds to png_set_strip_16 in libpng
set_strip_alpha
$png->set_strip_alpha ();
Strips the alpha channel of a PNG stream. Transparency? Gone. Not invited π«Ά.
To test whether your version of libpng supports set_strip_alpha, use libpng_supports with argument 'READ_STRIP_ALPHA':
if (libpng_supports ('READ_STRIP_ALPHA')) {
# do something
}
This function corresponds to png_set_strip_alpha in libpng
set_swap
$png->set_swap ();
βπ€ͺβ Untested. Swaps around the bytes of 16 bits/pixel images. See the libpng manual for details.
To test whether your version of libpng supports set_swap, use libpng_supports with argument 'READ_SWAP':
if (libpng_supports ('READ_SWAP')) {
# do something
}
This function corresponds to png_set_swap in libpng
set_swap_alpha
$png->set_swap_alpha ();
βπ€ͺβ Untested. See the libpng manual for details.
To test whether your version of libpng supports set_swap_alpha, use libpng_supports with argument 'READ_SWAP_ALPHA':
if (libpng_supports ('READ_SWAP_ALPHA')) {
# do something
}
This function corresponds to png_set_swap_alpha in libpng
set_tRNS_to_alpha
$png->set_tRNS_to_alpha
βπ€ͺβ Untested. See the libpng manual for details.
To test whether your version of libpng supports set_tRNS_to_alpha, use libpng_supports with argument 'READ_EXPAND':
if (libpng_supports ('READ_EXPAND')) {
# do something
}
This function corresponds to png_set_tRNS_to_alpha in libpng
π Other libpng functions π
get_chunk_cache_max
my $max = $png->get_chunk_cache_max ();
Gets the maximum number of ancillary chunks allowed. Also see set_chunk_cache_max.
To test whether your version of libpng supports get_chunk_cache_max, use libpng_supports with argument 'CHUNK_CACHE_MAX':
if (libpng_supports ('CHUNK_CACHE_MAX')) {
# do something
}
This function corresponds to png_png_get_chunk_cache_max in libpng
get_rgb_to_gray_status
my $badpixels = $png->get_rgb_to_gray_status ();
Returns a true value if there were some non-gray pixels in an RGB image after calling set_rgb_to_gray. Basically it snitches on pixels that were faking the monochrome aesthetic π.
π Saving bandwidth π
Try this one weird old get_rgb_to_gray_status trick to check whether an image marked as RGB is really monochrome or not. Not me using a status function as a bandwidth detective π:
use utf8;
use FindBin '$Bin';
use Image::PNG::Libpng ':all';
use Image::PNG::Const ':all';
my $file = 'life.png';
print "Size before: ", -s $file, "\n";
my $png = create_reader ($file);
$png->read_info ();
$png->set_rgb_to_gray ();
if ($png->get_rgb_to_gray_status ()) {
print "The image contained non-gray pixels.\n";
}
else {
print "The image was grayscale already.\n";
}
$png->read_image ();
$png->read_end ();
my $wpng = $png->copy_png ();
my $ihdr = $wpng->get_IHDR ();
$ihdr->{color_type} = PNG_COLOR_TYPE_GRAY;
$wpng->set_IHDR ($ihdr);
my $after = "life-gray.png";
$wpng->write_png_file ($after);
print "Size after: ", -s $after, "\n";
if (! png_compare ($file, $after)) {
print "The two files contain exactly the same image data.\n";
}
else {
print "The two files contain different image data.\n";
}
(This example is included as examples/xkcd.pl β https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/xkcd.pl β in the distribution.)
The output looks like this:
Size before: 97299
The image was grayscale already.
Size after: 46956
The two files contain exactly the same image data.
examples/life-gray.png is literally right there in the distribution β yes bestie, included, at https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/life-gray.png π
Correct use of Image::PNG::Libpng could have spared as many as 50,000 bytes from the indignity of being sent around the internet ππ no cap.
This also illustrates the use of png_compare β¨
Original image, licence statement and copyright notice are here: https://xkcd.com/2391/ π
get_user_height_max π¦
$png->get_user_height_max ();
Get the maximum height allowed for a PNG file. The default is 1 million pixels. These values can be changed by set_user_limits π
This function corresponds to png_get_user_height_max in libpng.
get_user_width_max πΈ
$png->get_user_width_max ();
Get the maximum width allowed for a PNG file. The default is 1 million pixels. These values can be changed by set_user_limits π
This function corresponds to png_get_user_width_max in libpng.
permit_mng_features π«Ά
$png->permit_mng_features ($mask);
βπ€ͺβ Untested. $mask is an integer containing flags. See the libpng manual for details.
(MNG, 'Multiple-image Network Graphics', is an image animation format related to PNG. It has not been widely adopted.) π¦
To test whether your version of libpng supports permit_mng_features, use libpng_supports with argument '"MNG_FEATURES"':
if (libpng_supports ('MNG_FEATURES')) {
# do something
}
This function corresponds to png_permit_mng_features in libpng.
set_add_alpha π
$png->set_add_alpha ($filler, $filler_loc);
βπ€ͺβ Untested. Change $png to add an alpha channel. This only works for grayscale or RGB images with bit depth of 8 or 16. $filler contains the alpha value to assign to each pixel, and $filler_loc is either PNG_FILLER_BEFORE or PNG_FILLER_AFTER. The function of set_add_alpha is set_filler and a change of the color type to add an alpha channel. See the libpng manual for details π
To test whether your version of libpng supports set_add_alpha, use libpng_supports with argument '"READ_FILLER"':
if (libpng_supports ('READ_FILLER')) {
# do something
}
This function corresponds to png_set_add_alpha in libpng.
set_alpha_mode π
$png->set_alpha_mode ($mode, $screen_gamma);
βπ€ͺβ Untested. $mode is an integer, one of the PNG_ALPHA_* constants. $screen_gamma is a floating point number. See the libpng manual for details.
To test whether your version of libpng supports set_alpha_mode, use libpng_supports with argument '"READ_ALPHA_MODE"':
if (libpng_supports ('READ_ALPHA_MODE')) {
# do something
}
This function corresponds to png_set_alpha_mode in libpng.
set_background π
$png->set_background (\%color, $bkgd_gamma_code, $need_expand, $gamma);
set_background sets the background of an image with an alpha channel or simple transparency (a tRNS chunk) with the color specified by %color. If $bkgd_gamma_code is set to PNG_BACKGROUND_GAMMA_SCREEN, it indicates that the supplied background color is in the gamma space of the display, else if it is set to PNG_BACKGROUND_GAMMA_FILE, the color is in the gamma space of the file. If $bkgd_gamma_code is set to PNG_BACKGROUND_GAMMA_UNIQUE, the value of $gamma is used, otherwise $gamma appears to be ignored and can be omitted. (This is not documented in the libpng manual or elsewhere. See https://github.com/glennrp/libpng/issues/358.) π§
If the background color is supplied at the original bit-depth for a grayscale image that is expanded to truecolor or to a higher bit-depth, $need_expand must be set to a true value, but if the background color is supplied at the expanded bit-depth, $need_expand must be set to a false value. Similarly for paletted images, if %color is supplied as a palette index ($color{index}), $need_expand must be set to a true value, but if %color is an RGB triplet, $need_expand must be set to a false value π
See Setting the background for an example.
To test whether your version of libpng supports set_background, use libpng_supports with argument '"READ_BACKGROUND"':
if (libpng_supports ('READ_BACKGROUND')) {
# do something
}
set_chunk_cache_max π
$png->set_chunk_cache_max (42);
Set the maximum number of ancilliary chunks allowed. The default is 1000. See also get_chunk_cache_max β¨
To test whether your version of libpng supports set_chunk_cache_max, use libpng_supports with argument '"CHUNK_CACHE_MAX"':
if (libpng_supports ('CHUNK_CACHE_MAX')) {
# do something
}
This function corresponds to png_png_set_chunk_cache_max in libpng.
set_filler π
$png->set_filler ($filler, $flags);
Set transformations in $png such that a filler byte $filler is added when an 8-bit grayscale image or 24-bit RGB image is read, and a filler byte is deleted when an 8-bit grayscale image or 24-bit RGB image is written. $flags may be PNG_FILLER_BEFORE or PNG_FILLER_AFTER. An error is produced if $png has bit depth less than 8 π«Ά
This does not change the color type of the image. See the related function set_add_alpha if you want to add an alpha channel.
To test whether your version of libpng supports set_filler, use libpng_supports with argument '"READ_FILLER"':
if (libpng_supports ('READ_FILLER')) {
# do something
}
This function corresponds to png_set_filler in libpng.
set_gamma π₯
$png->set_gamma ($screen_gamma, $output_gamma);
βπ€ͺβ Untested. $screen_gamma and $output_gamma should contain floating-point arguments. See the libpng manual for details.
To test whether your version of libpng supports set_gamma, use libpng_supports with argument '"READ_GAMMA"':
if (libpng_supports ('READ_GAMMA')) {
# do something
}
This function corresponds to png_set_gamma in libpng.
set_quantize π
$png->set_quantize (\@palette, $ncolors, \@histogram, $full_quantize);
The @palette part must be set to a palette similar to set_PLTE. $ncolors must be the length of @palette or shorter. @histogram can be an empty array or if not it needs to be an array of integers of exactly the same length as @palette. The integers represent the frequency of the colors in @palette. These integers can range from 0 to 65355. Larger values or negative values cause an error. The final argument, $full_quantize, should be 1 for RGB images or 0 for paletted images π
Experiments in quantization
This example program experiments with two ways to quantize a PNG image, first of all using a completely random palette, and second using colors picked from the image at random:
use utf8;
use FindBin '$Bin';
use Image::PNG::Libpng ':all';
my $file = "wave.png";
my $ncolors = 40;
my $palette = randompalette ($ncolors);
write_with_palette ($file, $palette, $ncolors, [], "random");
my $picked = points ($file, $ncolors);
my @hist = (1) x $ncolors;
write_with_palette ($file, $picked, $ncolors, \@hist, "picked");
exit;
sub write_with_palette
{
my ($file, $palette, $ncolors, $hist, $name) = @_;
my $rpng = create_reader ($file);
$rpng->set_quantize ($palette, $ncolors, $hist, 1);
$rpng->read_png ();
my $wpng = copy_png ($rpng);
$wpng->set_PLTE ($palette);
$wpng->write_png_file ("$name-$file");
}
sub points
{
my ($pngfile, $ncolors) = @_;
my $png = read_png_file ($pngfile);
my $rows = $png->get_rows ();
my $h = $png->height ();
my $w = $png->width ();
my $ch = $png->get_channels ();
my @p;
for (0..$ncolors-1) {
my $x = int (rand ($w));
my $y = int (rand ($h));
my $row = $rows->[$y];
my @pix = split ('', substr ($row, $x*$ch, $ch));
push @p, {
red => ord ($pix[0]),
green => ord ($pix[1]),
blue => ord ($pix[2]),
};
}
return \@p;
}
sub randompalette
{
my ($n) = @_;
my @p;
for (0..$n-1) {
my %color;
for my $c (qw!red green blue!) {
$color{$c} = int (rand (256))
}
push @p, \%color;
}
return \@p;
}
(This example is included as examples/q.pl at https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/q.pl in the distribution.) π
examples/wave.png is included in the distribution β https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/wave.png πΈ
examples/random-wave.png is included in the distribution β https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/random-wave.png π¦
examples/picked-wave.png is included in the distribution β https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/picked-wave.png π
set_rgb_to_gray π
$png->set_rgb_to_gray ();
$png->set_rgb_to_gray ($error_action, $red_weight, $green_weight);
Convert a PNG image from RGB (colored) to gray. See the libpng manual for details.
Without arguments, the libpng default values are used for $red_weight and $green_weight, and an error action of none is chosen. If the error action is set to a value of PNG_ERROR_ACTION_WARN or PNG_ERROR_ACTION_ERROR, pixels in the RGB image where the R, G and B values are not equal will cause a warning or error respectively. To get the default values for $red_weight or $green_weight, use any negative value. See the libpng manual for details π
If you choose PNG_ERROR_ACTION_NONE you can find out whether there were non-RGB pixels in your image using get_rgb_to_gray_status.
This function corresponds to png_png_set_rgb_to_gray in libpng with $error_action having a default value of PNG_ERROR_ACTION_NONE, and $red_weight and $green_weight both set to negative values.
Convert a colored image to gray
use utf8;
use FindBin '$Bin';
use Image::PNG::Libpng ':all';
use Image::PNG::Const ':all';
my $png = create_reader ("$Bin/luv.png");
$png->read_info ();
$png->set_rgb_to_gray ();
$png->read_image ();
$png->read_end ();
my $wpng = $png->copy_png ();
my $ihdr = $wpng->get_IHDR ();
$ihdr->{color_type} = PNG_COLOR_TYPE_GRAY_ALPHA;
$wpng->set_IHDR ($ihdr);
$wpng->write_png_file ("$Bin/grayface.png");
This example is included as examples/rgb-to-gray.pl β you can find it at https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/rgb-to-gray.pl β in the distribution. β¨
examples/grayface.png β https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/examples/grayface.png β is included in the distribution too. π
set_user_limits
$png->set_user_limits ($width, $height);
This lets you override libpng's restrictions to one million pixels in width and one million pixels in height for a PNG image. Lowkey powerful, bestie. π
This function corresponds to png_set_user_limits in libpng.
β¨ Other functions β¨
This section has other functions that don't correspond to anything in libpng itself β they're utility extras that got added to the module. Cute little bonus round, fr fr. π«Ά
color_type_channels
my $channels = color_type_channels ('PNG_COLOR_TYPE_RGB_ALPHA');
Returns the number of channels β aka the number of components of one pixel β of the specified color type. π
copy_row_pointers
$png->copy_row_pointers ($row_pointers);
This lets XS routines directly set the value of the row pointers for the PNG image. The memory is copied, so whatever is in the row pointers can be freed immediately after calling this. But the image data it points to is not copied, so that data needs to stay valid until the PNG is written. Don't free that part early, bestie π
The Perl scalar $row_pointers should be set up something like the following, where rp is the C pointer:
RETVAL = newSViv (PTR2IV (rp));
It's extracted from the Perl scalar using:
rp = INT2PTR (png_byte **, SvIV (row_pointers));
where row_pointers is the SV * corresponding to $row_pointers in the Perl script. See also set_row_pointers, which does the same thing but takes ownership of the memory. π«Ά
get_chunk
my $timechunk = $png->get_chunk ('tIME');
Get the specified chunk. This produces a fatal error if you ask for the IDAT (image data) chunk β use get_rows instead, okay? It returns undef if you ask for an unknown chunk name.
This is used by pnginspect to get the valid chunks. See also set_chunk. π
get_internals
my ($png_struct, $png_info) = get_internals ($png);
This function returns the 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 pointers, use something like this:
void access_png_internals (png, info)
SV * png;
SV * info;
PREINIT:
png_struct * cpng;
png_info * cinfo;
CODE:
cpng = INT2PTR (png_struct *, SvIV (png));
cinfo = INT2PTR (png_info *, SvIV (info));
An example exists in Image::PNG::Cairo. π
get_tRNS_palette
$png->get_tRNS_palette ();
This is not a libpng-equivalent function. Periodt.
image_data_diff
my $diff = image_data_diff ('a.png', 'b.png');
This returns the undefined value if the image data in a.png is the same as the image data in b.png. If the image data is different, it returns a readable text message describing the first difference found β for example, the height is different, or row 0 of the image data is different, etc. π
This function is used in testing this module. See also png_compare.
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 this was compiled with supports or does not support a particular facility. For the most part, these are taken directly from the C macros of libpng. β¨
The possible arguments to libpng_supports are:
16BITALIGNED_MEMORYARM_NEON_APIBENIGN_ERRORSBENIGN_READ_ERRORSBENIGN_WRITE_ERRORSbKGDβ Does libpng support thebKGDchunk?BUILD_GRAYSCALE_PALETTEBUILTIN_BSWAP16CHECK_FOR_INVALID_INDEXcHRMβ Does libpng support thecHRMchunk?cHRM_XYZβ This is local toImage::PNG::Libpngand not a part of libpng itself. It was necessary to extend libpng because the conditional compilation macro forset_cHRM_XYZandget_cHRM_XYZ,PNG_cHRM_SUPPORTED, is defined (true) for old libpngs which do not actually contain these functions.CHUNK_CACHE_MAXβ This is local toImage::PNG::Libpngand not a part of libpng itself. It was necessary to extend libpng because the conditional compilation macro forset_chunk_cache_maxandget_chunk_cache_max,PNG_USER_LIMITS_SUPPORTED, is defined (true) for old libpngs which do not actually contain these functions.CHUNK_MALLOC_MAXβ This is local toImage::PNG::Libpngand not a part of libpng itself. The reasons for this are identical to those forCHUNK_CACHE_MAX.COLORSPACECONSOLE_IOCONVERT_tIMEβ This is related to two deprecated functions,png_convert_from_time_tandpng_convert_from_struct_tm. βCONVERT_tIMEEASY_ACCESSERROR_NUMBERSERROR_TEXTeXIfβ Does libpng support theeXIfchunk?FIXED_POINTFIXED_POINT_MACROFLOATING_ARITHMETICFLOATING_POINTFORMAT_AFIRSTFORMAT_BGRgAMAβ Does libpng support thegAMAchunk?GAMMAGET_PALETTE_MAXβ Does your libpng supportget_palette_max?HANDLE_AS_UNKNOWNHANDLE_AS_UNKNOWNhISTβ Does libpng support thehISTchunk?iCCPβ Does libpng support theiCCPchunk?INCH_CONVERSIONSINFO_IMAGEIO_STATEiTXtβ Does libpng support international text?MIPS_MSA_APIMNG_FEATURESoFFsβ Does libpng support theoFFschunk?pCALβ Does libpng support thepCALextension?PEDANTIC_WARNINGSpHYsβ Does libpng support thepHYschunk?POINTER_INDEXINGPOWERPC_VSX_APIPROGRESSIVE_READREADβ Can libpng read PNGs?READ_16_TO_8READ_ALPHA_MODEβ Seeset_alpha_mode.READ_BACKGROUNDβ Seeset_background.READ_BGRβ Seeset_bgr.READ_COMPOSITE_NODIVREAD_COMPRESSED_TEXTREAD_EXPANDREAD_EXPAND_16READ_FILLERREAD_GAMMAβ Seeset_gamma.READ_GRAY_TO_RGBREAD_INTERLACINGREAD_INT_FUNCTIONSREAD_INVERTREAD_INVERT_ALPHAREAD_OPT_PLTEREAD_PACKREAD_PACKSWAPREAD_QUANTIZEREAD_RGB_TO_GRAYREAD_SCALE_16_TO_8READ_SHIFTREAD_STRIP_16_TO_8READ_STRIP_ALPHAREAD_SWAPREAD_SWAP_ALPHAREAD_tEXtREAD_TRANSFORMSREAD_USER_TRANSFORMREAD_zTXtSAVE_INT_32SAVE_UNKNOWN_CHUNKSsBITβ Does libpng support thesBITchunk?sCALβ Does libpng support thesCALextension? This actually tests for the presence of theget_sCAL_s/set_sCAL_sfunctions, so its behaviour is dependent on other factors for versions1.2and1.4of libpng.SEQUENTIAL_READSETJMPSET_OPTIONSET_UNKNOWN_CHUNKSSET_USER_LIMITSSIMPLIFIED_READSIMPLIFIED_READ_AFIRSTSIMPLIFIED_WRITESIMPLIFIED_WRITE_AFIRSTSIMPLIFIED_WRITE_BGRSIMPLIFIED_WRITE_STDIOsPLTβ Does libpng supportsPLTchunks?sRGBβ Does libpng support thesRGBchunk?STDIOSTORE_UNKNOWN_CHUNKSTEXTβ Does libpng support text?tEXtβ Does libpng supporttEXtchunks?tIMEβ Does libpng support thetIMEchunk?TIME_RFC1123tRNSβ Does libpng support thetRNSchunk?UNKNOWN_CHUNKSβ Does libpng support unknown chunks? SeePrivate chunks.USER_CHUNKSUSER_LIMITSβ Does libpng supportset_user_limitsand the related functionsget_user_width_max, andget_user_height_max?USER_LIMITSUSER_MEMUSER_TRANSFORM_INFOUSER_TRANSFORM_PTRWARNINGSWRITEβ Can libpng write pngs?WRITE_BGRWRITE_COMPRESSED_TEXTWRITE_CUSTOMIZE_COMPRESSIONβ Does libpng supportset_compression_leveland similar functions?
βπ€ͺβ It's not very clear that this returns a useful value, sinceset_compression_levelseems to be in libpngs from at least as far back as1.5.1, and yet this macro was only added to libpng in version1.6.13.
WRITE_CUSTOMIZE_ZTXT_COMPRESSIONβ Does libpng supportset_text_compression_leveland similar functions?WRITE_FILLERWRITE_FILTERWRITE_FLUSHWRITE_FLUSH_AFTER_IENDWRITE_INTERLACINGWRITE_INT_FUNCTIONSWRITE_INVERTWRITE_INVERT_ALPHAWRITE_OPTIMIZE_CMFWRITE_PACKWRITE_PACKSWAPWRITE_SHIFTWRITE_SWAPWRITE_SWAP_ALPHAWRITE_TRANSFORMSWRITE_USER_TRANSFORMWRITE_WEIGHTED_FILTERzTXtβ Does libpng supportzTXtchunks?
png_compare
if (png_compare ('a.png', 'b.png') == 0) {
print "The PNGs are the same.\n";
}
This compares the image data in two PNGs and returns 0 if they contain exactly the same image data, or 1 if they contain different image data. For a more detailed comparison, see image_data_diff. This does not compare to see if the PNG files "look like" each other, but whether each pixel contains exactly the same values. Please see Image::Similar for a looser comparison of images. πΈ
This uses the expand transform of libpng to read both the images, so it is able to compare images of different color types. It compares the alpha values as well as the color pixels. See Saving bandwidth for an example of comparing an RGB and a grayscale image. π
read_struct
if ($png->read_struct ()) {
warn "Can't write this, use copy_png to copy it";
}
This returns a true value if $png was created with create_read_struct or allied functions like read_from_scalar, and a false value if $png was created with create_write_struct or allied functions like copy_png. π¦
set_chunk
$png->set_chunk ('tIME', $timechunk);
Set the specified chunk. This produces a fatal error if given an IDAT (image data) chunk β use set_rows instead. It also produces a fatal error if given an unknown chunk name. No cap, it's strict.
The first argument is the chunk name, and then the second argument is a scalar containing whatever the chunk requires β for example, a hash reference for the tIME chunk as described under set_tIME and get_tIME. π
...bestie this one is literally just a lil convenience wrapper made for copy_png's benefit β together with get_valid it's what lets you copy PNG chunks in a cute lil loop instead of going one-by-one like a peasant π
set_image_data
$png->set_image_data ($image_data);
Sets the internal image data pointer to $image_data β¨. $image_data should hold a pointer to memory stored as an SvIV, allocated with Newx or something similar. This hands ownership of that memory over to $png, which will Safefree it when $png gets destroyed β so like, don't go freeing it yourself after, ok? π«Ά And ngl, calling this function with any value doesn't actually change the content of the PNG image itself. It's just pointer bookkeeping, no glow-up for your pixels.
set_row_pointers
$png->set_row_pointers ($row_pointers);
This sets the rows of the PNG image to $row_pointers using png_set_rows πΈ. $row_pointers must contain a pointer to memory stored as an SvIV, allocated with a Perl memory allocator like Newx or a similar function. Same deal as above: ownership of the memory transfers to $png, which will Safefree it when $png is destroyed. Also see copy_row_pointers, which does the exact same thing except it doesn't do the freeing part. iykyk.
split_alpha
my $split = $png->split_alpha ();
my $alpha = $split->{alpha};
my $color = $split->{data};
Splits the alpha channel away from the rest of the data π¦. Heads up: this only works for images with color types PNG_COLOR_TYPE_RGB_ALPHA and PNG_COLOR_TYPE_GRAY_ALPHA. This is not part of the libpng API β it was added to this module to help the author of PDF::Builder out, because accessing PNG images through Perl was being painfully, embarrassingly slow π.
To actually remove the alpha channel from an image, use set_background β check out "Setting the background" for an example. You could also use the transform PNG_TRANSFORM_STRIP_ALPHA in read_png_file, or set_strip_alpha, but lowkey that may leave spurious pixel values chilling in the transparent parts of the image π.
β¨ EXPORTS β¨
Nothing is exported by default, bestie β but literally every function in this module, object methods included, can be exported if you ask nicely π. The export tag 'all' exports everything in the module:
use Image::PNG::Libpng ':all';
That includes all the methods, which you can then use with the $png argument as the first argument. Slay.
π 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 does not use the info structure of libpng. Almost all libpng functions require two initial arguments, a png_structp and a png_infop. But here in Image::PNG::Libpng, both the png and the info are contained inside the object π. If you're the kind of person who needs access to the internals of an Image::PNG::Libpng object (looking at you, C programmers and XS programmers π), you can use get_internals to get at them.
This module also does not support the "end info" structure of PNGs when writing β although those are handled when reading. Noted.
Unused arguments omitted
This module eliminates unevaluated arguments of libpng π§. For example, libpng requires you to pass a pointer to a png_struct just to call the libpng version number function (see "get_libpng_ver"), but it literally ignores that structure. There are many similar instances of unevaluated arguments, and all of them have been eliminated from this module. Bye π
If you're the type who's interested in exactly which libpng arguments get omitted, you can find each instance in the file perl-libpng.c in the top directory of the distribution, at https://fastapi.metacpan.org/source/BKB/Image-PNG-Libpng-0.60/perl-libpng.c, inside the macro UNUSED_ZERO_ARG. Enjoy the rabbit hole π
Useless functions omitted
The functions from libpng which don't do anything have been omitted from this module π Like, why.
Function return values are used to return values
libpng is so inconsistent in its calling conventions, fr fr. 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 then uses the return value to indicate errors. Pick a lane!!
Image::PNG::Libpng uses only the return value. Errors and non-existence are indicated by a return value of the undefined value β¨
And further to that, libpng's error handling is also wildly inconsistent. Some functions use the return value to indicate errors, and some of the functions don't indicate errors at all β they just fail silently π. Even more inconsistently, some of the functions which use the return value to indicate an error use a non-zero value, and some use a zero value, to indicate an error. The chaos. The audacity.
No destructors
Freeing the memory allocated by create_read_struct and create_write_struct is automatically handled by Perl π«Ά You don't gotta do a thing.
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. They're basically retired icons still hanging around the group chat π
Other unimplemented parts of libpng
Memory management functions
The management of memory for libpng objects is handled automatically by this module, so it does not offer an interface to png_malloc and png_free or any of the other libpng memory handling functions π
Error handling functions
This module does not offer an interface to png_error and png_get_error_ptr or any of the other error handling functions of libpng. Instead it redirects the error and warning handlers to Perl's error stream π
Input and 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 β¨
Fixed point functions
There is currently no support for the PNG fixed point functions in this Perl module β that's the functions with the suffix _fixed π
List of unsupported functions
The following functions from the libpng API are unsupported by this module. Brace yourself, it's a long one π€
png_benign_errorβ π See "Error handling functions".png_build_grayscale_paletteβ βπ€ͺβ Undocumented function, but it is part of the public API. Seehttps://github.com/glennrp/libpng/issues/353.
This function builds an evenly-spaced grayscale palette at a specified bit depth into a user-supplied array. It is not used elsewhere in libpng.
png_chunk_benign_errorβ π See "Error handling functions".png_chunk_warningβ π See "Error handling functions".png_convert_from_struct_tmβ π Deprecated in libpng. This function related to thetIMEchunk is deprecated in libpng 1.7.png_convert_from_time_tβ π Deprecated in libpng. This function related to thetIMEchunk is deprecated in libpng 1.7.png_convert_to_rfc1123β π Deprecated in libpng. This function related to thetIMEchunk is deprecated in libpng 1.7.png_convert_to_rfc1123_bufferβ ππͺ This function was deliberately omitted from this module because it doesn't seem useful for Perl programmers.
This function is related to the tIME chunk; it seems fairly superfluous with the many other ways to manipulate time strings already in Perl.
png_data_freerβ π See "Memory management functions".png_freeβ π See "Memory management functions".png_free_dataβ π See "Memory management functions".png_get_cHRM_XYZ_fixedβ π See "Fixed point functions".png_get_cHRM_fixedβ π See "Fixed point functions".png_get_compression_typeβ ππ€‘ See "Useless functions omitted". Useless function which returns 0 since there is only one type of compression.png_get_copyrightβ ππͺ This function was deliberately omitted from this module because it doesn't seem useful for Perl programmers.
This function gives you the copyright string for libpng.
png_get_current_pass_numberpng_get_current_row_numberpng_get_error_ptrβ π See "Error handling functions".png_get_filter_typeβ ππ€‘ See "Useless functions omitted". This function returns the value of the unused fieldfilter_typein the PNG header, which is always 0. See "Unused arguments omitted".png_get_gAMA_fixedβ π See "Fixed point functions".png_get_header_verβ This function was omitted from this module because it merely duplicates another function.
Identical to get_libpng_ver.
png_get_header_versionβ This function was omitted from this module because it merely duplicates another function.
Identical to get_libpng_ver.
png_get_io_chunk_typepng_get_io_ptrpng_get_io_statepng_get_mem_ptrpng_get_pHYs_dpipng_get_pixel_aspect_ratiopng_get_pixel_aspect_ratio_fixedβ π See "Fixed point functions".png_get_pixels_per_inchpng_get_pixels_per_meterpng_get_progressive_ptrβ Incremental reading of PNGs is not handled yet.png_get_sCAL_fixedβ π See "Fixed point functions".png_get_signatureβ ππͺ This function was deliberately omitted from this module because it doesn't seem useful for Perl programmers.
Returns the PNG signature of a PNG you read in.
png_get_uint_31β ππͺ This function was deliberately omitted from this module because it doesn't seem useful for Perl programmers.
This produces an error if the unsigned integer argument is too big for a 31 bit number.
png_get_user_chunk_ptrpng_get_user_height_maxpng_get_user_transform_ptrpng_get_x_offset_inchespng_get_x_offset_inches_fixedβ π See "Fixed point functions".png_get_x_offset_micronspng_get_x_offset_pixelsβ Duplicatesget_oFFs.png_get_x_pixels_per_inchpng_get_x_pixels_per_meterβ Duplicatesget_oFFs.png_get_y_offset_inchespng_get_y_offset_inches_fixedβ π See "Fixed point functions".png_get_y_offset_micronspng_get_y_offset_pixelsβ Duplicatesget_oFFs.png_get_y_pixels_per_inchpng_get_y_pixels_per_meterβ Duplicatesget_oFFs.png_handle_as_unknownpng_image_begin_read_from_filepng_image_begin_read_from_stdiopng_image_finish_readpng_image_freeβ π See "Memory management functions".png_image_write_to_filepng_image_write_to_memoryβ π See "Memory management functions".
And that's the unsupported list β like, all of it, no cap π
png_image_write_to_stdiopng_process_datapng_process_data_pausepng_process_data_skippng_progressive_combine_rowpng_read_rowpng_read_rowspng_reset_zstreamβ π deprecated in libpng, bestie, so likeβ¦ don't. It resets the zstream of the zlib instance that's being used for the image data.png_save_int_32β ππͺ this one was deliberately left out of this module because it doesn't seem useful for Perl programmers. What it does: writes a 32 bit signed number into an octet buffer. Perl people will probably just usepackfor this, and honestly? valid.png_save_uint_16β ππͺ also deliberately omitted, same reason: doesn't seem useful for Perl programmers. It writes a 16 bit number into an octet buffer. Again:pack, babes.png_save_uint_32β ππͺ deliberately omitted for the exact same reason. Writes a 32 bit unsigned number into an octet buffer. Perl programmers will probably usepackfor this. A trilogy ofpackerasure honestly.png_set_alpha_mode_fixedβ π see "Fixed point functions".png_set_background_fixedβ π see "Fixed point functions".png_set_benign_errorsβ π see "Error handling functions".png_set_cHRM_XYZ_fixedβ π see "Fixed point functions".png_set_cHRM_fixedβ π see "Fixed point functions".png_set_check_for_invalid_indexpng_set_compression_methodβ ππ€‘ see "Useless functions omitted". This function in libpng corresponds to the unusedmethodparameter of zlib functions likedeflateInit2. See "zlib documentation". The libpng function literally just produces a warning if the user sets the value to anything but 8 β which is the value of the macroZ_DEFLATEDβ and then lets zlib produce an error. It's giving middle management.png_set_crc_actionβ π see "Error handling functions".png_set_error_fnβ π see "Error handling functions".png_set_filter_heuristicsβ π deprecated in libpng.png_set_filter_heuristics_fixedβ π see "Fixed point functions".png_set_flushpng_set_gAMA_fixedβ π see "Fixed point functions".png_set_gamma_fixedβ π see "Fixed point functions".png_set_interlace_handlingβ incremental writing is not handled. That's the whole note. That's it.png_set_invalidβ π see "Memory management functions".png_set_longjmp_fnβ βπ€ͺβ undocumented function, but it is part of the public API. Chaotic of libpng but okay.png_set_mem_fnβ π see "Memory management functions".png_set_optionpng_set_progressive_read_fnpng_set_read_status_fnpng_set_read_user_chunk_fnpng_set_read_user_transform_fnpng_set_sCAL_fixedβ π see "Fixed point functions".png_set_sRGB_gAMA_and_cHRMpng_set_shiftpng_set_sig_bytesβ ππͺ deliberately omitted from this module because it doesn't seem useful for Perl programmers. Noted and respected.png_set_strip_error_numbersβ ππ€‘ see "Useless functions omitted". Per the libpng manual, "we never got around to actually numbering the error messages", so likeβ¦ yeah, assuming this is not very useful. πpng_set_text_compression_methodβ ππ€‘ see "Useless functions omitted". Unsupported for the same reasons aspng_set_compression_method.png_set_unknown_chunk_locationβ this is related to some kind of bug in version 1.5 and previous of libpng. πpng_set_user_transform_infopng_set_write_status_fnβ π see "Error handling functions".png_set_write_user_transform_fnpng_start_read_imagepng_write_chunkpng_write_chunk_datapng_write_chunk_endpng_write_chunk_startpng_write_flushpng_write_info_before_PLTEpng_write_rowpng_write_rowspng_write_sig
Ok so that whole roster? It's an exhaustive list of unsupported libpng API functions, extracted from the libpng source code using util/api.pl in this module's repository. Exhaustive. Every last one. β¨
π§ Conditional compilation and old libpng versions
So here's the vibe: you can compile a version of the libpng library without support for various things. Like, a libpng with no text chunk support can be created by undefining the C macro PNG_TEXT_SUPPORTED. Wild, but true. This module supports the conditional compilation choices which we're aware of β but if you hit problems using this module because of a conditionally-compiled libpng, then let us know and we'll add the necessary facility. Teamwork, bestie. π«Ά
Currently we test this module against vanilla libpng versions 1.2.59, 1.4.22, 1.5.30, 1.6.47, and 1.6.45 before releases. There doesn't seem to have been a 1.3 or a 1.1 version of libpng. See <http://www.libpng.org/pub/png/pngnews.html>. Versions 1.0 and earlier of libpng are not tested against.
The following issues with older libpng versions may affect users of this module:
cHRM chunk
The get_cHRM_XYZ and set_cHRM_XYZ functions for the cHRM chunk are not present in pre-1.5.5 versions of libpng, but the conditional compilation macro of libpng for these newer functions is the same as for get_cHRM and set_cHRM functions, which are present on older versions of libpng. Messy, right? Because of this, this module includes its own protection macro, accessible via libpng_supports as cHRM_XYZ. These functions are disabled for libpng versions earlier than 1.5.5.
chunk_cache_max
The functions set_chunk_cache_max and get_chunk_cache_max are not protected by a libpng macro, so this module includes its own protection macro, accessible via libpng_supports as CHUNK_CACHE_MAX. These functions are disabled for libpng versions earlier than 1.4.0.
Compression level
Versions of libpng up to 1.5 behave erratically when set_compression_level or other set_compression_* functions are used to alter the compression of the image data. Erratic! π« Testing of compression-related functions is disabled by this Perl module for pre-1.6.13 versions of libpng.
Compression level and zlib-ng
Some people have compiled libpng with a new version of zlib known as zlib-ng. This gives different values for compression than the original zlib. On versions of this module earlier than 0.58, this caused some unimportant but annoying test failures where this module was making exact size comparisons. See <https://github.com/benkasminbullock/image-png-libpng/issues/40>. As far as we know, there is no way to detect whether zlib-ng is being used from Perl, so to support the use of zlib-ng, these tests have been switched off. The disabled tests can be restored by setting the environment variable ORIGINAL_ZLIB to a true value, if you want them. Like, if you really want them:
ORIGINAL_ZLIB=1 prove t/*.t
sCAL chunk
Support for the sCAL chunk is disabled within this module for pre-1.6 versions of libpng. Just how it is. π
Text chunk handling
Versions of libpng up to 1.6.3 produce erratic results with iTXt (international text) chunks. Testing of text-related chunks is disabled by this Perl module for pre-1.6.13 versions of libpng.
π¦ Not all constants are available
Plot twist: some of the libpng constants are defined in pnglibconf.h or pngconf.h, but Image::PNG::Const only looks at png.h to make its constants. So because of that, some constant values like PNG_Z_DEFAULT_COMPRESSION aren't currently available in Image::PNG::Const. This probably should be fixed to extract the constants from the other files in a future version. Future us problem. π
π STANDALONE SCRIPT
There's a standalone script, pnginspect, and it's installed with the distribution. It prints out the contents of the chunks of the PNG file on the command line. That's it, that's the whole feature, and honestly? Iconic. π
π SEE ALSO π
π The PNG specification
The PNG specification <http://www.w3.org/TR/PNG/> (link to W3 consortium) explains the details of the PNG format.
PNG The Definitive Guide by Greg Roelofs β yes, the book bestie. The book "PNG - The Definitive Guide" by Greg Roelofs, published in 1999 by O'Reilly is available online at <http://www.faqs.org/docs/png/> or <http://www.libpng.org/pub/png/book/>. π
π§ 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.
βπ€ͺβ heads up, bestie: 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. For programming in C using libpng, look at the header file png.h. In some cases, you need to look at the source code of the library. π
π Other documentation
There is a collection of function definitions under the title "Interface Definitions for libpng12" at <https://refspecs.linuxbase.org/LSB_4.0.0/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. β¨
π¦ zlib documentation
See <https://zlib.net/manual.html> for the zlib documentation.
ποΈ Other Perl modules on CPAN
These other modules may also be useful. π«Ά
πΈ Alien::PNG
Alien::PNG claims to be a way of "building, finding and using PNG binaries". It may help in installing libpng. We 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. We're interested in hearing feedback from users whether this works or not on various platforms.
πΌοΈ Imager
Imager, Imager::Files and Imager::Files::PNG contain support for reading and writing PNGs via libpng, as well as support for reading and writing various other kinds of image files, changing the images, converting, and more. π
π· Image::ExifTool
Image::ExifTool is a pure Perl (doesn't require a C compiler) solution for accessing the text segments of images. It supports PNG text segments.
π Image::Info
Image::Info gets information out of images. It supports PNG and is written in pure Perl, so it 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::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. π
π€ Image::PNG::Write::BW
Image::PNG::Write::BW writes black and white PNGs from strings.
π Image::Size
If you only need to read the sizes of images, Image::Size works with PNG and other image formats.
π AUTHOR π
Ben Bullock, <benkasminbullock@gmail.com> π«Ά
π COPYRIGHT & LICENCE π
This package and associated files are copyright (C) 2011-2026 Ben Bullock.
You can use, copy, modify and redistribute this package and associated files under the Perl Artistic Licence or the GNU General Public Licence. β
π okay that's the whole page, bestie β this one was served up byperl v5.42.3on2026-08-19, and it'sImage:...Libpng(3pm). bye! π¦π
π¦ where this page comes from
- ubuntu stonking: libimage-png-libpng-perl 0.60-1build1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms