From eb96ab962545cf9b403f18422f1de698d9619499 Mon Sep 17 00:00:00 2001 From: Andinus Date: Thu, 18 Nov 2021 16:56:58 +0530 Subject: Move frame generation to a module, update progress reporting --- lib/Fornax/CLI.rakumod | 123 +++++++++---------------------------------------- 1 file changed, 23 insertions(+), 100 deletions(-) (limited to 'lib/Fornax/CLI.rakumod') diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod index 8b18215..d066ebf 100644 --- a/lib/Fornax/CLI.rakumod +++ b/lib/Fornax/CLI.rakumod @@ -1,5 +1,4 @@ -use Cairo; -use Fornax::Hex2RGB; +use Fornax::GenerateFrame; subset File of Str where *.IO.f; @@ -19,7 +18,7 @@ multi sub MAIN( Int() :$batch = 4, #= number of iterations to process at once (default: 4) Int() :fps($frame-rate) = 1, #= frame rate for video solution (default: 1) Bool :$skip-video, #= skip video solution - Bool :$verbose = True, #= verbosity (default: True) + Bool :$debug, #= debug logs ) is export { my IO() $output = "%s/fornax-%s".sprintf( '/tmp', ('a'...'z', 'A'...'Z', 0...9).roll(8).join @@ -27,40 +26,14 @@ multi sub MAIN( mkdir $output; die "Output directory doesn't exist" unless $output.d; - put "[fornax] Output: '$output'" if $verbose; + put "[fornax] Output: '$output'"; my Str @lines = $input.IO.lines; my Int() %meta{Str} = Metadata.parse(@lines.first).Hash - or die "Cannot parse metadata"; - - # Cells as defined by fornax format. - constant $PATH = '.'; - constant $BLOK = '#'; - constant $DEST = '$'; - constant $STRT = '^'; - constant $VIS = '-'; - constant $CUR = '@'; - constant $CURPATH = '~'; + or die "Cannot parse metadata"; constant %CANVAS = :1920width, :1080height; - # Colors. - constant %C = ( - bg-main => "#ffffff", - - red-subtle-bg => "#f2b0a2", - blue-subtle-bg => "#b5d0ff", - cyan-subtle-bg => "#c0efff", - green-subtle-bg => "#aecf90", - - fg-main => "#000000", - - fg-special-cold => "#093060", - fg-special-warm => "#5d3026", - fg-special-mild => "#184034", - fg-special-calm => "#61284f", - ).map: {.key => hex2rgb(.value)}; - # Every cell must be square. Get the maximum width, height and use # that to decide which is to be used. my Int %cell = width => %CANVAS div %meta, @@ -79,7 +52,8 @@ multi sub MAIN( $side = %cell; } - enum IterStatus ; + my $render-start = now; + my Int $total-frames = @lines.elems - 1; my Promise @p; for @lines.skip.kv -> $idx, $iter is rw { @@ -88,89 +62,38 @@ multi sub MAIN( if @p.elems == $batch { await @p; @p = []; + + print "\r"; + print "%s Remaining: %.2fs Elapsed: %.2fs %s".sprintf( + "[fornax $idx/$total-frames]", + ((now - $render-start) / $idx) * ($total-frames - $idx), + now - $render-start, " ", + ); } push @p, start { - my IterStatus $status; - given $iter.substr(0, 1) { - when '|' { $status = Completed } - when '!' { $status = Blocked } - default { $status = Walking } - }; - - # Remove marker. - $iter .= substr(1) if $status == Completed|Blocked; - - put "[fornax] $idx $iter $status" if $verbose; - - my @grid = $iter.comb.rotor: %meta; - warn "Invalid grid: $idx $iter $status" unless @grid.elems == %meta; - - given Cairo::Image.create( - Cairo::FORMAT_ARGB32, %CANVAS, %CANVAS - ) { - given Cairo::Context.new($_) { - # Paint the entire canvas white. - .rgb: |%C; - .rectangle(0, 0, %CANVAS, %CANVAS); - .fill; - - for ^%meta -> $r { - for ^%meta -> $c { - my Int @target = %excess div 2 + $c * $side, - %excess div 2 + $r * $side, - $side, $side; - - .rectangle: |@target; - - given @grid[$r][$c] -> $cell { - # According to the format, current - # position may be prioritized over - # Destination symbol so we colorize it - # according to $status. - when $cell eq $CUR { - .rgba: |%C, 0.56; - .rgba: |%C, 0.72 if $status == Completed; - .rgba: |%C, 0.72 if $status == Blocked; - } - when $cell eq $CURPATH { - .rgba: |%C, 0.84; - .rgba: |%C, 0.96 if $status == Completed; - .rgba: |%C, 0.96 if $status == Blocked; - } - when $cell eq $VIS { - .rgba: |%C, 0.72; - } - when $cell eq $BLOK { .rgba: |%C, 0.56 } - when $cell eq $STRT|$DEST { .rgba: |%C, 0.72 } - default { .rgba: |%C, 0.08 } - } - .fill :preserve; - - .rgb: |%C; - .stroke; - } - } - } - .write_png("%s/%08d.png".sprintf: $output, $idx); - .finish; - } + generate-frame( + :%CANVAS, :%excess, :$side, :%meta, :$iter, :$idx, :$debug, + :out("%s/%08d.png".sprintf: $output, $idx), + ); } } # Wait for remaining jobs to finish. await @p; - put "[fornax] Generated images." if $verbose; + print "\r"; + put "[fornax] Generated $total-frames frames in %.2fs. %s".sprintf( + now - $render-start, " " x 16, + ); unless $skip-video { - put "[fornax] Creating a slideshow." if $verbose; + put "[fornax] Creating a slideshow."; - my Str $log-level = $verbose ?? "info" !! "error"; + my Str $log-level = $debug ?? "info" !! "error"; run «ffmpeg -loglevel "$log-level" -r "$frame-rate" -i "$output/\%08d.png" -vf 'tpad=stop_mode=clone:stop_duration=4' -vcodec libx264 -crf 28 -pix_fmt yuv420p "$output/solution.mp4"»; } - put "[fornax] Output: '$output'"; } multi sub MAIN( -- cgit 1.4.1-2-gfad0