Skip to content

Commit 0bf69b3

Browse files
matmenclaude
andcommitted
tests: a photo of smartphones instead of the old photo
tests/targets/external.png (and external.jpg) are now a square of bench/inputs/photo.jpg (Carlos Varela, CC BY 2.0, in the third party notices), scaled to 638x638; profile-card.png, the old README image, is replaced by screen.png, a settings window drawn with ImageScript (flat areas, text, rounded corners). Everything made from them is written again, by the fixture scripts and the tools they name: - tests/avif: aomenc 3.8.2, references by libavif 1.4.2 (no libyuv, as avifdec -u bilinear; reproduces every reference of the old files) - tests/jxl: cjxl/djxl 0.11.1 (the parts of the photo and the screen; the circle, patches, animations and conformance files are unchanged) - tests/ico, tests/hdr, tests/qoi: scripts/format-fixtures.py - tests/tiffs: scripts/tiff-fixtures.py, which now also writes the TIFFs Pillow writes (the photo scaled to 157x101 bicubic, as before). i16b stores v * 257: its high bytes, which ImageScript reads, were 0 - references: cwebp 1.6.0, cjxl -e 1 with AVX2 and without SIMD (qemu) - targets: fisheye, flip, effects (OVERWRITE_TEST) Every tool was checked against the old files first: they reproduce the old references. Two thresholds depend on the photo: monochrome AVIF is 13% smaller instead of 30% (the photo has little color), and JPEG quality 10 reaches 27.7 dB (as libjpeg does) instead of 28. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BsU2GDnECphmYTjLB5UeZv
1 parent 16af0cc commit 0bf69b3

122 files changed

Lines changed: 94 additions & 79 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎THIRD_PARTY_NOTICES.md‎

Lines changed: 1 addition & 0 deletions

‎scripts/avif-fixtures.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ def write(name, data, reference=avifdec):
265265
write('grain', avif([image(encode([yuv(photo(48, 40), '420', 8)], '420', 8, ['--cq-level=30', '--film-grain-test=1']), '420', 8, 48, 40)]))
266266
write('superres', avif([image(encode([yuv(photo(128, 96), '420', 8)], '420', 8, ['--cq-level=35', '--cpu-used=0', '--superres-mode=1',
267267
'--superres-kf-denominator=13', '--enable-restoration=1']), '420', 8, 128, 96)]))
268-
write('screen', avif([image(encode([yuv(source('profile-card.png', 200, 150), '420', 8)], '420', 8, ['--cq-level=30', '--tune-content=screen']), '420', 8, 200, 150)]))
268+
write('screen', avif([image(encode([yuv(source('screen.png', 200, 150), '420', 8)], '420', 8, ['--cq-level=30', '--tune-content=screen']), '420', 8, 200, 150)]))
269269

270270
# alpha (an auxiliary image), premultiplied too
271271
color, alpha = photo(48, 40), alpha_ramp(48, 40)

‎scripts/jxl-fixtures.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def write_pfm(path, im):
4141

4242

4343
photo = lambda w, h: source('external.png', w, h, (200, 120, 520, 440))
44-
text = lambda w, h: source('profile-card.png', w, h, (40, 40, 40 + w, 40 + h))
44+
text = lambda w, h: source('screen.png', w, h, (40, 40, 40 + w, 40 + h))
4545

4646
# lossless (Modular): the fast efforts (gradient, RLE), MA trees and the weighted predictor, palettes, alpha, 16 bits,
4747
# grey, floats

‎scripts/jxl-lossless-references.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
def images():
17-
for name in ['external.png', 'circle.png', 'profile-card.png', 'potato.png']:
17+
for name in ['external.png', 'circle.png', 'screen.png', 'potato.png']:
1818
yield name, np.asarray(Image.open(root / 'tests' / 'targets' / name).convert('RGBA'))
1919
# (grey: the red channel)
2020
red = np.asarray(Image.open(root / 'tests' / 'targets' / 'external.png').convert('RGBA'))[..., 0]

‎scripts/tiff-fixtures.py‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1-
# Writes the TIFFs of tests/tiffs that Pillow can't write: python3 scripts/tiff-fixtures.py (needs Pillow)
2-
# Most store the pixels of an existing fixture (rgba-tiff_lzw-pred, la-tiff_lzw, bw-tiff_deflate) in another way, so
3-
# they have to decode to the same output; the YCbCr ones are compared with libtiff (through Pillow)
1+
# Writes the TIFFs of tests/tiffs: python3 scripts/tiff-fixtures.py (needs Pillow with libtiff)
2+
# First the ones Pillow (libtiff) writes, from tests/targets/external.png scaled to 157x101, then those it can't write.
3+
# Most of these store the pixels of the first ones (rgba-tiff_lzw-pred, la-tiff_lzw, bw-tiff_deflate) in another way,
4+
# so they have to decode to the same output; the YCbCr ones are compared with libtiff (through Pillow)
45
import struct
56
import zlib
67
from pathlib import Path
8+
import numpy as np
79
from PIL import Image
810

911
root = Path(__file__).resolve().parent.parent
1012
out = root / 'tests' / 'tiffs'
13+
14+
source = Image.open(root / 'tests' / 'targets' / 'external.png').convert('RGB').resize((157, 101), Image.BICUBIC)
15+
source.convert('1').save(out / 'bw-tiff_deflate.tif', compression='tiff_adobe_deflate')
16+
source.convert('CMYK').save(out / 'cmyk-tiff_lzw-pred.tif', compression='tiff_lzw', tiffinfo={317: 2})
17+
source.convert('L').convert('F').save(out / 'f-tiff_adobe_deflate-pred.tif', compression='tiff_adobe_deflate', tiffinfo={317: 3})
18+
# (16 bits, big endian: v * 257, the high bytes are the 8-bit image)
19+
Image.frombytes('I;16B', source.size, (np.asarray(source.convert('L'), np.uint32) * 257).astype('>u2').tobytes()).save(out / 'i16b.tif')
20+
source.convert('LA').save(out / 'la-tiff_lzw.tif', compression='tiff_lzw')
21+
source.quantize(64).save(out / 'p-packbits.tif', compression='packbits')
22+
source.save(out / 'rgb-jpeg.tif', compression='jpeg')
23+
source.convert('RGBA').save(out / 'rgba-tiff_lzw-pred.tif', compression='tiff_lzw', tiffinfo={317: 2})
24+
1125
rgb = Image.open(out / 'rgba-tiff_lzw-pred.tif').convert('RGB')
1226
grey = Image.open(out / 'la-tiff_lzw.tif').convert('L')
1327
bw = Image.open(out / 'bw-tiff_deflate.tif').convert('1')

