81be9d710c5e51a45b5a8ef5b3067ef597e21314
3 # Read an input image, crop its border to a standard width, and
4 # convert it into a square output image. Parameters are:
6 # - the required total image size
7 # - the output border thickness
8 # - the input image file name
9 # - the output image file name.
11 ($osize, $oborder, $infile, $outfile) = @ARGV;
13 # Determine the input image's size.
14 $ident = `identify -format "%w %h" $infile`;
15 $ident =~ /(\d+) (\d+)/ or die "unable to get size for $infile\n";
18 # Read the input image data.
20 open IDATA
, "convert -depth 8 $infile rgb:- |";
21 push @
$data, $rgb while (read IDATA
,$rgb,3,0) == 3;
23 # Check we have the right amount of data.
26 die "wrong amount of image data ($al, expected $xl) from $infile\n"
29 # Find the background colour. We assume the image already has a
30 # border, so this is just the pixel colour of the top left corner.
33 # Crop rows and columns off the image to find the central rectangle
34 # of non-background stuff.
36 $ystart++ while $ystart < $h and scalar(grep { $_ ne $back } map { $data->[$ystart*$w+$_] } 0 .. ($w-1)) == 0;
38 $yend-- while $yend >= $ystart and scalar(grep { $_ ne $back } map { $data->[$yend*$w+$_] } 0 .. ($w-1)) == 0;
40 $xstart++ while $xstart < $w and scalar(grep { $_ ne $back } map { $data->[$_*$w+$xstart] } 0 .. ($h-1)) == 0;
42 $xend-- while $xend >= $xstart and scalar(grep { $_ ne $back } map { $data->[$_*$w+$xend] } 0 .. ($h-1)) == 0;
44 # Decide how much border we're going to put back on to make the
45 # image perfectly square.
46 $hexpand = ($yend-$ystart) - ($xend-$xstart);
48 $left = int($hexpand / 2);
50 $xend += $hexpand - $left;
51 } elsif ($hexpand < 0) {
53 $top = int($vexpand / 2);
55 $yend += $vexpand - $top;
57 $ow = $xend - $xstart + 1;
58 $oh = $yend - $ystart + 1;
59 die "internal computation problem" if $ow != $oh; # should be square
61 # And decide how much _more_ border goes on to add the bit around
63 $realow = int($ow * ($osize / ($osize - 2*$oborder)));
64 $extra = $realow - $ow;
65 $left = int($extra / 2);
67 $xend += $extra - $left;
68 $top = int($extra / 2);
70 $yend += $extra - $top;
71 $ow = $xend - $xstart + 1;
72 $oh = $yend - $ystart + 1;
73 die "internal computation problem" if $ow != $oh; # should be square
75 # Now write out the resulting image, and resize it appropriately.
76 open IDATA
, "| convert -size ${ow}x${oh} -depth 8 -resize ${osize}x${osize}! rgb:- $outfile";
77 for ($y = $ystart; $y <= $yend; $y++) {
78 for ($x = $xstart; $x <= $xend; $x++) {
79 if ($x >= 0 && $x < $w && $y >= 0 && $y < $h) {
80 print IDATA
$data->[$y*$w+$x];