Skip to content

Instantly share code, notes, and snippets.

@Winterhuman
Last active April 27, 2025 15:48
Show Gist options
  • Save Winterhuman/c03a892f131c17f2ace4a1c42e9de06f to your computer and use it in GitHub Desktop.
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 /bin/sh
# 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=3 ppm2png /tmp ||
pquit "Failed to overmount '/tmp'!\n"
# Write the P3 PPM header
ppm="/tmp/img.ppm"
printf "P3\n%d %d\n255\n" "$width" "$height" >"$ppm"
# Write the RGB IDs
## Many things worth noting here:
##
## 1. "A\0B\0C\n" is faster to write than "A\nB\nC\n" due to line buffering, so
## avoiding them actually improves the speed even with `sed` afterwards.
## 2. `>>file` outside the while-loop is faster since it reuses the file's FD.
## 3. Using a background job for `printf` **drastically** slows things down,
## because `$RANDOM` is evaluated before the background job starts.
count="$groups"
while [ "$count" -gt 0 ]; do
printf "%d\0%d\0%d\n" \
"$(( RANDOM % 6 + 1 ))" \
"$(( RANDOM % 6 + 8 ))" \
"$(( RANDOM % 6 + 15 ))"
count="$(( count - 1 ))"
done >>"$ppm"
sed -i "s/\o0/\n/g" "$ppm" || pquit "Failed to replace null bytes in '$ppm'!\n"
# Write the remaining partial ID groups (1-2 or 1, as opposed to a full 1-2-3)
if [ "$remainofgroups" -eq 2 ]; then
printf "%d\n%d\n" \
"$(( "$RANDOM" % 6 + 1 ))" \
"$(( "$RANDOM" % 6 + 8 ))" \
>>"$ppm"
elif [ "$remainofgroups" -eq 1 ]; then
printf "%d\n" "$(( "$RANDOM" % 6 + 1 ))" >>"$ppm"
fi
# Replace the numeric IDs with the actual RGB colours.
sed -i -e "s/^1$/0 255 170/" \
-e "s/^2$/0 223 148/" \
-e "s/^3$/0 191 127/" \
-e "s/^4$/0 159 106/" \
-e "s/^5$/0 127 85/" \
-e "s/^6$/0 96 64/" \
-e "s/^7$/0 64 42/" \
-e "s/^8$/255 187 0/" \
-e "s/^9$/223 164 0/" \
-e "s/^10$/191 140 0/" \
-e "s/^11$/159 117 0/" \
-e "s/^12$/127 93 0/" \
-e "s/^13$/96 70 0/" \
-e "s/^14$/64 47 0/" \
-e "s/^15$/255 76 136/" \
-e "s/^16$/223 66 119/" \
-e "s/^17$/191 57 102/" \
-e "s/^18$/159 48 85/" \
-e "s/^19$/127 38 68/" \
-e "s/^20$/96 29 51/" \
-e "s/^21$/64 19 34/" \
"$ppm"
# Write the leftover blank lines
printf "%${blank}s" ' ' | sed "s/ /0 0 0\n/g" >>"$ppm"
# Convert PPM 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() {
if [ -f "$1" ]; then
mv "$1" "${1}.old" ||
pquit "Failed to move existing '$1' image!\n"
fi
}
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 --all-oxi true /proc/self/fd/3 "header"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment