I've been through several solutions, and can't quite find a fast, efficient way to add dynamic, multi-line text/caption/annotation to an image using IMagick.
The script would take JSON data for several text areas to apply to an image, and the data includes all the font attributes: stroke, color, drop shadow, alignment, X & Y location (for the upper left corner), maximum width and rotation.
I've tried several methods of annotation and captions and simply can't get the text to behave. Here's what I'd like to be able to do:
And here's my code so far:
$data = '{
"baseImage" : "test-image.jpg",
"fields" : [
{
"name" : "name",
"default" : "You"
},
{
"name" : "email",
"default" : "you@yoursite.com"
}
],
"textareas": [
{
"font": "Alpha-Echo",
"align" : "left",
"size" : 24,
"color" : "#990000",
"stroke" : {
"color" : "#000000",
"width" : 0
},
"shadow" : {
"x" : 2,
"y" : 2,
"blur" : 6,
"color" : "#000000",
"opacity" : 0.5
},
"width" : 400,
"rotation" : 0,
"x" : 10,
"y" : 10,
"text" : "Welcome, {name}! How are you doing today?"
}
]
}';
$json = json_decode($data);
$imgBase->setBackgroundColor(new ImagickPixel('transparent'));
$imgBase->readImage($json->baseImage);
$imgBase->setImageFormat('png');
// get image dimensions
$w = $imgBase->getImageWidth();
$h = $imgBase->getImageHeight();
// loop through the textareas and fields
foreach($json->textareas as $textarea){
$captionHeight = $h - $textarea->y;
$drawText = $textarea->text;
foreach($json->fields as $field){
$fieldText = (!empty($_GET[$field->name]))? $_GET[$field->name] : $field->default;
$drawText = str_replace ('{' . $field->name . '}' , $fieldText , $drawText);
}
// create the caption
$theText = new Imagick();
$theText->newImage($textarea->width, $captionHeight, new ImagickPixel('transparent'));
$draw = new ImagickDraw();
if($textarea->stroke->width > 0){
$draw->setStrokeOpacity(1);
$draw->setStrokeColor($textarea->stroke->color);
$draw->setStrokeWidth($textarea->stroke->width);
$draw->setStrokeAntialias(true);
}
$draw->setGravity(1); // NORTH
$draw->setTextAlignment($alignment[$textarea->align]); // left = 1, center = 2, right = 3
$draw->setTextAntialias(true);
$draw->setFont($textarea->font);
$draw->setFontSize($textarea->size);
$draw->setFillColor($textarea->color);
$draw->rotate($textarea->rotation);
$draw->annotation($textarea->x, $textarea->y, $drawText);
$imgBase->drawImage($draw);
}
echo $imgBase->getImageBlob();
The issues I'm having are
- autowrapping text
- keeping it to a max width
- positioning (centering puts the text up and to the left as opposed to horizontally centering text, etc)
I'm assuming it can be done - it's available in the command line version of ImageMagick (http://www.imagemagick.org/Usage/text/#caption_bestfit) but IMagick is a different story. Any help is greatly appreciated!