Skip to content

Conversation

@tunglt1810
Copy link
Contributor

@tunglt1810 tunglt1810 commented Oct 24, 2025

Context

Currently, Viewer does not support render dicom CornealTopographyMapStorage with SOPClassUID 1.2.840.10008.5.1.4.1.1.82.1

If I only add SOP class uid to default extension, this is the image
image

Changes & Results

  • Add sop class uid CornealTopographyMapStorage in to default extension
  • Update logic build palette LUT at fetchPaletteColorLookupTableData
  • Result
image Compare with Weasis viewer image

Testing

Checklist

PR

  • [] My Pull Request title is descriptive, accurate and follows the
    semantic-release format and guidelines.

Code

  • [] My code has been well-documented (function documentation, inline comments,
    etc.)

Public Documentation Updates

  • [] The documentation page has been updated as necessary for any public API
    additions or removals.

Tested Environment

@netlify
Copy link

netlify bot commented Oct 24, 2025

Deploy Preview for ohif-dev ready!

Name Link
🔨 Latest commit 961b21b
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/691eacf861f57600079e3b55
😎 Deploy Preview https://deploy-preview-5522--ohif-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@tunglt1810 tunglt1810 changed the title support OPM with palette color LUT feature: support OPM with palette color LUT Oct 27, 2025
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

} else {
// If bitsPerEntry < 8, shift left
lut[i] = (lutValue16 << Math.abs(offsetBits)) & 0xff;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Palette Color Retrieval Breaks 8-bit Compatibility

The _getPaletteColor function now always reads palette data as 16-bit values, assuming the buffer is sized accordingly. This differs from the previous logic that handled both 8-bit and 16-bit data based on the bits parameter. For 8-bit palette data, this can cause buffer overruns and incorrect interpretation, impacting backward compatibility.

Fix in Cursor Fix in Web

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tunglt1810 please check this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @IbrahimCSAE ,
If you have another testcase, can you share it. So I can test this logic.

@IbrahimCSAE
Copy link
Collaborator

I have to test this with other color images I have to make sure they didn’t break @sedghi

@tunglt1810
Copy link
Contributor Author

tunglt1810 commented Oct 28, 2025

Hi @IbrahimCSAE ,
I updated the ticket description with overview if not change fetchPaletteColorLookupTableData.js
And there is a small problem that the wadors thumbnails are always black (screenshot 2) when first loading because the logic fet LUT color palette is async. You can check here
Load image: https://github.com/cornerstonejs/cornerstone3D/blob/299a34f3fa18444c85bd3b2f37a42b1de4586c4c/packages/dicomImageLoader/src/imageLoader/createImage.ts#L186
Convert colorspace
https://github.com/cornerstonejs/cornerstone3D/blob/main/packages/dicomImageLoader/src/imageLoader/convertColorSpace.ts
Fetch palette LUT
https://github.com/cornerstonejs/cornerstone3D/blob/299a34f3fa18444c85bd3b2f37a42b1de4586c4c/packages/dicomImageLoader/src/imageLoader/colorSpaceConverters/convertPALETTECOLOR.ts#L49C3-L49C16

lut[i] = (lutValue16 >> offsetBits) & 0xff;
} else {
// If bitsPerEntry < 8, shift left
lut[i] = (lutValue16 << Math.abs(offsetBits)) & 0xff;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a shift needed? offsetBits will be 0 for this case, so
lut[i] = lutValue16 && 0xff;
should be sufficient.

// Read 16-bit value (LUT is always 16-bit)
const lutValue16 = view.getUint16(i * 2, true);

// Apply Orthanc shift logic
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be orthanc specific - either reference the DICOM standard or specify that this is the format for sop class ...

for (let i = 0; i < numLutEntries; i++) {
lut[i] = data[i];
// Read 16-bit value (LUT is always 16-bit)
const lutValue16 = view.getUint16(i * 2, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to PS3.3 C.8.17.14.1.6 Bits Allocated, Bits Stored, and High Bit
you can have either 8 or 16 bit data. Please ensure that 8 bit data is handled.

// const data = bits === 16 ? new Uint16Array(buffer) : new Uint8Array(buffer);

const view = new DataView(buffer);
const offsetBits = bits - 8;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest isTwoByte = bits > 8

@wayfarer3130
Copy link
Contributor

Here is an image previously provided for fixing in OHIF:
anon.zip

@wayfarer3130
Copy link
Contributor

The attached image is 8 bit data, and is the test data we used previously for checking out the 8 bit palette colour fixes.

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.

4 participants