From 628693278076bbfea8cf69d4807be68f0c7bc851 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Sat, 23 Oct 2010 22:31:37 +0000 Subject: [PATCH] reorganize convert.c to convert.im test conversion in a 16-bit image a bit more precisely --- Changes | 10 +++++ Imager.xs | 4 +- MANIFEST | 2 +- convert.c => convert.im | 91 ++++++++++++++--------------------------- imager.h | 2 +- lib/Imager/Test.pm | 45 +++++++++++++++++++- t/t67convert.t | 55 +++++++++++++++++-------- 7 files changed, 126 insertions(+), 83 deletions(-) rename convert.c => convert.im (60%) diff --git a/Changes b/Changes index 98d4520c..8ded547f 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,15 @@ Imager release history. Older releases can be found in Changes.old +Imager 0.79 - unreleased +=========== + + - add Imager::Test to the POD coverage tests and document the missing + functions. + +Bug fixes: + + - treat the co-efficients for convert() as doubles instead of floats. + Imager 0.78 - 4 Oct 2010 =========== diff --git a/Imager.xs b/Imager.xs index 970d7df6..3a9ee1bb 100644 --- a/Imager.xs +++ b/Imager.xs @@ -1874,7 +1874,7 @@ i_convert(src, avmain) Imager::ImgRaw src AV *avmain PREINIT: - float *coeff; + double *coeff; int outchan; int inchan; SV **temp; @@ -1894,7 +1894,7 @@ i_convert(src, avmain) inchan = len; } } - coeff = mymalloc(sizeof(float) * outchan * inchan); + coeff = mymalloc(sizeof(double) * outchan * inchan); for (j = 0; j < outchan; ++j) { avsub = (AV*)SvRV(*av_fetch(avmain, j, 0)); len = av_len(avsub)+1; diff --git a/MANIFEST b/MANIFEST index 2b37b4dd..ce6501d9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -172,7 +172,7 @@ bmp.c Reading and writing Windows BMP files color.c Color translation and handling compose.im conv.im -convert.c +convert.im doco.perl datatypes.c draw.c diff --git a/convert.c b/convert.im similarity index 60% rename from convert.c rename to convert.im index db8ac1d2..ada2f266 100644 --- a/convert.c +++ b/convert.im @@ -1,7 +1,7 @@ /* =head1 NAME - convert.c - image conversions + convert.im - image conversions =head1 SYNOPSIS @@ -41,7 +41,7 @@ Now handles images with more than 8-bits/sample. */ i_img * -i_convert(i_img *src, const float *coeff, int outchan, int inchan) { +i_convert(i_img *src, const double *coeff, int outchan, int inchan) { int x, y; int i, j; int ilimit; @@ -62,67 +62,36 @@ i_convert(i_img *src, const float *coeff, int outchan, int inchan) { if (src->type == i_direct_type) { im = i_sametype_chans(src, src->xsize, src->ysize, outchan); - if (src->bits == i_8_bits) { - i_color *vals; - - /* we can always allocate a single scanline of i_color */ - vals = mymalloc(sizeof(i_color) * src->xsize); /* checked 04Jul05 tonyc */ - for (y = 0; y < src->ysize; ++y) { - i_glin(src, 0, src->xsize, y, vals); - for (x = 0; x < src->xsize; ++x) { - for (j = 0; j < outchan; ++j) { - work[j] = 0; - for (i = 0; i < ilimit; ++i) { - work[j] += coeff[i+inchan*j] * vals[x].channel[i]; - } - if (i < inchan) { - work[j] += coeff[i+inchan*j] * 255.9; - } - } - for (j = 0; j < outchan; ++j) { - if (work[j] < 0) - vals[x].channel[j] = 0; - else if (work[j] >= 256) - vals[x].channel[j] = 255; - else - vals[x].channel[j] = work[j]; - } - } - i_plin(im, 0, src->xsize, y, vals); - } - myfree(vals); - } - else { - i_fcolor *vals; - - /* we can always allocate a single scanline of i_fcolor - for a >8 image */ - vals = mymalloc(sizeof(i_fcolor) * src->xsize); /* checked 4Jul05 tonyc */ - for (y = 0; y < src->ysize; ++y) { - i_glinf(src, 0, src->xsize, y, vals); - for (x = 0; x < src->xsize; ++x) { - for (j = 0; j < outchan; ++j) { - work[j] = 0; - for (i = 0; i < ilimit; ++i) { - work[j] += coeff[i+inchan*j] * vals[x].channel[i]; - } - if (i < inchan) { - work[j] += coeff[i+inchan*j]; - } - } - for (j = 0; j < outchan; ++j) { - if (work[j] < 0) - vals[x].channel[j] = 0; - else if (work[j] >= 1) - vals[x].channel[j] = 1; - else - vals[x].channel[j] = work[j]; - } - } - i_plinf(im, 0, src->xsize, y, vals); +#code src->bits <= i_8_bits + IM_COLOR *vals; + + /* we can always allocate a single scanline of i_color */ + vals = mymalloc(sizeof(IM_COLOR) * src->xsize); /* checked 04Jul05 tonyc */ + for (y = 0; y < src->ysize; ++y) { + IM_GLIN(src, 0, src->xsize, y, vals); + for (x = 0; x < src->xsize; ++x) { + for (j = 0; j < outchan; ++j) { + work[j] = 0; + for (i = 0; i < ilimit; ++i) { + work[j] += coeff[i+inchan*j] * vals[x].channel[i]; + } + if (i < inchan) { + work[j] += coeff[i+inchan*j] * IM_SAMPLE_MAX; + } + } + for (j = 0; j < outchan; ++j) { + if (work[j] < 0) + vals[x].channel[j] = 0; + else if (work[j] >= IM_SAMPLE_MAX) + vals[x].channel[j] = IM_SAMPLE_MAX; + else + vals[x].channel[j] = work[j]; + } } - myfree(vals); + IM_PLIN(im, 0, src->xsize, y, vals); } + myfree(vals); +#/code } else { int count; diff --git a/imager.h b/imager.h index 89adcf46..085fea7b 100644 --- a/imager.h +++ b/imager.h @@ -214,7 +214,7 @@ int i_conv (i_img *im,const double *coeff,int len); void i_unsharp_mask(i_img *im, double stddev, double scale); /* colour manipulation */ -extern i_img *i_convert(i_img *src, const float *coeff, int outchan, int inchan); +extern i_img *i_convert(i_img *src, const double *coeff, int outchan, int inchan); extern void i_map(i_img *im, unsigned char (*maps)[256], unsigned int mask); float i_img_diff (i_img *im1,i_img *im2); diff --git a/lib/Imager/Test.pm b/lib/Imager/Test.pm index 0b4e776e..c9d7f507 100644 --- a/lib/Imager/Test.pm +++ b/lib/Imager/Test.pm @@ -18,6 +18,7 @@ $VERSION = "1.000"; is_color3 is_color4 is_color_close3 + is_fcolor1 is_fcolor3 is_fcolor4 color_cmp @@ -68,7 +69,7 @@ sub is_color3($$$$$) { my ($cr, $cg, $cb) = $color->rgba; unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue, $comment)) { - $builder->diag(<new; + + unless (defined $color) { + $builder->ok(0, $comment); + $builder->diag("color is undef"); + return; + } + unless ($color->can('rgba')) { + $builder->ok(0, $comment); + $builder->diag("color is not a color object"); + return; + } + + my ($cgrey) = $color->rgba; + unless ($builder->ok(abs($cgrey - $grey) <= $mindiff, $comment)) { + print <21; +use Test::More tests => 27; +use Imager::Test qw(test_colorf_gpix is_fcolor1 is_fcolor3); Imager::init("log"=>'testout/t67convert.log'); @@ -49,23 +50,41 @@ SKIP: } # test against 16-bit/sample images -SKIP: { - my $imbase16 = Imager::i_img_16_new(200, 200, 3); - - my $im16targ = i_convert($imbase16, [ [ 0, 0, 0, 1 ], - [ 0, 0, 0, 0 ], - [ 0, 0, 0, 0 ] ]); - skip("could not convert 16-bit image", 2) - unless ok($im16targ, "convert 16/bit sample image"); - # image should still be 16-bit - is(Imager::i_img_bits($im16targ), 16, "Image still 16-bit/sample"); - # make sure that it's roughly red - my $c = Imager::i_gpixf($im16targ, 0, 0); - my @ch = $c->rgba; - ok(abs($ch[0] - 1) <= 0.0001 && abs($ch[1]) <= 0.0001 && abs($ch[2]) <= 0.0001, - "image roughly red") - or print "# @ch\n"; + SKIP: + { + my $imbase16 = Imager::i_img_16_new(200, 200, 3); + + my $im16targ = i_convert($imbase16, [ [ 0, 0, 0, 1 ], + [ 0, 0, 0, 0 ], + [ 0, 0, 0, 0 ] ]); + ok($im16targ, "convert 16/bit sample image") + or skip("could not convert 16-bit image", 2); + + # image should still be 16-bit + is(Imager::i_img_bits($im16targ), 16, "Image still 16-bit/sample"); + + # make sure that it's roughly red + test_colorf_gpix($im16targ, 0, 0, NCF(1, 0, 0), 0.001, "image roughly red"); + } + SKIP: + { + my $imbase16 = Imager->new(xsize => 10, ysize => 10, bits => 16); + ok($imbase16->setpixel + (x => 5, y => 2, color => Imager::Color::Float->new(0.1, 0.2, 0.3)), + "set a sample pixel"); + my $c1 = $imbase16->getpixel(x => 5, y => 2, type => "float"); + is_fcolor3($c1, 0.1, 0.2, 0.3, "check it was set") + or print "#", join(",", $c1->rgba), "\n"; + + my $targ16 = $imbase16->convert(matrix => [ [ 0.05, 0.15, 0.01, 0.5 ] ]); + ok($targ16, "convert another 16/bit sample image") + or skip("could not convert", 3); + is($targ16->getchannels, 1, "convert should be 1 channel"); + is($targ16->bits, 16, "and 16-bits"); + my $c = $targ16->getpixel(x => 5, y => 2, type => "float"); + is_fcolor1($c, 0.538, 1/32768, "check grey value"); + } } # test against palette based images @@ -95,6 +114,7 @@ SKIP: } { # http://rt.cpan.org/NoAuth/Bug.html?id=9672 + # methods that return a new image should warn in void context my $warning; local $SIG{__WARN__} = sub { @@ -111,6 +131,7 @@ SKIP: } { # http://rt.cpan.org/NoAuth/Bug.html?id=28492 + # convert() doesn't preserve image sample size my $im = Imager->new(xsize => 20, ysize => 20, channels => 3, bits => 'double'); is($im->bits, 'double', 'check source bits'); -- 2.39.5