Archive for September, 2007

Imagick users. (That means you, probably)

I’ve been coding Imagick for some time now and I have no idea how people are using it. It’s time to hear about you. I would like to hear how you are using Imagick, how well does it work in our scenario and what examples you would like to see in my blog.

Leave comments and help me to help you (sounds like a cliche, I know) ;)

Imagick RC4

Released 2007-09-25. Hopefully the last release candidate before the stable release :)

ImagickDraw, a quick introduction to drawing

ImagickDraw is a pretty simple class once you get used to it. One could consider ImagickDraw object as an "operation fifo". All operations are executed in order when drawImage method is called. You could for example call rotate and it would affect all drawing operations executed after it on the specific object.

Here's a primitive example to get you started with drawing:

PHP:
  1. <?php
  2.  
  3. /* Create an empty canvas with white background */
  4. $im = new Imagick();
  5. $im->newImage( 400, 400, new ImagickPixel( "white" ) );
  6.  
  7. /* Now lets draw some stuff */
  8. $draw = new ImagickDraw();
  9.  
  10. /* Draw a green ellipse with red border */
  11. $draw->setStrokeColor( new ImagickPixel( "red" ) );
  12. $draw->setStrokeWidth( 2 );
  13. $draw->setFillColor( new ImagickPixel( "green" ) );
  14. $draw->ellipse( 200, 100, 50, 50, 0, 360 );
  15.  
  16. /* Render the ellipse on the canvas */
  17. $im->drawImage( $draw );
  18.  
  19. /* Png format */
  20. $im->setImageFormat( "png" );
  21.  
  22. header( "Content-Type: image/png" );
  23. echo $im;
  24. ?>

And the resulting image:

Result

Using delegates with Imag(eMag)ick

Propably the simplest way to use ffmpeg with Imagick is to configure the ffmpeg as a delegate for ImageMagick. I tested this quickly yesterday and I was able to get images out of an Xvid video.

ImageMagick relies on a number of delegate programs to support certain image formats. This means that when an image with a specific format is opened ImageMagick spawns the delegate program to handle the conversion from the original format. I my case the program was ffmpeg.

First start by adding a new delegate into ImageMagick's delegates.xml, inside the tag:

<delegate decode="ffmpeg" command='"ffmpeg" -i "%i" -y -vcodec png -ss %s -vframes 1 -an -f rawvideo "%o"' />

After this you should be able to use the following piece of code:

PHP:
  1. <?php
  2.  
  3. $im = new imagick();
  4. $im->newPseudoImage( 200, 200, "ffmpeg:test1.mpg[40]" );
  5. $im->setImageFormat( "png" );
  6.  
  7. header( "Content-Type: image/png" );
  8. echo $im;
  9.  
  10. ?>

The number inside [] is seconds from the begin of the video. Someone more proficient with ffmpeg can propably change that to framenumber but I was unable to find a way to get image output by frame.

setImageOpacity

There is a new comfortability method committed to the Imagick CVS. Imagick::setImageOpacity( 0.0 - 1.0 ) allows you to easily set image opaque. This is especially usable if you're creating an image which is used as a watermark.

Here's a simple example of the usage:

PHP:
  1. <?php
  2. /* Read test png image */
  3. $im = new Imagick( "test.png" );
  4.  
  5. /* Set opacity to 0.5 */
  6. $im->setImageOpacity( 0.5 );
  7.  
  8. /* Output the image */
  9. header( "Content-Type: image/png" );
  10. echo $im;
  11.  
  12. ?>

Resource limiting

ImageMagick supports wide variety of resource limiting. For example this code:

PHP:
  1. <?php
  2.  
  3. /* Create a new object */
  4. $im = new Imagick();
  5.  
  6. /* Set memory limit to 5MB */
  7. $im->setResourceLimit( Imagick::RESOURCETYPE_MEMORY, 5 );
  8.  
  9. /* Read a huge image :) */
  10. $im->readImage( "huge_image.png" );
  11. ?>

would limit the memory usage to 5MB. The "overflowing" memory is cached to the disk so you can basically handle as large images as you got diskspace. Of course processing is faster in memory so this is a classic trade-off between speed and resource usage.

Watermarking made simple

Well, I thought to post an example of one the most common operations in image handling with PHP. A watermark.

Here's the code:

PHP:
  1. <?php
  2.  
  3. /* Create Imagick object */
  4. $im = new Imagick( 'example.png' );
  5.  
  6. /* Create a drawing object and set the font size */
  7. $draw = new ImagickDraw();
  8. $draw->setFontSize( 30 );
  9.  
  10. /* Make the watermark semi-transparent */
  11. $draw->setFillAlpha( 0.4 );
  12.  
  13. /* Set gravity to the center. More about gravity:
  14.     http://www.imagemagick.org/Usage/annotating/#gravity */
  15. $draw->setGravity( Imagick::GRAVITY_CENTER );
  16.  
  17. /* Write the text on the image
  18.     Position x0,y0 (Because gravity is set to center)
  19.     Rotation 45 degrees.
  20. */
  21. $im->annotateImage( $draw, 0, 0, 45, "Copyright Example" );
  22.  
  23. /* Output */
  24. header( "Content-Type: image/{$im->getImageFormat()}" );
  25. echo $im;
  26.  
  27. ?>

Again some examples..cropThumbnailImage()

Well, among new features of imagick there is cropThumbnailImage. It's not really that new but it might be undocumented for most of the parts.

PHP:
  1. <?php
  2.  
  3. /* Read the image */
  4. $im = new imagick( "test.png" );
  5.  
  6. /* create the thumbnail */
  7. $im->cropThumbnailImage( 80, 80 );
  8.  
  9. /* Write to a file */
  10. $im->writeImage( "th_80x80_test.png" );
  11. ?>

Let's assume the source image in this example is 120x240. First it is scaled down to 80x160 and then cropped by the larger side (height in this case) from position x0,y40 to x80,y120. After this crop we have a fixed size 80x80 thumbnail.

Creating a PDF preview

Here is a simple example how to create a preview of PDF document's first page:

PHP:
  1. <?php
  2.  
  3. /* Read page 1 */
  4. $im = new imagick( 'test.pdf[0]' );
  5.  
  6. /* Convert to png */
  7. $im->setImageFormat( "png" );
  8.  
  9. /* Send out */
  10. header( "Content-Type: image/png" );
  11. echo $im;
  12.  
  13. ?>

The number between [] is the number of the page starting from 0.