Skip to content

Instantly share code, notes, and snippets.

@JohnMertz
Created January 20, 2021 18:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohnMertz/e9e4bcc521c55635b620092826c07e08 to your computer and use it in GitHub Desktop.
Save JohnMertz/e9e4bcc521c55635b620092826c07e08 to your computer and use it in GitHub Desktop.
Scan and automatically crop many images with SANE and ImageMagick
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
STDOUT->flush();
use File::Which qw( which );
foreach ( qw| convert scanimage | ) {
unless (which("$_")) {
die "Missing dependency: $_\n";
}
}
unless (scalar @ARGV) {
die "Requires project name as argumunt\n";
}
my $base;
my $resume = 0;
foreach (@ARGV) {
if ( $_ eq '-R' && !$resume ) {
$resume = 1;
} elsif (!defined($base)) {
$base = $_;
} else {
die "Invalid or extraneous argument $_\n";
}
}
if ( -d $base && !$resume ) {
die "Directory $base already exists. Use -R to resume an existing project.\n";
} else {
mkdir $base;
}
my @crops;
my $pid = 0;
my $ctr = 0;
if ($resume) {
while (-e sprintf("$base/$base-%03d.jpeg",$ctr)) {
$ctr++;
}
print "Resuming at $ctr\n.";
}
while ($ctr < 1000) {
my $file = sprintf("$base-%03d.jpeg",$ctr);
# Short delay just so that replace instruction follows after fork output
sleep 1;
print "Replace image then press Enter ('q' to finish) ";
my $c = getc;
if ($c eq 'q') {
last;
}
print "\rScanning to $base/$file\n";
#`cp carole-000.jpeg $file`;
`scanimage --format jpeg --output $base/$file --progress --mode Color --resolution 600`;
pipe(FROM_CHILD, TO_PARENT);
my $newpid = fork;
# Store all conversion pids
if ($newpid) {
close(TO_PARENT);
push @crops, $newpid;
$pid = $newpid;
# Convert image on another thread while scanning next image
} else {
close(FROM_CHILD);
# FAIL: cannot wait on sibling process, only child
# If there's already a conversion thread going wait for it to finish.
#if (scalar(@crops)) {
#my $wait = pop @crops;
#print "$$ waiting on $wait\n";
#waitpid($wait, 0);
#}
my ($wh, $t) = split(' ',`convert $base/$file -blur 0x30 -fuzz 5% -trim info: | cut -d ' ' -f 3-4`);
chomp $t;
my ($w, $h) = split('x',$wh);
my ($null, $x, $y) = split('\+',$t);
$| = 1;
print TO_PARENT "Cropping $base/$file in background width=$w height=$h x=$x y=$y \n";
$w -= 48;
$h -= 48;
`convert $base/$file -crop ${w}x${h}+${x}+${y} +repage $base/cropped-$file`;
exit;
}
$ctr++;
}
print "Finishing auto-cropping...\n";
for (my $i = 0; $i < scalar(@crops); $i++) {
waitpid($crops[$i], 0);
print "Finished " . ($i+1) . " of " . scalar(@crops) . " (${crops[$i]})\n";
}
print "Done\n";
exit(0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment