can try multiple formats per site
with a lot of refactoring, because the 'pick best' task needs to wait for the resizing tasks
This commit is contained in:
parent
36a3338ff2
commit
dc0081be69
1 changed files with 64 additions and 32 deletions
|
@ -1,19 +1,17 @@
|
|||
#!/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,
|
||||
#| 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 <png webp jpg>;
|
||||
|
||||
$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 <mkdir -p>, $out.dirname;
|
||||
cmd <convert>, $in, '-resize', $size, '-quality', $quality, $out;
|
||||
cmd <oxipng -q>, $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<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;
|
||||
{:name<mastodon>, :formats(@mastodon), :size($MASTO-SIZE)},
|
||||
{:name<itaku>, :formats(@itaku), :size($SQUARE)},
|
||||
{:name<furaffinity>, :formats(@furaffinity), :size($SQUARE)},
|
||||
{:name<gallery>, :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(*.<formats>).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;
|
||||
|
|
Loading…
Reference in a new issue