Consecutive SRT distorts

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
emery

Consecutive SRT distorts

Post by emery »

I need to do SRT rotation about multiple pivot points in sequence, but the way I'm doing it now is with multiple distorts, is it possible to consolidate these into one single rotate/translate, to reduce the data loss?

Thank you
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Consecutive SRT distorts

Post by anthony »

All SRT distorts are linear. They are simply a sub-set of Affine (Matrix) distortions.
When you combine such distortions together you eventually get a single Affine Distortion
That is a combined rotate,shear,scale,translate distortion (one and only one of each).

The way to combine the distortions is to start with a 'null' or 'unity' matrix, and then matrix multiply each of the individual distortions you want to apply in the sequence wanted. At the end you will have a single affine matrix (6 values) that you can apply ONCE to an image, using AffineProjection.


You can find out more about the individual parts by looking at the older Affine examples
http://www.imagemagick.org/Usage/distorts/affine/
These examples were written to use the older -affine ... -transform options. Internally these options now used +distort AffineProjection, and as such are obsolete, but they still work.

Their are also lots more information and book on Linear Affine Matrix Math, and I recommend them if you want to go further.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
emery

Re: Consecutive SRT distorts

Post by emery »

Thanks
emery

Re: Consecutive SRT distorts

Post by emery »

Don't I need to convert SRT arguments to an affine matrix? How do I get a 6 argument affine matrix from a pivoted rotation?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Consecutive SRT distorts

Post by anthony »

Affine Rotates....
http://www.imagemagick.org/Usage/distor ... affine_rot

this is essentially what the 'R' in SRT distort generates.

You can extract it from a SRT distort too by using verbose, on a one pixel image!
The '45' is the angle in degrees...

Code: Select all

    convert xc: -verbose  -distort SRT  '0,0  1.0  45  0,0' +verbose null:
Producing

Code: Select all

Affine Projection:
  -distort AffineProjection \
      '0.707107,0.707107,-0.707107,0.707107,0,-0'
Affine Distort, FX Equivalent:
  -fx 'ii=i+page.x+0.5; jj=j+page.y+0.5;
       xx=+0.707107*ii +0.707107*jj +0.000000;
       yy=-0.707107*ii +0.707107*jj +0.000000;
       p{ xx-page.x-.5, yy-page.x-.5 }'
The 6 Affine values IM calculated is in the second line!
And are basically the sine and cosine for a 45 degree angle. You can see the affine formula for 'dest to src' pixel mapping in the FX equivalent too...

Alternately there old 'perl' helper scripts which the affine examples talk about. These pre-date the newer distort operator, and was the fore-running for the SRT distortion method, but are still perfectly valid!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
emery

Re: Consecutive SRT distorts

Post by emery »

I'm using PHP Imagick, and it provides no way to get the affine matrix from an SRT distortion. I need to be able to calculate the entire affine matrix myself just given the consecutive pivots and angles.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Consecutive SRT distorts

Post by anthony »

Okay.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
emery

Re: Consecutive SRT distorts

Post by emery »

I'm sorry, I see now that the link you posted earlier has example code with the trig I need: http://www.imagemagick.org/Usage/scripts/affine_distort

Thank you. This should be perfect. =)

Just so you know, I wasn't being lazy. I just didn't fully understand that SRT was a direct subset of affine which made it hard to know what to Google for. Thanks again, your help is very appreciated.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Consecutive SRT distorts

Post by anthony »

"SRT" distortion is Affiine but without 'shearing'. It is just one wahy of specifying an affine distortion.

"Affine" distortion defines it using the movement of three points.

"AffineProjection" defines it in terms of a forward mapped affine matrix
(it converts forward to reverse mapping internally).

