Skip to content

fix(dicom): Fix rejected subimages, and reaching every frame - #5474

Merged
lgritz merged 2 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-dicom
Sep 29, 2026
Merged

lgritz merged 2 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-dicom

Conversation

@lgritz

@lgritz lgritz commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

This is follow-on work to PR #5468 -- after fixing the TIFF reader, I also turned up some similar issues in other format readers, and this PR addresses the issues in DICOM.

A failed seek_subimage left the reader thinking it was pointing at a subimage it had just refused, similar to what was uncovered for other formats in PR #5468 and #5470. Fixing that is the main point of this patch.

Second, along the way it was discovered that every frame past the first was unreachable. The subimage bound came from DicomImage::getFrameCount(), which is the number of frames the DicomImage loaded, not the number in the file. Instead, getNumberOfFrames() is the file's own count and is what we want.

But DICOMInput also never overrode current_subimage(), so it inherited the base class's "always 0" -- harmless while there could only be one subimage, wrong for multiple images.

Adds a testsuite for the DICOM format, which had none. The test writes its own small three-frame file rather than depending on an external image. Each frame is a different constant value, so the per-subimage hashes catch both losing the frames and reading the same frame repeatedly.

Assisted-by: Claude Code / Claude Opus 5

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Multi-frame capability is not advertised and the required subimage-count metadata is missing for higher-level APIs.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Fixes DICOM multi-frame seeking by tracking the file’s total frame count and decoder position, with a generated three-frame regression test.

Changes:

  • Corrects subimage/frame state handling and frame access.
  • Adds deterministic DICOM tests with per-frame hashes.
  • Registers the test suite when DCMTK is available.
File Description
src/​dicom.imageio/​dicominput.cpp Updates frame seeking and state tracking.
testsuite/​dicom/​src/​make_multiframe.py Generates a multi-frame DICOM fixture.
testsuite/​dicom/​run.py Runs the DICOM regression test.
testsuite/​dicom/​ref/​out.txt Stores expected dimensions and hashes.
src/​cmake/​testing.cmake Registers the DICOM test suite.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/dicom.imageio/dicominput.cpp
@lgritz lgritz added bug Crash or wrong behavior of an existing feature. file formats Image file formats, ImageInput, ImageOutput labels Sep 21, 2026
This is follow-on work to PR 5468 -- after fixing the TIFF reader, I
also turned up some similar issues in other format readers, and this PR
addresses the issues in DICOM.

Two problems in DICOMInput::seek_subimage(), both of which had been there
for as long as the reader has claimed to support subimages.

A failed seek left the reader pointing at a subimage it had just
refused, similar to what was uncovered for other formats in PR 5468
and 5470. Fixing that is the main point of this patch.

Second, along the way it was discovered that every frame past the
first was unreachable. The subimage bound came from
DicomImage::getFrameCount(), which is the number of frames the
DicomImage loaded, not the number in the file.  Instead,
getNumberOfFrames() is the file's own count and is what we want.

But DICOMInput also never overrode current_subimage(), so it inherited
the base class's "always 0" -- harmless while there could only be one
subimage, wrong for multiple images.

Adds a testsuite for the dicom format, which had none. The test writes its
own small three-frame file rather than depending on an external image. Each
frame is a different constant value, so the per-subimage hashes catch both
losing the frames and reading the same frame repeatedly.

Assisted-by: Claude Code / Claude Opus 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
@lgritz

lgritz commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

No objections for 2 weeks -> merge

@lgritz
lgritz merged commit a3e4f8f into AcademySoftwareFoundation:main Sep 29, 2026
126 of 128 checks passed
@lgritz
lgritz deleted the lg-dicom branch September 29, 2026 21:19
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Oct 3, 2026
…SoftwareFoundation#5474)

This is follow-on work to PR AcademySoftwareFoundation#5468 -- after fixing the TIFF reader, I
also turned up some similar issues in other format readers, and this PR
addresses the issues in DICOM.

A failed seek_subimage left the reader thinking it was pointing at a
subimage it had just refused, similar to what was uncovered for other
formats in PR AcademySoftwareFoundation#5468 and AcademySoftwareFoundation#5470. Fixing that is the main point of this
patch.

Second, along the way it was discovered that every frame past the first
was unreachable. The subimage bound came from
DicomImage::getFrameCount(), which is the number of frames the
DicomImage loaded, not the number in the file. Instead,
getNumberOfFrames() is the file's own count and is what we want.

But DICOMInput also never overrode current_subimage(), so it inherited
the base class's "always 0" -- harmless while there could only be one
subimage, wrong for multiple images.

Adds a testsuite for the DICOM format, which had none. The test writes
its own small three-frame file rather than depending on an external
image. Each frame is a different constant value, so the per-subimage
hashes catch both losing the frames and reading the same frame
repeatedly.

Assisted-by: Claude Code / Claude Opus 5

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Oct 10, 2026
…SoftwareFoundation#5474)

This is follow-on work to PR AcademySoftwareFoundation#5468 -- after fixing the TIFF reader, I
also turned up some similar issues in other format readers, and this PR
addresses the issues in DICOM.

A failed seek_subimage left the reader thinking it was pointing at a
subimage it had just refused, similar to what was uncovered for other
formats in PR AcademySoftwareFoundation#5468 and AcademySoftwareFoundation#5470. Fixing that is the main point of this
patch.

Second, along the way it was discovered that every frame past the first
was unreachable. The subimage bound came from
DicomImage::getFrameCount(), which is the number of frames the
DicomImage loaded, not the number in the file. Instead,
getNumberOfFrames() is the file's own count and is what we want.

But DICOMInput also never overrode current_subimage(), so it inherited
the base class's "always 0" -- harmless while there could only be one
subimage, wrong for multiple images.

Adds a testsuite for the DICOM format, which had none. The test writes
its own small three-frame file rather than depending on an external
image. Each frame is a different constant value, so the per-subimage
hashes catch both losing the frames and reading the same frame
repeatedly.

Assisted-by: Claude Code / Claude Opus 5

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Crash or wrong behavior of an existing feature. file formats Image file formats, ImageInput, ImageOutput

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants