Search code examples
phpimagick

Speed up PHP Imagick library PDF -> PNG conversion (20seconds !)


I am using Imagick to convert the first page of a PDF to a PNG image. It is working, but it is very slow.

A conversion takes between 8 and 20 seconds for a ~100kb PDF.

Is there a way to speed up the conversion?

My code :

$im = new Imagick($url);
$im->setIteratorIndex(0);
$im->setCompression(Imagick::COMPRESSION_LZW);
$im->setCompressionQuality(90);
$im->setImageFormat("png");
$im->writeImage('C:/Shared/test.png');

Solution

  • In fact , I don't need Imagick library to generate a simple JPG preview of the first page of a PDF, I just need GhostScript.

    Command line conversion with GhostScript is always faster than Imagick (command line or through PHP)

    Example with a 12 pages and 650kb :

    • Command line GhostScript => 0.6 second
    • Command line Imagick => 0.8 second
    • PHP extension Imagick => 2.22 seconds

    With some documents, Imagick takes 20 seconds against 1.5 second with direct GS command line.

    Here is my test script

       <?php
    
        $pathToPdf = realpath("in.pdf");
    
        $pathToJpg = "./out.jpg";
        $pathToPng = "./out.png";
    
        try
            {
    
            $time_start = microtime(true);      
            $gsCall = "\"C:\Program Files (x86)\gs\gs9.06\bin\gswin32.exe\" -q -dBATCH -dMaxBitmap=300000000 -dNOPAUSE -dSAFER -sDEVICE=jpeg -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -dFirstPage=1 -dLastPage=1 -sOutputFile=\"{0}\" \"{1}\" -c quit";
            $gsCall = str_replace(array('{0}', '{1}'), array($pathToJpg, $pathToPdf), $gsCall); // or use sprintf
            $str = exec($gsCall, $output=array(), $returnValue);
            echo $gsCall.'<br><br>';
            $time_end = microtime(true);
            $time = $time_end - $time_start;        
            if($returnValue == 0)              
                print "<br><br>Conversion OK ".$time;
            else 
                print "<br><br>Conversion failed.<br />".var_dump($output);     
    
            $time_start = microtime(true);          
            exec('convert "'.$pathToPdf.'[0]" "'.$pathToPng.'"', $output, $returnValue);                        
            $time_end = microtime(true);
            $time = $time_end - $time_start;
            if($returnValue == 0)              
                print "<br><br>Conversion OK ".$time;
            else 
                print "<br><br>Conversion failed.<br />".var_dump($output);
    
            $time_start = microtime(true);
            $im = new Imagick($pathToPdf);
            $im->setIteratorIndex(0);
            $im->setCompression(Imagick::COMPRESSION_LZW);
            $im->setCompressionQuality(90);
            $im->setImageFormat("png");
            $im->writeImage('\\\\DELL-PC\Shared\test.png');
            //$im->thumbnailImage(200, 0);
            //echo $im;
            $time_end = microtime(true);
            $time = $time_end - $time_start;
            print "<br><br>Conversion OK ".$time;
        }
    catch(Exception $e)
    {
        echo $e->getMessage();
    }
    ?>