Permalink
Browse files

PNG re-work: process the bKGD chunk into an i_background tag

  • Loading branch information...
tonycoz committed Apr 16, 2012
1 parent 86464bb commit 6fa6c8eeaba9314b330bafc0d3895227865af785
Showing with 81 additions and 5 deletions.
  1. +61 −3 PNG/impng.c
  2. +4 −2 PNG/t/10png.t
  3. BIN PNG/testimg/comment.png
  4. BIN PNG/testimg/cover.png
  5. +16 −0 fileformatdocs/pngdump.pl
View
@@ -276,7 +276,7 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
}
static void
-get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr, int bit_depth);
+get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr, int bit_depth, int color_type);
typedef struct {
char *warnings;
@@ -370,7 +370,7 @@ i_readpng_wiol(io_glue *ig) {
}
if (im)
- get_png_tags(im, png_ptr, info_ptr, bit_depth);
+ get_png_tags(im, png_ptr, info_ptr, bit_depth, color_type);
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
@@ -685,7 +685,8 @@ text_tags[] = {
static const int text_tags_count = sizeof(text_tags) / sizeof(*text_tags);
static void
-get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr, int bit_depth) {
+get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr,
+ int bit_depth, int color_type) {
png_uint_32 xres, yres;
int unit_type;
@@ -806,6 +807,63 @@ get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr, int bit_depth)
i_tags_set(&im->tags, "png_time", time_formatted, -1);
}
}
+
+ {
+ png_color_16 *back;
+ i_color c;
+
+ if (png_get_bKGD(png_ptr, info_ptr, &back)) {
+ switch (color_type) {
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ {
+ /* lib png stores the raw gray value rather than scaling it
+ to 16-bit (or 8), we use 8-bit color for i_background */
+
+ int gray;
+ switch (bit_depth) {
+ case 16:
+ gray = back->gray >> 8;
+ break;
+ case 8:
+ gray = back->gray;
+ break;
+ case 4:
+ gray = 0x11 * back->gray;
+ break;
+ case 2:
+ gray = 0x55 * back->gray;
+ break;
+ case 1:
+ gray = back->gray ? 0xFF : 0;
+ break;
+ default:
+ gray = 0;
+ }
+ c.rgb.r = c.rgb.g = c.rgb.b = gray;
+ break;
+ }
+
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ {
+ c.rgb.r = bit_depth == 16 ? (back->red >> 8) : back->red;
+ c.rgb.g = bit_depth == 16 ? (back->green >> 8) : back->green;
+ c.rgb.b = bit_depth == 16 ? (back->blue >> 8) : back->blue;
+ break;
+ }
+
+ case PNG_COLOR_TYPE_PALETTE:
+ c.rgb.r = back->red;
+ c.rgb.g = back->green;
+ c.rgb.b = back->blue;
+ break;
+ }
+
+ c.rgba.a = 255;
+ i_tags_set_color(&im->tags, "i_background", 0, &c);
+ }
+ }
}
static int
View
@@ -10,7 +10,7 @@ my $debug_writes = 1;
init_log("testout/t102png.log",1);
-plan tests => 210;
+plan tests => 211;
# this loads Imager::File::PNG too
ok($Imager::formats{"png"}, "must have png format");
@@ -579,8 +579,10 @@ SKIP:
is($im->tags(name => "png_interlace"), "0", "no interlace");
is($im->tags(name => "png_interlace_name"), "none", "no interlace (text)");
is($im->tags(name => "png_srgb_intent"), "0", "srgb perceptual");
- is($im->tags(name => "png_time"), "2012-04-15T03:36:50",
+ is($im->tags(name => "png_time"), "2012-04-16T07:37:36",
"modification time");
+ is($im->tags(name => "i_background"), "color(255,255,255,255)",
+ "background color");
}
sub limited_write {
View
Binary file not shown.
View
Binary file not shown.
View
@@ -29,6 +29,7 @@
}
my $colour_type;
+my $bits;
my $sline_len;
my $sline_left = 0;
my $row = 0;
@@ -54,6 +55,7 @@
Interlace: $inter
EOS
$colour_type = $ct;
+ $bits = $d;
my $channels = $ct == 2 ? 3 : $ct == 4 ? 2 : $ct == 6 ? 4 : 0;
my $bitspp = $channels * $d;
$sline_len = int((($w * $bitspp) + 7) / 8);
@@ -122,6 +124,20 @@
my @when = unpack("nCCCCC", $payload);
printf " Date: %d-%02d-%02d %02d:%02d:%02d\n", @when;
}
+ elsif ($type eq 'bKGD') {
+ if ($colour_type == 2 || $colour_type == 6) {
+ my @rgb = unpack("nnn", $payload);
+ printf " Background: rgb$bits(%d,%d,%d)\n", @rgb;
+ }
+ elsif ($colour_type == 0 || $colour_type == 4) {
+ my $g = unpack("n", $payload);
+ printf " Background: grey$bits(%d)\n", $g;
+ }
+ if ($colour_type == 3) {
+ my $index = unpack("C", $payload);
+ printf " Background: index(%d)\n", $index;
+ }
+ }
elsif ($type eq "IDAT" && $image) {
$sline_len
or die "IDAT before IHDR!?";

0 comments on commit 6fa6c8e

Please sign in to comment.