Reputation: 2604
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.
Upvotes: 0
Views: 3096
Reputation: 11220
libvips has a php binding now and it can do this task very quickly using only a little memory.
For example:
#!/usr/bin/env php
<?php
require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;
$im = Vips\Image::newFromFile($argv[1]);
$im->dzsave($argv[2], ["overlap" => 0, "tile-size" => 256, "depth" => "one"]);
On this laptop with a 10k x 10k jpeg image, I see:
$ time ./try260.php ~/pics/wtc.jpg x
real 0m2.262s
user 0m3.596s
sys 0m1.256s
And it's created 1369 jpeg files in x_files
:
$ ls x_files/0/ | wc
1369 1369 14319
There's a blogpost here about the dzsave
operator (the libvips thing that's being used here):
http://libvips.blogspot.co.uk/2013/03/making-deepzoom-zoomify-and-google-maps.html
Upvotes: 0
Reputation: 24439
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");
Upvotes: 4