Diagnosed visible faint grey rectangle around B&W ink art images on
pages with pure-white backgrounds. Root cause was format encoder
luminance shift in near-white pixels:
Source JPG corner: (253,253,253) = #FDFDFD = 99.2% white
AVIF q=65 (default): (250,250,250) = #FAFAFA = 98.0% (1.2% halo)
WebP q=80 (default): (249,249,249) = #F9F9F9 = 97.6% (1.6% halo)
Two changes:
1. avifenc now uses -y 444 (full chroma subsampling) instead of
default 4:2:0. Brings AVIF corner to #FBFBFB = 98.4%, smaller
file size as a bonus (~10% reduction on a typical art image).
2. WebP default quality raised 80 → 90. Reaches #FDFDFD = exact
match with source JPG. File size increases ~30% but eliminates
the halo entirely for WebP-capable browsers (vast majority).
AVIF still has 0.4% residual halo (libavif 0.11.1 ceiling at this
quality range — pushing higher yields no improvement, only file
size). Acceptable tradeoff: WebP is the served-by-default fallback
when AVIF isn't perfect.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two improvements after v0.2.1 deploy revealed the avif_status bug
wasn't fully fixed:
Fix:
Format_Generator::make_avif() now calls record_avif_outcome() at the
end of the synchronous path. Previously only the cron path recorded
outcomes, so wp h4b-img generate-missing-siblings (synchronous) left
4067 stale 'queued' rows even though it successfully generated 603
AVIFs on disk. process_avif_job() simplified to a thin wrapper
around make_avif(avif_async=false).
Added:
wp h4b-img reconcile-meta — walks _h4b_img_optim postmeta, checks
for .webp / .avif files on disk, and updates avif_status / webp size
fields to match reality. One-shot reconciliation for stale records
left by earlier plugin versions. --dry-run supported.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two related fixes to the AVIF pipeline:
Fix#1 — postmeta tracking
Format_Generator::process_avif_job() now updates _h4b_img_optim's
avif_status from 'queued' → 'done' (with byte size) or 'error' (with
reason) after the cron job runs. Previously the postmeta said
'queued' forever even when AVIF files existed on disk.
Fix#2 — root cause of missing AVIFs on rds.ink bulk run
wp_schedule_single_event(time()+30, …) coalesces identical args at
the same timestamp, so bulk-queueing hundreds of AVIF jobs in the
same second silently dropped many. Added wp h4b-img generate-missing-siblings
that walks attachment metadata, finds files missing .webp/.avif, and
generates them SYNCHRONOUSLY (no queue, no coalescing). Only processes
registered sizes by default; --include-orphans flag for disk-walk mode.
Verified on prod rds.ink: 1,134 of 1,737 registered images >=20KB have
AVIF, 603 are missing. Of 389 orphan files >=20KB missing AVIF, those
aren't referenced from any post/postmeta — correctly excluded.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>