Files
tyler 4da9a48d7c webpdec.h: single-file WebP decoder
libwebp 1.6.0's decode + demux path (lossy VP8, lossless VP8L, VP8X
container, ALPH alpha, and the WebPDemux/WebPAnimDecoder animation API)
amalgamated into one stb-style header, built as portable C99 with all
SIMD, threads and host file I/O disabled.

amalgamate.py regenerates webpdec.h from a pinned, auto-cloned libwebp
checkout; tests/run.sh checks decode output bit-exactly against
reference libwebp.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 03:28:11 +00:00

60 lines
1.9 KiB
Bash
Executable File

#!/bin/sh
# Build and run the webpdec.h tests. If Pillow is available, samples are
# generated and decode output is checked bit-exactly against reference libwebp;
# otherwise the tests just decode whatever .webp files are passed/present.
#
# sh tests/run.sh
set -e
cd "$(dirname "$0")/.." # repo root
CC=${CC:-cc}
CFLAGS="-O2 -std=c99 -Wall -I."
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
# Generate samples with Pillow if present (covers lossy, lossless, alpha,
# odd dimensions, and a multi-frame animation).
HAVE_PIL=0
if python3 - "$TMP" >/dev/null 2>&1 <<'PY'
import sys
from PIL import Image
d = sys.argv[1]
w, h = 137, 83
img = Image.new("RGBA", (w, h))
px = img.load()
for y in range(h):
for x in range(w):
px[x, y] = ((x*255)//w, (y*255)//h, (x*y) % 256, (x+y) % 256)
img.save(d+"/lossless.webp", lossless=True)
img.save(d+"/lossy.webp", quality=90)
frames = [Image.new("RGBA", (48, 32), (i*50 % 256, 80, 200, 255)) for i in range(5)]
frames[0].save(d+"/anim.webp", save_all=True, append_images=frames[1:],
duration=[100, 120, 140, 160, 180], loop=0, lossless=True)
PY
then HAVE_PIL=1; fi
echo "== build =="
$CC $CFLAGS -o "$TMP/test_decode" tests/test_decode.c -lm
$CC $CFLAGS -o "$TMP/test_demux" tests/test_demux.c -lm
if [ "$HAVE_PIL" = 1 ]; then
echo "== decode (still) =="
for k in lossless lossy; do
"$TMP/test_decode" "$TMP/$k.webp" "$TMP/$k.raw"
python3 - "$TMP/$k.webp" "$TMP/$k.raw" <<'PY'
import sys
from PIL import Image
ref = Image.open(sys.argv[1]).convert("RGBA").tobytes()
mine = open(sys.argv[2], "rb").read()
assert ref == mine, "%s: pixels differ from reference libwebp!" % sys.argv[1]
print(" %s: bit-exact vs reference libwebp" % sys.argv[1].split('/')[-1])
PY
done
echo "== demux + animation =="
"$TMP/test_demux" "$TMP/anim.webp"
else
echo "(Pillow not found -- decoding any .webp passed as args)"
for f in "$@"; do "$TMP/test_decode" "$f"; done
fi
echo "ALL TESTS PASSED"