Search code examples
phpperlimagemagickimagemagick-convert

PHP ImageMagick split large image to tiles


I am trying to split a large image to smaller tiles. I tried it using PHP ImageMagick cropImage() and I could do it successfully with the following code.

for($w = 0; $w < ($large_image_width/$tile_width); $w++){
    for($h = 0; $h < ($large_image_height/$tile_height); $h++){
        $X = $w*$tile_width;
        $Y = $h*$tile_height;

        $image = new Imagick($input_file);
        $image->cropImage($tile_width,$tile_height, $X,$Y);
        $image->writeImage("X" . ($w+1) . "Y" . ($h+1) . ".jpg");
    }
}

But it loops through each tile size and load the image again and again.

When I did more research, I found this link, which is a one liner using the command line.

convert -crop $WIDTHx$HEIGHT@ huge_file.png  tile_%d.png

I am wondering if the PHP ImageMagick extension got any function to do the same. Also I am comfortable to switch to Perl or someother library like GD.


Solution

  • You can reduce the $input_file I/O by loading the image once, then cloning the object.

    $source_image = new Imagick($input_file);
    for($w = 0; $w < ($large_image_width/$tile_width); $w++){
        for($h = 0; $h < ($large_image_height/$tile_height); $h++){
            $X = $w*$tile_width;
            $Y = $h*$tile_height;
    
            $image = clone $source_image;
            $image->cropImage($tile_width,$tile_height, $X,$Y);
            $image->writeImage("X" . ($w+1) . "Y" . ($h+1) . ".jpg");
        }
    }
    

    You can also optimize & reduce the for loop, or just call the one liner directly.

    system("convert -crop $WIDTHx$HEIGHT@ $input_file  tile_%d.png");