Skip to content

Conversation

@hjanuschka
Copy link
Collaborator

Summary

Fix multi-layer CMYK image blending by deferring CMS conversion until after blending operations complete.

Problem: For CMYK images with alpha blending across multiple layers, blending in RGB space (after CMS conversion) produces incorrect results. The correct approach is to blend in CMYK space first, then convert to RGB.

Solution: Defer CMS conversion for CMYK images when:

  1. The frame needs blending, OR
  2. The frame can be referenced by later frames (save_before_ct=false)

This ensures reference frames are saved in CMYK space so subsequent frames blend correctly before final CMS conversion.

Changes

  • jxl/src/frame/render.rs: Restructured CMS stage application to support deferred execution for CMYK blending

Credit

Based on the fix from @lilith in lilith/jxl-rs.

@veluca93 veluca93 requested a review from sboukortt January 23, 2026 08:34
For multi-layer CMYK images with alpha blending, the CMS conversion
(CMYK → RGB) must happen AFTER blending, not before. Blending in CMYK
space produces different results than blending in RGB space.

The fix defers CMS conversion for CMYK images when:
1. The frame needs blending, OR
2. The frame can be referenced by later frames (save_before_ct=false)

This ensures reference frames are saved in CMYK space so subsequent
frames can blend correctly before final CMS conversion.

Based on fix from lilith/jxl-rs.
@hjanuschka hjanuschka force-pushed the fix-cmyk-blending-order branch from 159f225 to 6170405 Compare January 23, 2026 09:06
@github-actions
Copy link

Benchmark @ 6170405

MULTI-FILE BENCHMARK RESULTS (4 files)
  CPU architecture: x86_64
  WARNING: System appears noisy: high system load (2.73). Results may be unreliable.
Statistics:
  Confidence:               99.0%
  Max relative error:        3.0%

Comparing: a5ae7dc1 (Base) vs f0ec2aa2 (PR)

File Base (MP/s) PR (MP/s) Δ%
bike.jxl 22.614 22.889 +1.22% ±3.0%
green_queen_modular_e3.jxl 7.878 7.896 +0.23% ±1.0%
green_queen_vardct_e3.jxl 21.108 20.948 -0.76% ±2.0%
sunset_logo.jxl 2.228 2.229 +0.04% ±0.3%

@jonsneyers
Copy link
Member

For multi-layer images, not only in the case of CMYK, the frame blending has to be done in the image space, not in the final decoded image space. This also makes a difference in the RGB case, e.g. if the image space is linear Rec2020 (i.e. that's what the imageheader says), and we're decoding to sRGB, then frames have to be kept in or converted to linear Rec2020 for frame blending and only after blending the result should be converted to the final decode space.

Are we doing this correctly?
It's a subtle point but it does make a difference.

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.

2 participants