‎tests/avif-encode.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ const compare = (a, b) => {
4949
const lossless = await Image.decode(await potato.encodeAVIF({quality: 100, effort: 0}));
5050
if (Buffer.compare(Buffer.from(lossless.bitmap), Buffer.from(potato.bitmap))) panic('quality 100 isn\'t lossless');
5151

52-
// gray: monochrome, smaller, lossless if asked
52+
// gray: monochrome, smaller (the photo has little color: by about 13%), lossless if asked
5353
const gray = photo.clone().saturation(0, {absolute: true});
5454
const grayAvif = await gray.encodeAVIF({effort: 0}), grayBack = await Image.decode(grayAvif);
55-
if (grayAvif.length >= full.length * 0.8 || compare(gray, grayBack)[0] < 35) panic(`gray: ${grayAvif.length} bytes, ${compare(gray, grayBack)[0].toFixed(2)} dB`);
55+
if (grayAvif.length >= full.length * 0.92 || compare(gray, grayBack)[0] < 35) panic(`gray: ${grayAvif.length} bytes, ${compare(gray, grayBack)[0].toFixed(2)} dB`);
5656
for (let i = 0; i < grayBack.bitmap.length; i += 4) if (grayBack.bitmap[i] !== grayBack.bitmap[i + 1] || grayBack.bitmap[i] !== grayBack.bitmap[i + 2]) panic('gray: colored pixels');
5757
if (Buffer.compare(Buffer.from((await Image.decode(await gray.encodeAVIF({quality: 100, effort: 0}))).bitmap), Buffer.from(gray.bitmap))) panic('gray: quality 100 isn\'t lossless');
5858

‎tests/avif.js‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ const maxDifference = (a, b) => {
1616

1717
// the AVIFs of scripts/avif-fixtures.py as libavif decodes them (with dav1d)
1818
const references = {
19-
'yuv420': '405544e4c21a8ed19c9d8f2143cbb43adbea3a73d59ff7a7b8742da0d59c6588',
20-
'yuv420-12bit': '9e563ff3f8597fafad1a4bdce52f93a350e4037f5dd7bb5f0b2b67bd0d753d2b',
21-
'yuv422-10bit': '53793513daa157cbe173221964b41c21f6a5b0d584515d99145b17640bdaa828',
22-
'yuv444': '6065428fd239cffa63075de349d60cd018da36c087237f3e2bbec4cf7428f7d2',
23-
'mono': '622fc95436c83d80dd7a0c563c3f8136f6d1c8cb5ecb8e44c755508244558e9e',
24-
'tools': '9800a057d96dff45046995e28f8639c9c9f793172784f6d74ee39c95c0321d8e',
25-
'segments': '03450e40e17ac1c9000f5a947da7977085c5de7faae1163fc63fa8d06b1a1bbd',
26-
'grain': 'fa558082b532265a9b26e678effd887f705ec809f253ff2775a1923347d8fd3a',
27-
'superres': 'b918a7dd27236f4f162d9fbcdbcb795266c40962f4e7366f999dab291534c4f6',
28-
'screen': '61ba64c8e8625e60b4d59208e6fac09cff5262ebfded088db6fe141cfbf2ab5a',
29-
'alpha': '9ba0669388bed8df1614aeeaba344cd0668731bf59016fdb596ae5d38b894e6a',
30-
'alpha-premultiplied': '857c21b5cff307239ab994ac2329d18a0af7746972cef0b921915b65478905ce',
31-
'grid': '08d32f7cb34e783f4f5cb4c0d595771bec261d79010d78f702b9e681c3196ac2',
32-
'transforms': '1a00ce63fc61032f0efcf1e9bb2f6e6a44f3835e085a4d0331dff11db04f730a',
33-
'sequence': 'ae85e62c2d5eb0db1f15430602cdfa41798fcbd5c7a006382efc23c615e54121',
19+
'yuv420': '8538965a0f7e917daac4f08481d827f8ab64b7db15d61c591fb3680c25547481',
20+
'yuv420-12bit': '90e1db5bd40f2418d01b6cff2f0a370c77270fcb6a86eb498b3eaf6228fb4232',
21+
'yuv422-10bit': 'd6191a34034304d914921b21cb4ddc9233cf85754461875c0837338c44674012',
22+
'yuv444': '5b9fdf4ea98158c29fb9551dc6186f0ae8042eea298ed21e246ed9e2198510d4',
23+
'mono': '2e14306840020f2e831088a9f3c5d59034d1f7f047b00e6b8988c6e096a6a8b8',
24+
'tools': '5cbb7c24c81ca6481ee6f4b8e9bdd6d00bd9854b120d12e9f52a3133905bb0e9',
25+
'segments': '012e024cc536ac4f3c2dcc326b064740546e45053863eff072a3465ca83fcd4d',
26+
'grain': 'c7a420818c09a0db23feca2a2404bc08fa9623f7c208ddb3b3c6e27698cd3082',
27+
'superres': 'b098e3ddc1828f5565ad1ab4bd11ea74c8d0fd31ecae675d0249c80ad289cc27',
28+
'screen': '4fac188ded63f814be85a2a5846cc4306e65b580dcebb91e9883ba67f927e77e',
29+
'alpha': '75997458251525c3c06ec8ef2149a90e32726831f1a599b1356c658d98bc849d',
30+
'alpha-premultiplied': 'ad09ce797bed32479ad72523ab188a39441ebc85976a284ab3da121702b19b46',
31+
'grid': 'b6f5c3be81ac52daabe55e9b0f5a4f6e9a5f1b4adcf82c013cdcc2588d542f74',
32+
'transforms': '38a9ade925431f685369468071feed32b90e3e2f5c855ea8040142ef1e0051cc',
33+
'sequence': '1b62b5829e6d56d35ff7f0cfa6b7fef6da9c5f85e58799ea5b679f2864eef125',
3434
};
3535

3636
(async () => {
180 Bytes
Binary file not shown.

‎tests/avif/alpha.avif‎

237 Bytes
Binary file not shown.

‎tests/avif/grain.avif‎

207 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)