Add the dependency

In your project’s ziran.toml; pin ref to a commit for reproducible builds.

[dependencies.webp]
git = "https://github.com/ziranlang/webp.git"
ref = "master"

Overview

WebpDecode(input: BorrowedBytes, options: DecodeOptions) -> DecodeResult owns straight RGBA8 pixels. WebpDecodeInto borrows a validated OutputBuffer and returns metadata/error without transferring its storage. Animation returns only the first complete composed frame and reports the source frame count. WebpDefaultOptions preserves the existing native WebP input cap of 2147483647 bytes; ordinary DefaultOptions can impose a smaller cap. webp/authored exposes the authored VP8L/VP8(+ALPH) still-image provider, including bounded scratch backing and portable execution with no native codec link. webp/authored_lossless retains the VP8L entry points and optional format trace. The API contract records ownership and capability limits.

webp/riff is an allocation-free authored RIFF parser with explicit length, padding, image header, animation frame rectangle/count and metadata limits. It is independently executed from source and saved IR in C, Go and the direct portable VM. Header validation and pixel decoding have separate tests.

LibwebpCapabilities truthfully reports caller-owned output, one execution lane and first-frame compatibility. Synchronous native calls cannot enforce an internal scratch-memory allocation ceiling or stop mid-call; those capabilities are false. Input/output/container limits and cooperative checks before/after native work remain enforced. Native opaque objects and borrowed frames are released before returning; native internal threads are disabled. No color management/HDR or encoding capability is exposed. The bridge rejects FastColor.

build-queue -- sh tests/engine_contract.sh
build-queue -- sh tests/riff.sh
build-queue -- sh tests/legacy_compare.sh
build-queue -- sh tests/dynamic_contract.sh
build-queue -- sh tests/package_import.sh
build-queue -- sh tests/all.sh

Tests reuse the independently pinned mandatory image-codec corpus. Only the optional legacy comparison reads the hash-pinned original Kryon decoder from its frozen baseline (or an unchanged original checkout), without changing it. The native tests use the existing pinned source package offline. Configure local ziran and image_codec overrides before locking during development; no bootstrap commit is needed. WEBP_SOURCE can select an existing source package with the exact declared revision. No native source is fetched during a build. All builds run through build-queue; no display is used.

The validated native artifact platform is currently Linux x86-64 GNU. Consumers request ziran pkg artifact webp:libwebp --platform linux-x86_64-gnu, add the returned descriptor's lib directory to link search paths, and link imagewebp and m. The same artifact includes self-contained libimagewebp.so; shared-link consumers must also provide its runtime search path or package it beside their application. Consumers importing webp/dynamic can call OpenDynamicWebp(path), DynamicWebpDecode/DynamicWebpDecodeInto and CloseDynamicWebp with no static codec linkage (only dl and m). The engine owns its library handle; keep it alive through every decode and do not copy or close it during a call. Returned pixels remain owned after closing it. Missing libraries/symbols produce an unavailable engine and explicit capability error. Other platforms fail explicitly until their recipes and actual execution are validated. The authored implementation status records completed pixel work and remaining acceptance gates. The stable bridge is not represented as a fully authored WebP decoder.

build-queue -- sh tests/benchmark.sh builds the stable build/bin/webp-bench. It verifies exact golden pixels before timing real warm file reads and decode calls. It records actual samples and active workers; unavailable CPU, RSS, allocation and energy instruments remain null. authored-vp8l selects lossless decoding; authored-still selects the authored VP8L/VP8/ALPH provider. The local test measures actual warm samples for both lossless and lossy input. Cold-cache timing, CPU time, RSS, allocations and energy remain unmeasured. A small successful case is not a general codec performance result.

webp/src/facade.zi

facade

Import with #import "webp/facade".

WebpDecode :: (input: BorrowedBytes, options: DecodeOptions) -> DecodeResult

The bridge is explicit until the independently authored engine has parity.

