Thread: Gradient fills

  1. #1
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158

    Gradient fills

    Am I right if I decide that the only way to paint a custom or radial gradient fill on a window is using multiple calls to SetPixel?

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    You could manipulate the image bits directly(GetDIBits) which should be quicker than using SetPixel. GradientFill will do triangles so it may be possible to adapt it for use; PatBlt only does rectangles so I doubt, even if it could be adapted, that the results would be any good.

    Another approach might be to draw, for example, a series of concentric, smooth shaded circles where the brush colour is shifted to match the required colour gradient. While this would be inefficient in that many pixels would be repeatedly drawn, it should be relatively simple to implement. Creating a memory bitmap with the required smooth shading from these brushes and blitting that to the window would probably be best as most of the performance hit would result from creating the fill pattern.

    Have you considered using the capabilities of a graphics api better suited to this sort of task such as opengl?
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    Quote Originally Posted by Ken Fitlike View Post
    You could manipulate the image bits directly(GetDIBits) which should be quicker than using SetPixel.
    Ok thanks for the tip. Well my gradient-filled area will contain multiple spots that blend with each other, and I'm already working on a function to calculate each pixel value. Speed does not really matter here, so I decided to do the calulations myself.

  4. #4
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    I'm not sure, but for gradients (blending one color into another), this formula is used:

    RATA and RATB are the ratios (number of parts of that color to mix), COLA and COLB are source and destination colors and MCOL is your result. Repeat this for each channel (red, green, then blue). This works when alpha is not involved. If it is, then this formula will only work with both the source and destination colors have 255 for the alpha.

  5. #5
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    Ulillillia, you and your formulas are very helpful. I'm going to study and apply your formula. My first experiment looks like this: , nice, ain't it? There only is some ugly side effect on the red gradient where the green one ends. Maybe replacing my formula by yours will help, otherwise I will see how else I can fix that.
    Last edited by pronecracker; 04-29-2007 at 10:19 AM.

  6. #6
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    The order you process the objects makes a difference in the overall appearance. They, like paintings, are drawn back to front. I've known this formula since 2002 and I've used it very extensively in my artwork. In fact, it's one of my most frequently used formulas. There are numerous derivatives such as fog, lighting (to some extent), alpha channel transparency, and other things. How I do it is like this:

    Problem: what color do I use when I have a 1/4-transparent object of a FF0000 color (red, based on the HTML notation) in front of a mountain half fogged out with a fog color of A0A8B0 and basic color of 805040 (a dark grayish brown)?
    Solution: You first process the fog which uses a very similar formula. You mix one part of the fog color with one part of the basic color. 160+128 gives 288 and half this (the total number of parts) is 144. The red is 144. Repeat for the green (168 and 80 gives 248, and 124 as the result), and the blue (176+64=240, becoming 120). This gives the color 907C78. From this color, you apply that from the transparent red object. 1/4 transparent means 1 part of that color is used and 3/4 (1 minus 1/4) is for the remainder, or 3 parts. You mix 3 parts of the red value, 144 with one part of the transparent object's red value, or 255. 144*3+255 gives 432+255 or 687. Divide this by 4, the total number of parts, and you get 171.75 which is rounded to 172. You repeat the same for the green and blue. Green gives (124*3+0*1)/(3+1), or 93, and blue gives (120*3+0*1)/(3+1) or 90. This yields the final result of AC5D5A, which is a reddish gray color with a very slight hint of orange. That's the principal behind it and a simple example. Try it and see what happens when you process the transparency first then the fog.

    Gradients are nothing more than an extension to this. Instead of constant ratios, the number of steps is used instead. If you want a fade from black to white as 5 pixels, your total number of parts is always going to be one less than that, or 4. Let's say you want a fade from red (FF0000) to green (about 00C000). The first one is the source, of which I traditionally use the COLA variable for. Because addition is commutative (you can add in any order), they can be in any order. The first color always uses every part available, or 4. This makes the first pixel as FF0000. For the second pixel, a trade of 1 part from the source is added to the destination. Red had 3 parts and green has 1. Put them into my color-averaging formula and you get BF3000 (rounding colors), a dark somewhat reddish orange color. The next pixel has another trade or 2 parts of each color. This gives 806000 a dark orangish color. One part red and 3 parts green is next giving 409000 followed by full green (0 parts red and 4 parts green), or 00C000. With 16 pixels being covered, you'd have 15 parts instead. If you want averaged antialiasing, the method is slightly different, but the ratios involved are always odd and instead of trading 1 value, it's 2. Also, the ratio is double that of the number of pixels to cover. For my red into green example, you'd have 9 parts red and 1 part green which gives E61300. Next would be 7 parts red and 3 parts green giving B33A00.
    Last edited by ulillillia; 04-29-2007 at 11:56 AM. Reason: Suggestion for trying something added to paragraph 2

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need a fast way to check if a point is within a line.
    By mike_g in forum Game Programming
    Replies: 5
    Last Post: 08-05-2008, 12:24 PM
  2. Blending two or more radial gradient fills
    By pronecracker in forum Windows Programming
    Replies: 7
    Last Post: 05-27-2007, 11:39 PM
  3. Gradient...
    By _Unregistered_ in forum Windows Programming
    Replies: 3
    Last Post: 05-01-2002, 05:12 PM
  4. flood fills?
    By cozman in forum Game Programming
    Replies: 1
    Last Post: 04-30-2002, 11:23 PM