#!/usr/bin/env raku enum Format ; #| 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 , $in, '-resize', $size, '-quality', $quality, $out; cmd , $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, :format($mastodon), :size($MASTO-SIZE)}, {:name, :format($itaku), :size($SQUARE)}, {:name, :format($furaffinity), :size($SQUARE)}, {:name, :format($gallery), :size($GALLERY-SQUARE)}, ].grep: * != 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 , $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; };