WebpDecodeInto :: (input: BorrowedBytes, output: OutputBuffer, options: DecodeOptions) -> WebpOutputResult

Source ↗

webp/src/engine.zi

engine

Import with #import "webp/engine".

LibwebpEngine :: 1
AuthoredStillEngine :: 2
WebpEngineCapabilities :: struct { still_images: bool; first_animation_frame: bool; caller_owned_output: bool; interrupt_native_decode: bool; enforces_native_scratch_limit: bool; max_active_workers: s32; }
WebpOutputResult :: struct { is_ok: bool; metadata: ImageMetadata; error: DecodeError; }

Compatibility budget for existing native WebP paths. Generic callers can

WebpDefaultOptions :: () -> DecodeOptions

Compatibility budget for existing native WebP paths. Generic callers can instead pass DefaultOptions() or lower explicit limits.

Source ↗

webp/src/riff.zi

riff

Import with #import "webp/riff".

WebpLossy :: 1
WebpLossless :: 2
WebpAnimation :: 3
MaxWebpChunks :: 65536
WebpProbeResult :: struct { is_ok: bool; metadata: ImageMetadata; kind: s32; payload: BorrowedBytes; payload_offset: s64; alpha: BorrowedBytes; alpha_offset: s64; error: DecodeError; }
WebpHasSignature :: (input: BorrowedBytes) -> bool

Prefix dispatch only. Structural validation remains WebpProbe's job; this predicate accepts a RIFF/WEBP prefix even if its declared body is incomplete.

WebpProbe :: (input: BorrowedBytes, limits: DecodeLimits) -> WebpProbeResult

Source ↗

webp/src/libwebp.zi

libwebp

Import with #import "webp/libwebp".

LibwebpCapabilities :: () -> WebpEngineCapabilities
LibwebpVersion :: () -> s32
LibwebpDecode :: (input: BorrowedBytes, options: DecodeOptions) -> DecodeResult
LibwebpDecodeInto :: (input: BorrowedBytes, output: OutputBuffer, options: DecodeOptions) -> WebpOutputResult

Source ↗

webp/src/dynamic.zi

dynamic

Import with #import "webp/dynamic".

DynamicWebpEngine :: struct { library: *void; api: WebpNativeApi; available: bool; }
OpenDynamicWebp :: (path: string) -> DynamicWebpEngine

Caller owns this library handle: do not copy it or close while decoding. A missing/incompatible library is an explicit unavailable engine.

CloseDynamicWebp :: (engine: *DynamicWebpEngine)
DynamicWebpVersion :: (engine: *DynamicWebpEngine) -> s32
DynamicWebpDecode :: (engine: *DynamicWebpEngine, input: BorrowedBytes, options: DecodeOptions) -> DecodeResult
DynamicWebpDecodeInto :: (engine: *DynamicWebpEngine, input: BorrowedBytes, output: OutputBuffer, options: DecodeOptions) -> WebpOutputResult

Source ↗

webp/src/authored_lossless.zi

authored_lossless

Import with #import "webp/authored_lossless".

WebpAuthoredLosslessDecode :: (input: BorrowedBytes, options: DecodeOptions, trace: *LosslessTrace) -> DecodeResult

Authored VP8L only. No native symbols or fallback. Lossy/animation return an explicit capability failure. Optional trace records observed format events.

WebpAuthoredLosslessDecodeInto :: (input: BorrowedBytes, output: OutputBuffer, options: DecodeOptions, trace: *LosslessTrace) -> WebpOutputResult

Source ↗

webp/src/authored.zi

authored

Import with #import "webp/authored".

WebpAuthoredDecode :: (input: BorrowedBytes, options: DecodeOptions) -> DecodeResult

Authored strict still-image provider. VP8L and VP8(+ALPH) use Ziran only; animation and unimplemented color modes fail explicitly. No native fallback.

WebpAuthoredDecodeInto :: (input: BorrowedBytes, output: OutputBuffer, options: DecodeOptions) -> WebpOutputResult

Source ↗

Documents