Creating Gradients Programmatically in Python
For various sites I often want to create a narrow gradient image. This site has two, for example, the grey background gradient and the purple header gradient.
Rather than having to open up a drawing tool every time I want to create one of these, I thought I'd write a Python script to generate a PNG of a gradient according to declarative specifications.
The result is
http://jtauber.com/2008/05/gradient.py
Only linear gradients are currently supported although you can have any number of them at different vertical offsets and it's easy to modify the code to support other gradient functions.
The code itself is 50 lines long and has no dependencies other than the standard library. I've included some samples based on the gradients on jtauber.com and Pinax.
For example, this gradient:
is produced with the following code:
write_png("test2.png", 50, 90, gradient([ (0.43, (0xBF, 0x94, 0xC0), (0x4C, 0x26, 0x4C)), # top (0.85, (0x4C, 0x26, 0x4C), (0x27, 0x13, 0x27)), # bottom (1.0, (0x66, 0x66, 0x66), (0xFF, 0xFF, 0xFF)), # shadow ]))
The 30-line write_png function could also be used more generally for generating any RGB PNGs.
Comments (11)
Christof on May 18, 2008:
If using binary save for the images the script does work on windows too:
# line 31
out = open(filename, "wb")
I also get a DeprecationWarning: struct integer overflow
masking is deprecated
out.write(struct.pack("!I", checksum))
Any other way to do it?
But a very useful script, thanks!
James Tauber on May 18, 2008:
The DeprecationWarning seems harmless. I get it too. Not sure how to prevent it, though.
Rich LaMarche on May 18, 2008:
Very cool. Another command line way to create gradients is with ImageMagick. This is a good pointer http://softwareas.com/imagemagick-one-second-gradient-images
Jim Dabell on May 18, 2008:
Like you, I have been trying to automate graphics generation. However, I have taken a different route. I have opted to write SVG and translate it into raster images with rsvg/batik.
You can see the SVG equivalent of your example here:
There are a few advantages to doing it this way. It allows for more complex images than simple gradients. You can start an idea off in a graphics application like Inkscape and have it generate SVG as a starting point. You can use template languages like Genshi to generate images. You have the option of serving the SVG directly for some clients.
Rene Dudfield on May 19, 2008:
hi,
here's an example of doing that stuff in pygame... with a few more different types of gradients:
http://www.pygame.org/project/307/
cheers,
Scott Johnson on May 19, 2008:
Very nice! I can confirm Christof's statement above that "wb" is needed for this to work on Windows.
I think the major win with this code is that it doesn't need any non-standard libraries.
As for the DeprecationWarning, the following code will suppress it:
import warnings
warnings.simplefilter("ignore",DeprecationWarning)
Scott Johnson on May 19, 2008:
Here's a revised version of the code containing both the support for Windows and suppression of the DeprecationWarning:
http://pastie.textmate.org/199703
Nick on July 28, 2008:
If you don't hate XML too much, you could have achieved a similar effect using something like:
#!/bin/bash
cat >gradient.svg <<EOF
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="100" height="100">
<defs>
<linearGradient id="g">
<stop style="stop-color:#cc0000;" offset="0" />
<stop style="stop-color:#0012cc;" offset="1" />
</linearGradient>
</defs>
<rect style="fill:url(#g)" width="100" height="100" />
</svg>
EOF
inkscape gradient.svg --export-png=gradient.png
ryan on Oct. 19, 2008:
I found the gradient.py here for now: http://pastie.org/pastes/199770/
Oscar on Nov. 15, 2008:
I played with gradient.py for a bit. Cleaned it up (fixed the DeprecationWarning, not just silenced it). I also added transparency.
Pretty cool that you can save PNGs with 30 readable lines of python, using only the standard library.
Last Modified: May 18, 2008
Author: James Tauber
Empty on May 18, 2008:
Very cool. Thanks for sharing.