Skip to content

Commit

Permalink
ENH: Add DICOM patcher rule to fix compressed ultrasound discolorization
Browse files Browse the repository at this point in the history
Photometric intepretation field of compressed ultrasound images was ambiguous before DICOM CP156
(https://dicom.nema.org/medical/dicom/Final/cp156_ft.pdf) and there are DICOM images in the wild
that contain photometric interpretation value (RGB) that is inconsistent with the compressed transfer syntax
(JPEG). See https://groups.google.com/g/comp.protocols.dicom/c/EPkbFOMBOhE for more details.

The new DICOM patcher rule modifies RGB photometric interpretation to YBR_FULL_422 if the transfer syntax
of the image is JPEG, because JPEG compression is practically always used with YBR_FULL_422.
  • Loading branch information
lassoan committed Mar 22, 2024
1 parent 6639f29 commit e91cb00
Showing 1 changed file with 48 additions and 1 deletion.
49 changes: 48 additions & 1 deletion Modules/Scripted/DICOMPatcher/DICOMPatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ def setup(self):
" Useful if many ultrasound acquisitions appear in the same series."))
parametersFormLayout.addRow("Split ultrasound series by instance number", self.splitUltrasoundSeriesByInstanceNumberCheckBox)

self.fixCompressedUltrasoundPhotometricInterpretationCheckBox = qt.QCheckBox()
self.fixCompressedUltrasoundPhotometricInterpretationCheckBox.checked = True
self.fixCompressedUltrasoundPhotometricInterpretationCheckBox.setToolTip(_(
"If checked, then photometric interpretation of JPEG-compressed ultrasound will be set to YBR_FULL_422."
" This is useful for fixing inconsistency in JPEG-compressed images that used RGB as photometric interpretation"
" due to ambiguity in the DICOM standard before CP156."
" See https://groups.google.com/g/comp.protocols.dicom/c/EPkbFOMBOhE"
" and https://dicom.nema.org/medical/dicom/Final/cp156_ft.pdf for more details."))
parametersFormLayout.addRow("Fix compressed ultrasound photometric interpretation", self.fixCompressedUltrasoundPhotometricInterpretationCheckBox)


characterSetLayout = qt.QHBoxLayout()

self.specifyCharacterSetCheckBox = qt.QCheckBox()
Expand Down Expand Up @@ -182,6 +193,8 @@ def onPatchButton(self):
self.logic.addRule("FixExposureFiasco")
if self.splitUltrasoundSeriesByInstanceNumberCheckBox.checked:
self.logic.addRule("SplitUltrasoundSeriesByInstanceNumber")
if self.fixCompressedUltrasoundPhotometricInterpretationCheckBox.checked:
self.logic.addRule("FixCompressedUltrasoundPhotometricInterpretation")
if self.forceSamePatientNameIdInEachDirectoryCheckBox.checked:
self.logic.addRule("ForceSamePatientNameIdInEachDirectory")
if self.forceSameSeriesInstanceUidInEachDirectoryCheckBox.checked:
Expand Down Expand Up @@ -223,7 +236,7 @@ def __init__(self, parameters=None):
def addLog(self, text):
logging.info(text)
if self.logCallback:
self.logCallback(text)
self.logCallback(" " + text)

def processStart(self, inputRootDir, outputRootDir):
pass
Expand Down Expand Up @@ -642,6 +655,40 @@ def processDataSet(self, ds):
ds.SeriesNumber = ds.SeriesNumber * 1000 + ds.InstanceNumber


#
#
#


class FixCompressedUltrasoundPhotometricInterpretation(DICOMPatcherRule):
def __init__(self, parameters=None):
super().__init__(parameters)
self.requiredTags = ["SOPClassUID"]
self.supportedSOPClassUIDs = [
"1.2.840.10008.5.1.4.1.1.3.1", # Ultrasound Multiframe Image Storage
"1.2.840.10008.5.1.4.1.1.6.1", # Ultrasound Image Storage
]

def processStart(self, inputRootDir, outputRootDir):
self.seriesInstanceUidAndInstanceNumberToNewSeriesInstanceUidMap = {}

def processDataSet(self, ds):
import pydicom

# Return if this is not an ultrasound series
for tag in self.requiredTags:
if not hasattr(ds, tag):
return
if ds.SOPClassUID not in self.supportedSOPClassUIDs:
return

# If the image is JPEG-compressed then
if ds.file_meta.TransferSyntaxUID == pydicom.uid.JPEGBaseline8Bit:
if ds.PhotometricInterpretation == "RGB":
self.addLog("Compressed JPEG image was found with RGB photometric interpretation. Changed it to YBR_FULL_422.")
ds.PhotometricInterpretation = "YBR_FULL_422"


#
# DICOMPatcherLogic
#
Expand Down

0 comments on commit e91cb00

Please sign in to comment.