Cairo Radial Gradient
Asked Answered
S

1

9

I'm using a radial gradient in Cairo, but I'm not getting the expected results. The radial gradient I'm getting is much less fuzzy than I'd expect and I can't seem to fiddle with the color stops in order to get the desired results. Here is the code:

cairo_pattern_t *pat;

pat = cairo_pattern_create_radial(100.0, 100.0, 0.0, 100.0, 100.0, 20.0);
cairo_pattern_add_color_stop_rgba(pat, 0, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 0);

Here is an image of what I'm talking about.

radial gradient

Swede answered 6/7, 2012 at 2:3 Comment(4)
How did you create the 'What I want' image?Sweettalk
I went into Pixelmator and used a brush that with 0% hardness set.Swede
The cairo result is using interpolating linearily. Each pixel further away from the center gets 2 shades of gray lighter. The 'What I want'-result isn't linear. If you want me to guess, the Pixelmator result is gamma corrected, which works around the human vision.Sweettalk
Is there a possible solution other than placing colour stops in a non-linear fashion programmatically?Swede
S
7

The #cairo IRC channel suggested (Thanks Company!) to use cairo_mask() instead of cairo_paint() to draw the gradient. That results in a squared instead of linear progression.

I did the following in lua. Sorry for the language, but it's easier to prototype something. This maps 1:1 to the C API and shouldn't be hard to translate:

cairo = require("lgi").cairo

s = cairo.ImageSurface(cairo.Format.ARGB32, 200, 100)
c = cairo.Context(s)
c:set_source_rgb(1, 1, 1)
c:paint()

p = cairo.Pattern.create_radial(50, 50, 0, 50, 50, 20)
p:add_color_stop_rgba(0, 0, 0, 0, 1)
p:add_color_stop_rgba(1, 0, 0, 0, 0)

c:save()
c:rectangle(0, 0, 100, 100)
c:clip()
c.source = p
c:paint()
c:restore()

p = cairo.Pattern.create_radial(50, 50, 2, 50, 50, 25)
p:add_color_stop_rgba(0, 0, 0, 0, 1)
p:add_color_stop_rgba(1, 0, 0, 0, 0)

c:translate(100, 0)
c:save()
c:rectangle(0, 0, 100, 100)
c:clip()
c.source = p
c:mask(p)
c:restore()

s:write_to_png("test.png")

To me, the second circle (The one that was cairo_mask()'d with a black source) looks a lot more like what you want:

The image that the lua code produces

Sweettalk answered 7/7, 2012 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.