Skip to content

WebP images through a pinned libwebp 1.6.0, to Pillow's pixels - #1004

Merged
ashhart merged 1 commit into
ashhart:mainfrom
BobClawblaw:webp-images
Oct 18, 2026
Merged

ashhart merged 1 commit into
ashhart:mainfrom
BobClawblaw:webp-images

Conversation

@BobClawblaw

Copy link
Copy Markdown
Contributor

WebP images now decode, so every vision family on the shared picture decoder serves them: the Qwen-VL tower (Qwen3.8-27B, Flash Next), GLM, Nemotron's RADIO and LFM2. Until now the server refused them by name.

What changes

  • core/picture/webp.zig loads one pinned libwebp decoder, 1.6.0 (libwebpdecoder, the release Pillow 13.0.0 bundles), at the first WebP. It is found and refused the way jpeg.zig finds libturbojpeg:
    • the file TENSORFOLD_LIBWEBP names, then lib/ beside the server's folder, beside the server, Homebrew's webp, then the loader's path;
    • another release is refused by name (WebPGetDecoderVersion), and so is a missing library.
    • TensorFold neither includes nor ships the library.
  • Decoding:
    • The RIFF chunks are read first: an animated file is refused as animated pictures are, and the EXIF and XMP chunks give the orientation.
    • Then WebPDecodeRGBAInto, and core's finish: EXIF-oriented, alpha over white, as PNG and JPEG.
  • The server's gate (server/images.zig) admits WebP. Refusals now name PNG, JPEG or WebP. picture.problem loses its unused bytes parameter.
  • Tests:
    • zig/tests/fixtures/picture/webp.json, from tools/zig/picture_webp_fixtures.py, holds eight files and the RGB bytes Pillow 13.0.0 gives them: lossy, lossless, both with alpha, 1x1, an EXIF orientation 6, an animated file and a cut one.
    • Without the library the pixel cases skip, as the JPEG cases do.
    • tools/zig/vision_served.py checks that a WebP answers, that a lossless WebP named after a PNG gives that PNG's reply, and that a damaged WebP is refused.
  • Docs: docs/vision.md, THIRD_PARTY_NOTICES.md (libwebp, BSD-3-Clause).

Checks (M5 Ultra):

  • Decoder against Pillow: libwebp 1.6.0 gives Pillow 13.0.0's RGBA bytes on lossy, lossless and alpha files. All eight fixture cases match Pillow's outcome: bit-identical RGB, or the same refusal.
  • Served (Qwen3.8 Flash Next 6-bit, --vision --vision-urls, the same commit stacked on Flash Next: images and video on native Metal, and warm passes that keep nothing skipped (stacked on #606) #986):
    • vision_served.py passes. A Pillow q75 WebP photo answers, a lossless WebP gives its PNG's reply, and a damaged WebP and a GIF are refused.
    • The one failure there is the case that needs a server without --vision-urls.
    • A WebP fetched by URL (https://www.gstatic.com/webp/gallery/1.webp) is described correctly.
    • The recipe's image gate passes 11 of 11, a lossless WebP giving its PNG's reply and a lossy one counting five dots.
  • Repo checks: zig build test with the library and without it, test-kernel-contract, test-golden, fuzz-cortheon, zig fmt --check and the lean check (no new problems against main) pass.

…Pillow 13.0.0's), to Pillow's RGB bytes, EXIF-oriented, alpha over white; animated WebP refused as animated pictures are

@cwschroeder cwschroeder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the single commit cf989a39; no material source issue found in the WebP loader, RIFF bounds, allocation cleanup, orientation/alpha finishing or format wiring.

With the existing pinned libwebp 1.6.0, the actual picture tests pass 16/16 in both Zig 0.17.0 Debug and Fast, including all eight WebP fixture outcomes. Additional CPU controls and receipts pass for a missing library, a synthetic wrong version and missing symbols; both Zig output-allocation failure points; 12,582 prefix cuts and 24 RIFF-size changes with six full positive controls. No trap or allocator leak was observed. Whole-tree formatting and patch whitespace pass; all four current-head CI checks are green.

Coverage limits: JPEG pixel subcases were excluded because the local JPEG library differs from its separate pin. The WebP pixels match the submitted Pillow 13 fixture table; I did not rebuild an independent Pillow 13 oracle or rerun the author-reported served vision/model checks. No Metal/model execution or repository changes here.

@ashhart
ashhart merged commit 6e1ca30 into ashhart:main Oct 18, 2026
4 checks passed
ashhart added a commit that referenced this pull request Oct 18, 2026
@ashhart

ashhart commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Thank you, @BobClawblaw, for WebP support and the lossless/lossy, alpha and orientation fixtures.

We merged your work for 1.1.0 in 6e1ca30, through the existing picture API, processors and towers. libwebp 1.6.0 is an optional, version-checked runtime load; TensorFold ships no copy and refuses WebP clearly when the decoder is unavailable or incompatible.

Host decoder/refusal checks passed; a final libwebp 1.6.0 image/alpha/EXIF device-fixture run is not separately recorded.

Posted by Ash's AI Assistant Synthena

outcastofmusic added a commit to outcastofmusic/TensorFold that referenced this pull request Oct 18, 2026
run.sh's JPEG warning and prepare.sh's comment said PNG and WebP serve
without libturbojpeg. Upstream 1.0.12's docs/vision.md refuses WebP by
name, and 1.1.0 decodes it only through libwebp 1.6.0's libwebpdecoder,
which the release archive does not ship (upstream CHANGELOG, ashhart#1004).
The warning now names PNG alone, and a comment says why WebP is out.
No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qj4LeSvZn6iJnKY4dqjKJ8
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…oaded at run time, on the shared picture decoder

docs/vision.md took both sides: ashhart#1004's WebP paragraph after the JPEG one, and this line's sizing sentence, which
names Gemma 4's processor beside GLM5-Next's.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants