zomgistania

Main page | About | Articles | Previous Posts | Archives

Wednesday, July 12, 2006

Feed button generator - graphics with PHP and ImageMagick

On the other day while browsing, an idea struck me... You often see these "RSS Feed", "CSS 2.0" and other buttons in the style of my new RSS feed link. I thought it would be cool to try to make a PHP script which would generate these graphics!

So I present you...

The feed button generator!



The button generator uses PHP and ImageMagick. The interface uses JavaScript for the color picker and for quickly displaying the newly generated image without having the page to refresh or such. It's Web 2.0, baby!

ImageMagick is a quite advanced graphics toolkit which works from the console. There is also an interface for PHP, but as it requires a recompile of PHP, I didn't install it. I used exec() to use the imagick command line tools.


The image generation script itself is quite simple. It checks for $_GET variables which contain the options for the button, like the text on the left side and uses a default value for each if there's no user-defined value.

Each of the GET variables used are ran through escapeshellcmd() to make sure the user can't try anything we don't want him to.

The ImageMagick command used, however, is worth a better look:


$cmd = IMAGICK_PATH.'convert -size '.$w.'x'.$h.' xc:black ';
$cmd.= '-fill white -draw \'rectangle 1,1 '.($w-2).','.($h-2).'\' ';
$cmd.= '-fill "#'.$lsbgcol.'" -draw \'rectangle 2,2 '.$vbarpos.','.($h-3).'\' ';
$cmd.= '-fill "#'.$rsbgcol.'" -draw \'rectangle '.($vbarpos+2).',2 '.($w-3).','.($h-3).'\' ';
$cmd.= '-font lucon.ttf -pointsize 10 -fill "#'.$lstcol.'" -draw "text 5,11 \''.$lstext.'\'" ';
$cmd.= '-fill "#'.$rstcol.'" -draw "text '.($vbarpos+4).',11 \''.$rstext.'\'" ';
$cmd.= $path.'/'.$tmpname;


It probably looks quite complicated with all the inline variables. So let's also display a sample output for that.

/usr/bin/convert -size 80x15 xc:black -fill white -draw 'rectangle 1,1 78,13' -fill "#FF6600" -draw 'rectangle 2,2 30,12' -fill "#898E79" -draw 'rectangle 32,2 77,12' -font lucon.ttf -pointsize 10 -fill "#FFFFFF" -draw "text 5,11 'RSS'" -fill "#FFFFFF" -draw "text 34,11 'Feed'" /wwwroot/projects/feedbutton/1152680468.gif

And it might still look complicated, so let me explain it a bit.

Starting with the IMAGICK_PATH.. it's the path to the ImageMagick binaries, in this case "/usr/bin/". The applications name is convert.

the -size parameter is probably self explanatory. It sets the size of the canvas to 80x15. $w and $h contain the values for this.

xc:black sets the background color of the canvas to black. You could use hexadecimal color values here too, like xc:FFFFFF.

with -fill, you set the fill color for drawing and the text color for drawing text. As you can see from further, you can use hexadecimal values too but they have to be inside quotes.

the -draw parameter draws all kinds of shapes. In this case, we're just drawing a bunch of rectangles and some text.
Draw takes some parameters of it's own which go inside single quotes. The first parameter is the type of the shape to draw, for example, rectangle. When drawing rectangles, you also have to give it the top left corner and the width and the height of the rectangle.

As we want to have the button to have a one pixel border, we set the top left corner of the rectangle at 1,1 and the width and height to 78,13. The rectangle's width and height are determined by width-2 and height-2 as seen in the code.

After drawing the first rectangle, the fill color is switched to the color of the box on the left side. It's drawn in exactly the same fashion as the first one. However, this time we're using the position of the middle bar as the width.

Next, the script draws the right side box. This time the starting position's x position is set to middle bar position + 2 to make the one pixel white bar appear in the middle, thus the name "middle bar". (In the code the variables name comes from "vertical bar position", it's before I figured out a better name for it)


As you can see, drawing rectangles is easy. If you wanted to draw more rectangles, you would just add more -draw parameters and -fill's for changing colors.


Now the only thing left to draw are the texts that appear in the button. This is done in a very similar way as the rectangle drawing.

First, the font is defined with -font parameter. lucon.ttf was stolen from my windows' font directory and moved to the server... it's "Lucida Console".

-pointsize defines the size of the font.

To draw the text, the rectangle parameter is just switched to text. The two numbers are the top left corner of the position of the text and after that comes the text to draw.

Drawing more text is yet again done by adding another draw parameter.

Finally, our newly created button is saved with a temporary file name, which is generated by PHP using date(). The $path variable holds the path of the script so it's saved to the correct directory.
The path can be found by calling substr($_SERVER['SCRIPT_FILENAME'],0,strrpos($_SERVER['SCRIPT_FILENAME'],'/'));



After saving the image to disk, the image.php script calls header('Content-Type: image/gif') and include()'s the temporary file. After this the file is unlink()'d as it's not needed anymore.



The JavaScript color picker is Tigra Color Picker. Other than that, the JavaScript in the page is quite simple, as it only changes the src attribute of the img element which displays the image generated. The page should also work in case JavaScript is unavailable for some reason. In that case, the user gets redirected to the image.php script which will display a graphic with the users' configuration.

Note that you'll have to remove any # characters from an URL if you're using it as an image's src attribute... otherwise you'll end up in trouble and get a very random looking error and random behavior. At least in my case.


You can find more info on ImageMagic, including installation info from their homepage.
Here are many examples of using ImageMagic

1 Comments:

  • Awesome! Well done.

    By Anonymous Anonymous, at 3:14 PM  

Post a Comment

<< Home