- added the det() function to the transform2() engine.
authorTony Cook <tony@develop=help.com>
Mon, 10 Dec 2007 03:21:33 +0000 (03:21 +0000)
committerTony Cook <tony@develop=help.com>
Mon, 10 Dec 2007 03:21:33 +0000 (03:21 +0000)
   added the sample quad_to_square.pl

Changes
MANIFEST
lib/Imager/Engines.pod
lib/Imager/Regops.pm
regmach.c
regmach.h
samples/README
samples/quad_to_square.pl [new file with mode: 0644]
t/t58trans2.t

diff --git a/Changes b/Changes
index 288f130..e3cfc64 100644 (file)
--- a/Changes
+++ b/Changes
@@ -13,6 +13,11 @@ Imager 0.62 - unreleased
    So henceforth Imager uses the dlopen() family of functions, and you 
    will need version 10.3 or later of OS X.
 
+ - added the det() function to the transform2() engine.
+   added the sample quad_to_square.pl
+   Courtesy Richard Fairhurst.
+   http://rt.cpan.org/Ticket/Display.html?id=31244
+
 Bug fixes:
 
  - samples/gifscale.pl sourced the base value for gif_top from
index 5048227..1e9441b 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -206,6 +206,7 @@ samples/gifscale.pl Scale an animated GIF, preserving animation info
 samples/inline_capture2image.pl         convert captured BGR data to an image
 samples/inline_replace_color.pl  replace colors using Inline::C
 samples/interleave.pl
+samples/quad_to_square.pl      Transform a quadrilateral into a square
 samples/replace_color.pl replace colors using transform2()
 samples/samp-form.cgi
 samples/samp-image.cgi
index 6561d4a..4278471 100644 (file)
@@ -403,6 +403,21 @@ I<N> B<exp> -- I<N>
 
 =back
 
+=item det(a, b, c, d)
+
+Calculate the determinant of the 2 x 2 matrix;
+
+  a b
+  c d
+
+rpnexpr usage:
+
+=over
+
+I<Na> I<Nb> I<Nc> I<Nd> B<det> -- I<N>
+
+=back
+
 =back
 
 =head3 Constants
index 8e0ade1..e2ed07e 100644 (file)
@@ -57,9 +57,10 @@ use constant RBC_HSVA => 47;
 use constant RBC_ALPHA => 48;
 use constant RBC_LOG => 49;
 use constant RBC_EXP => 50;
-use constant RBC_OP_COUNT => 51;
+use constant RBC_DET => 51;
+use constant RBC_OP_COUNT => 52;
 
-@EXPORT = qw(RBC_ADD RBC_SUBTRACT RBC_MULT RBC_DIV RBC_MOD RBC_POW RBC_UMINUS RBC_MULTP RBC_ADDP RBC_SUBTRACTP RBC_SIN RBC_COS RBC_ATAN2 RBC_SQRT RBC_DISTANCE RBC_GETP1 RBC_GETP2 RBC_GETP3 RBC_VALUE RBC_HUE RBC_SAT RBC_HSV RBC_RED RBC_GREEN RBC_BLUE RBC_RGB RBC_INT RBC_IF RBC_IFP RBC_LE RBC_LT RBC_GE RBC_GT RBC_EQ RBC_NE RBC_AND RBC_OR RBC_NOT RBC_ABS RBC_RET RBC_JUMP RBC_JUMPZ RBC_JUMPNZ RBC_SET RBC_SETP RBC_PRINT RBC_RGBA RBC_HSVA RBC_ALPHA RBC_LOG RBC_EXP RBC_OP_COUNT);
+@EXPORT = qw(RBC_ADD RBC_SUBTRACT RBC_MULT RBC_DIV RBC_MOD RBC_POW RBC_UMINUS RBC_MULTP RBC_ADDP RBC_SUBTRACTP RBC_SIN RBC_COS RBC_ATAN2 RBC_SQRT RBC_DISTANCE RBC_GETP1 RBC_GETP2 RBC_GETP3 RBC_VALUE RBC_HUE RBC_SAT RBC_HSV RBC_RED RBC_GREEN RBC_BLUE RBC_RGB RBC_INT RBC_IF RBC_IFP RBC_LE RBC_LT RBC_GE RBC_GT RBC_EQ RBC_NE RBC_AND RBC_OR RBC_NOT RBC_ABS RBC_RET RBC_JUMP RBC_JUMPZ RBC_JUMPNZ RBC_SET RBC_SETP RBC_PRINT RBC_RGBA RBC_HSVA RBC_ALPHA RBC_LOG RBC_EXP RBC_DET RBC_OP_COUNT);
 
 %Attr =
   (
@@ -127,6 +128,14 @@ use constant RBC_OP_COUNT => 51;
     'result' => 'r',
     'types' => 'r',
     },
