Skip to content

JPEG 2000 support via the hayro-jpeg2000#787

Open
bowenxuuu wants to merge 5 commits into
Enet4:masterfrom
bowenxuuu:JPEG2000-via-hayro-jpeg2000
Open

JPEG 2000 support via the hayro-jpeg2000#787
bowenxuuu wants to merge 5 commits into
Enet4:masterfrom
bowenxuuu:JPEG2000-via-hayro-jpeg2000

Conversation

@bowenxuuu

@bowenxuuu bowenxuuu commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

follow up #751

fix #730

@bowenxuuu

Copy link
Copy Markdown
Contributor Author

decode by openjpeg-sys
111

decode by hayro-jpeg2000
222

@LaurenzV
The colors decoded by hayro-jpeg2000 appear incorrect, but I haven't yet figured out the root cause.

Comment thread transfer-syntax-registry/src/adapters/jpeg2k.rs
@bowenxuuu

Copy link
Copy Markdown
Contributor Author

https://github.com/LaurenzV/hayro/blob/20888608e8682f57a23632924fd87d2858fca359/hayro-jpeg2000/src/lib.rs#L550-L551

After I changed T::from_scaled_f32() to T::from_native_f32(), everything works as expected.

This image decode by T::from_native_f32() of hayro-jpeg2000.
333

@LaurenzV

Copy link
Copy Markdown

Is this image available somewhere so I can try it myself?

@bowenxuuu

Copy link
Copy Markdown
Contributor Author

Here's the DICOM image.

img.zip

@LaurenzV

Copy link
Copy Markdown

Okay, so I get it now. The method I added always scales to 16-bit, but what you want is something that always preserves the native bit depth. I think it's best if I instead expose an API for the raw f32 samples, then this should be the same as you are currently doing.

@LaurenzV

Copy link
Copy Markdown

Could you try this one instead? LaurenzV/hayro#1243

I think the code should then look something like this:

#[cfg(feature = "hayro-jpeg2000")]
{
    use hayro_jpeg2000::{DecodeSettings, DecoderContext, Image};

    let image = Image::new(&frame_data, &DecodeSettings::default())
        .whatever_context("hayro-jpeg2000 read image failure")?;

    let mut ctx = DecoderContext::default();
    let decoded = image
        .decode(&mut ctx)
        .whatever_context("hayro-jpeg2000 decoder failure")?;

    let components = decoded.components();

    for (component_i, component) in components.iter().enumerate() {
        if component_i >= samples_per_pixel as usize {
            warn!(
                "JPEG 2000 image has more components than expected ({} >= {})",
                component_i, samples_per_pixel
            );
            break;
        }

        for (i, sample) in component.samples().iter().enumerate() {
            let offset = base_offset
                + i * samples_per_pixel as usize * bytes_per_sample as usize
                + component_i * bytes_per_sample as usize;

            let sample = sample.round() as u32;
            dst[offset..offset + bytes_per_sample as usize]
                .copy_from_slice(&sample.to_le_bytes()[..bytes_per_sample as usize]);
        }
    }
}

@bowenxuuu

Copy link
Copy Markdown
Contributor Author

@LaurenzV Thanks, it works well now.

@LaurenzV

Copy link
Copy Markdown

Should be included in version 0.4.0 now. :)

@bowenxuuu

Copy link
Copy Markdown
Contributor Author

@Enet4 Hello

@Enet4 Enet4 added A-lib Area: library C-transfer-syntax Crate: dicom-transfer-syntax-registry labels Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-lib Area: library C-transfer-syntax Crate: dicom-transfer-syntax-registry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hayro-jpeg2000 A memory-safe, pure-Rust JPEG 2000 decoder.

3 participants