- writing a 2 or 4 channel image to a BMP file will now write that
authorTony Cook <tony@develop=help.com>
Tue, 1 Apr 2008 09:48:59 +0000 (09:48 +0000)
committerTony Cook <tony@develop=help.com>
Tue, 1 Apr 2008 09:48:59 +0000 (09:48 +0000)
   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
bmp.c
t/t107bmp.t

diff --git a/Changes b/Changes
index 8eefac5..9b32bd5 100644 (file)
--- 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 e7fc54f..7c3bb4d 100644 (file)
--- 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);
index c65cddd..6a9496a 100644 (file)
@@ -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;