Skip to content

Fix lossless decoding of point transformed and interleaved multi component scans - #25

Open
daker wants to merge 1 commit into
rii-mango:masterfrom
daker:point-transform
Open

Fix lossless decoding of point transformed and interleaved multi component scans#25
daker wants to merge 1 commit into
rii-mango:masterfrom
daker:point-transform

Conversation

@daker

@daker daker commented Aug 13, 2026

Copy link
Copy Markdown

ScanHeader parses Al out of the SOS header and nothing ever read it, so scans encoded with a point transform decoded wrong in two ways.

T.81 H.1.2.1 seeds the prediction for the first sample of a scan with 2^(P - Pt - 1), not 2^(P - 1). Lossless prediction chains additively, so a wrong seed offsets every sample in the frame: a 16 bit scan with Al = 2 came out 24576 high.

The encoder also right shifted every sample by Al before encoding (T.81 A.4.1), so the decoder has to shift them back. Without it the frame keeps 1/2^Al of its dynamic range.

The shift runs once the whole frame is decoded rather than in setValue, because prediction reads previously decoded samples back out of outputData and those reads have to stay in the point transformed domain.

Fixes cornerstonejs/cornerstone3D#757
Fixes cornerstonejs/cornerstone3D#1116

@daker

daker commented Aug 13, 2026

Copy link
Copy Markdown
Author

@rii-mango hi, can you look at the proposed fix ?

@daker daker changed the title Apply the point transform when decoding lossless scans Fix lossless decoding of point transformed and interleaved multi component scans Aug 13, 2026
…onent scans

ScanHeader parses Al out of the SOS header and nothing ever read it, so
scans encoded with a point transform decoded wrong in two ways.

T.81 H.1.2.1 seeds the prediction for the first sample of a scan with
2^(P - Pt - 1), not 2^(P - 1). Lossless prediction chains additively, so a
wrong seed offsets every sample in the frame: a 16 bit scan with Al = 2 came
out 24576 high.

The encoder also right shifted every sample by Al before encoding (T.81
A.4.1), so the decoder has to shift them back. Without it the frame keeps
1/2^Al of its dynamic range.

The shift runs once the whole frame is decoded rather than in setValue,
because prediction reads previously decoded samples back out of outputData
and those reads have to stay in the point transformed domain.

Fixes cornerstonejs/cornerstone3D#757
Fixes cornerstonejs/cornerstone3D#1116
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.

[Bug] can not render US file [Bug] dicom-image-loader: Image all white - wrong min/max pixel values

1 participant