Skew Image by only 1 pixel

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
AlexZ
Posts: 7
Joined: 2019-02-28T07:22:45-07:00
Authentication code: 1152

Skew Image by only 1 pixel

Post by AlexZ » 2019-06-19T06:22:47-07:00

Hi all,

I want to skew the top side of an image by 1 pixel to the right. In the comand line option I found the shear command. To calculate the shear angle. I used:

<shear angle> = arctan(1/<vertical image resolution>)

In the present case I had a vertical resolution of 19787 pixel, so I get a shear angle of 0,0028956274 degree, means the command line I used is:

"In.tiff" -shear 0.0028956274 "Out.tiff"

To test it I used a solid black image. Unfortunately the left border of the image is skewed less than 1 pixel (I guess around 0.5) and the right side is skewed more than 1 pixel (i guess around 1.5). I know the angle is very small, but necessary for the application. Is there any way to solve this?

Regards, Alex

snibgo
Posts: 11994
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Skew Image by only 1 pixel

Post by snibgo » 2019-06-19T06:52:50-07:00

What version of IM?

The documentation http://www.imagemagick.org/script/comma ... .php#shear seems to be wrong. It says:

Code: Select all

When Ydegrees is omitted it defaults to 0.
... but experimentation suggests that when Ydegrees is omitted it defaults to Xdegrees. So I suggest you use:

Code: Select all

magick "In.tiff" -shear 0.0028956274x0 "Out.tiff"
Does that help?
snibgo's IM pages: im.snibgo.com

User avatar
GeeMack
Posts: 711
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: Skew Image by only 1 pixel

Post by GeeMack » 2019-06-19T07:19:10-07:00

AlexZ wrote:
2019-06-19T06:22:47-07:00
I want to skew the top side of an image by 1 pixel to the right.
You can use "-distort affine" to get that result, while letting ImageMagick calculate the angle.

Code: Select all

convert in.tiff -virtual-pixel black +distort affine "0,0 1,0 0,%[h] 0,%[h] 1,%[h] 1,%[h]" -shave 1 out.tiff
That essentially slides the top row one pixel to the right, keeps the bottom row locked in place, and moves all the intermediate rows fractionally to create the shear angle.

Using the plus form of "+distort" adjusts the viewport size to contain the entire resulting image, and in most instances it will add another single pixel all around in order to not lose any information at the edges. The "-shave 1" removes that single row of pixels all around. If you want to maintain the input viewport dimensions, just use "-distort" instead of the "+" plus form, and don't "-shave" it at the end.

If you're using IM version 7, use "magick" instead of "convert".

User avatar
fmw42
Posts: 25378
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Skew Image by only 1 pixel

Post by fmw42 » 2019-06-19T08:21:41-07:00

What is your platform? Please always provide your IM version and platform when asking questions. If you are on a Unix-like system, then I have a bash unix shell script (skew) for imagemagick that will skew by either degrees or pixels. See my link below.

AlexZ
Posts: 7
Joined: 2019-02-28T07:22:45-07:00
Authentication code: 1152

Re: Skew Image by only 1 pixel

Post by AlexZ » 2019-06-21T01:58:01-07:00

snibgo wrote:
2019-06-19T06:52:50-07:00
What version of IM?

The documentation http://www.imagemagick.org/script/comma ... .php#shear seems to be wrong. It says:

Code: Select all

When Ydegrees is omitted it defaults to 0.
... but experimentation suggests that when Ydegrees is omitted it defaults to Xdegrees. So I suggest you use:

Code: Select all

magick "In.tiff" -shear 0.0028956274x0 "Out.tiff"
Does that help?
Actually I use imageMagick 7.0.8-29 with windows 10 64bit

I checked adding x0 to the shear command, but it did not change the result.
GeeMack wrote:
2019-06-19T07:19:10-07:00

You can use "-distort affine" to get that result, while letting ImageMagick calculate the angle.

Code: Select all

convert in.tiff -virtual-pixel black +distort affine "0,0 1,0 0,%[h] 0,%[h] 1,%[h] 1,%[h]" -shave 1 out.tiff
That essentially slides the top row one pixel to the right, keeps the bottom row locked in place, and moves all the intermediate rows fractionally to create the shear angle.

Using the plus form of "+distort" adjusts the viewport size to contain the entire resulting image, and in most instances it will add another single pixel all around in order to not lose any information at the edges. The "-shave 1" removes that single row of pixels all around. If you want to maintain the input viewport dimensions, just use "-distort" instead of the "+" plus form, and don't "-shave" it at the end.

If you're using IM version 7, use "magick" instead of "convert".
I checked this solution, basically it works, but if I check the result picture there are some artefacts in the upper left and upper right corner.

Code: Select all

magick In.tiff -virtual-pixel white +distort affine "0,0 1,0 0,%[h] 0,%[h] 1,%[h] 1,%[h]" -shave 1 Out.tiff
I tested a solid black square and changed the background for the skew operation to white.
In this case the upper left corner pixel is not white, but the pixel below are white.
For the upper right corner the pixel is not black, but the ones below are black.

Is there any way to improve this?

User avatar
fmw42
Posts: 25378
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Skew Image by only 1 pixel

Post by fmw42 » 2019-06-21T07:43:25-07:00

Please post your input and output images to some free hosting service and put the URL here so we can check against your results.

snibgo
Posts: 11994
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Skew Image by only 1 pixel

Post by snibgo » 2019-06-21T08:04:42-07:00

The "+distort" sets canvas offsets, so you might want "+repage" before saving.

The distort uses the default filter. You might prefer a specific filter, such as "-filter Point" (or even Box) before the distort.

Each pixel has a non-zero area. The distort process actually re-samples pixels, rather than simply "moving" them. You can manipulate the height parameters to, for example, get your expected result on the bottom row.

To more clearly see what happens, I use a 5x5 black square, and don't shave, and scale up the result:

Code: Select all

magick -size 5x5 xc:Black  -virtual-pixel white  -filter Point +distort affine "0,0 1,0 0,%[fx:h-0.5] 0,%[fx:h-0.5] 1,%[fx:h-0.5] 1,%[fx:h-0.5]" +repage +write info: -scale 4000x4000% skew5x5.png
Image

EDIT to add: And to get top and bottom as you might want it (note the 0.5 offsets to move the centres of the pixels):

Code: Select all

magick -size 5x5 xc:Black  -virtual-pixel white  -filter Point +distort affine "0.5,0.5 1.5,0.5 0,%[fx:h-0.5] 0,%[fx:h-0.5] 1,%[fx:h-0.5] 1,%[fx:h-0.5]" +repage +write info: -scale 4000x4000% skew5x5b.png
Image
snibgo's IM pages: im.snibgo.com

AlexZ
Posts: 7
Joined: 2019-02-28T07:22:45-07:00
Authentication code: 1152

Re: Skew Image by only 1 pixel

Post by AlexZ » 2019-07-09T06:51:19-07:00

Hi all,

sorry for the late reply...
It works now, thanks!

Post Reply