Radial gradients with opacity in PHP
Asked Answered
D

3

3

I need to create a PNG radial gradient with opacity. I've looked through GDLib but I can't see a way to generate radial gradients. Does anyone know of a way with GDlib or any other graphics library for PHP?

I suppose worst-case I could generate it pixel-by-pixel using GDLib but how does one even start to do the math on that?

The goal is to generate sexy lighting effect background PNGs for web pages. An example of the effect can be seen on the header here which uses this background image. I've tried generic white lighting effect PNGs but it doesn't look anywhere near as good as tinted lighting, so my generated PNGs will take into account the website's color scheme.

I assume server-side is the way to go because browser support for CSS radial gradients is so patchy.

Disgorge answered 7/7, 2011 at 18:51 Comment(3)
GD's a quick and dirty image manipulator. Simple operations are the name of the game. Radial operations are advanced stuff, not suited for GD. You could try the Gimp, which has a full scripting interface with bindings for most languages (though not PHP, apparently).Victoriavictorian
It's to be executed on a linux web server without X - I don't know how successful I'd be in getting Gimp runningDisgorge
gimp has a command-line 'batch' mode, so it can run headless.Victoriavictorian
B
1

Why not use a combination of imagecolorallocatealpha() and imageellipse() or imagefilledellipse()?

Edit:

See this class for an example of what I mean. You should be able to extend this to support alpha.

Edit2:

I have made some modifications to the class above to yield alpha support. It's not perfect, but it works for ellipses and such:

http://codepad.org/1eZ3Km0J

Broadus answered 7/7, 2011 at 19:3 Comment(2)
This is interesting. It iteratively increments the color and then draws a series of progressively smaller filled ellipses. However, it is not clear to me that one can draw an ellipse on the alpha channel: the gd functions seem to use the RGB channels implicity (?)Comminute
@Comminute I'm testing aib's math by creating 127 different opacities of the same color with imagecolorallocatealpha() then using those to render pixels. I guess the same could be applied with concentric imagefilledellipse()Disgorge
C
1

the classic video game trick is to apply a gradient texture, rather than compute the light. this is a perfect use for the technique.

make a grayscale gradient at a large-ish pixel dimension (2048px square is common) and several smaller ones (1024,512,256px etc) pick the closest one for your need (scaling up may exaggerate banding, scaling down may introduce moire).

use php gd function such as imagecopymerge. depending on intent, you could store the result on first use.

Comminute answered 7/7, 2011 at 18:58 Comment(3)
Sounds great but I'd like to apply that gradient texture as the opacity map (if that's a phrase) for a dynamic solid color...Disgorge
ahh. I think you'd need to set up the alpha channel and then set the pixels individually using GDComminute
But then again, you could sample or specify the page background color, copymerge the gradient onto an image the solid color, and then copy merge the result onto your desired image. Obviously not a true alpha channel solution.Comminute
B
1

Why not use a combination of imagecolorallocatealpha() and imageellipse() or imagefilledellipse()?

Edit:

See this class for an example of what I mean. You should be able to extend this to support alpha.

Edit2:

I have made some modifications to the class above to yield alpha support. It's not perfect, but it works for ellipses and such:

http://codepad.org/1eZ3Km0J

Broadus answered 7/7, 2011 at 19:3 Comment(2)
This is interesting. It iteratively increments the color and then draws a series of progressively smaller filled ellipses. However, it is not clear to me that one can draw an ellipse on the alpha channel: the gd functions seem to use the RGB channels implicity (?)Comminute
@Comminute I'm testing aib's math by creating 127 different opacities of the same color with imagecolorallocatealpha() then using those to render pixels. I guess the same could be applied with concentric imagefilledellipse()Disgorge
S
1

I suppose worst-case I could generate it pixel-by-pixel using GDLib but how does one even start to do the math on that?

The math is easy, alpha = max_alpha - (distance_to_center / radius) where the distance is Euclidean, i.e. sqrt( (x1-x2)^2 + (y1-y2)^2 ).

Supporting answered 7/7, 2011 at 19:16 Comment(8)
I get a diamond-shaped gradient not circular. Am I messing it up somehow?Disgorge
Does it need more π and sin/cos? My math isn't very good, if you could point me in the right direction that'd be great. The rest of the code is finished \o/Disgorge
Like the old joke goes: pi R round, cake r squared.Comminute
@Tak: Did you miss that square root? Here, let me make it more explicit.Supporting
Nope, even without the sqrt you should get a circle. Did you miss the squares?Supporting
Oh and I just tested the formula in Java. Works as advertised.Supporting
Thanks aib, must be my code! I'd love to get this working (even though Justin's answer was best for my application). I may fork it to another question and add a comment here laterDisgorge
@Disgorge Be sure to let me know if you do.Supporting

© 2022 - 2024 — McMap. All rights reserved.