Imagick and Gmagick builds available for Windows

The new Windows build page http://valokuva.org/magick/ contains builds for both Imagick and Gmagick. All builds are done using VC9 and PHP 5.3.

ImageMagick builds are QuantumDepth 16 (default).
GraphicsMagick builds are QuantumDepth 8 (default).

Please note that these builds won’t work with the official PHP.net binaries which are compiled using VC6.

Edit: Pierre corrected me that there are official VC9 builds of PHP available at http://windows.php.net/download/

New and old extensions

I’ve been fairly busy lately writing a few new PHP extensions. Here is a short introduction of each one of them and what they can do:

1. tokyo_tyrant

This is an extension to connect to the Tokyo Tyrant key value store. It supports the normal key value API and the table API. The feature-set should match quite closely what Tokyo Tyrant client libraries expose. The first version of this extension has been released in PECL.

2. zbarcode

This is the latest extension under works: it wraps ImageMagick and ZBar libraries and provides an OO API for scanning barcodes from images. It is currently under heavy development but hopefully it will be in PECL later on.

3. dmtx

Another barcode extension. Reads and writes data matrices (2D barcode). The API would need some refactoring but it seems to be working fine as it is.

Hardware failure

Hi,

my blog has been down for about the last week now because of problems with the server hardware. I am trying to provision new hardware and restore the service back to normal as soon as possible. Currently things are running from a backup VPS so the site might be a bit slow from time to time.

Fake uploading files

Fake uploading files

A few days ago I encountered a problem where I needed to test a controller that handles file uploads. I couldn't find an easy way to unit test the code which used built-in uploading functionality so I decided to whip up this simple extension that allows to fake file uploads.

The extension is doing things that shouldn't be done, it probably doesn't even run anywhere else than on CLI, it is insecure, it might behave incorrectly but in this scenario it worked fine so I decided to share it. Don't ask for support or any updates for this extension and use it on your own risk. I take no responsibility of anything (especially related to this extension).

The following example code might work with the extension:

PHP:
  1. <?php
  2. fakeupload_file("userFile", '/Users/test/test.txt',
  3.                         "/tmp/upload.tmp", "text/plain", "This is a test upload");
  4.  
  5. var_dump(is_uploaded_file('/tmp/upload.tmp'));
  6.  
  7. var_dump($_FILES);
  8.  
  9. var_dump(move_uploaded_file("/tmp/upload.tmp", "/tmp/test_file.txt"));
  10.  
  11. unlink("/tmp/test_file.txt");
  12. ?>

And it can be executed using:

PHP:
  1. # php -dfakeupload.enabled=1 test.php
  2. bool(true)
  3. array(1) {
  4.   ["userFile"]=>
  5.   array(5) {
  6.     ["name"]=>
  7.     string(20) "/Users/test/test.txt"
  8.     ["type"]=>
  9.     string(10) "text/plain"
  10.     ["tmp_name"]=>
  11.     string(15) "/tmp/upload.tmp"
  12.     ["error"]=>
  13.     int(0)
  14.     ["size"]=>
  15.     int(21)
  16.   }
  17. }
  18. bool(true)

The source can be found here: fakeupload-0.0.2.tgz

Perspective transformations

Finally (after a long break) I managed to force myself to update the PHP documentation and this time it was distortImage code example. Things have been hectic lately but that does not quite explain the 6 months(?) break between this and the previous post. As a matter of a fact there is no excuse for such a long silence so I will try to update this blog a bit more often from now on.

Back in the day I used to blog the examples and update the documentation if I remembered but I am trying to fix this bad habit. Most of the latest examples have been updated in to the manual. In the case of the two last examples I updated the documentation first and then blogged on the subject.

I took some time to actually understand the perspective transformations properly using the excellent ImageMagick examples (mainly created by Anthony Thyssen) as a reference. The basic idea of perspective distortion seems simple: to distort the control points to new locations. Grabbing the syntax for Imagick was easy, an array of control point pairs in the form of:

PHP:
  1. array(source_x, source_y, dest_x, dest_y ... )

The following example uses the built-in checkerboard pattern to demonstrate perspective distortion:

