- Added i_bumpmap_complex to do more accurate bumpmapping
- added an image type with doubles as samples
- change i_copy() and i_sametype() to handle double/sample images
+ - added basic POD to trans2.c
+ - transform2 now uses the error interface
=================================================================
}
-{
- my $got_expr;
- sub transform2 {
- my ($opts, @imgs) = @_;
-
- if (!$got_expr) {
- # this is fairly big, delay loading it
- eval "use Imager::Expr";
- die $@ if $@;
- ++$got_expr;
- }
-
- $opts->{variables} = [ qw(x y) ];
- my ($width, $height) = @{$opts}{qw(width height)};
- if (@imgs) {
- $width ||= $imgs[0]->getwidth();
- $height ||= $imgs[0]->getheight();
- my $img_num = 1;
- for my $img (@imgs) {
- $opts->{constants}{"w$img_num"} = $img->getwidth();
- $opts->{constants}{"h$img_num"} = $img->getheight();
- $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
- $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
- ++$img_num;
- }
- }
- if ($width) {
- $opts->{constants}{w} = $width;
- $opts->{constants}{cx} = $width/2;
- }
- else {
- $Imager::ERRSTR = "No width supplied";
- return;
- }
- if ($height) {
- $opts->{constants}{h} = $height;
- $opts->{constants}{cy} = $height/2;
- }
- else {
- $Imager::ERRSTR = "No height supplied";
- return;
- }
- my $code = Imager::Expr->new($opts);
- if (!$code) {
- $Imager::ERRSTR = Imager::Expr::error();
- return;
- }
-
- my $img = Imager->new();
- $img->{IMG} = i_transform2($opts->{width}, $opts->{height}, $code->code(),
- $code->nregs(), $code->cregs(),
- [ map { $_->{IMG} } @imgs ]);
- if (!defined $img->{IMG}) {
- $Imager::ERRSTR = "transform2 failed";
- return;
- }
-
- return $img;
+sub transform2 {
+ my ($opts, @imgs) = @_;
+
+ require "Imager/Expr.pm";
+
+ $opts->{variables} = [ qw(x y) ];
+ my ($width, $height) = @{$opts}{qw(width height)};
+ if (@imgs) {
+ $width ||= $imgs[0]->getwidth();
+ $height ||= $imgs[0]->getheight();
+ my $img_num = 1;
+ for my $img (@imgs) {
+ $opts->{constants}{"w$img_num"} = $img->getwidth();
+ $opts->{constants}{"h$img_num"} = $img->getheight();
+ $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
+ $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
+ ++$img_num;
+ }
+ }
+ if ($width) {
+ $opts->{constants}{w} = $width;
+ $opts->{constants}{cx} = $width/2;
+ }
+ else {
+ $Imager::ERRSTR = "No width supplied";
+ return;
+ }
+ if ($height) {
+ $opts->{constants}{h} = $height;
+ $opts->{constants}{cy} = $height/2;
+ }
+ else {
+ $Imager::ERRSTR = "No height supplied";
+ return;
+ }
+ my $code = Imager::Expr->new($opts);
+ if (!$code) {
+ $Imager::ERRSTR = Imager::Expr::error();
+ return;
}
+
+ my $img = Imager->new();
+ $img->{IMG} = i_transform2($opts->{width}, $opts->{height}, $code->code(),
+ $code->nregs(), $code->cregs(),
+ [ map { $_->{IMG} } @imgs ]);
+ if (!defined $img->{IMG}) {
+ $Imager::ERRSTR = Imager->_error_as_msg();
+ return;
+ }
+
+ return $img;
}
sub rubthrough {
-BEGIN { $| = 1; print "1..10\n"; }
+BEGIN { $| = 1; print "1..12\n"; }
END {print "not ok 1\n" unless $loaded;}
use Imager;
+sub ok($$$);
+
$loaded = 1;
print "ok 1\n";
# error handling
my $opts = { rpnexpr=>'x x 10 / sin 10 * y + get1' };
my $im3 = Imager::transform2($opts);
-print $im3 ? "not ok 2\n" : "ok 2\n";
-print defined($Imager::ERRSTR) ? "ok 3\n" : "not ok 3\n";
+ok(2, !$im3, "returned an image on error");
+ok(3, defined($Imager::ERRSTR), "No error message on failure");
# image synthesis
my $im4 = Imager::transform2({
width=>300, height=>300,
rpnexpr=>'x y cx cy distance !d y cy - x cx - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 cy * 3.1416 / 1 @a2 sin 1 + 2 / hsv'});
-print $im4 ? "ok 4\n" : "not ok 4\n";
+ok(4, $im4, "synthesis failed");
if ($im4) {
$im4->write(type=>'pnm', file=>'testout/t56a.ppm')
my $im5 = Imager::transform2({
rpnexpr=>'x x 10 / sin 10 * y + getp1'
}, $im1);
-print $im5 ? "ok 5\n" : "not ok 5\n";
+ok(5, $im5, "image distortion");
if ($im5) {
$im5->write(type=>'pnm', file=>'testout/t56b.ppm')
|| die "Cannot write testout/t56b.ppm";
rpnexpr=>'x h / !rat x w2 % y h2 % getp2 !pat x y getp1 @rat * @pat 1 @rat - * +'
};
my $im6 = Imager::transform2($opts,$im1,$im2);
-print $im6 ? "ok 6\n" : "not ok 6 # $opts->{error}\n";
+ok(6, $im6, "image combination");
if ($im6) {
$im6->write(type=>'pnm', file=>'testout/t56c.ppm')
|| die "Cannot write testout/t56c.ppm";
$inputs[0]{desc} or print "not ";
print "ok 10\n";
# at some point I might want to test the actual transformations
+
+# check lower level error handling
+my $im7 = Imager::transform2({rpnexpr=>'x y getp2', width=>100, height=>100});
+ok(11, !$im7, "expected failure on accessing invalid image");
+print "# ", Imager->errstr, "\n";
+ok(12, Imager->errstr =~ /not enough images/, "didn't get expected error");
+
+sub ok ($$$) {
+ my ($num, $test, $desc) = @_;
+
+ if ($test) {
+ print "ok $num\n";
+ }
+ else {
+ print "not ok $num # $desc\n";
+ }
+ $test;
+}
+
#include "image.h"
#include "regmach.h"
-/* foo test */
+/*
+=head1 NAME
+
+trans2.c - entry point for the general transformation engine
+
+=head1 SYNOPSIS
+
+ int width, height, channels;
+ struct rm_ops *ops;
+ int op_count;
+ double *n_regs;
+ int n_regs_count;
+ i_color *c_regs;
+ int c_regs_count;
+ i_img **in_imgs;
+ int in_imgs_count;
+ i_img *result = transform2(width, height, channels, ops, ops_count,
+ n_regs, n_regs_count, c_regs, c_regs_count,
+ in_imgs, in_imgs_count);
+
+=head1 DESCRIPTION
+
+This (short) file implements the transform2() function, just iterating
+over the image - most of the work is done in L<regmach.c>
+
+=cut
+*/
i_img* i_transform2(int width, int height, int channels,
struct rm_op *ops, int ops_count,
int x, y;
i_color val;
int i;
+ int need_images;
+
+ i_clear_error();
/* since the number of images is variable and the image numbers
for getp? are fixed, we can check them here instead of in the
register machine - this will help performance */
+ need_images = 0;
for (i = 0; i < ops_count; ++i) {
switch (ops[i].code) {
case rbc_getp1:
case rbc_getp2:
case rbc_getp3:
- if (ops[i].code - rbc_getp1 + 1 > in_imgs_count) {
- /* Foo */
- return NULL;
+ if (ops[i].code - rbc_getp1 + 1 > need_images) {
+ need_images = ops[i].code - rbc_getp1 + 1;
}
}
}
+
+ if (need_images > in_imgs_count) {
+ i_push_errorf(0, "not enough images, code requires %d, %d supplied",
+ need_images, in_imgs_count);
+ return NULL;
+ }
new_img = i_img_empty_ch(NULL, width, height, channels);
for (x = 0; x < width; ++x) {
return new_img;
}
+
+/*
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=head1 SEE ALSO
+
+Imager(3), regmach.c
+
+=cut
+*/