Skip to content

16-bit lossy VarDCT for RGB/RGBA#84

Merged
SureshKViswanathan merged 2 commits into
mainfrom
feature/vardct-16bit-lossy-encode
Jul 1, 2026
Merged

16-bit lossy VarDCT for RGB/RGBA#84
SureshKViswanathan merged 2 commits into
mainfrom
feature/vardct-16bit-lossy-encode

Conversation

@SureshKViswanathan

Copy link
Copy Markdown
Contributor

Summary

  • Lossy VarDCT previously accepted only 8-bit RGB/RGBA and silently fell back to lossless Modular for 16-bit input, even though lossless Modular has supported 8- and 16-bit since v1.0. This closes that gap: VarDCTEncoder, VarDCTBitstreamWriter, and JXLDecoder now handle 16-bit RGB/RGBA end-to-end.
  • Fixes a latent bug along the way: the alpha-unpack in VarDCTBitstreamWriter.buildFrameSections used a byte stride only correct for 8-bit samples, which would have corrupted 16-bit RGBA alpha.
  • encodeAnimation now rejects frames that disagree on bit depth instead of silently misdeclaring the shared ImageMetadata.
  • Includes release bump to v1.3.0 (CHANGELOG, JXLToolVersion, Package.swift/CLAUDE.md status).

Test plan

  • swift build -c release clean
  • djxl 0.11.2 oracle: 16-bit RGB/RGBA/multi-group VarDCT bitstreams decode via djxl within 3–16/65535 max-diff of our own decoder (alpha bit-exact)
  • Byte-for-byte regression diff against a pre-change build (isolated git worktree): 8-bit lossy VarDCT, 8/16-bit lossless Modular, and multi-frame animation all byte-identical — zero drift on the existing default path
  • 7 new XCTest additions (routing, round-trip, djxl-byte-equality RGB/RGBA/multi-group, mixed-bit-depth-animation-throws) — logic verified via a throwaway executable target linked against the built library, since this dev env has no Xcode/XCTest; needs a real swift test -c release run on an Xcode host to close the loop

🤖 Generated with Claude Code

Ranjithkumar and others added 2 commits July 1, 2026 17:23
Lossy VarDCT previously accepted only 8-bit RGB/RGBA and silently fell
back to lossless Modular for 16-bit input, even though the lossless
Modular path has supported 8- and 16-bit since v1.0. This closes that
gap:

- VarDCTEncoder.forward accepts .uint16 frames; srgb8ToLinear
  generalises to srgbToLinear(_:maxValue:), keeping the 8-bit pixel
  loop byte-for-byte unchanged (no per-pixel branch on the default
  hot path) and adding a separate 16-bit loop.
- VarDCTBitstreamWriter threads the real bit depth into
  ImageMetadata/ExtraChannelInfo instead of hardcoding 8, and fixes a
  latent alpha-unpack stride bug (frame.data[i*ch+3] only gave the
  right byte for 1-byte samples) that would have corrupted 16-bit
  RGBA alpha. encodeAnimation now rejects frames that disagree on bit
  depth rather than silently misdeclaring the shared metadata.
- JXLDecoder's VarDCT reconstruction reads metadata.bitDepth and
  emits a uint16 ImageFrame when appropriate, mirroring the pattern
  the Modular path already used in assembleImageFrame.

Verified via the djxl 0.11.2 oracle (16-bit RGB/RGBA/multi-group
bitstreams decode within max-diff 3-16/65535 of our own decoder;
alpha bit-exact) and a byte-for-byte regression diff against a
pre-change build (8-bit lossy, 8/16-bit lossless, and multi-frame
animation all byte-identical — zero drift on the existing default
path).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bump JXLToolVersion 1.2.0 -> 1.3.0, Package.swift status, CLAUDE.md's
implementation-status table, and add the CHANGELOG 1.3.0 entry.

Highlights (full notes in CHANGELOG.md):
- Lossy VarDCT now accepts 16-bit RGB/RGBA (previously 8-bit only),
  matching the lossless Modular path's bit-depth range. Existing
  8-bit lossy and all lossless output is byte-for-byte unchanged.
- Fixes a latent 16-bit RGBA alpha-channel corruption bug in the
  VarDCT bitstream writer's alpha-unpack stride.

Verified via reference libjxl 0.11.2 (djxl accepts every generated
16-bit bitstream; our decoder agrees with djxl within a few LSBs) and
a byte-for-byte regression diff against a pre-change build. The full
XCTest suite needs an Xcode host (this dev env has only
CommandLineTools); the djxl spec gate was exercised via CLI
round-trips, and the new tests' logic was additionally verified
through a throwaway executable target linked against the built
library (removed before this commit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@SureshKViswanathan SureshKViswanathan merged commit c3862e6 into main Jul 1, 2026
3 of 4 checks passed
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.

1 participant