commit 353f528154016c4af9c72c6b4a87906aae7cd3a9 Author: nullprop Date: Sat Nov 5 19:24:52 2022 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..466e248 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +out/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..29b9095 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 nullprop + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fecaa3b --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# ffmpeg-life + +Conway's Game of Life in ffmpeg. + +See it in action [here](https://nullprop.sh/ffmpeg-life/). diff --git a/gosper.png b/gosper.png new file mode 100644 index 0000000..f9ace1c Binary files /dev/null and b/gosper.png differ diff --git a/life.sh b/life.sh new file mode 100755 index 0000000..fcfdcb8 --- /dev/null +++ b/life.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# +# --------------------------------------------------------- +# +# script for Conway's Game of Life using ffmpeg filters +# +# usage: life.sh +# +# example: life.sh gosper.png 200 12 10 +# would produce a 200 frame video of life from gosper.png +# at 12 fps and 10x resolution of the original image. +# +# --------------------------------------------------------- +# +# nullprop - 2022 + + +set -e + +if [ "$#" -ne 4 ]; then + echo "invalid number of parameters" + echo "usage: life.sh " + exit +fi + +INPUT=$1 +FRAMES=$2 +FPS=$3 +SCALE=$4 + +rm -rf ./out +mkdir out +cp $INPUT out/frame-00000.png + +# check if pixel (X, Y) is alive +is_alive () { + echo "\ + eq( r(X,Y), 0)*\ + eq( g(X,Y), 0)*\ + eq( b(X,Y), 0)\ + " +} + +# check if pixel (X, Y) with offset ($1, $2) is alive. +# if position is outside image bounds, it is considered dead. +is_alive_off () { + echo "\ + eq( r(X$1,Y$2), 0)*\ + eq( g(X$1,Y$2), 0)*\ + eq( b(X$1,Y$2), 0)*\ + lt(X$1, W)*\ + gte(X$1, 0)*\ + lt(Y$2, H)*\ + gte(Y$2, 0)\ + " +} + +# check if pixel (X, Y) has $1 neighbours +has_neighbours () { + echo "\ + eq(\ + $1,\ + $(is_alive_off -1 -1) +\ + $(is_alive_off -1 +0) +\ + $(is_alive_off -1 +1) +\ + $(is_alive_off +0 -1) +\ + $(is_alive_off +0 +1) +\ + $(is_alive_off +1 -1) +\ + $(is_alive_off +1 +0) +\ + $(is_alive_off +1 +1)\ + )\ + " +} + +# should the pixel (X, Y) be alive? +should_live () { + echo "\ + $(is_alive)*$(has_neighbours 2) +\ + $(is_alive)*$(has_neighbours 3) +\ + ifnot($(is_alive), $(has_neighbours 3)) + " +} + +# load image from $1, +# step the game forward, +# and save image to $2 +step () { + ffmpeg \ + -i $1 \ + -vf \ + geq="\ + r='if( $(should_live), 0, 255 )':\ + b='if( $(should_live), 0, 255 )':\ + g='if( $(should_live), 0, 255 )':\ + a=255: + interpolation=nearest" \ + $2 +} + +# generate frames +for ((i=0; i