Creating Images with PHP

They have: 8 posts

Joined: Feb 2003

My webhost has the GD librarys and I'm trying to create an image with some text.

I want $text to be in the image and the size of the image to be however long the text is. How would I do this? $text will be different sizes every time the script is executed.

Mark Hensler's picture

He has: 4,048 posts

Joined: Aug 2000

Is this SiC from G4B2S?

Zend has a good article on using the PHP GD library here:
http://www.zend.com/zend/tut/dynamic.php

I altered a script I wrote a while ago. I just tested it on linux with PHP 4.3.0 & Apache 2.

<?php
//
// Author: Mark Hensler
//
//
//


// size of font
$textSize       = 2;

// pixels between lines of text
$textGutter     = 0;

// paddings around text
// between text and border
$paddingBottom  = 4;
$paddingLeft    = 4;
$paddingRight   = 4;
$paddingTop     = 4;

// margins around image
// between border and image outer edge
$marginBottom   = 2;
$marginLeft     = 2;
$marginRight    = 2;
$marginTop      = 2;

// text to print
$message[] = \"Mark Hensler - \\"Pay no attention to the man behind the curtain.\\"\";
$message[] = \"[\\"Max Albert\\"] [Email] [ICQ]\";


// pick a color scheme
// 1 = grayblack on white
// 2 = white on blue
$colorscheme = 2;


////////////////////////////////////////////////////////////////////////////////
//                                DO NO EDIT BELOW                            //
////////////////////////////////////////////////////////////////////////////////

// find the longest line
$max_length = 0;
foreach (
$message as $line) {
    if (strlen(
$line) > $max_length) {
       
$max_length = strlen($line);
    }
}

// size of font
$textHeight     = imageFontHeight($textSize);
$textWidth      = imageFontWidth($textSize);

// find the message demensions:
$textboxHeight  = (count($message) * ($textHeight)) + ((count($message)-1) * $textGutter) + ($paddingBottom + $paddingTop);
$textboxWidth   = ($max_length * $textWidth) + ($paddingLeft + $paddingRight);

// actual size of created image will varry (based on font size, margins, paddings, and textbox size)
// ...and the total is:
$imgHeight      = $marginTop + $textboxHeight + $marginBottom + 1;
$imgWidth       = $marginLeft + $textboxWidth + $marginRight + 1;

// now we make the image
$image = imageCreate ($imgWidth, $imgHeight);

// load the color scheme (RGB 0-255)
switch (
$colorscheme) {
    case 2:
        //scheme2   (white on blue)
       
$colorBG        = imagecolorallocate ($image, 0, 0, 200);
       
$colorBorder    = imagecolorallocate ($image, 150, 200, 255);
       
$colorText      = imagecolorallocate ($image, 255, 255, 255);
        break;
    case 1:
    default:
        //scheme1   (grayblack on white)
       
$colorBG        = imagecolorallocate ($image, 255, 255, 255);
       
$colorBorder    = imagecolorallocate ($image, 50, 50, 50);
       
$colorText      = imagecolorallocate ($image, 0, 0, 0);
        break;
}

// draw background
imageFilledRectangle(
$image, 0, 0, ($imgWidth - 1), ($imgHeight - 1), $colorBG);


// draw the text
for (
$i=0; $i<count($message); $i++) {
    imageString (
$image, $textSize, ($marginLeft + $paddingLeft + 1), ($marginTop + $paddingTop - $textHeight + (($i+1) * ($textHeight) + ($i * $textGutter))), $message[$i], $colorText);
}

// draw a box around the image
imageRectangle(
$image, $marginLeft, $marginTop, ($imgWidth - $marginRight - 1), ($imgHeight - $marginBottom - 1), $colorBorder);



// set the content type
//header(\"Content-type:  image/gif\");
header(\"Content-type:  image/png\");

// create an interlaced image for better loading in the browser
imageInterlace(
$image, 1);

// mark background color as being transparent
//imageColorTransparent(
$image, $colorBG);

// now send the picture to the client (this outputs all image data directly)
//imageGIF(
$image);
imagePNG(
$image);
?>
You can keep adding $message[] lines. The image will dynamically stretch to fit all the text you provide.

Mark Hensler
If there is no answer on Google, then there is no question.

Mark Hensler's picture

He has: 4,048 posts

Joined: Aug 2000

They have: 8 posts

Joined: Feb 2003

