Skip to content

Initial JPEG XL decoder#755

Open
kmilos wants to merge 7 commits into
darktable-org:developfrom
kmilos:kmilos/dng_jxl
Open

Initial JPEG XL decoder#755
kmilos wants to merge 7 commits into
darktable-org:developfrom
kmilos:kmilos/dng_jxl

Conversation

@kmilos

@kmilos kmilos commented Oct 11, 2024

Copy link
Copy Markdown
Contributor

Refs. #516

This is just a basic POC, largely based around the darktable imageio_jxl reader.


if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
size_t size =
basicinfo.xsize * basicinfo.ysize * basicinfo.num_color_channels;

Check warning

Code scanning / CodeChecker

The left operand of '*' is a garbage value

The left operand of '*' is a garbage value
JxlDecoderDestroy(decoder);

const Array2DRef<uint16_t> tmp(complete_buffer.data(),
basicinfo.num_color_channels * basicinfo.xsize,

Check warning

Code scanning / CodeChecker

The left operand of '*' is a garbage value

The left operand of '*' is a garbage value
@github-actions

Copy link
Copy Markdown

The proposed diff is not clang-formatted.
To make this check pass, download the following patch
(via browser, you must be logged-in in order for this URL to work),
(NOTE: save it into the repo checkout dir for the snippet to work)
https://github.com/darktable-org/rawspeed/actions/runs/15758629170/artifacts/3363237698
... and run:

cd <path/to/repo/checkout> # NOTE: use your own path here
unzip clang-format.patch.zip
git stash # Temporairly stash away any preexisting diff
git apply clang-format.patch # Apply the diff
git add -u # Stage changed files
git commit -m "Applying clang-format" # Commit the patch
git push
git stash pop # Unstast preexisting diff
rm clang-format.patch.zip clang-format.patch

@schwittlick

Copy link
Copy Markdown

Anything we can do to move this forward?

@0fbcb238c0

Copy link
Copy Markdown

LibRaw 0.22 released with support for compiling with Adobe's DNG SDK. Are there plans to use it for decoding 1.7 DNGs with JXL?

@kmilos

kmilos commented Jan 16, 2026

Copy link
Copy Markdown
Contributor Author

Anything we can do to move this forward?

There has been zero feedback on this PR so far.

Are there plans

No such plans here.

In any case, I'm personally not intending to keep working on this given the current circumstances. Anyone should feel free to pick up this POC and run with it.

@MaykThewessen

Copy link
Copy Markdown

Hi @kmilos, thanks for getting this started. Since you flagged it as a stalled PoC open for adoption, I picked it up and ran an independent verification against a real Apple ProRAW file. Happy to take this the rest of the way (rebase, fix the static-analysis/format nits, add a regression sample) if that's welcome.

Independent verification

Built rs-identify from the PR head (131c543) on macOS arm64 with libjxl 0.11.2 (-DWITH_JXL=ON, Apple clang 21) and ran it against a real iPhone 16 Pro Max ProRAW DNG (DNG 1.7, the raw image is in SubIFD0: 8064x6048, BitsPerSample 10, SamplesPerPixel 3, PhotometricInterpretation LinearRaw, Compression 52546 = JPEG XL, tiled 2016x2016 → 12 JXL codestreams).

The good news: the decode path is correct and produces a sane image. With one trivial fix (below) rs-identify reports:

make / model:    Apple / iPhone 16 Pro Max   (canonical_model matches)
isCFA:           0          (LinearRaw, 3-channel)
cpp / bpp:       3 / 6
dataType:        0 (UINT16),  whitePoint 65535
dimUncropped:    8064x6048
dimCropped:      8064x6048
decode time:     ~1.4 s, peak RSS ~350 MB

Per-channel mean works out to ~26k in 16-bit space, consistent with libjxl scaling the 10-bit codestream samples up to 16-bit. I also decoded all 12 tiles standalone with libjxl to confirm the ranges are plausible and there's no clipping/garbage.

Honest scope: I verified decode-without-error plus plausible dimensions/stats, not pixel-exact output against a reference. I did not test the 2x2 interleaved-CFA path (my sample is LinearRaw, interleave 1x1) — that path is unexercised here.

One blocker I hit (and the fix)

As-written, the decode loop hangs / spins forever on this file. Root cause is in JpegXLDecompressor::decode:

size_t size = basicinfo.xsize * basicinfo.ysize * basicinfo.num_color_channels; // element COUNT
complete_buffer.resize(size);
JxlDecoderSetImageOutBuffer(decoder, &pixel_format, complete_buffer.data(), size); // expects BYTES

JxlDecoderSetImageOutBuffer's size argument is in bytes, but size is the element count. Since the pixel format is JXL_TYPE_UINT16, libjxl needs size * 2 bytes, sees a buffer declared half that size, and returns JXL_DEC_ERROR. That return value isn't checked, so the loop keeps getting JXL_DEC_NEED_IMAGE_OUT_BUFFER, re-sets the same too-small buffer, and never reaches JXL_DEC_FULL_IMAGE. I reproduced this in isolation against libjxl 0.11.2: the as-written call returns status 1 (error) every iteration (passed 12192768, needs 24385536), while passing size * sizeof(uint16_t) decodes one tile in ~0.06 s.

Fix is one line:

JxlDecoderSetImageOutBuffer(decoder, &pixel_format, complete_buffer.data(),
                            size * sizeof(uint16_t));

(and ideally check its return value and ThrowRDE on non-JXL_DEC_SUCCESS).

On the issues you flagged

  • CodeChecker uninitialized variable: JxlBasicInfo basicinfo; (declared uninitialized, read after the loop). If a malformed stream ever reached JXL_DEC_FULL_IMAGE without first emitting JXL_DEC_BASIC_INFO, the post-loop Array2DRef/copy would read garbage. JxlBasicInfo basicinfo = {}; plus a "basic info never arrived" guard addresses it.
  • clang-format: for what it's worth, all six changed files are already clean against the repo .clang-format with clang-format 22, so that may have resolved in the later commits.

Offer to help finish it

If you're happy to hand this off, I'd be glad to: (1) land the buffer-size fix + return-value check, (2) zero-init basicinfo, (3) add a small public-domain iPhone ProRAW JPEG-XL sample as a decode regression test, and (4) rebase on current develop. I have our own working JPEG XL decoder so this is purely about helping #755 land, not duplicating it. Let me know if you'd prefer me to push commits onto this branch or open a follow-up PR.

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.

5 participants