+  'det' =>
+    {
+    'func' => 1,
+    'opcode' => 51,
+    'parms' => 4,
+    'result' => 'r',
+    'types' => 'rrrr',
+    },
   'distance' =>
     {
     'func' => 1,
@@ -346,7 +355,7 @@ use constant RBC_OP_COUNT => 51;
   'op_count' =>
     {
     'func' => 0,
-    'opcode' => 51,
+    'opcode' => 52,
     'parms' => 0,
     'result' => undef,
     'types' => '',
@@ -369,10 +378,10 @@ use constant RBC_OP_COUNT => 51;
     },
   'print' =>
     {
-    'func' => 0,
+    'func' => 1,
     'opcode' => 45,
     'parms' => 1,
-    'result' => undef,
+    'result' => 'r',
     'types' => 'r',
     },
   'red' =>
index 02ea5e3..c7fe613 100644 (file)
--- a/regmach.c
+++ b/regmach.c
@@ -421,9 +421,14 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count,
       break;
 
     case rbc_print:
+      nout = na;
       printf("r%d is %g\n", codes->ra, na);
       break;
 
+    case rbc_det:
+      nout = na*nd-nb*nc;
+      break;
+
     default:
       /*croak("bad opcode"); */
       printf("bad op %d\n", codes->code);
index e8df6ea..ed1e303 100644 (file)
--- a/regmach.h
+++ b/regmach.h
@@ -53,12 +53,13 @@ enum rm_byte_codes {
   rbc_jumpnz, /* jump if ra != 0 to jb */
   rbc_set, /* ra -> r */
   rbc_setp, /* pa -> p*/
-  rbc_print, /* prints ra */
+  rbc_print, /* print(ra) -> r -- prints, leaves on stack */
   rbc_rgba, /* rgba(ra, rb, rc, rd) -> p */
   rbc_hsva, /* hsva(ra, rb, rc, rd) -> p */
   rbc_alpha, /* alpha(pa) -> r */
   rbc_log, /* log(ra) -> r */
   rbc_exp, /* exp(ra) -> r */
+  rbc_det, /* det(ra, rb, rc, rd) -> r */
   rbc_op_count
 };
 
index a6ce36d..a45f37a 100644 (file)
@@ -110,3 +110,9 @@ gifscale.pl
   Scales an animated GIF image, preserving GIF animation information
   and adjusting the image screen positions to account for the scale
   factor.
+
+quad_to_square.pl
+
+  Sample from Richard Fairhurst demonstrating the use of the transform2()
+  det() function.  Transforms an arbitrary quadrilateral in the input into
+  a square on the output.
diff --git a/samples/quad_to_square.pl b/samples/quad_to_square.pl
new file mode 100644 (file)
index 0000000..97230d9
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/perl -w
+use strict;
+# Convert quadrilateral to square
+
+use Imager;
+
+my $src=Imager->new();
+$src->open(file=>"oldmap_200px.jpg");
+
+# example co-ordinates of quadrilateral
+my $x0=12; my $y0=4; # top left
+my $x1=157; my $y1=0; # top right
+my $x2=140; my $y2=150; # bottom right
+my $x3=27; my $y3=159; # bottom left
+
+my $code=<<EOF;
+xa=((h-y)*x0+y*x3)/h; ya=((h-y)*y0+y*y3)/h;
+xb=((h-y)*x1+y*x2)/h; yb=((h-y)*y1+y*y2)/h;
+xc=((w-x)*x0+x*x1)/w; yc=((w-x)*y0+x*y1)/w;
+xd=((w-x)*x3+x*x2)/w; yd=((w-x)*y3+x*y2)/w;
+
+d=det(xa-xb,ya-yb,xc-xd,yc-yd);
+d=if(d==0,1,d);
+
+px=det(det(xa,ya,xb,yb),xa-xb,det(xc,yc,xd,yd),xc-xd)/d;
+py=det(det(xa,ya,xb,yb),ya-yb,det(xc,yc,xd,yd),yc-yd)/d;
+return getp1(px,py);
+EOF
+
+my $newimg=Imager::transform2({
+expr=>$code,
+width=>200,
+height=>200,
+constants=>{x0=>$x0,y0=>$y0,
+x1=>$x1,y1=>$y1,
+x2=>$x2,y2=>$y2,
+x3=>$x3,y3=>$y3}},
+($src));
+$newimg->write(file=>"output_imager.jpg");
+
+=head1 NAME
+
+quad_to_square.pl - transform an arbitrary quadrilateral to a square.
+
+=head1 SYNOPSIS
+
+  perl quad_to_square.pl
+
+=head1 DESCRIPTION
+
+Courtesy Richard Fairhurst:
+
+I've been using it to rectify ("square up") a load of roughly scanned
+maps, so that an arbitrary quadrilateral is resized into a square. The
+transform2 function is ideal for that.
+
+Thought you might be interested to see what people are doing with
+Imager - feel free to include this in the sample code.
+
+=head1 AUTHOR
+
+Richard Fairhurst
+
+=cut
index 39f7f7e..46db20a 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 36;
+use Test::More tests => 37;
 BEGIN { use_ok('Imager'); }
 use Imager::Test qw(is_color3);
 
@@ -134,6 +134,9 @@ EOS
 op_test('000000', <<'EOS', 50, 82, 0, 'exp log');
 1 exp log 50 * 0.5 + 0.5 exp 50 * 0 rgb
 EOS
+op_test('800000', <<'EOS', 128, 0, 0, 'det');
+1 0 0 1 det 128 * 1 1 1 1 det 128 * 0 rgb
+EOS
 
 use Imager::Transform;
 
@@ -168,7 +171,7 @@ sub op_test ($$$$$$) {
   {
     my $out = Imager::transform2({ rpnexpr => $code }, $im);
     unless ($out) {
-      fail("$comment: coult not compile $code - ".Imager->errstr);
+      fail("$comment: could not compile $code - ".Imager->errstr);
       return;
     }
     my $found = $out->getpixel(x => 0, y => 0);