Yes it's me from G4B2S. I remember you were on these forums so thats why I came here.

Smiling

They have: 8 posts

Joined: Feb 2003

And now how would I go about actually saving that as an image. Not just displaying the image when the script is executed?

Mark Hensler's picture

He has: 4,048 posts

Joined: Aug 2000

Welcome to TWF!

You mean saving that into a .png file? The easiest way to do that would probably have one script (script1) run the image script (script2), and save the output to a file.

For example: (untested)

<?php
// script 1

ob_start();
if (
read_file(\"script2.php?message[]=\".URLEncode('Line 1').\"&message[]=\".URLEncode('Line 2').\")) {
   
$image = ob_get_contents();
    if (
$fp = fopen(\"image1.png\", \"r+\")) {
        fwrite(
$fp, $image);
        fclose(
$fp);
    }
}
ob_end_clean();
?>

Mark Hensler
If there is no answer on Google, then there is no question.

They have: 8 posts

Joined: Feb 2003

I'm not getting it to work. Well I got it to display what I wanted the first time, I just can't get your save routine to work.

They have: 8 posts

Joined: Feb 2003

I got it to work. Smiling Laughing out loud

<?php
// now send the picture to the client (this outputs all image data directly)
//imageGIF($image);
imagePNG($image);
?>

changed to

<?php
// now save the picture
//imageGIF($image, $filename);
$filename = \"file.png\";
imagePNG(
$image, $filename);
?>

Mark Hensler's picture

He has: 4,048 posts

Joined: Aug 2000

Oh cool. I didn't know that those functions took an optional filename. Very handy.

They have: 8 posts

Joined: Feb 2003

It is all working.

<?php
if ($pw != '[edited out]') { exit(\"What are you doing?\"); }

$textSize       = 2;

$textGutter     = 0;

$paddingBottom  = 4;
$paddingLeft    = 4;
$paddingRight   = 4;
$paddingTop     = 4;

$marginBottom   = 2;
$marginLeft     = 2;
$marginRight    = 2;
$marginTop      = 2;

$message[] = \"|SiC| is currently listening to:\";
$message[] = $song;

$max_length = 0;
foreach (
$message as $line) {
    if (strlen(
$line) > $max_length) {
       
$max_length = strlen($line);
    }
}

$textHeight     = imageFontHeight($textSize);
$textWidth      = imageFontWidth($textSize);

$textboxHeight  = (count($message) * ($textHeight)) + ((count($message)-1) * $textGutter) + ($paddingBottom + $paddingTop);
$textboxWidth   = ($max_length * $textWidth) + ($paddingLeft + $paddingRight);

$imgHeight      = $marginTop + $textboxHeight + $marginBottom + 1;
$imgWidth       = $marginLeft + $textboxWidth + $marginRight + 1;

$image = imageCreate ($imgWidth, $imgHeight);

$colorBG        = imagecolorallocate ($image, 200, 0, 0);
$colorBorder    = imagecolorallocate ($image, 153, 153, 153);
$colorText      = imagecolorallocate ($image, 255, 255, 255);

imageFilledRectangle(
$image, 0, 0, ($imgWidth - 1), ($imgHeight - 1), $colorBG);

for (
$i=0; $i<count($message); $i++) {
    imageString (
$image, $textSize, ($marginLeft + $paddingLeft + 1), ($marginTop + $paddingTop - $textHeight + (($i+1) * ($textHeight) + ($i * $textGutter))), $message[$i], $colorText);
}

imageRectangle(
$image, $marginLeft, $marginTop, ($imgWidth - $marginRight - 1), ($imgHeight - $marginBottom - 1), $colorBorder);

imageInterlace(
$image, 1);

imagePNG(
$image, \"song.png\");
?>

And if anyone wants to see what it is doing you can see here:
http://www.drewhopkins.com/song/song.png

This is just displaying what song winamp is currently playing. I have a winamp pluging that submits a URL every time the song changes and this is the script it loads from that URL.

*added*
Just in case anyone wants to know $pw and $song are from the URL.

http://www.site.com/script.php?pw=whatever&song=The+Song

Mark Hensler's picture

He has: 4,048 posts

Joined: Aug 2000

Looking at the image, you might want to trim($song) before assigning it to $message[].

They have: 8 posts

Joined: Feb 2003

Okay, I'll try it out tomorrow when I get home from school.

Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.