diff options
Diffstat (limited to 'apps/plugins/puzzles/icons/square.pl')
-rwxr-xr-x | apps/plugins/puzzles/icons/square.pl | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/apps/plugins/puzzles/icons/square.pl b/apps/plugins/puzzles/icons/square.pl new file mode 100755 index 0000000000..815b94b532 --- /dev/null +++ b/apps/plugins/puzzles/icons/square.pl | |||
@@ -0,0 +1,95 @@ | |||
1 | #!/usr/bin/perl | ||
2 | |||
3 | # Read an input image, crop its border to a standard width, and | ||
4 | # convert it into a square output image. Parameters are: | ||
5 | # | ||
6 | # - the required total image size | ||
7 | # - the output border thickness | ||
8 | # - the input image file name | ||
9 | # - the output image file name. | ||
10 | |||
11 | ($osize, $oborder, $infile, $outfile) = @ARGV; | ||
12 | |||
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"; | ||
16 | ($w, $h) = ($1, $2); | ||
17 | |||
18 | # Read the input image data. | ||
19 | $data = []; | ||
20 | open IDATA, "convert -depth 8 $infile rgb:- |"; | ||
21 | push @$data, $rgb while (read IDATA,$rgb,3,0) == 3; | ||
22 | close IDATA; | ||
23 | # Check we have the right amount of data. | ||
24 | $xl = $w * $h; | ||
25 | $al = scalar @$data; | ||
26 | die "wrong amount of image data ($al, expected $xl) from $infile\n" | ||
27 | unless $al == $xl; | ||
28 | |||
29 | # Find the background colour, by looking around the entire border | ||
30 | # and finding the most popular pixel colour. | ||
31 | for ($i = 0; $i < $w; $i++) { | ||
32 | $pcount{$data->[$i]}++; # top row | ||
33 | $pcount{$data->[($h-1)*$w+$i]}++; # bottom row | ||
34 | } | ||
35 | for ($i = 1; $i < $h-1; $i++) { | ||
36 | $pcount{$data->[$i*$w]}++; # left column | ||
37 | $pcount{$data->[$i*$w+$w-1]}++; # right column | ||
38 | } | ||
39 | @plist = sort { $pcount{$b} <=> $pcount{$a} } keys %pcount; | ||
40 | $back = $plist[0]; | ||
41 | |||
42 | # Crop rows and columns off the image to find the central rectangle | ||
43 | # of non-background stuff. | ||
44 | $ystart = 0; | ||
45 | $ystart++ while $ystart < $h and scalar(grep { $_ ne $back } map { $data->[$ystart*$w+$_] } 0 .. ($w-1)) == 0; | ||
46 | $yend = $h-1; | ||
47 | $yend-- while $yend >= $ystart and scalar(grep { $_ ne $back } map { $data->[$yend*$w+$_] } 0 .. ($w-1)) == 0; | ||
48 | $xstart = 0; | ||
49 | $xstart++ while $xstart < $w and scalar(grep { $_ ne $back } map { $data->[$_*$w+$xstart] } 0 .. ($h-1)) == 0; | ||
50 | $xend = $w-1; | ||
51 | $xend-- while $xend >= $xstart and scalar(grep { $_ ne $back } map { $data->[$_*$w+$xend] } 0 .. ($h-1)) == 0; | ||
52 | |||
53 | # Decide how much border we're going to put back on to make the | ||
54 | # image perfectly square. | ||
55 | $hexpand = ($yend-$ystart) - ($xend-$xstart); | ||
56 | if ($hexpand > 0) { | ||
57 | $left = int($hexpand / 2); | ||
58 | $xstart -= $left; | ||
59 | $xend += $hexpand - $left; | ||
60 | } elsif ($hexpand < 0) { | ||
61 | $vexpand = -$hexpand; | ||
62 | $top = int($vexpand / 2); | ||
63 | $ystart -= $top; | ||
64 | $yend += $vexpand - $top; | ||
65 | } | ||
66 | $ow = $xend - $xstart + 1; | ||
67 | $oh = $yend - $ystart + 1; | ||
68 | die "internal computation problem" if $ow != $oh; # should be square | ||
69 | |||
70 | # And decide how much _more_ border goes on to add the bit around | ||
71 | # the edge. | ||
72 | $realow = int($ow * ($osize / ($osize - 2*$oborder))); | ||
73 | $extra = $realow - $ow; | ||
74 | $left = int($extra / 2); | ||
75 | $xstart -= $left; | ||
76 | $xend += $extra - $left; | ||
77 | $top = int($extra / 2); | ||
78 | $ystart -= $top; | ||
79 | $yend += $extra - $top; | ||
80 | $ow = $xend - $xstart + 1; | ||
81 | $oh = $yend - $ystart + 1; | ||
82 | die "internal computation problem" if $ow != $oh; # should be square | ||
83 | |||
84 | # Now write out the resulting image, and resize it appropriately. | ||
85 | open IDATA, "| convert -size ${ow}x${oh} -depth 8 -resize ${osize}x${osize}! rgb:- $outfile"; | ||
86 | for ($y = $ystart; $y <= $yend; $y++) { | ||
87 | for ($x = $xstart; $x <= $xend; $x++) { | ||
88 | if ($x >= 0 && $x < $w && $y >= 0 && $y < $h) { | ||
89 | print IDATA $data->[$y*$w+$x]; | ||
90 | } else { | ||
91 | print IDATA $back; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | close IDATA; | ||