From dc0081be69f9a8a451808f908bb2327471b86057 Mon Sep 17 00:00:00 2001 From: rhiannon morris Date: Tue, 21 Nov 2023 23:23:27 +0100 Subject: [PATCH] can try multiple formats per site with a lot of refactoring, because the 'pick best' task needs to wait for the resizing tasks --- bin/make-sizes | 96 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/bin/make-sizes b/bin/make-sizes index f75f23e..0ed4e62 100755 --- a/bin/make-sizes +++ b/bin/make-sizes @@ -1,19 +1,17 @@ #!/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, + #| formats to use for mastodon (png, webp, jpg, default, skip) + :m(:$mastodon) = 'default', + #| formats to use for itaku + :i(:$itaku) = 'default', + #| formats to use for furaffinity/weasyl + :f(:$furaffinity) = 'default', + #| formats to use for gallery.n.w + :g(:$gallery) = 'default', #| webp/jpg quality setting (default 98) Int :Q(:$quality) = 98, #| only run conversions explicitly mentioned @@ -37,14 +35,25 @@ sub verbose(*@args) { say "> @args[]" if $verbose } # fixup args -die "furaffinity/weasyl don't know what webp are" if $furaffinity == webp; +enum Format ; -$mastodon ||= $only ?? skip !! webp; -$itaku ||= $only ?? skip !! webp; -$furaffinity ||= $only ?? skip !! png; -$gallery ||= $only ?? skip !! webp; +sub to-formats($_, *@default) { + when 'skip' { Empty } + when 'default' { $only ?? Empty !! @default } + when Format { $_ } + .lc.split(',').map: { Format::{$_} // die qq/unrecognised format "$_"/ } +} -(@files .= map: *.IO) ||= $*CWD.dir: test => /:i \.[jpe?g|png]$/; +die "furaffinity/weasyl don't know what webp are" if $furaffinity ~~ /:i webp/; + +my @mastodon = to-formats $mastodon, webp; +my @itaku = to-formats $itaku, webp; +my @furaffinity = to-formats $furaffinity, png, jpg; +my @gallery = to-formats $gallery, webp; + +unless @files.=map(*.IO) { + @files = $*CWD.dir: test => /:i \.[jpe?g|png]$/ && *.IO.f; +} for @files { die "$_ is not a regular file" unless .f; } @@ -57,34 +66,57 @@ sub convert($in, $name, $size, $format) { cmd , $out.dirname; cmd , $in, '-resize', $size, '-quality', $quality, $out; cmd , $out if $format == png; + $out } constant $SIZE = 2800; constant $SQUARE = "{$SIZE}x{$SIZE}>"; -constant $MASTO-SIZE = "{1280**2}@"; +constant $MASTO-SIZE = "{1280²}@"; 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; + {:name, :formats(@mastodon), :size($MASTO-SIZE)}, + {:name, :formats(@itaku), :size($SQUARE)}, + {:name, :formats(@furaffinity), :size($SQUARE)}, + {:name, :formats(@gallery), :size($GALLERY-SQUARE)}, +]; # 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 @tasks; + +sub task-serial(&body, :$if = True) { body if $if; } + +sub task-parallel(&body, :$if = True) { + state $sem = Semaphore.new: $jobs; + return unless $if; + my $task = start { $sem.acquire; my $res = body; $sem.release; $res } + @tasks.push: $task; + $task } +constant &task = $dry-run ?? &task-serial !! &task-parallel; -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; -}; +my @todo = (@files X @sites).map: -> ($file, %rest) { hash :$file, %rest }; +my $len = @todo.map(*.).sum; +my $index; + +for @todo -> (:$file, :$name, :@formats, :$size) { + my @outputs = @formats.map: -> $format { + my $i = ++$index; my $base = $file.basename; + task { + say "[$i/$len] $name $base ($format)"; + convert $file, $name, $size, $format; + } + } + + task if => !$dry-run && @outputs > 1, { + my $keep = @outputs».=result.map({$_ => .s}).min(*.value).key; + verbose "# keeping $keep"; + for @outputs { next when $keep; cmd "rm", $_ } + } +} + +@tasks».result;