I need to split a large (up to 16384x16384px) image into smaller chunks, usually 512x512. For doing this, I'm using the simple perl script below:
#!/usr/bin/perl
use warnings;
use strict;
my $size = '512x512';
unless ($ARGV[0]) { die "Missing filename as arg" }
unless (-e $ARGV[0]) { die "$ARGV[0] not found.\n" }
my ($newfile, undef) = split(/\./,$ARGV[0]);
system("convert $ARGV[0] -crop $size $newfile" . "_%03d.png");
Now, the thing is, I need to build an index of the smaller pieces which includes the position offset in the original image, for example in the case of a 1024x1024 source image:
image_000.png 0,0
image_001.png 512,0
image_002.png 0,512
image_003.png 512,512
...or something similar. Basically, just to keep track of the position each particular chunk had in the original image.
Since the convert
command passed to system()
I was thinking of just doing a glob of the files and sorting them, as some quick experimentation shows that the smaller chunks are numbered in the order left to right, top to bottom (intuitively) and build the index based on that, but I'm thinking there must be something simpler involving perls own interface to ImageMagick
So my questions then are:
1. What is the Image::Magick
equivalent of convert $ARGV[0] -crop $size $newfile" . "_%03d.png
?
2. Is it possible to build the index based on data from the $image object once I have managed to avoid a system() call?
PS:
$size
... in fact, I don't know why i chose to have that variable at all. identify
command can be taken into account somehow?I solved it the only way i know how: Screw perlmagic, and do it via command line instead. The below script works on both rectangular and square images. Index is printed to the screen.
use warnings;
use strict;
my $size = '512x512';
my $offset = 512;
unless ($ARGV[0]) { die "Missing filename as arg" }
unless (-e $ARGV[0]) { die "$ARGV[0] not found.\n" }
my ($newfile, undef) = split(/\./,$ARGV[0]);
system("convert $ARGV[0] -crop $size $newfile" . "_%03d.png");
my @files = glob($newfile . "_*");
@files = sort(@files);
my (undef, undef, $origsize) = split(/\s+/,`identify $ARGV[0]`);
my ($maxX, $maxY) = split(/x/,$origsize);
$maxX /= $offset;
$maxY /= $offset;
my $x = 0;
my $y = 0;
foreach my $file (@files)
{
print "$file\t" . $x * $offset . "\t" . $y * $offset . "\n";
$x++;
if ($x >= $maxX)
{
$x = 0;
$y++;
}
}
__END__