Page 1 of 1
Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-12T16:05:35-07:00
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):
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
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
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!
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-12T17:22:39-07:00
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
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T10:50:25-07:00
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:
And one with a 67 degree angle:
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.
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T11:05:13-07:00
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
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.
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T11:35:23-07:00
by whoisgregg
Me and geometry are not getting along. :/
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T12:19:09-07:00
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.
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T12:36:59-07:00
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
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T14:54:19-07:00
by el_supremo
There's some trigonometry involved in finding a general solution for this problem.
In this diagram:
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
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T17:22:11-07:00
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.
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-13T20:32:24-07:00
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
45 degrees:
convert -size 600x600 gradient: -distort SRT '45' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +repage grad45.png
65 degrees:
convert -size 600x600 gradient: -distort SRT '65' -gravity center -crop 600x100+0+0 -contrast-stretch 0 +repage grad65.png
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
I have now updated my anglegradient script to make the above easier to use. see
http://www.fmwconcepts.com/imagemagick/index.html
Re: Gradient Rotate SRT not behaving as I expected
Posted: 2008-12-14T19:09:52-07:00
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!