From 35f405264be186b7f5bce96036318946376196df Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Fri, 11 Nov 2005 11:04:23 +0000 Subject: [PATCH] - setmask() now returns true on success and reports a missing mask parameter. - double per sample images were ignoring the channel mask. --- Changes | 3 ++ Imager.pm | 15 ++++++++- imagei.h | 3 ++ imgdouble.c | 60 +++++++++++++++++++++++++++------- t/t022double.t | 88 ++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 153 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index e3d893c4..a5cc4bba 100644 --- a/Changes +++ b/Changes @@ -1165,6 +1165,9 @@ Revision history for Perl extension Imager. - maxcolors now must be at least 1 when creating a paletted image. - converted t/t022double.t to use Test::More - t1 library re-initialization modified to support T1Lib 5.1.0 +- setmask() now returns true on success and reports a missing mask + parameter. +- double per sample images were ignoring the channel mask. ================================================================= diff --git a/Imager.pm b/Imager.pm index a2a6af85..ded8642f 100644 --- a/Imager.pm +++ b/Imager.pm @@ -2711,8 +2711,17 @@ sub getmask { sub setmask { my $self = shift; my %opts = @_; - if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; } + if (!defined($self->{IMG})) { + $self->{ERRSTR} = 'image is empty'; + return undef; + } + unless (defined $opts{mask}) { + $self->_set_error("mask parameter required"); + return; + } i_img_setmask( $self->{IMG} , $opts{mask} ); + + 1; } # Get number of colors in an image @@ -3362,4 +3371,8 @@ Imager::Expr(3), Imager::Matrix2d(3), Imager::Fountain(3) Affix::Infix2Postfix(3), Parse::RecDescent(3) http://imager.perl.org/ +Other perl imaging modules include: + +GD(3), Image::Magick(3), Graphics::Magick(3). + =cut diff --git a/imagei.h b/imagei.h index 1dc7f4cd..fb6a5a8f 100644 --- a/imagei.h +++ b/imagei.h @@ -54,4 +54,7 @@ extern UTIL_table_t i_UTIL_table; #define HAVE_SNPRINTF #endif +/* test if all channels are writable */ +#define I_ALL_CHANNELS_WRITABLE(im) (((im)->ch_mask & 0xF) == 0xf) + #endif diff --git a/imgdouble.c b/imgdouble.c index 8dc4ccc6..5f063a62 100644 --- a/imgdouble.c +++ b/imgdouble.c @@ -148,8 +148,15 @@ static int i_ppix_ddoub(i_img *im, int x, int y, i_color *val) { return -1; off = (x + y * im->xsize) * im->channels; - for (ch = 0; ch < im->channels; ++ch) - ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]); + if (I_ALL_CHANNELS_WRITABLE(im)) { + for (ch = 0; ch < im->channels; ++ch) + ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]); + } + else { + for (ch = 0; ch < im->channels; ++ch) + if (im->ch_mask & (1<idata)[off+ch] = Sample8ToF(val->channel[ch]); + } return 0; } @@ -174,8 +181,15 @@ static int i_ppixf_ddoub(i_img *im, int x, int y, i_fcolor *val) { return -1; off = (x + y * im->xsize) * im->channels; - for (ch = 0; ch < im->channels; ++ch) - ((double *)im->idata)[off+ch] = val->channel[ch];; + if (I_ALL_CHANNELS_WRITABLE(im)) { + for (ch = 0; ch < im->channels; ++ch) + ((double *)im->idata)[off+ch] = val->channel[ch]; + } + else { + for (ch = 0; ch < im->channels; ++ch) + if (im->ch_mask & (1 << ch)) + ((double *)im->idata)[off+ch] = val->channel[ch]; + } return 0; } @@ -222,10 +236,21 @@ static int i_plin_ddoub(i_img *im, int l, int r, int y, i_color *vals) { r = im->xsize; off = (l+y*im->xsize) * im->channels; count = r - l; - for (i = 0; i < count; ++i) { - for (ch = 0; ch < im->channels; ++ch) { - ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]); - ++off; + if (I_ALL_CHANNELS_WRITABLE(im)) { + for (i = 0; i < count; ++i) { + for (ch = 0; ch < im->channels; ++ch) { + ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]); + ++off; + } + } + } + else { + for (i = 0; i < count; ++i) { + for (ch = 0; ch < im->channels; ++ch) { + if (im->ch_mask & (1 << ch)) + ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]); + ++off; + } } } return count; @@ -264,10 +289,21 @@ static int i_plinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) { r = im->xsize; off = (l+y*im->xsize) * im->channels; count = r - l; - for (i = 0; i < count; ++i) { - for (ch = 0; ch < im->channels; ++ch) { - ((double *)im->idata)[off] = vals[i].channel[ch]; - ++off; + if (I_ALL_CHANNELS_WRITABLE(im)) { + for (i = 0; i < count; ++i) { + for (ch = 0; ch < im->channels; ++ch) { + ((double *)im->idata)[off] = vals[i].channel[ch]; + ++off; + } + } + } + else { + for (i = 0; i < count; ++i) { + for (ch = 0; ch < im->channels; ++ch) { + if (im->ch_mask & (1 << ch)) + ((double *)im->idata)[off] = vals[i].channel[ch]; + ++off; + } } } return count; diff --git a/t/t022double.t b/t/t022double.t index c3c11557..da7e27a5 100644 --- a/t/t022double.t +++ b/t/t022double.t @@ -1,7 +1,7 @@ #!perl -w use strict; use lib 't'; -use Test::More tests => 49; +use Test::More tests => 81; BEGIN { use_ok(Imager => qw(:all :handy)) } require "t/testtools.pl"; @@ -136,6 +136,64 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/, } } +{ # check the channel mask function + # we want to check all four of ppix() and plin(), ppix() and plinf() + # basic test procedure: + # first using default/all 1s mask, set to white + # make sure we got white + # set mask to skip a channel, set to grey + # make sure only the right channels set + + print "# channel mask tests\n"; + my $im = Imager->new(xsize => 10, ysize=>10, bits=>'double'); + + # 8-bit color tests + my $white = NC(255, 255, 255); + my $grey = NC(128, 128, 128); + my $white_grey = NC(128, 255, 128); + + print "# with ppix\n"; + ok($im->setmask(mask=>~0), "set to default mask"); + ok($im->setpixel(x=>0, 'y'=>0, color=>$white), "set to white all channels"); + test_color_gpix($im->{IMG}, 0, 0, $white); + ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1"); + ok($im->setpixel(x=>0, 'y'=>0, color=>$grey), "set to grey, no channel 2"); + test_color_gpix($im->{IMG}, 0, 0, $white_grey); + + print "# with plin\n"; + ok($im->setmask(mask=>~0), "set to default mask"); + ok($im->setscanline(x=>0, 'y'=>1, pixels => [$white]), + "set to white all channels"); + test_color_gpix($im->{IMG}, 0, 1, $white); + ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1"); + ok($im->setscanline(x=>0, 'y'=>1, pixels=>[$grey]), + "set to grey, no channel 2"); + test_color_gpix($im->{IMG}, 0, 1, $white_grey); + + # float color tests + my $whitef = NCF(1.0, 1.0, 1.0); + my $greyf = NCF(0.5, 0.5, 0.5); + my $white_greyf = NCF(0.5, 1.0, 0.5); + + print "# with ppixf\n"; + ok($im->setmask(mask=>~0), "set to default mask"); + ok($im->setpixel(x=>0, 'y'=>2, color=>$whitef), "set to white all channels"); + test_colorf_gpix($im->{IMG}, 0, 2, $whitef); + ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1"); + ok($im->setpixel(x=>0, 'y'=>2, color=>$greyf), "set to grey, no channel 2"); + test_colorf_gpix($im->{IMG}, 0, 2, $white_greyf); + + print "# with plinf\n"; + ok($im->setmask(mask=>~0), "set to default mask"); + ok($im->setscanline(x=>0, 'y'=>3, pixels => [$whitef]), + "set to white all channels"); + test_colorf_gpix($im->{IMG}, 0, 3, $whitef); + ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1"); + ok($im->setscanline(x=>0, 'y'=>3, pixels=>[$greyf]), + "set to grey, no channel 2"); + test_colorf_gpix($im->{IMG}, 0, 3, $white_greyf); +} + sub NCF { return Imager::Color::Float->new(@_); } @@ -144,8 +202,22 @@ sub test_colorf_gpix { my ($im, $x, $y, $expected) = @_; my $c = Imager::i_gpixf($im, $x, $y); ok($c, "got gpix ($x, $y)"); - ok(colorf_cmp($c, $expected) == 0, - "got right color ($x, $y)"); + unless (ok(colorf_cmp($c, $expected) == 0, + "got right color ($x, $y)")) { + print "# got: (", join(",", ($c->rgba)[0,1,2]), ")\n"; + print "# expected: (", join(",", ($expected->rgba)[0,1,2]), ")\n"; + } +} + +sub test_color_gpix { + my ($im, $x, $y, $expected) = @_; + my $c = Imager::i_get_pixel($im, $x, $y); + ok($c, "got gpix ($x, $y)"); + unless (ok(color_cmp($c, $expected) == 0, + "got right color ($x, $y)")) { + print "# got: (", join(",", ($c->rgba)[0,1,2]), ")\n"; + print "# expected: (", join(",", ($expected->rgba)[0,1,2]), ")\n"; + } } sub test_colorf_glin { @@ -168,3 +240,13 @@ sub colorf_cmp { || $s1[2] <=> $s2[2]; } +sub color_cmp { + my ($c1, $c2) = @_; + + my @s1 = $c1->rgba; + my @s2 = $c2->rgba; + + return $s1[0] <=> $s2[0] + || $s1[1] <=> $s2[1] + || $s1[2] <=> $s2[2]; +} -- 2.39.5