[rt #85746] add support for libpng 1.6
authorTony Cook <tony@develop-help.com>
Fri, 7 Jun 2013 13:07:40 +0000 (23:07 +1000)
committerTony Cook <tony@develop-help.com>
Fri, 7 Jun 2013 13:07:40 +0000 (23:07 +1000)
1.6 changed the default to ignore "benign" read errors, I now unignore
them explicitly with an option to ignore them.

PNG/Makefile.PL
PNG/PNG.pm
PNG/PNG.xs
PNG/README
PNG/impng.c
PNG/impng.h
PNG/t/10png.t
PNG/testimg/badcrc.png
lib/Imager/Files.pod

index 1481744..a98e174 100644 (file)
@@ -68,8 +68,14 @@ else {
 
 require Imager::Probe;
 
+# these are mostly needed when pkg-config isn't available
 my @alts =
   (
+   {
+    altname => "v1.6",
+    incsuffix => "libpng16",
+    libbase => "png16",
+   },
    {
     altname => "v1.5",
     incsuffix => "libpng15",
@@ -96,7 +102,7 @@ my %probe =
   (
    name => "PNG",
    altname => "Generic",
-   pkg => [ qw/libpng15 libpng14 libpng12 libpng10 libpng/ ],
+   pkg => [ qw/libpng libpng16 libpng15 libpng14 libpng12 libpng10/ ],
    inccheck => sub { -e File::Spec->catfile($_[0], "png.h") },
    libbase => "png",
    testcode => _png_test_code(),
index d0433ba..85de61c 100644 (file)
@@ -4,7 +4,7 @@ use Imager;
 use vars qw($VERSION @ISA);
 
 BEGIN {
-  $VERSION = "0.87";
+  $VERSION = "0.88";
 
   require XSLoader;
   XSLoader::load('Imager::File::PNG', $VERSION);
@@ -16,7 +16,10 @@ Imager->register_reader
    single => 
    sub { 
      my ($im, $io, %hsh) = @_;
-     $im->{IMG} = i_readpng_wiol($io);
+     my $flags = 0;
+     $hsh{png_ignore_benign_errors}
+       and $flags |= IMPNG_READ_IGNORE_BENIGN_ERRORS;
+     $im->{IMG} = i_readpng_wiol($io, $flags);
 
      unless ($im->{IMG}) {
        $im->_set_error(Imager->_error_as_msg);
index cc90923..1048b44 100644 (file)
@@ -14,8 +14,9 @@ DEFINE_IMAGER_CALLBACKS;
 MODULE = Imager::File::PNG  PACKAGE = Imager::File::PNG
 
 Imager::ImgRaw
-i_readpng_wiol(ig)
+i_readpng_wiol(ig, flags=0)
         Imager::IO     ig
+       int            flags
 
 undef_int
 i_writepng_wiol(im, ig)
@@ -25,5 +26,12 @@ i_writepng_wiol(im, ig)
 unsigned
 i_png_lib_version()
 
+int
+IMPNG_READ_IGNORE_BENIGN_ERRORS()
+  CODE:
+    RETVAL = IMPNG_READ_IGNORE_BENIGN_ERRORS;
+  OUTPUT:
+    RETVAL
+
 BOOT:
        PERL_INITIALIZE_IMAGER_CALLBACKS;
index d786557..4b2fe74 100644 (file)
@@ -2,6 +2,9 @@ Imager::File::PNG provides PNG file format support for Imager.
 
 It requires libpng, including development files, to be installed.
 
+libpng 1.2 or later is supported, with minor extra features with
+libpng 1.4 and libpng 1.5.3.
+
 For Linux distributions this typically requires installation of the
 associated -dev or -devel package.
 
index 1ede7f8..dcc8524 100644 (file)
@@ -1,6 +1,7 @@
 #include "impng.h"
 #include "png.h"
 #include <stdlib.h>
+#include <string.h>
 
 /* this is a way to get number of channels from color space 
  * Color code to channel number */
@@ -270,7 +271,7 @@ static void
 cleanup_read_state(i_png_read_statep);
 
 i_img*
-i_readpng_wiol(io_glue *ig) {
+i_readpng_wiol(io_glue *ig, int flags) {
   i_img *im = NULL;
   png_structp png_ptr;
   png_infop info_ptr;
@@ -293,7 +294,17 @@ i_readpng_wiol(io_glue *ig) {
     return NULL;
   }
   png_set_read_fn(png_ptr, (png_voidp) (ig), wiol_read_data);
-  
+
+#if PNG_LIBPNG_VER >= 10400
+  png_set_benign_errors(png_ptr, (flags & IMPNG_READ_IGNORE_BENIGN_ERRORS) ? 1 : 0);
+#else
+  if (flags & IMPNG_READ_IGNORE_BENIGN_ERRORS) {
+    i_push_error(0, "libpng too old to ignore benign errors");
+    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+    return NULL;
+  }
+#endif
+
   info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL) {
     png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
@@ -308,7 +319,7 @@ i_readpng_wiol(io_glue *ig) {
     cleanup_read_state(&rs);
     return NULL;
   }
-  
+
   /* we do our own limit checks */
   png_set_user_limits(png_ptr, PNG_DIM_MAX, PNG_DIM_MAX);
 
index ed4f180..af8225a 100644 (file)
@@ -3,7 +3,10 @@
 
 #include "imext.h"
 
-i_img    *i_readpng_wiol(io_glue *ig);
+i_img    *i_readpng_wiol(io_glue *ig, int flags);
+
+#define IMPNG_READ_IGNORE_BENIGN_ERRORS 1
+
 undef_int i_writepng_wiol(i_img *im, io_glue *ig);
 unsigned i_png_lib_version(void);
 
index 8b332d3..4cabe53 100644 (file)
@@ -10,7 +10,7 @@ my $debug_writes = 1;
 
 init_log("testout/t102png.log",1);
 
-plan tests => 248;
+plan tests => 249;
 
 # this loads Imager::File::PNG too
 ok($Imager::formats{"png"}, "must have png format");
@@ -178,6 +178,16 @@ EOS
   is($im->errstr, "IHDR: CRC error", "check error message");
 }
 
+SKIP:
+{ # ignoring "benign" errors
+  Imager::File::PNG::i_png_lib_version() > 10400
+      or skip "Cannot skip benign errors in libpng this old", 1;
+  my $im = Imager->new;
+  ok($im->read(file => "testimg/badcrc.png", type => "png",
+              png_ignore_benign_errors => 1),
+     "read bad crc with png_ignore_benign_errors");
+}
+
 { # write error reporting
   my $im = test_image();
   ok(!$im->write(type => "png", callback => limited_write(1), buffered => 0),
index 36f6d6b..c6e391b 100644 (file)
Binary files a/PNG/testimg/badcrc.png and b/PNG/testimg/badcrc.png differ
index b5e70e2..88f5dc6 100644 (file)
@@ -1473,6 +1473,18 @@ C<i_background> - set from the C<sBKG> when reading an image file.
 
 =back
 
+=for stopwords
+CRC
+
+X<png_ignore_benign_errors>If you're using F<libpng> 1.4 or later, you
+can choose to ignore file format errors the authors of F<libpng>
+consider I<benign>, this includes at least CRC errors and palette
+index overflows.  Do this by supplying a true value for the
+C<png_ignore_benign_errors> parameter to the read() method:
+
+  $im->read(file => "foo.png", png_ignore_benign_errors => 1)
+    or die $im->errstr;
+
 =head2 ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)
 
 Icon and Cursor files are very similar, the only differences being a