Last active
November 19, 2015 08:34
-
-
Save jussikinnula/508bbd57abbe69d47f8e to your computer and use it in GitHub Desktop.
Equivalent to ImageMagick's "trim" with Perl's Imager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use Imager; | |
use File::Path qw(make_path); | |
use File::Basename; | |
use Inline with => 'Imager'; | |
use Inline C => <<'EOS' => WITH => 'Imager'; | |
void trim(Imager::ImgRaw img, int fuzz, SV* res_top, SV* res_left, SV* res_right, SV* res_bottom) { | |
int top = 0; | |
int left = 0; | |
int right = img->xsize; | |
int bottom = img->ysize; | |
int x, y, ch; | |
i_color first, c; | |
// Get the "matching" color from first pixel | |
i_gpix(img, left, top, &first); | |
// Find top | |
for (y = top; y < img->ysize; ++y) { | |
int match = 0; | |
for (x = left; x < img->xsize; ++x) { | |
i_gpix(img, x, y, &c); | |
for (ch = 0; ch < img->channels; ++ch) { | |
if (c.channel[ch] < (first.channel[ch] - fuzz) || c.channel[ch] > (first.channel[ch] + fuzz)) { | |
match = 1; | |
break; | |
} | |
} | |
} | |
if (match) { | |
top = y; | |
break; | |
} | |
} | |
// Find bottom | |
for (y = bottom; y > top; --y) { | |
int match = 0; | |
for (x = left; x < img->xsize; ++x) { | |
i_gpix(img, x, y-1, &c); | |
for (ch = 0; ch < img->channels; ++ch) { | |
if (c.channel[ch] < (first.channel[ch] - fuzz) || c.channel[ch] > (first.channel[ch] + fuzz)) { | |
match = 1; | |
break; | |
} | |
} | |
} | |
if (match) { | |
bottom = y; | |
break; | |
} | |
} | |
// Find left | |
for (x = left; x < img->xsize; ++x) { | |
int match = 0; | |
for (y = top; y < bottom; ++y) { | |
i_gpix(img, x, y, &c); | |
for (ch = 0; ch < img->channels; ++ch) { | |
if (c.channel[ch] < (first.channel[ch] - fuzz) || c.channel[ch] > (first.channel[ch] + fuzz)) { | |
match = 1; | |
break; | |
} | |
} | |
} | |
if (match) { | |
left = x; | |
break; | |
} | |
} | |
// Find right | |
for (x = right; x > left; --x) { | |
int match = 0; | |
for (y = top; y < bottom; ++y) { | |
i_gpix(img, x-1, y, &c); | |
for (ch = 0; ch < img->channels; ++ch) { | |
if (c.channel[ch] < (first.channel[ch] - fuzz) || c.channel[ch] > (first.channel[ch] + fuzz)) { | |
match = 1; | |
break; | |
} | |
} | |
} | |
if (match) { | |
right = x; | |
break; | |
} | |
} | |
sv_setiv(res_top, top); | |
sv_setiv(res_bottom, bottom); | |
sv_setiv(res_left, left); | |
sv_setiv(res_right, right); | |
} | |
EOS | |
die "Usage: trim.pl [source_image] [source_image] [fuzziness]\n" | |
unless @ARGV and $ARGV[0] and $ARGV[1]; | |
my ($source, $target, $fuzziness) = @ARGV; | |
$fuzziness = $fuzziness || 0; | |
my ($target_filename, $target_path) = fileparse($target); | |
my $target_filetype = (split(/\./, $target_filename))[1] || 'png'; | |
$target_filetype = 'jpeg' if $target_filetype eq 'jpg' or $target_filetype eq 'jpe'; | |
my $imager = Imager->new( file => $source ) | |
or die "Cannot open $source -file: ", Imager->errstr(); | |
# Trim background | |
my ($top, $left, $right, $bottom); | |
trim($imager, $fuzziness, $top, $left, $right, $bottom); | |
$imager = $imager->crop( | |
left => $left, | |
right => $right, | |
top => $top, | |
bottom => $bottom, | |
); | |
# Fit the original image to a square box | |
# First create directory for the file | |
make_path($target_path) if $target_path and $target_path ne './'; | |
# Then store it | |
$imager->write( file => $target, type => $target_filetype ) | |
or die "Cannot write $target -file: ", Imager->errstr(); | |
print "Done.\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment