feat(h5): refine report layout, add finger-following tabs and optimize images
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Export smaller delivery JPEGs; never overwrite the PSD-derived originals.
|
||||
|
||||
Only opaque-on-white product cards are candidates. Other WebPs are already
|
||||
smaller than JPEG, and logos/icons/masks need their original transparency.
|
||||
"""
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageChops, ImageStat
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DIRECTORY = ROOT / 'h5/assets/img/ui-20261012'
|
||||
|
||||
|
||||
def main():
|
||||
assets = []
|
||||
for age in (25, 35, 50):
|
||||
source = DIRECTORY / f'product-{age}.webp'
|
||||
rgba = Image.open(source).convert('RGBA')
|
||||
image = Image.new('RGB', rgba.size, 'white')
|
||||
image.paste(rgba, mask=rgba.getchannel('A'))
|
||||
for quality in (90, 92, 94, 96):
|
||||
buffer = io.BytesIO()
|
||||
image.save(buffer, 'JPEG', quality=quality, subsampling=0,
|
||||
optimize=True, progressive=True)
|
||||
encoded = buffer.getvalue()
|
||||
decoded = Image.open(io.BytesIO(encoded)).convert('RGB')
|
||||
rms = ImageStat.Stat(ImageChops.difference(image, decoded)).rms
|
||||
mse = sum(value ** 2 for value in rms) / 3
|
||||
psnr = 10 * math.log10(255 ** 2 / mse) if mse else 100
|
||||
if psnr >= 40 and len(encoded) < source.stat().st_size * .9:
|
||||
break
|
||||
else:
|
||||
raise RuntimeError(f'No suitably small high-quality JPEG for {source}')
|
||||
target = source.with_suffix('.jpg')
|
||||
target.write_bytes(encoded)
|
||||
assets.append({
|
||||
'source': str(source.relative_to(ROOT)),
|
||||
'source_sha256': hashlib.sha256(source.read_bytes()).hexdigest(),
|
||||
'source_bytes': source.stat().st_size,
|
||||
'file': str(target.relative_to(ROOT)),
|
||||
'sha256': hashlib.sha256(encoded).hexdigest(),
|
||||
'bytes': len(encoded), 'size': list(image.size),
|
||||
'quality': quality, 'subsampling': 0, 'progressive': True,
|
||||
'matte': '#FFFFFF', 'psnr_db': round(psnr, 2),
|
||||
})
|
||||
manifest = {
|
||||
'description': 'Smaller product-card delivery images. Original PSD crops preserved.',
|
||||
'retained': 'Background/scan WebPs are smaller than JPEG; transparent icons/masks remain PNG.',
|
||||
'assets': assets,
|
||||
'source_bytes': sum(row['source_bytes'] for row in assets),
|
||||
'delivery_bytes': sum(row['bytes'] for row in assets),
|
||||
}
|
||||
destination = ROOT / 'design/ui-20261012/delivery-optimization-20261012.json'
|
||||
destination.write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + '\n', encoding='utf8')
|
||||
print(json.dumps(manifest, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user