PHP:
  1. <?php
  2. /* Create new object */
  3. $im = new Imagick();
  4.  
  5. /* Create new checkerboard pattern */
  6. $im->newPseudoImage(100, 100, "pattern:checkerboard");
  7.  
  8. /* Set the image format to png */
  9. $im->setImageFormat('png');
  10.  
  11. /* Fill background area with transparent */
  12. $im->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
  13.  
  14. /* Activate matte */
  15. $im->setImageMatte(true);
  16.  
  17. /* Control points for the distortion */
  18. $controlPoints = array( 10, 10,
  19.                         10, 5,
  20.  
  21.                         10, $im->getImageHeight() - 20,
  22.                         10, $im->getImageHeight() - 5,
  23.  
  24.                         $im->getImageWidth() - 10, 10,
  25.                         $im->getImageWidth() - 10, 20,
  26.  
  27.                         $im->getImageWidth() - 10, $im->getImageHeight() - 10,
  28.                         $im->getImageWidth() - 10, $im->getImageHeight() - 30);
  29.  
  30. /* Perform the distortion */ 
  31. $im->distortImage(Imagick::DISTORTION_PERSPECTIVE, $controlPoints, true);
  32.  
  33. /* Ouput the image */   
  34. header("Content-Type: image/png");
  35. echo $im;
  36. ?>

Here is the source image:
checker before

And the result:
after

Fill patterns

My work life has been quite busy lately and I haven't had a chance to sit down and blog. I have been touring around London and some parts of the northern England consulting and organizing some training here and there. Luckily I have had the chance to do some work on Imagick and the 2.2.0 beta release is getting closer. The internal structure was completely restructured and broken down into several smaller files. During this time Imagick was adapted to follow the PHP Coding Standards more closely. Still a work in progress :)

I committed slightly modified version of this example to PHP Manual http://uk.php.net/manual/en/imagick.examples.php page a few days ago. The example illustrates using an image as a part of a named fill pattern. The fill pattern is used to annotate text but the named pattern could also be used to fill any shapes that allow fill to be specified (include circles, ellipses, rectangles, polygons etc etc). The code itself is pretty straight forward: Read the image, create the pattern and use the pattern as a fill.

The ice formations image is from http://www.photoeverywhere.co.uk/west/winterholiday/slides/iceformations5679.htm.

PHP:
  1. <?php
  2.  
  3. /* Create a new imagick object */
  4. $im = new Imagick( 'iceformations5679.JPG' );
  5.  
  6. /* Create imagickdraw object */
  7. $draw = new ImagickDraw();
  8.  
  9. /* Start a new pattern called "ice" */
  10. $draw->pushPattern( 'ice'  , 0  , 0  , 50  , 50 );
  11.  
  12. /* Composite the image on the pattern */
  13. $draw->composite( Imagick::COMPOSITE_OVER, 0, 0, 50, 50, $im );
  14.  
  15. /* Close the pattern */
  16. $draw->popPattern();
  17.  
  18. /* Use the pattern called "ice" as the fill */
  19. $draw->setFillPatternURL( '#ice' );
  20.  
  21. /* Set font size to 52 */
  22. $draw->setFontSize( 52 );
  23.  
  24. /* Annotate some text */
  25. $draw->annotation( 5, 50, "Hello World!" );
  26.  
  27. /* Create a new canvas and white image */
  28. $canvas = new Imagick();
  29. $canvas->newImage( 310, 70, "white" );
  30.  
  31. /* Add black border around the resulting image */
  32. $canvas->borderImage( 'black', 1, 1 );
  33.  
  34. /* Draw the ImagickDraw on to the canvas */
  35. $canvas->drawImage( $draw );
  36.  
  37. /* Set the format to PNG */
  38. $canvas->setImageFormat( 'png' );
  39.  
  40. /* Output the image */
  41. header( "Content-Type: image/png" );
  42. echo $canvas;
  43. ?>

And the result is here:

phplondon conference 2008

To summarize it: I had fun :) My conference preparations started about two weeks before the conference. The PHPLondon fellows (Paul, Matt and Richard) asked me to do a small presentation about Imagick at the pre-conference social event. The presentation I assembled ended up being a little over two hours, give or take. The hardest part was to trim down from two hours to about 40 minutes (I didn't want to bore the people with too many code examples). The slides are available at http://valokuva.org/talks if you need them for some reason.

My conference day was pretty hectic from the beginning to the end. I gave a few demos about the products that we represent and the moment I opened my mouth for the first time people started leaving the room. I hope that it had something to do with the "My Framework is better than yours?" talk starting at the same time ;)

I met quite a lot of new people at the conference and of course it was nice to see the familiar faces from other conferences and PHPLondon meetings. I was especially happy that I was able to answer the questions Nigel James had ;)

A huge thanks to the organizers for making this day possible!

Tags:

Seam carving

Today I was reading trough the ImageMagick ChangeLog and noticed an interesting entry. "Add support for liquid rescaling". I rushed to check the MagickWand API docs and there it was: MagickLiquidRescaleImage! After about ten minutes of hacking the Imagick support was done. Needless to say; I was excited :)

For those who don't know what seam carving is check the demo here. More detailed information about the algorithm can be found here: "Seam Carving for Content-Aware Image Resizing" by Shai Avidan and Ariel Shamir

To use this functionality you need to install at least ImageMagick 6.3.8-2 and liblqr. Remember to pass --with-lqr to ImageMagick configuration line. You can get liblqr here: http://liblqr.wikidot.com/. The Imagick side of the functionality should appear in the CVS today if everything goes as planned.

Here is a really simple example just to illustrate the results of the operation. The parameters might be far from optimal (didn't do much testing yet). The original dimensions of image are 500x375 and the resulting size is 500x200.

Update: the functionality is pending until license issues are solved.

PHP:
  1. <?php
  2.  
  3. /* Create new object */
  4. $im = new Imagick( 'test.jpg' );
  5.  
  6. /* Scale down */
  7. $im->liquidRescaleImage( 500, 200, 3, 25 );
  8.  
  9. /* Display */
  10. header( 'Content-Type: image/jpg' );
  11. echo $im;
  12.  
  13. ?>

The original image by flickr/jennconspiracy

result

And the result:

result

Update. On kenrick's request here is an image which is scaled down to 300x300

result2

Typesetting

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:
  1. <?php
  2.  
  3. /* How wide is our image */
  4. $image_width = 200;
  5.  
  6. /* Give zero for autocalculating the height */
  7. $image_height = 200;
  8.  
  9. /* Specify the text */
  10. $text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  11.          Mauris lectus mi, mattis non, euismod vel, sagittis nec, ipsum.";
  12.  
  13. /* Instanciate imagick */
  14. $im = new Imagick();
  15.  
  16. /* Create new image using caption: pseudo format */
  17. $im->newPseudoImage( $image_width, $image_height, "caption:" . $text );
  18.  
  19. /* Put 1px border around the image */
  20. $im->borderImage( 'black', 1, 1 );
  21.  
  22. /* PNG format */
  23. $im->setImageFormat( "png") ;
  24.  
  25. /* Output */
  26. header( "Content-Type: image/png" );
  27. echo $im;
  28.  
  29. ?>

Here is image with width 100 and height 0:

width_100_height_0.png

Width 100 Height 50:

width_100_height_50.png

Width 200 Height 200 (as you can see the font size is now larger):

width_200_height_200.png

Padding thumbnail with color

I know, it's been a while since I last blogged. This is because a lot of things are happening in my personal life. I recently relocated to London from Finland and started a new job. Things are quite busy but I will try to post an example now and then. In the meanwhile I would like to hear about sites using Imagick, so if your project is not super secret please post an url and maybe a small explanation what you're doing with Imagick on the site. This is purely for my personal interest.

Anyway, to the point. Today's example originates from a question asked by a user. How do I thumbnail the image inside given dimensions proportionally and fill the "blank" areas with a color? Well, the answer is here :)

The code is for Imagick 2.1.0 but adapting to older versions should not be hard.

PHP:
  1. <?php
  2. /* Define width and height of the thumbnail */
  3. $width = 100;
  4. $height = 100;
  5.  
  6. /* Instanciate and read the image in */
  7. $im = new Imagick( "test.png" );
  8.  
  9. /* Fit the image into $width x $height box
  10. The third parameter fits the image into a "bounding box" */
  11. $im->thumbnailImage( $width, $height, true );
  12.  
  13. /* Create a canvas with the desired color */
  14. $canvas = new Imagick();
  15. $canvas->newImage( $width, $height, 'pink', 'png' );
  16.  
  17. /* Get the image geometry */
  18. $geometry = $im->getImageGeometry();
  19.  
  20. /* The overlay x and y coordinates */
  21. $x = ( $width - $geometry['width'] ) / 2;
  22. $y = ( $height - $geometry['height'] ) / 2;
  23.  
  24. /* Composite on the canvas  */
  25. $canvas->compositeImage( $im, imagick::COMPOSITE_OVER, $x, $y );
  26.  
  27. /* Output the image*/
  28. header( "Content-Type: image/png" );
  29. echo $canvas;
  30.  
  31. ?>

The source image:
test.png

The resulting image:
testphp.png