Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_graphics/tests/jpeg/gen.sh

3.9 KiB, 5 runs, executable

created by r1870400018:17597, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1#!/bin/bash
2# Regenerates the JPEG fixtures in this directory.
3#
4# Nothing here is a photograph: every source image is generated by this script, written out as a
5# PPM, and handed to ImageMagick to compress. The JPEGs are therefore ImageMagick's work and not
6# ours, which is the point -- a codec that agrees only with itself has been tested against nothing.
7#
8# Requires ImageMagick's `convert`. Run from this directory.
9set -eu
10cd "$(dirname "$0")"
11tmp=$(mktemp -d)
12trap 'rm -rf "$tmp"' EXIT
13
14# ---- The sources, each written as a binary PPM by a short Python program. ----
15python3 - "$tmp" <<'PYEOF'
16import sys, os, math
17d = sys.argv[1]
18
19def ppm(name, w, h, fn):
20 px = bytearray()
21 for y in range(h):
22 for x in range(w):
23 r, g, b = fn(x, y)
24 px += bytes((r & 255, g & 255, b & 255))
25 with open(os.path.join(d, name + ".ppm"), "wb") as f:
26 f.write(b"P6\n%d %d\n255\n" % (w, h))
27 f.write(px)
28
29# A smooth two-axis gradient: the easy case, where every block is nearly flat.
30ppm("gradient", 64, 48, lambda x, y: (x * 4, y * 5, (x + y) * 2))
31
32# Deterministic noise: the hard case, where every coefficient carries something.
33def noise(x, y):
34 s = (x * 1103515245 + y * 12345 + 7) & 0x7FFFFFFF
35 s = (s ^ (s >> 13)) * 2654435761 & 0x7FFFFFFF
36 return (s & 255, (s >> 8) & 255, (s >> 16) & 255)
37ppm("noise", 33, 17, noise)
38
39# Saturated primaries in hard-edged blocks: the case chroma subsampling is worst at.
40def prim(x, y):
41 c = [(255,0,0), (0,255,0), (0,0,255), (255,255,0),
42 (0,255,255), (255,0,255), (255,255,255), (0,0,0)]
43 return c[((x // 8) + (y // 8) * 3) % 8]
44ppm("primaries", 48, 32, prim)
45
46# A single pixel, where every edge case in an upsampler meets at once.
47ppm("tiny", 1, 1, lambda x, y: (200, 40, 90))
48
49# Odd dimensions, so that neither axis is a multiple of a block or an MCU.
50ppm("odd", 17, 13, lambda x, y: (
51 int(127 + 120 * math.sin(x * 0.7)),
52 int(127 + 120 * math.sin(y * 0.9)),
53 int(127 + 120 * math.sin((x + y) * 0.5)),
54))
55
56# Four pixels across: the chrominance plane is then two samples wide, which is where the triangle
57# filter has no interior to work over and libjpeg falls back to replicating.
58ppm("narrow", 4, 6, lambda x, y: (255 if x < 2 else 0, 0 if x < 2 else 255, (x * 60 + y * 20) % 256))
59
60# A grey ramp, for the single-component path.
61ppm("ramp", 40, 24, lambda x, y: ((x * 6) % 256,) * 3)
62PYEOF
63
64# ---- The JPEGs. ----
65c() { convert "$tmp/$1.ppm" "${@:3}" "$2.jpg"; }
66
67c gradient gradient_q90_444 -quality 90 -sampling-factor 1x1
68c gradient gradient_q75_420 -quality 75 -sampling-factor 2x2
69c gradient gradient_q50_422 -quality 50 -sampling-factor 2x1
70c gradient gradient_q80_prog -quality 80 -sampling-factor 2x2 -interlace JPEG
71c noise noise_q95_444 -quality 95 -sampling-factor 1x1
72c noise noise_q60_420 -quality 60 -sampling-factor 2x2
73c noise noise_q85_prog -quality 85 -sampling-factor 1x1 -interlace JPEG
74c primaries primaries_q92_444 -quality 92 -sampling-factor 1x1
75c primaries primaries_q70_420 -quality 70 -sampling-factor 2x2
76c primaries primaries_q70_422 -quality 70 -sampling-factor 2x1
77c tiny tiny_q90_420 -quality 90 -sampling-factor 2x2
78c odd odd_q88_444 -quality 88 -sampling-factor 1x1
79c odd odd_q64_420 -quality 64 -sampling-factor 2x2
80c odd odd_q88_prog -quality 88 -sampling-factor 2x2 -interlace JPEG
81c gradient gradient_q80_1x2 -quality 80 -sampling-factor 1x2
82c narrow narrow_q90_420 -quality 90 -sampling-factor 2x2
83c narrow narrow_q90_422 -quality 90 -sampling-factor 2x1
84c ramp ramp_q90_grey -quality 90 -colorspace Gray -type Grayscale
85c ramp ramp_q90_prog -quality 90 -colorspace Gray -type Grayscale -interlace JPEG
86
87# Restart markers, which nothing above exercises.
88convert "$tmp/noise.ppm" -quality 80 -sampling-factor 2x2 -define jpeg:restart-interval=2 \
89 noise_q80_rst.jpg
90
91# The reference decodings, as ImageMagick reads its own files back.
92for f in *.jpg; do
93 convert "$f" "${f%.jpg}.ppm"
94done
95
96ls -l