Search code examples
imagemagickgdimage-manipulationgraphicsmagick

Is ImageMagick the fastest way to overlay images? How do I make faster or is there a faster tech I'm unaware of?


I'm in the process of building an image manipulation Nginx CDN/cache server to overlay millions of unique SVG designs files on apparel jpegs. Similar tutorial here: http://sumitbirla.com/2011/11/how-to-build-a-scalable-caching-resizing-image-server/

I have written a test script here:

<?php

$cmd = "composite GOSHEN.svg blank-tshirt.jpg -geometry 600x700+456+335 JPG:-";

header("Content-type: image/jpeg");
passthru($cmd);
exit();

?>

Here is an example result:

My issue is that ImageMagick is so slow. Besides more CPU/Memory, are there any tricks to make it faster? Are there any alternative technologies that could be faster to overlay images?

Any help is much appreciated.


Solution

  • php-vips can be quite a bit quicker than imagick. I made a test program for you:

    #!/usr/bin/env php
    <?php
    
    require __DIR__ . '/vendor/autoload.php';
    use Jcupitt\Vips;
    
    for($i = 0; $i < 100; $i++) {
        $base = Vips\Image::newFromFile($argv[1], ["access" => "sequential"]);
        $overlay = Vips\Image::newFromFile($argv[2], ["access" => "sequential"]);
    
        // centre the overlay on the image, but lift it up a bit    
        $left = ($base->width - $overlay->width) * 0.5;
        $top = ($base->height - $overlay->height) * 0.45;
    
        $out = $base->composite2($overlay, "over", ["x" => $left, "y" => $top]);
    
        // write to stdout with a mime header
        $out->jpegsave_mime();
    }       
    

    Using the test images from your server:

    http://build9.hometownapparel.com/pics/

    Then running on my desktop machine (Ubuntu 17.10, a fast i7 CPU) I see:

    $ time ./overlay.php blank-tshirt.jpg GOSHEN.svg > /dev/null
    real    0m2.488s
    user    0m13.446s
    sys 0m0.328s
    

    So about 25ms per image. I see this result (taken from the first iteration, obviously):

    sample output

    I tried a looping version of your imagemagick example:

    #!/usr/bin/env php
    <?php
    
    header("Content-type: image/jpeg");
    
    for($i = 0; $i < 100; $i++) {
        $cmd = "composite GOSHEN.svg blank-tshirt.jpg -geometry 600x700+456+335 JPG:-";
    
        passthru($cmd);
    }     
    

    Running it against IM-6.9.7-4 (the version packaged for Ubuntu) I see:

    $ time ./magick.php > /dev/null
    real    0m29.084s
    user    0m42.289s
    sys 0m4.716s
    

    Or 290ms per image. So on this test, php-vips is more than 10x faster. It's a bit unfair: imagick would probably be a little quicker than just shelling out to composite.

    There's another benchmark here:

    https://github.com/jcupitt/php-vips-bench

    On that one, php-vips is about 4x faster than imagick and needs 8x less memory.

    Here's the whole thing packaged as a Dockerfile you should be able to run anywhere:

    https://github.com/jcupitt/docker-builds/tree/master/php-vips-ubuntu-16.04