How to do a sub-pixel (float) crop

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?".
Post Reply
Ocirne94
Posts: 9
Joined: 2016-06-29T15:12:30-07:00
Authentication code: 1151

How to do a sub-pixel (float) crop

Post by Ocirne94 »

Hi all,
I'm trying to implement some basic panning/zooming animation where several (overlapping) regions are cropped from an image at slowly moving locations.
These locations often happen to be specified by floating point pixel indices, which the normal -crop operator converts to integer: the result is a lot of stuttering in the panning motion, corresponding to integer "jumps" in the crop region.
A solution I've tried is to work on a zoomed image (2x or 4x) and then scale everything down, which kinda works but quickly overwhelms my computational resources.
Apparently the -distort SRT operator supports sub-pixel accuracy, but I can't figure out how to get a proper result.
Any tips?
Thank you very much!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to do a sub-pixel (float) crop

Post by fmw42 »

You can use fractional values in the x,y coords in http://www.imagemagick.org/Usage/distorts/#srt. The shift is determined by the start X,Y and the NewX,NewY. So if you just want to shift, then

Code: Select all

-distort SRT "X,Y 1 0 NewX,NewY" where scale=1 and rotation=0
or

Use the viewport to define the size and offset (position). See http://www.imagemagick.org/Usage/distor ... t_viewport. If you use -set, you can do inline computations of the coordinates or size via %[fx:...] calculations.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to do a sub-pixel (float) crop

Post by snibgo »

As Fred says. See also my "Animation with SRT" page for, well, details of doing animation (pan, zoom and rotate) with "-distort SRT".
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to do a sub-pixel (float) crop

Post by fmw42 »

Animation with SRT is on snibgo's web site at http://im.snibgo.com/animsrt.htm (not the IM Usage pages). He apparently has some command examples to do that for Windows. But the concepts carry over to Unix as well. There is some syntax difference between Unix and Windows, so you may want to see http://www.imagemagick.org/Usage/windows/
Ocirne94
Posts: 9
Joined: 2016-06-29T15:12:30-07:00
Authentication code: 1151

Re: How to do a sub-pixel (float) crop

Post by Ocirne94 »

Thank you very much for your answers.
So, given my crop regions have both noninteger dimensions and location, IIUC I have to
1- translate with SRT by a float amount so the region to be cropped has its top-left pixel at (0,0)
2- resize (with SRT) so that the region to be cropped has integer dimensions (the final dimensions I want, obviously integer, the scale factor is easily computed)
3- set the viewport to the region's area.
I think I should translate before resizing as some more detail should be retained this way -> 2 srt commands.

Now (provided the above is correct), I use IM through python 3 (Wand bindings), and I can't seem to be able to find the viewport command?!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to do a sub-pixel (float) crop

Post by fmw42 »

The PythonMagick may not be updated to use all the features of the command line.

Nevertheless, I am not sure IM can deal with fraction pixel dimension (WxH). I do not think you can save such even if IM internally can handle it.

One of the developers would need to respond about both.
Ocirne94
Posts: 9
Joined: 2016-06-29T15:12:30-07:00
Authentication code: 1151

Re: How to do a sub-pixel (float) crop

Post by Ocirne94 »

I'm not trying to save fractionary pixel dimensions, I extract a fractionary region (fractionary - in terms of position and dimensions - on the original image, but it's rigidly scaled to integer dimensions prior to cropping/viewporting) and then save it.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to do a sub-pixel (float) crop

Post by snibgo »

Ocirne94 wrote:1- translate with SRT by a float amount so the region to be cropped has its top-left pixel at (0,0)
2- resize (with SRT) so that the region to be cropped has integer dimensions (the final dimensions I want, obviously integer, the scale factor is easily computed)
3- set the viewport to the region's area.
I think I should translate before resizing as some more detail should be retained this way -> 2 srt commands.
While developing, for convenience you might want multiple consecutive SRTs.

Most detail is retained if you do it in a single SRT command. A single SRT can be split into as many consecutive SRTs as you want, at the cost of speed and precision.

Multiple consecutive SRTs can be combined into a single SRT.
snibgo's IM pages: im.snibgo.com
Ocirne94
Posts: 9
Joined: 2016-06-29T15:12:30-07:00
Authentication code: 1151

Re: How to do a sub-pixel (float) crop

Post by Ocirne94 »

Ok but IIRC the SRT first applies scale, then translate: shouldn't there be more detail left if I downscale at the end?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to do a sub-pixel (float) crop

Post by snibgo »

See http://www.imagemagick.org/script/comma ... hp#distort for what "-distort SRT" does.
Distort image by first scaling and rotating about a given 'center', before translating that 'center' to the new location, in that order.
Or, to put this another way:

1. Translate to put the given 'center' at the origin.

2. Scale and rotate about the origin.

3. Translate to put the origin at the new location.

But it does all this in a single operation, without rounding to integers at each stag
snibgo's IM pages: im.snibgo.com
Ocirne94
Posts: 9
Joined: 2016-06-29T15:12:30-07:00
Authentication code: 1151

Re: How to do a sub-pixel (float) crop

Post by Ocirne94 »

Ok, I think I've understood the srt part. This would explain why the output of these two commands is the same, also in terms of visual detail:

convert 1.tif -define distort:viewport=900x600+0+0 -distort SRT "0.5,0 0.5 0 0,0" 1_single.tif

convert 1.tif -distort SRT "0.5,0 1 0 0,0" -define distort:viewport=900x600+0+0 -distort SRT "0,0 0.5 0" 1_double.tif

(I was expecting the second one to need -distort SRT "1,0 1 0 0,0", given the resize; but apparently the coordinates aren't scaled).

I'm still a bit puzzled about how (and in which order) the viewport operates. For the second command, I get 3 different results according to the -define position. I think I can interpret them, but it confuses me that the viewport crop appears to be applied after the srt which appears after the -define.

with -define before the distorts:
Image

with -define between the distorts (correct result):
Image

with -define after the distorts (actually doesn't get resized, so would be 20 MP):
Image
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to do a sub-pixel (float) crop

Post by snibgo »

"-define" is a setting. Settings don't change the image. But they affect how an operator works to change an image.

So "-define distort:viewport" does nothing to the image, but it does affect any "-distort" operations that come after it.


The documentation http://www.imagemagick.org/script/comma ... hp#distort isn't massively clear but, yes, "-define distort:viewport={geometry_string}" is effectively applied after the other work done by "-distort".

Does that explain things?

You might take a close look at my "Animation with SRT" page for further explanation.
snibgo's IM pages: im.snibgo.com
Ocirne94
Posts: 9
Joined: 2016-06-29T15:12:30-07:00
Authentication code: 1151

Re: How to do a sub-pixel (float) crop

Post by Ocirne94 »

Ok, I've got it working (the whole thing is a multithread keyframe-based animation system). In the end I had to directly call convert as a sub-process, as no python binding apparently provides the viewport feature.
Yes, the documentation is a bit confusing at first for someone who doesn't know the inner workings.
Thank you very much for your help!
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How to do a sub-pixel (float) crop

Post by anthony »

Just remember viewport is only interger based. It defined what pixels in the distorted output space is in the final image (as well as the final images virtual offset).

The SRT (or really a Affine Matrix transformation - or any other distortion method really) will distort based on the sub-pixel coordinates.
For example a resize (scaling) with sub-pixel coordinates...
http://www.imagemagick.org/Usage/resize/#distort

Note also that draw can draw things in sub-pixel coordinates too, however it uses pixel coordinates (integers refer to the middle of the pixel) while distort uses the more mathematical coordinates (integers refer to the top left corner of a pixel). That can be important for alignment between the two systems.

The Command line options page
http://www.imagemagick.org/script/comma ... hp#distort
is more of a quick reference. The better and more detailed description of distort and all its options is in IM Exmaples
http://www.imagemagick.org/Usage/distorts/#distort

To really understand distort... read it :-)
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply