v1.4.0: grayscale/oversized/int16 VarDCT + broader JPEG decode#85
Merged
Merged
Conversation
Close three lossy-encode gaps that previously fell back to lossless Modular, plus a signed-pixel type. Existing RGB/RGBA VarDCT and all lossless output is byte-for-byte unchanged. - Grayscale lossy VarDCT (1ch + 2ch gray+alpha, 8/16-bit): encoded as a 3-channel XYB frame with X ≈ 0 and a grayscale ColorEncoding — the representation libjxl uses; the decoder collapses RGB→gray on output. Multi-group and animation covered; djxl decodes it as grayscale. - Oversized VarDCT: raise the encoder size cap 8192 -> 16384 px/side (a resource-safety limit, not correctness). Verified wide/tall/square beyond the old cap; the group indexing was audited for large numGroups. - PixelType.int16 (DICOM CT): the encoder level-shifts to unsigned offset-binary up front so the VarDCT/Modular core is untouched; JXLDecoder.decode(_:signedOutput:) reconstructs the signed frame. - Fix: multi-frame VarDCT reported wasLossless=true, mislabelling every animation as a lossless encode. Adds regression tests (grayscale, oversized, int16) that would have caught the previous silent fallbacks. Full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Broaden the pure-Swift JPEG pixel decoder (JPEGDecoder.decode) beyond baseline 8-bit. Note: 12-bit and lossless JPEGs cannot be losslessly recompressed to JXL — the jbrd format is 8-bit-DCT-only (libjxl's own cjxl rejects them) — so this is pixel decode (JPEG -> ImageFrame), not recompression. - decode(_:) now delegates to decodeToCoefficients (already SOF1/SOF2 capable) plus dequant/IDCT/colour, covering progressive (SOF2), extended-sequential (SOF1) and 12-bit precision (-> .uint16 frame with raw 0..4095 values), with a precision-generalised YCbCr->RGB. Verified <= 6 LSB vs djpeg -nosmooth. - New JPEGLosslessDecoder (SOF3, ITU-T T.81 Annex H) for DICOM Lossless JPEG (.70): all 7 predictors, 2..16-bit, grayscale and 3-component, interleaved and non-interleaved scans, restart intervals (incl. the first-line-after-reset horizontal-prediction rule). decode(_:) routes SOF3 automatically. Byte-exact vs djpeg across the full sweep. - Converts the stale "rejects progressive" pixel-decode test into a positive DCT-family test; adds a byte-exact lossless test. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Bump JXLToolVersion 1.3.0 -> 1.4.0, Package.swift status prose, and finalise the CHANGELOG 1.4.0 entry. Highlights (full notes in CHANGELOG.md): - Grayscale / grayscale+alpha lossy VarDCT (8/16-bit), the way libjxl stores it; djxl decodes the output as grayscale. - Oversized VarDCT: size cap raised 8192 -> 16384 px/side. - Signed 16-bit pixels (PixelType.int16) for DICOM CT; encoder level-shifts, decode(_:signedOutput:) reconstructs the signed frame. - Broader JPEG decode: progressive, extended-sequential, 12-bit, and SOF3 lossless (byte-exact vs djpeg). Verified against reference libjxl 0.11.2 (djxl) and libjpeg-turbo 3.1.4 (djpeg); full XCTest suite green (717 tests, 0 failures). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes four coverage gaps. Existing 8-/16-bit RGB/RGBA VarDCT and all lossless output is byte-for-byte unchanged; full XCTest suite green (717 tests, 0 failures). Verified against reference libjxl 0.11.2 (
djxl) and libjpeg-turbo 3.1.4 (djpeg).Grayscale lossy VarDCT
1-channel grayscale and 2-channel grayscale+alpha, 8/16-bit. Encoded the way libjxl does it — a 3-channel XYB frame whose X plane is ≈ 0 (R = G = B after inverse opsin) carrying a grayscale
ColorEncoding; the decoder collapses RGB→gray on output. Multi-group + animation covered;djxldecodes the output as grayscale. (Corrects the prompt's premise that grayscale needed a separate non-XYB path.)Oversized VarDCT
Encoder size cap raised 8192 → 16384 px/side (a resource-safety limit, not correctness — the multi-AC/DC-group machinery indexes with
Int). Verified wide (8704×256), tall (256×8448), and square (8256×8256).Signed 16-bit (
PixelType.int16)The DICOM CT case. Encoder level-shifts
.int16→ unsigned offset-binary up front so the VarDCT/Modular core is untouched;JXLDecoder.decode(_:signedOutput:)reconstructs the signed frame. Byte-exact through the lossless Modular path.Broader JPEG decode
JPEGDecoder.decodenow covers progressive (SOF2), extended-sequential (SOF1), 12-bit (→.uint16), and SOF3 lossless (newJPEGLosslessDecoder: 7 predictors, 2–16-bit, gray/RGB, interleaved/non-interleaved, restart). Byte-exact vsdjpegfor lossless; ≤ 6 LSB for the DCT family.Also fixed
Multi-frame VarDCT reported
wasLossless=true, mislabelling every animation as lossless.🤖 Generated with Claude Code