Affine by the way is a sub-set of "Perspective" and "PerspectiveProjection"
It is also a subset of another distortion that is still incomplete (though a solution
has been worked out "Bilinear" distortion (another four point distortion)

Another distortion that I have not implemented is "3D rotation" which is perspective but defined using 3D rotation angles, rotation point and a depth of view. This is a bit like a SRT distortion for perspective.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
emery

Re: Consecutive SRT distorts

Post by emery »

I ported your affine rotation script to my code and it works great on one rotation, but not with consecutive rotations at different pivot points.

Could you tell me if I am doing the matrix multiplication correctly?

Code: Select all

	protected $affineMatrix = array(
		1,0,
		0,1,
		0,0
	);

	protected function matrixMult($m1, $m2, $rows, $cols) {

		$res = array();

		for($i = 0; $i < $rows; $i++) {
			for($j = 0; $j < $cols ; $j++) {
				$res[$cols*$i+$j] = 0;
				for($k = 0; $k < $cols; $k++) {
						$res[$cols*$i+$j] += $m1[$cols*$i+$k] * $m2[$cols*$k+$j];
				}
			}
		}

		return $res;
	}
Usage:

Code: Select all

	public function rotate($degrees, $fromX='full/2+sl', $fromY='full/2+st') {
		$px = $this->parseShapeLength($fromX, $this->getWidth());
		$py = $this->parseShapeLength($fromY, $this->getHeight());	
		$degrees = $this->parseShapeLength($degrees);

		$rads = deg2rad($degrees);
		$c = cos($rads);
		$s = sin($rads);

		$sx = $c;
		$rx = $s;
		$ry = -$s;
		$sy = $c;

		$tx = $px;
		$ty = $py;

 		$tx -= $px*$c - $py*$s;
 		$ty -= $px*$s + $py*$c;
 
		$affine = array(
			$sx,$rx,
			$ry,$sy,
			$tx,$ty);

		$this->affineMatrix = $this->matrixMult($this->affineMatrix, $affine, 3, 2);

	}

Code: Select all

	public function transformImage($img, $x, $y) { // called before rendering

		$result = $this->createBuffer();
		$result->compositeImage($img, Imagick::COMPOSITE_OVER, $x, $y);
		$result->distortImage(Imagick::DISTORTION_AFFINEPROJECTION, $this->affineMatrix, false);	

		return $result;
	}
I'm sure the affine is correct because when I use it on ImagickDraw::affine consecutively the resulting vector graphic is perfect. There has to be something wrong with my matrix multiply... but I tested it against several matrices and got correct results.



This is what happens when I do a 0-10 degree rotation about 0,0 (animated), followed by 8 consecutive 45 degrees rotations about the center of the containing image.

The black rectangles are the vector graphic, and the linear gradient squares are the image affected by the same affine transformation, in an attempt to overlay them. They should be exactly the same.

With "bestfit" off:
Image
With "bestfit" on:
Image

Any suggestion is welcome since I am completely stuck.
emery

Re: Consecutive SRT distorts

Post by emery »

Here is a more precise example of the problem:

Original
Image

Rotate 40 degrees about center:
Image

Rotate an addition 10 degrees about center: (wrong)
Image

Subsequent rotations appear to take a 0,0 pivot point.

Here are the affine matrices:

Code: Select all

Initial:
1 0
0 1
0 0

After 40 degree rotation:
0.766044443119   0.642787609687
-0.642787609687  0.766044443119
157.350580242    -88.3171661538 

After following 10 degree rotation:
0.642787609687   0.766044443119
-0.766044443119  0.642787609687
45.8515420369    -3.45119133611
Last edited by emery on 2009-08-11T13:54:30-07:00, edited 1 time in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Consecutive SRT distorts

Post by fmw42 »

you probably did not take into account the new size before computing your second rotate. the center is at a different location.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Consecutive SRT distorts

Post by fmw42 »

I need a better understanding of the separate steps you want to consolidate into one affine matrix. Also why do two rotations about the center when you can just add the rotation angles and make one rotation?
emery

Re: Consecutive SRT distorts

Post by emery »

fmw42 wrote:you probably did not take into account the new size before computing your second rotate. the center is at a different location.
The first rotation about the center doesn't change the center.
fmw42 wrote:I need a better understanding of the separate steps you want to consolidate into one affine matrix. Also why do two rotations about the center when you can just add the rotation angles and make one rotation?
It's just to reproduce the problem, specifically to test that it isn't the center being miscalculated. I've checked the center by dumping the variables, it is correct. (200,172 for both rotates)


I'm trying to consolidate multiple rotations of different or same pivot points into one affine.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Consecutive SRT distorts

Post by fmw42 »

The first rotation about the center doesn't change the center.
Yes it does, if you rotate about the center, then afterwards as the image is bigger the new center will be further from the upper left corner. So to do the second rotation about the center, you need to specify a new center as well.
Last edited by fmw42 on 2009-08-11T14:12:24-07:00, edited 1 time in total.
Post Reply