Skip to content

Commit

Permalink
Image Plane Module for SecondaryCaptureImageStorage
Browse files Browse the repository at this point in the history
Create an extension for SecondaryCaptureImageStorage as if Image Plane
Module would be optional.

This will allow reading IPP/IOP/PixelSpacing for
SecondaryCaptureImageStorage for some particular dataset.

Make this feature opt-in per the discussion:

* #158

This extension does not implement Basic Pixel Spacing Calibration Macro
Attributes since the original target dataset to support is as follow:

    $ dcmdump 000198cd-cd88-4760-97d1-21bbea047fff.dcm | grep Spacin
    (0018,0088) DS [1]                                      #   2, 1 SpacingBetweenSlices
    (0028,0030) DS [.33\.33]                                #   8, 2 PixelSpacing

> If Pixel Spacing Calibration Type (0028,0A02) and Imager Pixel Spacing
> (0018,1164) and Nominal Scanned Pixel Spacing (0018,2010) are absent,
> then it cannot be determined whether or not correction or calibration
> have been performed.

References:

* https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.8.6.2.html#table_C.8-25
* https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_10.7.html#table_10-10

Co-authored-by: Matt McCormick <[email protected]>
Co-authored-by: Mihail Isakov <[email protected]>
Co-authored-by: Steve Pieper <[email protected]>
  • Loading branch information
4 people committed Mar 25, 2024
1 parent 033b6d8 commit 0609129
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Applications/Cxx/gdcminfo.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ static void PrintHelp()
std::cout << " --force-rescale force rescale." << std::endl;
std::cout << " --force-spacing force spacing." << std::endl;
std::cout << " --mosaic dump image information of MOSAIC." << std::endl;
std::cout << " --scipm Include Image Plane Module for Secondary Capture Image." << std::endl;

std::cout << "General Options:" << std::endl;
std::cout << " -V --verbose more verbose (warning+error)." << std::endl;
Expand Down Expand Up @@ -626,6 +627,7 @@ int main(int argc, char *argv[])
std::string xmlpath;
int forcerescale = 0;
int forcespacing = 0;
int scipm = 0;

int resourcespath = 0;
int verbose = 0;
Expand All @@ -647,6 +649,7 @@ int main(int argc, char *argv[])
{"force-rescale", 0, &forcerescale, 1},
{"force-spacing", 0, &forcespacing, 1},
{"mosaic", 0, &mosaic, 1},
{"scipm", 0, &scipm, 1},

{"verbose", 0, &verbose, 1},
{"warning", 0, &warning, 1},
Expand Down Expand Up @@ -769,6 +772,7 @@ int main(int argc, char *argv[])

gdcm::ImageHelper::SetForceRescaleInterceptSlope(forcerescale ? true : false);
gdcm::ImageHelper::SetForcePixelSpacing(forcespacing ? true : false);
gdcm::ImageHelper::SetSecondaryCaptureImagePlaneModule(scipm ? true : false);

if( filename.empty() )
{
Expand Down
23 changes: 21 additions & 2 deletions Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace gdcm
bool ImageHelper::ForceRescaleInterceptSlope = false;
bool ImageHelper::PMSRescaleInterceptSlope = true;
bool ImageHelper::ForcePixelSpacing = false;
bool ImageHelper::SecondaryCaptureImagePlaneModule = false;

static bool GetOriginValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector<double> &ori)
{
Expand Down Expand Up @@ -578,7 +579,7 @@ std::vector<double> ImageHelper::GetOriginValue(File const & f)

// else
const Tag timagepositionpatient(0x0020, 0x0032);
if( ms != MediaStorage::SecondaryCaptureImageStorage && ds.FindDataElement( timagepositionpatient ) )
if( (ms != MediaStorage::SecondaryCaptureImageStorage || SecondaryCaptureImagePlaneModule) && ds.FindDataElement( timagepositionpatient ) )
{
const DataElement& de = ds.GetDataElement( timagepositionpatient );
Attribute<0x0020,0x0032> at = {{0,0,0}}; // default value if empty
Expand Down Expand Up @@ -730,7 +731,7 @@ std::vector<double> ImageHelper::GetDirectionCosinesValue(File const & f)
}

dircos.resize( 6 );
if( ms == MediaStorage::SecondaryCaptureImageStorage || !GetDirectionCosinesFromDataSet(ds, dircos) )
if( (ms == MediaStorage::SecondaryCaptureImageStorage && !SecondaryCaptureImagePlaneModule) || !GetDirectionCosinesFromDataSet(ds, dircos) )
{
dircos[0] = 1;
dircos[1] = 0;
Expand Down Expand Up @@ -774,6 +775,16 @@ bool ImageHelper::GetForcePixelSpacing()
return ForcePixelSpacing;
}

void ImageHelper::SetSecondaryCaptureImagePlaneModule(bool b)
{
SecondaryCaptureImagePlaneModule = b;
}

bool ImageHelper::GetSecondaryCaptureImagePlaneModule()
{
return SecondaryCaptureImagePlaneModule;
}

bool GetRescaleInterceptSlopeValueFromDataSet(const DataSet& ds, std::vector<double> & interceptslope)
{
Attribute<0x0028,0x1052> at1;
Expand Down Expand Up @@ -1264,6 +1275,14 @@ Tag ImageHelper::GetSpacingTagFromMediaStorage(MediaStorage const &ms)
t = Tag(0x3002,0x0011); // ImagePlanePixelSpacing
break;
case MediaStorage::SecondaryCaptureImageStorage:
if( ImageHelper::SecondaryCaptureImagePlaneModule ) {
// Make SecondaryCaptureImagePlaneModule act as ForcePixelSpacing
// This is different from Basic Pixel Spacing Calibration Macro Attributes
t = Tag(0x0028,0x0030);
} else {
t = Tag(0x0018,0x2010);
}
break;
case MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage:
case MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage:
case MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage:
Expand Down
8 changes: 8 additions & 0 deletions Source/MediaStorageAndFileFormat/gdcmImageHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ class GDCM_EXPORT ImageHelper
static void SetForcePixelSpacing(bool);
static bool GetForcePixelSpacing();

/// Opt into Image Plane Module for Secondary Capture Image Storage
/// Enable reading Image Position Patient (IPP), Image Orientation Patient
/// (IOP) and Pixel Spacing (0028,0030)
/// This is a custom extension for some existing dataset (academic)
static void SetSecondaryCaptureImagePlaneModule(bool);
static bool GetSecondaryCaptureImagePlaneModule();

/// This function checks tags (0x0028, 0x0010) and (0x0028, 0x0011) for the
/// rows and columns of the image in pixels (as opposed to actual distances).
/// The output is {col , row}
Expand Down Expand Up @@ -156,6 +163,7 @@ class GDCM_EXPORT ImageHelper
static bool ForceRescaleInterceptSlope;
static bool PMSRescaleInterceptSlope;
static bool ForcePixelSpacing;
static bool SecondaryCaptureImagePlaneModule;
};

} // end namespace gdcm
Expand Down

0 comments on commit 0609129

Please sign in to comment.