Friday, October 29, 2010

Creating shadows with ImageMagick

1. Shadows for an image (create a shadow using Imagick::shadowImage and overlay the original image on top)

<?php
/* Read the image into the object /
$im = new Imagick( ‘totoro.png’ );
$im->setImageFormat("png");

/ Make the image a little smaller, maintain aspect ratio /
$im->thumbnailImage( 200, null );

/ Clone the current object /
$shadow = $im->clone();

/ Set image background color to black (the color of the shadow) /
$shadow->setImageBackgroundColor( new ImagickPixel( ‘black’ ) );

/ Create the shadow /
$shadow->shadowImage( 80, 3, 5, 5 );

/ Imagick::shadowImage only creates the shadow. That is why the original image is composited over it /
$shadow->compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 );
$content = $shadow->getImageBlob();

$shadow->destroy();
$im->destroy(); 

/ Display the image */
header( "Content-Type: image/jpeg" );
header(’Content-Length: ‘ . strlen($content)); 
echo $content;
?>

2. Shadow for text

Note that the trick for multi-line text is to insert a new line character (\n) in your string. You can also use the rotation degree to control the layout, but make sure you use the correct size text canvas image because when you queryFontMetrics, it is based on the horizontal layout.

<?php
// overlay the text
$draw = new ImagickDraw();
$draw->setFont(’Helvetica’);
$draw->setFontSize(13);
$draw->setFillColor(new ImagickPixel(’#B8B8B8′));

$text = "HELLO\nWORLD!"; // for multi-line text, insert new line char

$textcanvas = new Imagick();
$textprops = $textcanvas->queryFontMetrics($draw, $text, true); //you need to turn multiline on, the last param
$textw = intval($textprops[’textWidth’]);
$texth = intval($textprops[’textHeight’]);
$textcanvas->newImage($textw+20, $texth+20, new ImagickPixel(’transparent’)); //give 20 pixel spaces around the text
$textcanvas->setImageFormat(’png’);
$textcanvas->annotateImage($draw, 10, $texth, 0, $text);

// create shadow
$shadow = $textcanvas->clone();
$shadow->setImageBackgroundColor(new ImagickPixel(’black’));
$shadow->shadowImage(80, 3, 5, 5);
$shadow->compositeImage($textcanvas, Imagick::COMPOSITEOVER, 0, 0);
$shadoww = $shadow->getImageWidth();
$shadowh = $shadow->getImageHeight();

// overlay the shadowed text on the given background image
$bg = new Imagick(’background.png’);
$bg->setImageFormat(’png’);
$bgw = $bg->getImageWidth();
$bgh = $bg->getImageHeight();

//$bg->compositeImage($shadow, Imagick::COMPOSITEOVER, 0, ($bgh-$shadowh));
$bg->compositeImage($shadow, Imagick::COMPOSITEOVER, 0, 0);

// let’s show the image
$content = $bg->getImageBlob();
$textcanvas->destroy();
$shadow->destroy();
$bg->destroy();

header(’Content-Type: image/png’);
header(’Content-Length: ‘ . strlen($content));
echo $content;
?> 


 

Somehow, I still don’t know how to adjust the line spacing between multi-lines. I also found that ImagickDraw::setFontWeight did not work for me. Anyone knows how to fix those two issues? 

 

Reference:

1. Mikko’s blog (the best place for ImageMagick samples, who can beat the IM developer himself) 

1 comment:

  1. Thanks for sharing... Note though, it is Imagick::COMPOSITE_OVER, not Imagick::COMPOSITEOVER (I guess it's post formatting error).

    ReplyDelete