misc/bin/make-sizes

86 lines
2.6 KiB
Raku
Executable file

#!/usr/bin/env raku
enum Format <DEFAULT skip png webp jpg>;
#| resize images for uploading to gallery sites
unit sub MAIN(
#| number of concurrent jobs (default min{10, # cores})
Int :j(:$jobs) = min(10, $*KERNEL.cpu-cores),
#| format to use for mastodon (png, webp, jpg, skip)
Format :m(:$mastodon) is copy = DEFAULT,
#| format to use for itaku
Format :i(:$itaku) is copy = DEFAULT,
#| format to use for furaffinity/weasyl
Format :f(:$furaffinity) is copy = DEFAULT,
#| format to use for gallery.n.w
Format :g(:$gallery) is copy = DEFAULT,
#| webp/jpg quality setting (default 98)
Int :Q(:$quality) = 98,
#| only run conversions explicitly mentioned
Bool :O(:$only) = False,
Bool :n(:$dry-run) = False,
Bool :v(:$verbose) = False,
#| out dir, default ./out
IO :o(:$outdir) = 'out'.IO,
#| defaults to all *.png & *.jpg files in the current dir
*@files,
);
sub cmd(*@args) {
say "> @args[]" if $dry-run || $verbose;
run @args unless $dry-run;
}
sub verbose(*@args) { say "> @args[]" if $verbose }
# fixup args
die "furaffinity/weasyl don't know what webp are" if $furaffinity == webp;
$mastodon ||= $only ?? skip !! webp;
$itaku ||= $only ?? skip !! webp;
$furaffinity ||= $only ?? skip !! png;
$gallery ||= $only ?? skip !! webp;
(@files .= map: *.IO) ||= $*CWD.dir: test => /:i \.[jpe?g|png]$/;
for @files { die "$_ is not a regular file" unless .f; }
# running imagemagick (and oxipng sometimes) 🪄
sub convert($in, $name, $size, $format) {
my $out = $outdir.child($in.basename).extension("$name.$format");
cmd <convert>, $in, '-resize', $size, '-quality', $quality, $out;
cmd <oxipng -q>, $out if $format == png;
}
constant $SIZE = 2800;
constant $SQUARE = "{$SIZE}x{$SIZE}>";
constant $MASTO-SIZE = "{1280**2}@";
constant $GALLERY-SIZE = 3000;
constant $GALLERY-SQUARE = "{$GALLERY-SIZE}x{$GALLERY-SIZE}>";
my @sites = [
{:name<mastodon>, :format($mastodon), :size($MASTO-SIZE)},
{:name<itaku>, :format($itaku), :size($SQUARE)},
{:name<furaffinity>, :format($furaffinity), :size($SQUARE)},
{:name<gallery>, :format($gallery), :size($GALLERY-SQUARE)},
].grep: *<format> != skip;
# go go go
sub parallel(@vals, &f) {
my $sem = Semaphore.new: $jobs;
my @tasks = @vals.map: { start { $sem.acquire; f $_; $sem.release } };
@tasks».result;
}
cmd <mkdir -p>, $outdir;
my @todo = @files X @sites;
parallel @todo, -> ($file, % (:$name, :$format, :$size)) {
state $i++;
say "[$i/@todo.elems()] $name $file.basename()";
convert $file, $name, $size, $format;
};