Skip to content

Instantly share code, notes, and snippets.

@Winterhuman
Last active December 12, 2025 19:00
Show Gist options
  • Select an option

  • Save Winterhuman/c03a892f131c17f2ace4a1c42e9de06f to your computer and use it in GitHub Desktop.

Select an option

Save Winterhuman/c03a892f131c17f2ace4a1c42e9de06f to your computer and use it in GitHub Desktop.
A script which finds the minimum PNG dimensions for a given aspect ratio and pixel count, creates a colour-cycling PPM file, and then converts it to PNG.
#!/usr/bin/env -S unshare --mount --map-root-user /usr/bin/bash
# Licensed under the Zero-Clause BSD terms: https://opensource.org/license/0bsd
# Requires: imagemagick & [sisyphus](https://gist.github.com/Winterhuman/21d7b148db40ff041f397b07a7aafb83)
#
# Argument 1: Number of pixels to fill, required
# Argument 2: Height ratio, default 23
# Argument 3: Width ratio, default 5
set -Ceuf
pstat() {
printf "%b\033[1m%b\033[0;39m" "${2:-\033[1m\033[34m::\033[0;39m }" "$1"
}
pquit() {
pstat "$1" "\033[1m\033[31m!!\033[0;39m "
exit 1
}
# Using '$RANDOM' is the only non-POSIX part of this script
_="${RANDOM:?"$(pquit "The 'RANDOM' environment variable is not available!\n")"}"
# Check if all arguments are valid
fill="${1:?"$(pquit "No arguments given!\n")"}"
if ! printf "%d" "$fill" >/dev/null 2>&1 || [ "$fill" -le 0 ]; then
pquit "'$fill' is not a positive integer!\n"; fi
pstat "Fill: $fill\n"
hratio="${2:-"23"}"
wratio="${3:-"5"}"
if ! printf "%d" "$hratio" "$wratio" >/dev/null 2>&1 ||
[ "$hratio" -le 0 ] || [ "$wratio" -le 0 ]; then
pquit "Aspect ratio values must be positive integers!\n"; fi
# Calculate the optimal/minimal image dimensions for the given fill value
calc_w() {
## '+ wratio - 1' yields a rounded up answer, instead of rounded down
printf "%d\n" "$(( (("$1" * hratio) + wratio - 1 ) / wratio ))"
}
calc_h() {
printf "%d\n" "$(( ( ("$1" * wratio) + hratio - 1 ) / hratio ))"
}
height="1"
width="$(calc_w "$height")"
bad="0"
## 'input + 1' is required to make this round up, since '$wratio' is in
## both the numerator and denominator (manual calculations verify this).
### '-1' is omitted from 'hratio + wratio' to handle '2:1' ratios.
good="$((
( (fill + 1) * wratio + hratio + wratio ) /
(hratio + wratio)
))"
good="$(( "$(calc_h "$good")" + 2 ))"
if [ "$good" -gt 1 ]; then
while [ "$bad" -le "$(( good - 1 ))" ]; do
if [ "$(( width * height ))" -le "$fill" ]; then
bad="$(( height + 1 ))"
else
good="$height"
fi
height="$(( (bad + good) / 2 ))"
width="$(calc_w "$height")"
done
fi
height="$good"
width="$(calc_w "$height")"
blank="$(( (height * width) - fill ))"
groups="$(( fill / 3 ))"
remainofgroups="$(( fill % 3 ))"
pstat "Image dimensions: $width x $height\n"
pstat "Pixel fill: ${fill}px (${blank}px left)\n"
# Setup a private tmpfs for this script to use, which is what 'unshare' is for.
## 'nr_inodes' must be >= to 'max number of files + 1'
mount -t tmpfs -o nosuid,nodev,noexec,size=256M,nr_inodes=7 ppm2png /tmp/ ||
pquit "Failed to overmount '/tmp/'!\n"
# Create the PPM file.
## Create the P3 PPM header
cat <<-PPM >/tmp/header &
P3
$width $height
255
PPM
## Create the blank lines.
### This method is faster than: `printf "%*s" "$blank" | sed "s/ /0 0 0\n/g"`
yes "0 0 0" | head --lines="$blank" >>/tmp/blank &
## Create the filled-in lines.
### This method is faster than the usual `[ "$count" -gt 0 ]` method. The `yes`
### method shown above is faster, but it would repeat the same "random" value
rand_fill() {
while :; do
printf "%d\n" "$(( RANDOM % 6 + 1 ))"
done | head --lines="$groups"
}
### Replace the colour indexes with their hex values
#### `[] ||` corrects for unclean divisions (e.g. 5 fill = 1 group + 2 remainder)
{
rand_fill
[ "$remainofgroups" -lt 1 ] || printf "%d\n" "$(( RANDOM % 6 + 1 ))"
} | sed -e "s/^1$/0 255 179/" \
-e "s/^2$/33 219 155/" \
-e "s/^3$/43 185 132/" \
-e "s/^4$/46 151 110/" \
-e "s/^5$/45 119 88/" \
-e "s/^6$/41 89 67/" \
-e "s/^7$/34 60 48/" >>/tmp/1 &
{
rand_fill
[ "$remainofgroups" -ne 2 ] || printf "%d\n" "$(( RANDOM % 6 + 1 ))"
} | sed -e "s/^1$/255 185 0/" \
-e "s/^2$/219 160 26/" \
-e "s/^3$/185 137 34/" \
-e "s/^4$/151 113 37/" \
-e "s/^5$/119 91 37/" \
-e "s/^6$/89 69 35/" \
-e "s/^7$/60 49 30/" >>/tmp/2 &
rand_fill | sed \
-e "s/^1$/255 47 120/" \
-e "s/^2$/220 48 105/" \
-e "s/^3$/186 48 91/" \
-e "s/^4$/153 46 77/" \
-e "s/^5$/122 42 64/" \
-e "s/^6$/91 37 50/" \
-e "s/^7$/62 31 38/" >>/tmp/3 &
wait
## Combine the PPM file parts
ppm="/tmp/img.ppm"
{
cat /tmp/header
## `head` removes the final empty line when '$fill' isn't cleanly
## divisible by 3
paste --delimiters="\n" /tmp/1 /tmp/2 /tmp/3 | head --lines="$fill"
cat /tmp/blank
} >"$ppm"
## Save some space, just in case '$tmp_img' would bring it over the size limit
rm /tmp/header /tmp/1 /tmp/2 /tmp/3 /tmp/blank >/dev/null 2>&1 ||:
# Convert the PPM file to PNG
tmp_img="/tmp/tmp.png"
magick "$ppm" -transparent "#000" "$tmp_img" ||
pquit "Failed to create '$tmp_img'!\n"
# Move any existing output to a new '.old' path
mv_exist() {
[ -f "$1" ] || return 0
mv "$1" "$1.old"
}
mv_exist "header.png"
mv_exist "header.webp"
## Optimise PNG with 'sisyphus'
pstat "Optimising with Sisyphus...\n"
## '$tmp_img' exists outside Sisyphus's private tmpfs, meaning it can't see it.
## So, instead of copying '$tmp_img' somewhere, just give it a file descriptor
exec 3<"$tmp_img"
sisyphus --max-procs 24 --all-oxi true --results 16 /proc/self/fd/3 "header"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment