Ever had the situation where you have a piece of string which you need to overlay on an image? Maybe a situation where the area reserved for the string is known in pixels but you need to know the font size to fill most of the area? Think no more!
Here is a small example of how to fit a certain piece of a string on to an area of which you know the width and the height or only the width. The magic happens through the ImageMagick CAPTION: format. You can see from the example images how the parameters actually affect the image.
- <?php
- /* How wide is our image */
- $image_width = 200;
- /* Give zero for autocalculating the height */
- $image_height = 200;
- /* Specify the text */
- $text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
- Mauris lectus mi, mattis non, euismod vel, sagittis nec, ipsum.";
- /* Instanciate imagick */
- $im = new Imagick();
- /* Create new image using caption: pseudo format */
- $im->newPseudoImage( $image_width, $image_height, "caption:" . $text );
- /* Put 1px border around the image */
- $im->borderImage( 'black', 1, 1 );
- /* PNG format */
- $im->setImageFormat( "png") ;
- /* Output */
- header( "Content-Type: image/png" );
- echo $im;
- ?>
Here is image with width 100 and height 0:
Width 100 Height 50:
Width 200 Height 200 (as you can see the font size is now larger):



#1 by Assissotom on January 17, 2008 - 1:54 pm
Quote
Very good site! I like it! Thanks!
Trackback: PHPDeveloper.org
Pingback: developercast.com » Mikko Koppanen’s Blog: Typesetting
Pingback: Mikko Koppanen’s Blog: Typesetting | MT-Soft Website Development
#2 by Edsel P. Mabilangan on January 30, 2008 - 9:01 pm
Quote
Do you know how to make a gradient font using imagick?
#3 by Ertai on February 7, 2008 - 4:02 pm
Quote
Does somebody know how to change the color of a single pixel??
For example:
$image(x,y,c) = 255;
where x is the column, y is the row and c is the channel.
#4 by Miika on February 8, 2008 - 8:14 pm
Quote
Hi, didn’t know where to put this question, but is there way to replace color from image ?
Regards,
Miika
#5 by Mikko Koppanen on February 9, 2008 - 1:53 pm
Quote
Miika,
there is color flood fill, paint transparent, paint opaque and so on. Are you looking to replace color in some area? Single pixel? Or all occurances of the color in the image?
#6 by Ertai on February 11, 2008 - 6:50 pm
Quote
How do I access a single pixel for reading and writing??
#7 by Mikko Koppanen on February 11, 2008 - 6:56 pm
Quote
Ertai,
with pixelregioniterator.
#8 by Ertai on February 12, 2008 - 9:38 pm
Quote
I still don’t understand it.
How do I change the RGB color of a pixel at position (10,10)??
Could you put an example??
#9 by Mikko Koppanen on February 12, 2008 - 10:31 pm
Quote
Ertai,
see the post “ImagickPixelIterator is not read only after all”. It illustrates the usage of the iterator.
#10 by Albertini on February 13, 2008 - 3:15 pm
Quote
Hi Koppanen,
Somewhat similar to Ertai, I would like to know how to make a random access to pixels. I have installed imagick 2.1.0RC3 lib.
I don’t want to iterate the pixels for performance purposes.
Thanks in advance,
Albertini
#11 by Thomas on February 16, 2008 - 10:49 pm
Quote
If I put line break in my text string then will it support line break?
And what about alignment of string. Can I do left, center and right?
#12 by Francois on February 27, 2008 - 1:31 am
Quote
Great blog, I learn a lot thanks to you
I was wondering in this example, is there a way to make the background transparent?
I was able after a few google search to find that when you create a ImagickPixel you can specify the opacity as two more hex character but with the newPseudoImage you do not specify the background color. I’m asking because when I overlay this text on my image there is big white square. Maybe I just don’t know how to overlay two images by blending them correctly together, but I have just started using Imagick last Wednesday. Any help would be appreciated.
#13 by Niels Pardon on March 3, 2008 - 12:10 am
Quote
I’ve tested this example with ImageMagick 6.3.9 and Imagick 2.1.1RC1 on Debian Etch and it took over 10 minutes to render! Is this a normal behaviour?
#14 by Mikko Koppanen on March 3, 2008 - 12:13 am
Quote
Niels Pardon,
sounds a bit long to me. I will have to test with 6.3.9 but I guess it’s more about the gs version you’re running.
#15 by esr2587758 on March 10, 2008 - 7:20 am
Quote
hello,mikko.
i also have Francois’s problem,
Do you have a good way to help us.
#16 by multimedia professional on April 16, 2008 - 3:21 pm
Quote
Its so nice of you to share this information. this will surely help. keep posting those good blogs you have.
#17 by Nick E on May 12, 2008 - 11:23 pm
Quote
Francois, esr2587758
If you’re still experiencing this issue, try to set the background color to transparent BEFORE “newPseudoImage()”
for instance. Just ran into the problem myself, corrected by moving the “setBackgroundColor()” BEFORE “newPseudoImage()”
#18 by Mathieu De Kermadec on May 13, 2008 - 2:37 pm
Quote
If your image takes a lot of time to render, maybe you could try to force which font imageMagick must use to create the pseudo image, it works for me:
$im = new Imagick();
$im->setFont(‘/path/to/your/fonts/arial.ttf’);
$im->newPseudoImage( $image_width, $image_height, “caption:” . $text );
#19 by Francois on May 21, 2008 - 5:56 pm
Quote
Thank you very much Nick E, I will try that.
#20 by John M on August 20, 2008 - 3:01 pm
Quote
Great article. I’ve been trying to figure out how to do exactly this with PHP natively for a while. Is there anyway to set the font to use? The convert application lets you set the font as a parameter. e.g.
convert -size 200×200 -background white -font verdana.ttf caption:”The quick red fox jumped over the lazy brown dog.” -flatten caption3.png
I can’t see a way to specify the font to the Imagick() class. It can only be set to the ImagickDraw() class which is unused if you are just creating a caption as above.
Thanks
#21 by Pete on October 10, 2008 - 8:48 pm
Quote
Hi there, thank you for all the examples. i realy can get much information.
can anyone tell me how to get this example on a existing png image?
it have to be multiline text with nice font
i would be thankfull
#22 by Dan on October 21, 2008 - 3:58 pm
Quote
Thanks a lot for all these example, they really help me with the library.
Now, concerning this example, i tried to find another example showing how to composite multiline text over an image, while constraining the space in which it will be rendered. Let’s say 3 paragraph of text which i want to fin in a 100px column, with specified font and size.
I tried with labelImage but i couldnt get anything to write on the image, then i tried with annotation, but i cant find how to restrain the column to 100px (well i know i can create an 100px width image, but then the text would just overflow on the sides).
I could use what you show in this example, but then if the text is smaller in length (it comes from a cms and could be only 2-3 lines), it would be really larger than what i want it to be.
If anyone can help, it would be greatly appreciated. Thank you very much!
#23 by anoop on February 16, 2009 - 4:12 pm
Quote
hi
is there a way to change the color of the text when creating using newPseudoImage() ?
Anoop
#24 by burroughsc on March 18, 2009 - 12:13 pm
Quote
I’ve tried a few things for changing the colour of the text when using newPseudoImage. The closest I have come is:
/* Create new image using caption: pseudo format */
$im->newPseudoImage( $image_width, $image_height, “caption:” . $text );
$im->paintOpaqueImage ( ‘#000000′, ‘#ff7722′, 100);
Looks a bit nasty though. There must be a way of doing this! Anyone?
#25 by burroughsc on March 18, 2009 - 4:40 pm
Quote
Frustrated by the use of “caption” and the “newPseudoImage” in terms of colouring the text, I came up with this… Which uses the ImagickDraw object and annotation method. So much more control of the drawing, and it attempts to auto-fit.
setFont($fontFace);
/* Annotation gravity */
$draw->setGravity (Imagick::GRAVITY_CENTER);
/* New image */
$canvas->newImage($width, $height, $pixel);
$words = preg_split(“/[ \t]+/”, $text);
while (TRUE) {
$newLine = TRUE;
$done = TRUE;
$theText = ”;
$draw->setFontSize( $fontSize );
for($i=0,$j=count($words);$iqueryFontMetrics( $draw, $theText.(!$newLine ? ‘ ‘ : ”).$words[$i]);
if($metrics['textWidth'] $height) {
$fontSize -= 2;
$done = FALSE;
break; // Break out of the ‘for’ loop.
}
}
if($done) {
break; // Break out of the ‘while’ loop.
}
}
/* Black text */
$pixel->setColor(‘light gray’);
$draw->setFillColor($pixel);
/* Create text */
$canvas->annotateImage($draw, 0, 0, 0, $theText);
/* Give image a format */
$canvas->setImageFormat(‘jpg’);
/* Give the image a border */
$canvas->borderImage( ‘black’, 1, 1);
/* Output the image with headers */
header(‘Content-type: image/jpg’);
echo $canvas;
?>
#26 by burroughsc on March 18, 2009 - 4:41 pm
Quote
chopped off some of the script… Here is the full script.
setFont($fontFace);
/* Annotation gravity */
$draw->setGravity (Imagick::GRAVITY_CENTER);
/* New image */
$canvas->newImage($width, $height, $pixel);
$words = preg_split(“/[ \t]+/”, $text);
while (TRUE) {
$newLine = TRUE;
$done = TRUE;
$theText = ”;
$draw->setFontSize( $fontSize );
for($i=0,$j=count($words);$iqueryFontMetrics( $draw, $theText.(!$newLine ? ‘ ‘ : ”).$words[$i]);
if($metrics['textWidth'] $height) {
$fontSize -= 2;
$done = FALSE;
break; // Break out of the ‘for’ loop.
}
}
if($done) {
break; // Break out of the ‘while’ loop.
}
}
/* Black text */
$pixel->setColor(‘light gray’);
$draw->setFillColor($pixel);
/* Create text */
$canvas->annotateImage($draw, 0, 0, 0, $theText);
/* Give image a format */
$canvas->setImageFormat(‘jpg’);
/* Give the image a border */
$canvas->borderImage( ‘black’, 1, 1);
/* Output the image with headers */
header(‘Content-type: image/jpg’);
echo $canvas;
?>
#27 by burroughsc on March 18, 2009 - 4:42 pm
Quote
/* Size */
$width = 300;
$height = 200;
/* Font */
$fontFace = ‘Verdana’;
$fontSize = 64;
/* The annotation text */
$text = “The quick brown fox jumps over the lazy dog.”;
/* Create some objects */
$canvas = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel(‘gray’);
/* Font properties */
$draw->setFont($fontFace);
#28 by JiB on July 25, 2009 - 4:39 pm
Quote
is there any other way to use images directly into web page something like below
<img src="getImageBlob(); ?>”>
or any other way but with similar results.
not following procedure
header(’Content-type: image/jpg’);
echo echo $im->getImageBlob();
Thanks Fellas
Anybody have any idea
#29 by Mikko Koppanen on July 25, 2009 - 4:47 pm
Quote
JiB,
No, not really.
#30 by Gavin Foster on July 28, 2009 - 4:56 pm
Quote
JiB: something like
newImage(688, 176, new ImagickPixel(‘white’));
$image->setImageFormat(‘jpeg’);
…
?>
<img src="data:image/gif;base64,” />
#31 by Gavin Foster on July 28, 2009 - 4:58 pm
Quote
doh, try this:
JiB: something like
<?php
$image = new Imagick();
$image->newImage(688, 176, new ImagickPixel(‘white’));
$image->setImageFormat(‘jpeg’);
$image->setImageFormat(’jpeg’);
…
?>
image)?>†/>
#32 by Gavin Foster on July 28, 2009 - 4:58 pm
Quote
still didnt get the last line right:
<img src=”data:image/gif;base64,<?=base64_encode($this->image)?>” />
#33 by 1001 Fonts on November 23, 2009 - 11:19 pm
Quote
I am looking for an Imagick method to annotate multiline text. I have a problem with the CAPTION: format. example from above, as it does not allow to set the font size like for an ImagickDraw object. On the other side, the Imagick annotateImage method respects a given font size, but does not support multiline text?!? I have stumbled across the multiline parameter for the queryFontMetrics method, but don’t see how I can really make use of it. I thought I would ask if anybody knows of some available code to handle this request or if I have overlooked something in the Imagick set of classes?
#34 by antonio lorusso on April 16, 2010 - 4:59 pm
Quote
I was lookig to use the gravity parameter like in the iamgemagick example “convert -background lightblue -fill blue -font Candice -pointsize 40 -size 320x -gravity Center caption:’ImageMagick Rules OK!’ caption_centered.gif” but I did not manage how to do it. Is there a way to center the text?
#35 by antonio lorusso on April 16, 2010 - 5:01 pm
Quote
I was looking on how to use the gravity parameter like in the imagemagick example “convert -background lightblue -fill blue -font Candice -pointsize 40 -size 320x -gravity Center caption:’ImageMagick Rules OK!’ caption_centered.gif” but I did find anything in the manual. Is there a way to center the text?
#36 by Sprike on June 25, 2010 - 5:19 pm
Quote
@burroughsc Nice usage they’re I have chosen to go with something similar to your method as it gives a lot more control over the text, What I am in the middle of is creating a function that gives the user the ability to upload an image, crop the image to they’re liking and place some text on top of it, whilst also being able to chose type face, size, color and horizontal and vertical alignment.
Nearly done, will upload code to net finished.
#37 by Trung PHan on August 4, 2010 - 1:34 am
Quote
Brilliant !
#38 by בניית אתרים on November 10, 2011 - 7:50 pm
Quote
I get
Fatal error: Uncaught exception ‘ImagickException’ with message ‘unable to get type metrics `Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris lectus mi, mattis non, euismod vel, sagittis nec, ipsum.”
#39 by Will on November 27, 2011 - 6:10 pm
Quote
I found this to be a lot slower than adding text via a draw object and annotating.. Have you noticed this difference also?
#40 by Daniel Pfeiffer on January 9, 2012 - 1:08 am
Quote
To change the text color, add
$im->setOption(“fill”,”white”);
before you create the psuedo image.
#41 by Iulian on March 28, 2012 - 11:11 am
Quote
How can i make bold text?
#42 by Donald Wheaton on October 11, 2012 - 1:06 am
Quote
I fixed my ‘unable to get type metrics’ error by updating ghostscript.
#43 by Donald Wheaton on October 11, 2012 - 1:09 am
Quote
Sorry, still have the same ‘unable to get type metics’ error. I don’t know why it worked once.