prevent pointer vs int size warnings on 64-bit builds of perl.
- add our own INT2PTR and PTR2IV definitions when perl doesn't
supply them
+ - difference() method
=================================================================
return $self;
}
+sub difference {
+ my ($self, %opts) = @_;
+
+ defined $opts{mindist} or $opts{mindist} = 0;
+
+ defined $opts{other}
+ or return $self->_set_error("No 'other' parameter supplied");
+ defined $opts{other}{IMG}
+ or return $self->_set_error("No image data in 'other' image");
+
+ $self->{IMG}
+ or return $self->_set_error("No image data");
+
+ my $result = Imager->new;
+ $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
+ $opts{mindist})
+ or return $self->_set_error($self->_error_as_msg());
+
+ return $result;
+}
+
# destructive border - image is shrunk by one pixel all around
sub border {
else {
$ERRSTR = $msg;
}
+ return;
}
# Default guess for the type of an image from extension
myfree(yo);
myfree(ival);
+Imager::ImgRaw
+i_diff_image(im, im2, mindist=0)
+ Imager::ImgRaw im
+ Imager::ImgRaw im2
+ int mindist
void
i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
i_img_exorcise(©);
}
+/*
+=item i_diff_image(im1, im2, mindiff)
+
+Creates a new image that is transparent, except where the pixel in im2
+is different from im1, where it is the pixel from im2.
+
+The samples must differ by at least mindiff to be considered different.
+
+=cut
+*/
+
+i_img *
+i_diff_image(i_img *im1, i_img *im2, int mindiff) {
+ i_img *out;
+ int outchans, diffchans;
+ int xsize, ysize;
+ i_img temp;
+
+ i_clear_error();
+ if (im1->channels != im2->channels) {
+ i_push_error(0, "different number of channels");
+ return NULL;
+ }
+
+ outchans = diffchans = im1->channels;
+ if (outchans == 1 || outchans == 3)
+ ++outchans;
+
+ xsize = min(im1->xsize, im2->xsize);
+ ysize = min(im1->ysize, im2->ysize);
+
+ out = i_sametype_chans(im1, xsize, ysize, outchans);
+
+ if (im1->bits == i_8_bits && im2->bits == i_8_bits) {
+ i_color *line1 = mymalloc(2 * xsize * sizeof(*line1));
+ i_color *line2 = line1 + xsize;
+ i_color empty;
+ int x, y, ch;
+
+ for (ch = 0; ch < MAXCHANNELS; ++ch)
+ empty.channel[ch] = 0;
+
+ for (y = 0; y < ysize; ++y) {
+ i_glin(im1, 0, xsize, y, line1);
+ i_glin(im2, 0, xsize, y, line2);
+ for (x = 0; x < xsize; ++x) {
+ int diff = 0;
+ for (ch = 0; ch < diffchans; ++ch) {
+ if (line1[x].channel[ch] != line2[x].channel[ch]
+ && abs(line1[x].channel[ch] - line2[x].channel[ch]) > mindiff) {
+ diff = 1;
+ break;
+ }
+ }
+ if (!diff)
+ line2[x] = empty;
+ }
+ i_plin(out, 0, xsize, y, line2);
+ }
+ myfree(line1);
+ }
+ else {
+ i_fcolor *line1 = mymalloc(2 * xsize * sizeof(*line1));
+ i_fcolor *line2 = line1 + xsize;
+ i_fcolor empty;
+ int x, y, ch;
+ double dist = mindiff / 255;
+
+ for (ch = 0; ch < MAXCHANNELS; ++ch)
+ empty.channel[ch] = 0;
+
+ for (y = 0; y < ysize; ++y) {
+ i_glinf(im1, 0, xsize, y, line1);
+ i_glinf(im2, 0, xsize, y, line2);
+ for (x = 0; x < xsize; ++x) {
+ int diff = 0;
+ for (ch = 0; ch < diffchans; ++ch) {
+ if (line1[x].channel[ch] != line2[x].channel[ch]
+ && abs(line1[x].channel[ch] - line2[x].channel[ch]) > dist) {
+ diff = 1;
+ break;
+ }
+ }
+ if (!diff)
+ line2[x] = empty;
+ }
+ i_plinf(out, 0, xsize, y, line2);
+ }
+ myfree(line1);
+ }
+
+ return out;
+}
+
struct fount_state;
static double linear_fount_f(double x, double y, struct fount_state *state);
static double bilinear_fount_f(double x, double y, struct fount_state *state);
}
}
+/*
+=item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
+
+Returns an image of the same type (sample size).
+
+For paletted images the equivalent direct type is returned.
+
+=cut
+*/
+
+i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
+ if (src->bits == 8) {
+ return i_img_empty_ch(NULL, xsize, ysize, channels);
+ }
+ else if (src->bits == i_16_bits) {
+ return i_img_16_new(xsize, ysize, channels);
+ }
+ else if (src->bits == i_double_bits) {
+ return i_img_double_new(xsize, ysize, channels);
+ }
+ else {
+ i_push_error(0, "Unknown image bits");
+ return NULL;
+ }
+}
+
/*
=item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
void i_img_info(i_img *im,int *info);
extern i_img *i_sametype(i_img *im, int xsize, int ysize);
+extern i_img *i_sametype_chans(i_img *im, int xsize, int ysize, int channels);
i_img *i_img_pal_new(int x, int y, int ch, int maxpal);
void i_turbnoise(i_img *im,float xo,float yo,float scale);
void i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure);
void i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure);
+i_img *i_diff_image(i_img *im, i_img *im2, int mindist);
typedef enum {
i_fst_linear,
i_fst_curved,
unload_plugin("dynfilt/dyntest.so")
or die "unable to load plugin\n";
+ $out = $img->difference(other=>$other_img);
=head1 DESCRIPTION
Linux, Solaris, HPUX, OpenBSD, FreeBSD, TRU64/OSF1, AIX.
If you test this on other systems please let me know.
+=head2 Image Difference
+
+You can create a new image that is the difference between 2 other images.
+
+ my $diff = $img->difference(other=>$other_img);
+
+For each pixel in $img that is different to the pixel in $other_img,
+the pixel from $other_img is given, otherwise the pixel is transparent
+black.
+
+This can be used for debugging image differences ("Where are they
+different?"), and for optimizing animated GIFs.
+
+Note that $img and $other_img must have the same number of channels.
+The width and heigh of $diff will be the minimum of each of the width
+and height of $img and $other_img.
=cut
my $im_other = Imager->new(xsize=>150, ysize=>150);
$im_other->box(xmin=>30, ymin=>60, xmax=>120, ymax=>90, filled=>1);
-print "1..43\n";
+print "1..45\n";
test($imbase, 1, {type=>'autolevels'}, 'testout/t61_autolev.ppm');
segments=>$f4, super_sample=>'grid',
ftype=>'linear', combine=>'color' },
'testout/t61_regress_fount.ppm');
+my $im2 = $imbase->copy;
+$im2->box(xmin=>20, ymin=>20, xmax=>40, ymax=>40, color=>'FF0000', filled=>1);
+$im2->write(file=>'testout/t61_diff_base.ppm');
+my $im3 = Imager->new(xsize=>150, ysize=>150, channels=>3);
+$im3->box(xmin=>20, ymin=>20, xmax=>40, ymax=>40, color=>'FF0000', filled=>1);
+my $diff = $imbase->difference(other=>$im2);
+print $diff ? "ok 44\n" : "not ok 44\n";
+if ($im3 && $diff) {
+ print Imager::i_img_diff($im3->{IMG}, $diff->{IMG}) ? "not ok 45\n" : "ok 45\n";
+}
+else {
+ print "ok 45 # skip\n";
+}
sub test {
my ($in, $num, $params, $out) = @_;