Archived

This topic is now archived and is closed to further replies.

Gradients ?

This topic is 5126 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, Happy Thanksgiving. I''m trying to code my own color gradient like they have in the paint programs. They usually have a few options like linear, rectangular, circular, and radial; right now I just want to understand the linear version with two colors. I can easily do it in the four primary directions (0, 90, 180, 270 degrees) but I can''t figure out how to do different angles. So, for example, if I want 45 degrees it will go from the top left to the bottom right. Do I take the pixel position and rotate it ? (I actually just thought of that while writing this.) I guess it''s best to have the pixel values range from 0.0...1.0, I know what to do after that (like color interpolation using more than two colors and stuff like that.) Thanks.

Share this post


Link to post
Share on other sites
There are several ways to do this. The most conceptually simple one, assuming you''re filling a certain range by with a gradiant form a point (x1,y1) to (x2,y2), is to take the vector from (x1,y1) to (x2,y2), call it V. Then for each point in the fill area (x,y) take the vector W from (x1,y1) to (x,y). Determine the projection of W onto V, call it U. The take |U| over |V|, call it p. If p is less than 0, set p to 0. If p is greater than 1, set p to 1. You can then use p as a fractional value to interpolate between the starting and ending color values.

A Bi-linear gradiant can be done by, instead of setting p to 0 when less than 0, taking the absolute value of p.

Of course, this has pretty cruddy performance.

A faster way, would be to section the region into three areas by the means of two parallel lines. These lines would be determined by having perpendicular slopes to the vector V and passing through (x1,y1) and (x2,y2). On each line, the pixels would have the value of the corresponding point. Then you can do horizontal (or vertical) scans from each parallel line from one color value to the other. This can be done in a fast integer algorithm a la Bresenham''s. The areas outside the lines would take the color of the nearest line.


Also, Gimp (www.gimp.org) is open-source, so you can always go peek at it''s gradiant routines.

Share this post


Link to post
Share on other sites
It''s sort of like texture mapping. First you''ll need to interpolate down the rectangle, and then across. Interpolating seems confusing, but it really makes sense after you mess with it a lot. Basically you take the difference in the colors and divide it by the height. So if you have a 50 pixel tall rect, with 255 red in the top left corner, and 128 red in the bottom left, you''ll make your left delta value (128 - 255) / 50 = -2.54. Now you could use floats, but if fixed point would be better so you don''t have to do 3 float-to-int conversions each pixel. Just use floats if you''ve never messed with fp before.
Anyway, just separate the colors into red, green and blue and calculate the deltas for each of them the same way ((end - start) / steps), and do that on the right corners too.
Then each line down the rect, add those deltas to your left/right colors. Then take (right - left) / width and loop across the rect, adding that delta to your color, and plotting pixels.

That''s just if you have colors in each corner that you want to fade between. Photoshop''s gradient is a bit different, since you can specift what length/angle of area to do the transition across. I guess the way I''d do that is get the slope and end points of the line you draw with the mouse, and then take -1/slope (if you''ve done math, that makes a line perpendicular to the one you drew with the mouse) and then the x position on the top row of your picture where you''ll start to fade from one color to the other will be xStart - yStart * (-1/slope). Imagine travelling along a line at the angle of the gradient until you hit the top of the picture. Then do that with your end point, and just fill with color1 until you get to the start point, interpolate between color1 and color2 across the area between start and end, then fill with color2 until you hit the right edge. Add -1/slope to your start and end points, and repeat.

For radial, just use the old distance formula sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) where x1/y1 is your current pixel, and x2/y2 is the center point of your gradient. The length of the line drawn with the mouse (again, use the distance formula to get the length) will be your radius. Just fill with the outside color if you''re distance is greater than radius, otherwise your distance between the inside color and outside color will be dist/radius. So say your distance is 20 and your radius is 60, 20/60 = .333, so your color will be .333*in+(1-.333)*out.

The first one where you just interpolate between the corners is the easiest, and a good exercize in how to interpolate to get a better idea of how the other ones work.

Share this post


Link to post
Share on other sites