InsightSoftwareConsortium / InsightSoftwareConsortium/ITK
BUG: GDCMImageIO mis-decodes single-bit pixel data for DICOM Segmentation Storage (SEG) objects
- Dominant language
- C++
- Stars
- 1.7k
- Forks
- 748
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 64
Description
`GDCMImageIO` mis-decodes single-bit pixel data for DICOM SEG (Segmentation Storage) objects: instead of unpacked binary 0/1 values it returns unscaled `uint8` values spanning the full 0-255 range. Found while cross-validating against `pydicom` using real-world fixtures from the [highdicom](https://github.com/ImagingDataCommons/highdicom) test suite, during triage of #6639 (the fix for #6629's single-bit row-padding bug) — confirmed this is a **separate, unrelated** bug: identical mismatch reproduces both before and after the #6639 fix.
Reproduction
Fixtures (from `ImagingDataCommons/highdicom` `data/test_files/`, MIT licensed): `seg_image_cr_binary.dcm`, `seg_image_ct_binary.dcm`, `seg_image_ct_binary_overlap.dcm`, `seg_image_ct_binary_single_frame.dcm` — all `SOPClassUID = 1.2.840.10008.5.1.4.1.1.66.4` (Segmentation Storage), `BitsAllocated=1`.
```python
import itk, pydicom
ds = pydicom.dcmread("seg_image_ct_binary_single_frame.dcm")
pa = ds.pixel_array # sum=1832, values are 0/1
img = itk.imread("seg_image_ct_binary_single_frame.dcm", imageio=itk.GDCMImageIO.New())
arr = itk.array_from_image(img) # sum=467160, dtype=uint8, min=0, max=255
```
467160 far exceeds the maximum possible sum (16384) for a 128x128 binary mask — GDCM is not treating the pixel data as single-bit for this SOP Class at all.
Two further SEG fixtures fail outright with `ITK ERROR GDCMImageIO(...): Cannot read requested file` (`seg_image_sm_control_labelmap.dcm`, `_palette_color.dcm`), and four more throw `An invalid logic behavior occurred b1 && cosines.size() == 6` (`seg_image_sm_control.dcm`, `_dots.dcm`, `_numbers.dcm`, `_dots_tiled_full.dcm`) — these are multi-frame SEG objects whose orientation lives only in `PerFrameFunctionalGroupsSequence`, not a top-level `ImageOrientationPatient`. May be the same root cause as the byte-range bug, or a separate one.
Environment
- ITK 6.0.0 (built from `main` post-#6639, and independently reproduced against the 5.4.6 pip wheel)
- pydicom 3.0.2 as ground truth
- macOS (Darwin 25.5.0)
Contributor guide
Research direction
Start with Modules/IO/GDCM/src/itkGDCMImageIO.cxx and reproduce the mismatch using .devlocal/pr6639-triage/highdicom-crossval/crossval.py and the listed highdicom fixtures. Compare single-bit SEG output with pydicom, then investigate the reported multi-frame failures separately. Done means single-bit SEG data yields unpacked 0/1 values and the affected fixtures no longer fail as described.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- computer-vision
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100