Permalink
Browse files

PNG re-work: support writing 16-bit/sample images

  • Loading branch information...
tonycoz committed Apr 14, 2012
1 parent b8961d0 commit d9610331e256aefb8d97f265ad74ae8e9a7c1c85
Showing with 84 additions and 4 deletions.
  1. +49 −2 PNG/impng.c
  2. +35 −2 PNG/t/10png.t
View
@@ -24,6 +24,9 @@ read_bilevel(png_structp png_ptr, png_infop info_ptr, i_img_dim width, i_img_dim
static int
write_direct8(png_structp png_ptr, png_infop info_ptr, i_img *im);
+static int
+write_direct16(png_structp png_ptr, png_infop info_ptr, i_img *im);
+
static int
write_paletted(png_structp png_ptr, png_infop info_ptr, i_img *im, int bits);
@@ -154,7 +157,7 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
fprintf(stderr, "Internal error, channels = %d\n", channels);
abort();
}
- bits = 8;
+ bits = im->bits > 8 ? 16 : 8;
mm_log((1, "i_writepng: direct output\n"));
}
@@ -247,7 +250,13 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
return 0;
}
}
- else {
+ else if (bits == 16) {
+ if (!write_direct16(png_ptr, info_ptr, im)) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ return 0;
+ }
+ }
+ else {
if (!write_direct8(png_ptr, info_ptr, im)) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return 0;
@@ -800,6 +809,44 @@ write_direct8(png_structp png_ptr, png_infop info_ptr, i_img *im) {
return 1;
}
+static int
+write_direct16(png_structp png_ptr, png_infop info_ptr, i_img *im) {
+ unsigned *data, *volatile vdata = NULL;
+ unsigned char *tran_data, * volatile vtran_data = NULL;
+ i_img_dim samples_per_row = im->xsize * im->channels;
+
+ i_img_dim y;
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ if (vdata)
+ myfree(vdata);
+ if (vtran_data)
+ myfree(vtran_data);
+
+ return 0;
+ }
+
+ png_write_info(png_ptr, info_ptr);
+
+ vdata = data = mymalloc(samples_per_row * sizeof(unsigned));
+ vtran_data = tran_data = mymalloc(samples_per_row * 2);
+ for (y = 0; y < im->ysize; y++) {
+ i_img_dim i;
+ unsigned char *p = tran_data;
+ i_gsamp_bits(im, 0, im->xsize, y, data, NULL, im->channels, 16);
+ for (i = 0; i < samples_per_row; ++i) {
+ p[0] = data[i] >> 8;
+ p[1] = data[i] & 0xff;
+ p += 2;
+ }
+ png_write_row(png_ptr, (png_bytep)tran_data);
+ }
+ myfree(tran_data);
+ myfree(data);
+
+ return 1;
+}
+
static int
write_paletted(png_structp png_ptr, png_infop info_ptr, i_img *im, int bits) {
unsigned char *data, *volatile vdata = NULL;
View
@@ -2,15 +2,15 @@
use strict;
use Imager qw(:all);
use Test::More;
-use Imager::Test qw(test_image_raw test_image is_image);
+use Imager::Test qw(test_image_raw test_image is_image is_imaged test_image_16 test_image_double);
my $debug_writes = 1;
-d "testout" or mkdir "testout";
init_log("testout/t102png.log",1);
-plan tests => 192;
+plan tests => 204;
# this loads Imager::File::PNG too
ok($Imager::formats{"png"}, "must have png format");
@@ -535,6 +535,39 @@ SKIP:
is($in->tags(name => "png_bits"), 1, "1 bit representation");
}
+SKIP:
+{
+ my $im = test_image_16();
+ ok($im->write(file => "testout/rgb16.png", type => "png"),
+ "write 16-bit/sample image")
+ or diag("Could not write rgb16.png: ".$im->errstr);
+ my $in = Imager->new(file => "testout/rgb16.png")
+ or diag("Could not read rgb16.png: ".Imager->errstr);
+ ok($in, "read rgb16.png back in")
+ or skip("Could not load image to check", 4);
+ is_imaged($in, $im, 0, "check image matches");
+ is($in->bits, 16, "check we got a 16-bit image");
+ is($in->type, "direct", "check it's direct");
+ is($in->tags(name => "png_bits"), 16, "check png_bits");
+}
+
+SKIP:
+{
+ my $im = test_image_double();
+ my $cmp = $im->to_rgb16;
+ ok($im->write(file => "testout/rgbdbl.png", type => "png"),
+ "write double/sample image - should write as 16-bit/sample")
+ or diag("Could not write rgbdbl.png: ".$im->errstr);
+ my $in = Imager->new(file => "testout/rgbdbl.png")
+ or diag("Could not read rgbdbl.png: ".Imager->errstr);
+ ok($in, "read pngdbl.png back in")
+ or skip("Could not load image to check", 4);
+ is_imaged($in, $cmp, 0, "check image matches");
+ is($in->bits, 16, "check we got a 16-bit image");
+ is($in->type, "direct", "check it's direct");
+ is($in->tags(name => "png_bits"), 16, "check png_bits");
+}
+
sub limited_write {
my ($limit) = @_;

0 comments on commit d961033

Please sign in to comment.