App-ImageMagickUtils
view release on metacpan or search on metacpan
lib/App/ImageMagickUtils.pm view on Meta::CPAN
],
};
sub downsize_image {
require File::Which;
require Image::Size;
require IPC::System::Options;
#require Filename::Type::Image;
my %args = @_;
my $convert_path = File::Which::which("convert");
my $downsize_to = $args{downsize_to};
my $skip_whatsapp = $args{skip_whatsapp} // 1;
my $skip_downsized = $args{skip_downsized} // 1;
unless ($args{-dry_run}) {
return [400, "Cannot find convert in path"] unless defined $convert_path;
return [400, "convert path $convert_path is not executable"] unless -x $convert_path;
}
my ($num_files, $num_success) = (0, 0);
my $trash;
FILE:
for my $file (@{$args{files}}) {
log_info "Processing file %s ...", $file;
$num_files++;
unless (-f $file) {
log_error "No such file %s, skipped", $file;
next FILE;
}
#my $res = Filename::Type::Image::check_image_filename(filename => $file);
my ($width, $height, $fmt) = Image::Size::imgsize($file);
unless ($width) {
log_error "Filename '%s' is not image (%s), skipped", $file, $fmt;
next FILE;
}
if ($skip_whatsapp) {
require Regexp::Pattern::Filename::Type::Image::WhatsApp;
if ($file =~ $Regexp::Pattern::Filename::Type::Image::WhatsApp::RE{filename_type_image_whatsapp}{pat}) {
log_info "Filename '%s' looks like a WhatsApp image, skip downsizing due to --skip-whatsapp option is in effect", $file;
next FILE;
}
}
if ($skip_downsized) {
if ($file =~ /\.(?:\d+p?-)?q(?:\d{1,3})\.\w+\z/) {
log_info "Filename '%s' looks like it's already downsized, skip downsizing due to --skip-downsized option is in effect", $file;
next FILE;
}
}
my $q = $args{quality} // 40;
my @convert_args = (
$file,
);
my $downsized;
#say "D:downsize_to=<$downsize_to>, width=<$width>, height=<$height>, q=<$q>";
DOWNSIZE: {
last unless $downsize_to;
my $ratio;
my $shortest_side = $width > $height ? $height : $width;
last unless $shortest_side > $downsize_to;
$downsized++;
push @convert_args, "-resize", "$downsize_to^>";
} # DOWNSIZE
push @convert_args, "-quality", $q;
my $output_file = $file;
my $ext = $downsized ? ".$downsize_to-q$q.jpg" : ".q$q.jpg";
$output_file =~ s/(\.\w{3,4})?\z/($1 eq ".jpg" ? "" : $1) . $ext/e;
push @convert_args, (
$output_file,
);
if ($args{-dry_run}) {
log_info "[DRY-RUN] Running $convert_path with args %s ...", \@convert_args;
$num_success++;
next FILE;
}
log_info "Running $convert_path with args %s ...", \@convert_args;
IPC::System::Options::system(
$convert_path, @convert_args,
);
if ($?) {
my ($exit_code, $signal, $core_dump) = ($? < 0 ? $? : $? >> 8, $? & 127, $? & 128);
log_error "convert for $file failed: exit_code=$exit_code, signal=$signal, core_dump=$core_dump";
} else {
if ($args{trash_original}) {
require File::Trash::FreeDesktop;
$trash //= File::Trash::FreeDesktop->new;
log_info "Trashing original file %s ...", $file;
# will die upon failure, currently we don't trap
$trash->trash($file);
} elsif ($args{delete_original}) {
# currently we ignore the results
log_info "Deleting original file %s ...", $file;
unlink $file;
}
$num_success++;
}
}
$num_success == 0 ? [500, "All files failed"] : [200];
}
$SPEC{convert_image_to} = {
v => 1.1,
summary => 'Convert images using ImageMagick\'s \'convert\' utility, with multiple file support and automatic output naming',
description => <<'MARKDOWN',
This is a simple wrapper to ImageMagick's `convert` utility to let you process
multiple files using a single command:
% convert-image-to --to pdf *.jpg
( run in 1.530 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )