90 lines
2.7 KiB
Raku
Executable file
90 lines
2.7 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(Str) :o(:$outdir) = 'out'.IO,
|
|
#| use a subdirectory for each site
|
|
Bool :d(:$subdirs) = False,
|
|
#| 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 = $subdirs
|
|
?? $outdir.child($name).child($in.basename).extension("$format")
|
|
!! $outdir.child($in.basename).extension("$name.$format");
|
|
cmd <mkdir -p>, $out.dirname;
|
|
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;
|
|
}
|
|
|
|
|
|
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;
|
|
};
|