Gradient Rotate SRT not behaving as I expected

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
whoisgregg

Gradient Rotate SRT not behaving as I expected

Post by whoisgregg »

Hello! :)

I need to produce angled gradients in various widths and heights which include each extreme of the gradient in the final image and has an even transition from one corner/edge to the other.

For example, if I needed a 600px wide by 100px tall image with a gradient rotated 15 degrees, this is the output I am looking for (generated manually in Fireworks):
Image

My first attempt at generating this using SRT was this code:

Code: Select all

convert -size 600x100 gradient:#0000-#000f -distort SRT '15' attempt_1.png
Image

But unfortunately, the output was not ideal because (I believe) the center of the rotation of angle. So I attempted to provide values that would center the rotation, and I got closer:

Code: Select all

 convert -size 600x100 gradient:#0000-#000f -distort SRT '300, 50, 1.0, 1.0, 15, 300, 50' attempt_2.png
Image

Unfortunately, as you can see there is a large band of solid opaque black in the bottom left corner and a large band of solid transparent in the top right corner... Not quite what I was expecting.

At this point I'm a bit stumped... any pointers you can provide will be appreciated!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Gradient Rotate SRT not behaving as I expected

Post by fmw42 »

You have several problems. First your image size 600x100 is not equivalent to 15 degrees diagonally, but more like 16.5 degrees. I will presume you want the image size to be 600x100 and what you really want is corner to diagonal corner gradient. Second, I don't believe IM supports 4-digit hex values. See http://imagemagick.org/script/color.php. Third, you may want to enclose your hex values in quotes.

In order to get corner to corner diagonal gradient, you would do the following (for a black to white gradient).

convert -size 600x600 gradient: -distort SRT '45' -resize 600x100! gradient.png
whoisgregg

Re: Gradient Rotate SRT not behaving as I expected

Post by whoisgregg »

Thank you for your reply, fmw42! I hope I can clarify what I'm looking for. :)

The 15 degree angle was just a random example, varying output should be possible for any angle. Here's an example of the same 600x100 image with a 45 degree gradient angle:
Image

And one with a 67 degree angle:
Image

Each one includes both ends of the gradient range in the 600x100 area and evenly transitions from one end to the other.

Regarding 4-digit hex values, the fourth digit is the alpha transparency value. The examples above are alpha transparent PNGs (hence the background color of the forum page showing through the images).

I went ahead and enclosed the hex values in quotes, but it did not affect the output. From a "best practices" point of view, I'll use quotes in the future. :)
whoisgregg

Re: Gradient Rotate SRT not behaving as I expected

Post by whoisgregg »

Regarding the code you posted, what it ends up doing is changing the perceived angle of gradient from 45 degrees to about 9.5 degrees when it compresses the height of the image:

Code: Select all

convert -size 600x600 gradient:"#0000-#000f" -distort SRT "45" -resize 600x100! attempt_3.png
Image

The good news is that output is far closer to what I want to achieve, so I'm going to go play with geometry to see if I can figure out what input values to give to accomplish the actual final angle. :D
whoisgregg

Re: Gradient Rotate SRT not behaving as I expected

Post by whoisgregg »

Me and geometry are not getting along. :/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Gradient Rotate SRT not behaving as I expected

Post by fmw42 »

To do what you want, you probably need to use -fx and "roll your own" gradients according to some formula for the angle and the image size. Or some combination of what i wrote before with some angle in the initial square gradient other than 45 degress that will then be converted by resize angle to the actual angle you want. Both are a bit complex.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Gradient Rotate SRT not behaving as I expected

Post by fmw42 »

Why do you need the alpha channel. Your image is pure black and the gradient is controlled by the alpha. You don't need the alpha. See if this is what you want for 45degrees or change the 45 to whatever you angle you want.

convert -size 600x600 gradient: -distort SRT '45' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +repage tmp.png
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Gradient Rotate SRT not behaving as I expected

Post by el_supremo »

There's some trigonometry involved in finding a general solution for this problem.
In this diagram:
Image
the final result that is required is the rectangle with dimensions w by h which is outlined in yellow.
It is cropped from a larger rotated rectangle containing the gradient.
If the angle of rotation is "theta" degrees clockwise then the length of the long side of this rectangle is w*cos(theta)+h*sin(theta) as shown in the diagram. The length of the other side is w*sin(theta)+h*cos(theta). In principle what we need to do is create this larger rectangle with the gradient, rotate it and then crop out the rectangle we need but with this sort of calculation involved there's no way you can do it without using some sort of script or program.
I wrote a C program which creates the gradient and then uses affine transforms to shift it so that its centre is at 0,0, rotate it and then shift it back again. It then crops the required rectangle. The resulting rectangle has at least one white pixel at the top right and one black pixel at the bottom left.
I also tried scripting it (using TCL) to use a command line call to convert. In this case I did things a different way. It rotates the gradient around the top left corner (the ImageMagick origin) and then crops the gradient from the middle. It doesn't work out as precisely as the C program because either the bottom left pixel isn't pure black or the top right pixel isn't pure white. But it is close.
Here's the TCL code. I can post the (larger) C code if someone wants it.

Code: Select all

# Dimensions of final rectangle
	set w 600
	set h 100
# rotation angle in degrees
	set theta 15
# Convert degrees to radians
	set rad_theta [expr $theta*4*atan(1.)/180.]
# Compute the dimensions needed for the rectangular gradient so that it will
# hold the final image after rotation
	set gh [expr int($w*sin($rad_theta) + $h*cos($rad_theta) + 0.5)]
	set gw [expr int($w*cos($rad_theta) + $h*sin($rad_theta) + 0.5)]
# Execute the convert program (called imconvert here to avoid conflict with the Windows convert command)
	exec imconvert ( -size $gw\x$gh gradient:white-black -write rotgrad_g.png +distort SRT $theta -write rotgrad_b.png ) +repage -gravity center -crop $w\x$h+0+0 +repage rotgrad.png
Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
whoisgregg

Re: Gradient Rotate SRT not behaving as I expected

Post by whoisgregg »

Pete, it's like you can read my mind. That's exactly what I'm looking for!

Your diagram looks just like the Fireworks file I was using to generate my expected output. At some point I tried to reverse engineer the values involved, but it turns out that reverse engineering trigonometry is a bit harder than it sounds. Well, actually it might be precisely as hard as it sounds. Either way, it was hard and I didn't get far. :(

Thank you very much for sharing your knowledge. :)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Gradient Rotate SRT not behaving as I expected

Post by fmw42 »

I think this method is easier --- no calculations.

25 degrees:
convert -size 600x600 gradient: -distort SRT '25' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +repage grad25.png
Image

45 degrees:
convert -size 600x600 gradient: -distort SRT '45' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +repage grad45.png
Image

65 degrees:
convert -size 600x600 gradient: -distort SRT '65' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +repage grad65.png
Image

45 degrees red to blue:
convert -size 600x600 gradient: -distort SRT '45' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +level-colors red,blue +repage grad45_redblue.png
Image


I have now updated my anglegradient script to make the above easier to use. see http://www.fmwconcepts.com/imagemagick/index.html
Last edited by fmw42 on 2008-12-17T19:32:10-07:00, edited 1 time in total.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Gradient Rotate SRT not behaving as I expected

Post by anthony »

I would avoid the whole rotatating a gradient issue, and all the maths too.

Recent addition to IM was the -sparse-colors option.

In this you can set two points that the color, and have it generate a gradient to fit those points.

See http://www.imagemagick.org/Usage/canvas/#barycentric

Code: Select all

convert -size 600x100 xc:  \
     -sparse-color  Barycentric  '0,99 black  599,0 white' \
     diagonal_gradient.png
By adding a third point, you can control the rotation, the point does NOT even have to be on the image proper!

Code: Select all

convert -size 600x100 xc:  \
     -sparse-color  Barycentric  '0,99 black   599,0 white  100,125 black' \
     diagonal_gradient_2.png
You can do some much simpler math for the angle between the two black points, which determines the iso-color angle of the gradient!

PS: the 100,125 position was just a rough 'guess' on my part.

But you only have two calculations for one extra point to get what you want!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply