From 07d9c639c6df63309633567443f4d2e93f91afc6 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Tue, 1 Apr 2008 09:48:59 +0000 Subject: [PATCH] - writing a 2 or 4 channel image to a BMP file will now write that image as if composited against a background, black by default, overridable with the i_background tag/parameter. http://rt.cpan.org/Ticket/Display.html?id=30075 --- Changes | 15 ++++++++++----- bmp.c | 19 +++++++++++++------ t/t107bmp.t | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/Changes b/Changes index 8eefac5a..9b32bd52 100644 --- a/Changes +++ b/Changes @@ -41,16 +41,21 @@ Imager 0.63 - unreleased bugzilla. http://rt.cpan.org/Ticket/Display.html?id=32926 - - writing a 2 or 4 channel image to a JPEG will now write that image as - if composited against a background, black by default, overridable - with the i_background tag/parameter. + - writing a 2 or 4 channel image to a JPEG file will now write that + image as if composited against a background, black by default, + overridable with the i_background tag/parameter. https://rt.cpan.org/Ticket/Display.html?id=29876 - - writing a 2 or 4 channel image to a PGM/PPM will now write that - image as if composited against a background, black by default, + - writing a 2 or 4 channel image to a PGM/PPM file will now write + that image as if composited against a background, black by default, overridable with the i_background tag/parameter. http://rt.cpan.org/Ticket/Display.html?id=30074 + - writing a 2 or 4 channel image to a BMP file will now write that + image as if composited against a background, black by default, + overridable with the i_background tag/parameter. + http://rt.cpan.org/Ticket/Display.html?id=30075 + Bug fixes: - Imager::Matrix2d->translate() now only requires one of the x or y diff --git a/bmp.c b/bmp.c index e7fc54fd..7c3bb4d0 100644 --- a/bmp.c +++ b/bmp.c @@ -575,9 +575,6 @@ write_8bit_data(io_glue *ig, i_img *im) { return 1; } -static int bgr_chans[] = { 2, 1, 0, }; -static int grey_chans[] = { 0, 0, 0, }; - /* =item write_24bit_data(ig, im) @@ -593,6 +590,9 @@ write_24bit_data(io_glue *ig, i_img *im) { unsigned char *samples; int y; int line_size = 3 * im->xsize; + i_color bg; + + i_get_file_background(im, &bg); /* just in case we implement a direct format with 2bytes/pixel (unlikely though) */ @@ -605,11 +605,18 @@ write_24bit_data(io_glue *ig, i_img *im) { if (!write_bmphead(ig, im, 24, line_size * im->ysize)) return 0; - chans = im->channels >= 3 ? bgr_chans : grey_chans; - samples = mymalloc(line_size); /* checked 29jun05 tonyc */ + samples = mymalloc(4 * im->xsize); memset(samples, 0, line_size); for (y = im->ysize-1; y >= 0; --y) { - i_gsamp(im, 0, im->xsize, y, samples, chans, 3); + unsigned char *samplep = samples; + int x; + i_gsamp_bg(im, 0, im->xsize, y, samples, 3, &bg); + for (x = 0; x < im->xsize; ++x) { + unsigned char tmp = samplep[2]; + samplep[2] = samplep[0]; + samplep[0] = tmp; + samplep += 3; + } if (ig->writecb(ig, samples, line_size) < 0) { i_push_error(0, "writing image data"); myfree(samples); diff --git a/t/t107bmp.t b/t/t107bmp.t index c65cddd8..6a9496aa 100644 --- a/t/t107bmp.t +++ b/t/t107bmp.t @@ -1,8 +1,8 @@ #!perl -w use strict; -use Test::More tests => 201; +use Test::More tests => 211; use Imager qw(:all); -use Imager::Test qw(test_image_raw is_image); +use Imager::Test qw(test_image_raw is_image is_color3); init_log("testout/t107bmp.log",1); my $debug_writes = 0; @@ -617,6 +617,36 @@ for my $comp (@comp) { ok(grep($_ eq 'bmp', Imager->write_types), "check bmp in write types"); } +{ + # RT #30075 + # give 4/2 channel images a background color when saving to BMP + my $im = Imager->new(xsize=>16, ysize=>16, channels=>4); + $im->box(filled => 1, xmin => 8, color => '#FFE0C0'); + $im->box(filled => 1, color => NC(0, 192, 192, 128), + ymin => 8, xmax => 7); + ok($im->write(file=>"testout/t107_alpha.bmp", type=>'bmp'), + "should succeed writing 4 channel image"); + my $imread = Imager->new; + ok($imread->read(file => 'testout/t107_alpha.bmp'), "read it back"); + is_color3($imread->getpixel('x' => 0, 'y' => 0), 0, 0, 0, + "check transparent became black"); + is_color3($imread->getpixel('x' => 8, 'y' => 0), 255, 224, 192, + "check color came through"); + is_color3($imread->getpixel('x' => 0, 'y' => 15), 0, 96, 96, + "check translucent came through"); + my $data; + ok($im->write(data => \$data, type => 'bmp', i_background => '#FF0000'), + "write with red background"); + ok($imread->read(data => $data, type => 'bmp'), + "read it back"); + is_color3($imread->getpixel('x' => 0, 'y' => 0), 255, 0, 0, + "check transparent became red"); + is_color3($imread->getpixel('x' => 8, 'y' => 0), 255, 224, 192, + "check color came through"); + is_color3($imread->getpixel('x' => 0, 'y' => 15), 127, 96, 96, + "check translucent came through"); +} + sub write_test { my ($im, $filename) = @_; local *FH;