1 package Imager::Matrix2d;
9 Imager::Matrix2d - simple wrapper for matrix construction
14 $m1 = Imager::Matrix2d->identity;
15 $m2 = Imager::Matrix2d->rotate(radians=>$angle, x=>$cx, y=>$cy);
16 $m3 = Imager::Matrix2d->translate(x=>$dx, y=>$dy);
17 $m4 = Imager::Matrix2d->shear(x=>$sx, y=>$sy);
18 $m5 = Imager::Matrix2d->reflect(axis=>$axis);
19 $m6 = Imager::Matrix2d->scale(x=>$xratio, y=>$yratio);
22 use Imager::Matrix2d qw(:handy);
23 # various m2d_* functions imported
24 # where m2d_(.*) calls Imager::Matrix2d->$1()
28 This class provides a simple wrapper around a reference to an array of
29 9 co-efficients, treated as a matrix:
35 Most of the methods in this class are constructors. The others are
38 Note that since Imager represents images with y increasing from top to
39 bottom, rotation angles are clockwise, rather than counter-clockwise.
45 use vars qw(@EXPORT_OK %EXPORT_TAGS @ISA);
47 require 'Exporter.pm';
48 @EXPORT_OK = qw(m2d_rotate m2d_identity m2d_translate m2d_shear
49 m2d_reflect m2d_scale);
52 handy=> [ qw(m2d_rotate m2d_identity m2d_translate m2d_shear
53 m2d_reflect m2d_scale) ],
63 Returns the identity matrix.
68 return bless [ 1, 0, 0,
73 =item rotate(radians=>$angle)
75 =item rotate(degrees=>$angle)
77 Creates a matrix that rotates around the origin, or around the point
78 (x,y) if the 'x' and 'y' parameters are provided.
83 my ($class, %opts) = @_;
86 if (defined $opts{radians}) {
87 $angle = $opts{radians};
89 elsif (defined $opts{degrees}) {
90 $angle = $opts{degrees} * 3.1415926535 / 180;
93 $Imager::ERRSTR = "degrees or radians parameter required";
97 if ($opts{'x'} || $opts{'y'}) {
100 return $class->translate('x'=>-$opts{'x'}, 'y'=>-$opts{'y'})
101 * $class->rotate(radians=>$angle)
102 * $class->translate('x'=>$opts{'x'}, 'y'=>$opts{'y'});
105 my $sin = sin($angle);
106 my $cos = cos($angle);
107 return bless [ $cos, -$sin, 0,
113 =item translate(x=>$dx, y=>$dy)
115 =item translate(x=>$dx)
117 =item translate(y=>$dy)
119 Translates by the specify amounts.
124 my ($class, %opts) = @_;
126 if (defined $opts{'x'} || defined $opts{'y'}) {
127 my $x = $opts{'x'} || 0;
128 my $y = $opts{'y'} || 0;
129 return bless [ 1, 0, $x,
134 $Imager::ERRSTR = 'x or y parameter required';
138 =item shear(x=>$sx, y=>$sy)
144 Shear by the given amounts.
148 my ($class, %opts) = @_;
150 if (defined $opts{'x'} || defined $opts{'y'}) {
151 return bless [ 1, $opts{'x'}||0, 0,
155 $Imager::ERRSTR = 'x and y parameters required';
159 =item reflect(axis=>$axis)
161 Reflect around the given axis, either 'x' or 'y'.
163 =item reflect(radians=>$angle)
165 =item reflect(degrees=>$angle)
167 Reflect around a line drawn at the given angle from the origin.
172 my ($class, %opts) = @_;
174 if (defined $opts{axis}) {
175 my $result = $class->identity;
176 if ($opts{axis} eq "y") {
177 $result->[0] = -$result->[0];
179 elsif ($opts{axis} eq "x") {
180 $result->[4] = -$result->[4];
183 $Imager::ERRSTR = 'axis must be x or y';
190 if (defined $opts{radians}) {
191 $angle = $opts{radians};
193 elsif (defined $opts{degrees}) {
194 $angle = $opts{degrees} * 3.1415926535 / 180;
197 $Imager::ERRSTR = 'axis, degrees or radians parameter required';
202 return $class->rotate(radians=>-$angle) * $class->reflect(axis=>'x')
203 * $class->rotate(radians=>$angle);
206 =item scale(x=>$xratio, y=>$yratio)
208 Scales at the given ratios.
210 You can also specify a center for the scaling with the cx and cy
216 my ($class, %opts) = @_;
218 if (defined $opts{'x'} || defined $opts{'y'}) {
219 $opts{'x'} = 1 unless defined $opts{'x'};
220 $opts{'y'} = 1 unless defined $opts{'y'};
221 if ($opts{cx} || $opts{cy}) {
222 return $class->translate('x'=>-$opts{cx}, 'y'=>-$opts{cy})
223 * $class->scale('x'=>$opts{'x'}, 'y'=>$opts{'y'})
224 * $class->translate('x'=>$opts{cx}, 'y'=>$opts{cy});
227 return bless [ $opts{'x'}, 0, 0,
233 $Imager::ERRSTR = 'x or y parameter required';
240 Implements the overloaded '*' operator. Internal use.
242 Currently both the left and right-hand sides of the operator must be
247 my ($left, $right, $order) = @_;
249 if (ref($right) && UNIVERSAL::isa($right, __PACKAGE__)) {
251 ($left, $right) = ($right, $left);
258 $accum += $left->[3*$i + $k] * $right->[3*$k + $j];
260 $result[3*$i+$j] = $accum;
263 return bless \@result, __PACKAGE__;
266 # presumably N * matrix or matrix * N
267 return undef; # for now
273 Implements the overloaded binary '+' operator.
275 Currently both the left and right sides of the operator must be
276 Imager::Matrix2d objects.
280 my ($left, $right, $order) = @_;
282 if (ref($right) && UNIVERSAL::isa($right, __PACKAGE__)) {
285 push @result, $left->[$_] + $right->[$_];
288 return bless \@result, __PACKAGE__;
297 Implements the overloaded stringification operator.
299 This returns a string containing 3 lines of text with no terminating
302 I tried to make it fairly nicely formatted. You might disagree :)
311 if (length() > $maxlen) {
315 $maxlen <= 9 or $maxlen = 9;
317 my @left = ('[ ', ' ', ' ');
318 my @right = ("\n", "\n", ']');
320 my $width = $maxlen+2;
324 my $val = $m->[$i*3+$j];
325 if (length $val > 9) {
326 $val = sprintf("%9f", $val);
327 if ($val =~ /\./ && $val !~ /e/i) {
333 $out .= sprintf("%-${width}s", "$val, ");
343 The following functions are shortcuts to the various constructors.
345 These are not methods.
347 You can import these methods with:
349 use Imager::Matrix2d ':handy';
357 =item m2d_translate()
370 return __PACKAGE__->identity;
374 return __PACKAGE__->rotate(@_);
378 return __PACKAGE__->translate(@_);
382 return __PACKAGE__->shear(@_);
386 return __PACKAGE__->reflect(@_);
390 return __PACKAGE__->scale(@_);
397 Tony Cook <tony@develop-help.com>
401 Needs a way to invert matrixes.
405 Imager(3), Imager::Font(3)
407 http://imager.perl.org/