#include "gdcmImageHelper.h"
#include "gdcmMediaStorage.h"
#include "gdcmFile.h"
#include "gdcmDataSet.h"
#include "gdcmDataElement.h"
#include "gdcmItem.h"
#include "gdcmSequenceOfItems.h"
#include "gdcmGlobal.h"
#include "gdcmDictEntry.h"
#include "gdcmDicts.h"
#include "gdcmAttribute.h"
#include "gdcmImage.h"
#include "gdcmDirectionCosines.h"
#include "gdcmSegmentedPaletteColorLookupTable.h"
#include "gdcmByteValue.h"
#include <cmath>
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)
{
ori.clear();
if( !ds.FindDataElement( tfgs ) ) return false;
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false;
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0020,0x9113);
if( !subds.FindDataElement(tpms) ) return false;
SmartPointer<SequenceOfItems> sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ();
if( sqi2 && !sqi2->IsEmpty() )
{
const Item &item2 = sqi2->GetItem(1);
const DataSet & subds2 = item2.GetNestedDataSet();
const Tag tps(0x0020,0x0032);
if( !subds2.FindDataElement(tps) ) return false;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0020,0x0032> at;
at.SetFromDataElement( de );
ori.push_back( at.GetValue(0) );
ori.push_back( at.GetValue(1) );
ori.push_back( at.GetValue(2) );
return true;
}
return false;
}
static bool GetDirectionCosinesValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector<double> &dircos)
{
dircos.clear();
if( !ds.FindDataElement( tfgs ) ) return false;
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false;
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0020,0x9116);
if( !subds.FindDataElement(tpms) ) return false;
SmartPointer<SequenceOfItems> sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ();
if( !(sqi2 && sqi2->GetNumberOfItems()) ) return false;
gdcm_assert( sqi2 && sqi2->GetNumberOfItems() );
const Item &item2 = sqi2->GetItem(1);
const DataSet & subds2 = item2.GetNestedDataSet();
const Tag tps(0x0020,0x0037);
if( !subds2.FindDataElement(tps) ) return false;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0020,0x0037> at;
at.SetFromDataElement( de );
dircos.push_back( at.GetValue(0) );
dircos.push_back( at.GetValue(1) );
dircos.push_back( at.GetValue(2) );
dircos.push_back( at.GetValue(3) );
dircos.push_back( at.GetValue(4) );
dircos.push_back( at.GetValue(5) );
return true;
}
static bool GetInterceptSlopeValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector<double> &intslope)
{
intslope.clear();
if( !ds.FindDataElement( tfgs ) ) return false;
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false;
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0028,0x9145);
if( !subds.FindDataElement(tpms) ) return false;
SmartPointer<SequenceOfItems> sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ();
gdcm_assert( sqi2 );
const Item &item2 = sqi2->GetItem(1);
const DataSet & subds2 = item2.GetNestedDataSet();
double intercept;
{
const Tag tps(0x0028,0x1052);
if( !subds2.FindDataElement(tps) ) return false;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0028,0x1052> at;
at.SetFromDataElement( de );
intercept = at.GetValue();
}
double slope;
{
const Tag tps(0x0028,0x1053);
if( !subds2.FindDataElement(tps) ) return false;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0028,0x1053> at;
at.SetFromDataElement( de );
slope = at.GetValue();
}
intslope.push_back( intercept );
intslope.push_back( slope );
gdcm_assert( intslope.size() == 2 );
return true;
}
static bool ComputeZSpacingFromIPP(const DataSet &ds, double &zspacing)
{
const Tag t1(0x5200,0x9229);
const Tag t2(0x5200,0x9230);
std::vector<double> cosines;
bool b1 = GetDirectionCosinesValueFromSequence(ds, t1, cosines)
|| GetDirectionCosinesValueFromSequence(ds,t2,cosines);
if(!b1)
{
cosines.resize( 6 );
bool b2 = ImageHelper::GetDirectionCosinesFromDataSet(ds, cosines);
if( b2 )
{
gdcmWarningMacro( "Image Orientation (Patient) cannot be stored here!. Continuing" );
b1 = b2;
}
else
{
gdcmErrorMacro( "Image Orientation (Patient) was not found" );
cosines[0] = 1;
cosines[1] = 0;
cosines[2] = 0;
cosines[3] = 0;
cosines[4] = 1;
cosines[5] = 0;
}
}
gdcm_assert( b1 && cosines.size() == 6 );
const Tag tfgs(0x5200,0x9230);
if( !ds.FindDataElement( tfgs ) ) return false;
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
if( !sqi ) return false;
gdcm_assert( sqi );
double normal[3];
DirectionCosines dc( cosines.data() );
dc.Cross( normal );
DirectionCosines::Normalize(normal);
SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems();
if( nitems > 1 ) {
std::vector<double> dircos_subds2; dircos_subds2.resize(6);
std::vector<double> distances;
std::set<double> unique_distances;
for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0)
{
const Item &item = sqi->GetItem(i0);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0020,0x9113);
if( !subds.FindDataElement(tpms) ) return false;
SmartPointer<SequenceOfItems> sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ();
gdcm_assert( sqi2 );
const Item &item2 = sqi2->GetItem(1);
const DataSet & subds2 = item2.GetNestedDataSet();
if( ImageHelper::GetDirectionCosinesFromDataSet(subds2, dircos_subds2) )
{
gdcm_assert( dircos_subds2 == cosines );
}
const Tag tps(0x0020,0x0032);
if( !subds2.FindDataElement(tps) ) return false;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0020,0x0032> ipp;
ipp.SetFromDataElement(de);
double dist = 0;
for (int i = 0; i < 3; ++i) dist += normal[i]*ipp[i];
distances.push_back( dist );
unique_distances.insert(dist);
}
gdcm_assert( distances.size() == nitems );
if( unique_distances.size() != distances.size() )
{
if( distances.size() % distances.size() == 0 )
{
if( distances[0] == *unique_distances.begin() )
{
distances.assign(unique_distances.begin(), unique_distances.end());
nitems = unique_distances.size();
}
}
}
double meanspacing = 0;
double prev = distances[0];
for(unsigned int i = 1; i < nitems; ++i)
{
const double current = distances[i] - prev;
meanspacing += current;
prev = distances[i];
}
bool timeseries = false;
if( nitems > 1 )
{
meanspacing /= (double)(nitems - 1);
if( meanspacing == 0.0 )
{
gdcmWarningMacro( "Assuming time series for Z-spacing" );
meanspacing = 1.0;
timeseries = true;
}
}
zspacing = meanspacing;
if( nitems > 1 )
gdcm_assert( zspacing != 0.0 );
if( !timeseries )
{
const double ZTolerance = 1e-3; prev = distances[0];
for(unsigned int i = 1; i < nitems; ++i)
{
const double current = distances[i] - prev;
if( fabs(current - zspacing) > ZTolerance )
{
gdcmDebugMacro( "This Enhanced Multiframe is not supported for now: " << i << " gives " << fabs(current - zspacing) );
zspacing = 1.0;
return false;
}
prev = distances[i];
}
}
} else {
zspacing = 1.0;
const Tag tfgs0(0x5200,0x9229);
if( !ds.FindDataElement( tfgs0 ) ) return true;
SmartPointer<SequenceOfItems> sqi0 = ds.GetDataElement( tfgs0 ).GetValueAsSQ();
if( !(sqi0 && sqi0->GetNumberOfItems() > 0) ) return true;
const Item &item = sqi0->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0028,0x9110);
if( !subds.FindDataElement(tpms) ) return true;
SmartPointer<SequenceOfItems> sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ();
gdcm_assert( sqi2 );
const Item &item2 = sqi2->GetItem(1);
const DataSet & subds2 = item2.GetNestedDataSet();
const Tag tps(0x0018,0x0088);
if( !subds2.FindDataElement(tps) ) return true;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0018,0x0088> at;
at.SetFromDataElement( de );
zspacing = at.GetValue();
}
return true;
}
static bool GetSpacingValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector<double> &sp)
{
if( !ds.FindDataElement( tfgs ) ) return false;
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false;
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0028,0x9110);
if( !subds.FindDataElement(tpms) ) return false;
SmartPointer<SequenceOfItems> sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ();
gdcm_assert( sqi2 );
const Item &item2 = sqi2->GetItem(1);
const DataSet & subds2 = item2.GetNestedDataSet();
const Tag tps(0x0028,0x0030);
if( !subds2.FindDataElement(tps) ) return false;
const DataElement &de = subds2.GetDataElement( tps );
Attribute<0x0028,0x0030> at;
at.SetFromDataElement( de );
sp.push_back( at.GetValue(1) );
sp.push_back( at.GetValue(0) );
#if 0#endif
double zspacing;
bool b = ComputeZSpacingFromIPP(ds, zspacing);
if( !b ) return false;
sp.push_back( zspacing );
return true;
}
static SmartPointer<SequenceOfItems> InsertOrReplaceSQ( DataSet & ds, const Tag &tag )
{
SmartPointer<SequenceOfItems> sqi;
if( !ds.FindDataElement( tag ) )
{
sqi = new SequenceOfItems;
DataElement de( tag );
de.SetVR( VR::SQ );
de.SetValue( *sqi );
gdcm_assert( de.GetVL().IsUndefined() );
de.SetVLToUndefined();
ds.Insert( de );
}
sqi = ds.GetDataElement( tag ).GetValueAsSQ();
sqi->SetLengthToUndefined();
DataElement de_dup = ds.GetDataElement( tag );
de_dup.SetValue( *sqi );
ds.Replace( de_dup );
return sqi;
}
static bool GetUltraSoundSpacingValueFromSequence(const DataSet& ds, std::vector<double> &sp)
{
const Tag tsqusreg(0x0018,0x6011);
if( !ds.FindDataElement( tsqusreg ) ) return false;
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tsqusreg ).GetValueAsSQ();
if( !sqi ) return false;
gdcm_assert( sqi );
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
Attribute<0x0018,0x602c> at1;
Attribute<0x0018,0x602e> at2;
const DataElement &de1 = subds.GetDataElement( at1.GetTag() );
at1.SetFromDataElement( de1 );
gdcm_assert( at1.GetNumberOfValues() == 1 );
const DataElement &de2 = subds.GetDataElement( at2.GetTag() );
at2.SetFromDataElement( de2 );
gdcm_assert( at2.GetNumberOfValues() == 1 );
sp.push_back( at1.GetValue() );
sp.push_back( at2.GetValue() );
return true;
}
static void SetUltraSoundSpacingValueFromSequence(DataSet& ds, std::vector<double> const &spacing)
{
const Tag tsqusreg(0x0018,0x6011);
SmartPointer<SequenceOfItems> sqi = InsertOrReplaceSQ( ds, tsqusreg);
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item1 = sqi->GetItem(1);
item1.SetVLToUndefined();
DataSet &subds = item1.GetNestedDataSet();
Attribute<0x0018,0x602c> at1;
at1.SetValue( spacing[0] );
Attribute<0x0018,0x602e> at2;
at2.SetValue( spacing[1] );
subds.Replace( at1.GetAsDataElement() );
subds.Replace( at2.GetAsDataElement() );
}
std::vector<double> ImageHelper::GetOriginValue(File const & f)
{
std::vector<double> ori;
MediaStorage ms;
ms.SetFromFile(f);
const DataSet& ds = f.GetDataSet();
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::OphthalmicTomographyImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
const Tag t1(0x5200,0x9229);
const Tag t2(0x5200,0x9230);
if( GetOriginValueFromSequence(ds,t1, ori)
|| GetOriginValueFromSequence(ds, t2, ori) )
{
gdcm_assert( ori.size() == 3 );
return ori;
}
ori.resize( 3 );
gdcmWarningMacro( "Could not find Origin" );
return ori;
}
if( ms == MediaStorage::NuclearMedicineImageStorage )
{
const Tag t1(0x0054,0x0022);
if( ds.FindDataElement( t1 ) )
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( t1 ).GetValueAsSQ();
if( sqi && sqi->GetNumberOfItems() >= 1)
{
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag timagepositionpatient(0x0020, 0x0032);
gdcm_assert( subds.FindDataElement( timagepositionpatient ) );
Attribute<0x0020,0x0032> at = {{0,0,0}}; at.SetFromDataSet( subds );
ori.resize( at.GetNumberOfValues() );
for( unsigned int i = 0; i < at.GetNumberOfValues(); ++i )
{
ori[i] = at.GetValue(i);
}
return ori;
}
}
ori.resize( 3 );
gdcmWarningMacro( "Could not find Origin" );
return ori;
}
ori.resize( 3 );
const Tag timagepositionpatient(0x0020, 0x0032);
if( (ms != MediaStorage::SecondaryCaptureImageStorage || SecondaryCaptureImagePlaneModule) && ds.FindDataElement( timagepositionpatient ) )
{
const DataElement& de = ds.GetDataElement( timagepositionpatient );
Attribute<0x0020,0x0032> at = {{0,0,0}}; at.SetFromDataElement( de );
for( unsigned int i = 0; i < at.GetNumberOfValues(); ++i )
{
ori[i] = at.GetValue(i);
}
}
else
{
ori[0] = 0;
ori[1] = 0;
ori[2] = 0;
}
gdcm_assert( ori.size() == 3 );
return ori;
}
bool ImageHelper::GetDirectionCosinesFromDataSet(DataSet const & ds, std::vector<double> & dircos)
{
const Tag timageorientationpatient(0x0020, 0x0037);
if( ds.FindDataElement( timageorientationpatient ) )
{
const DataElement& de = ds.GetDataElement( timageorientationpatient );
Attribute<0x0020,0x0037> at = {{1,0,0,0,1,0}}; at.SetFromDataElement( de );
for( unsigned int i = 0; i < at.GetNumberOfValues(); ++i )
{
dircos[i] = at.GetValue(i);
}
DirectionCosines dc( dircos.data() );
if( !dc.IsValid() )
{
dc.Normalize();
if( dc.IsValid() )
{
gdcmWarningMacro( "DirectionCosines was not normalized. Fixed" );
const double * p = dc;
dircos = std::vector<double>(p, p + 6);
}
else
{
gdcmWarningMacro( "Could not get DirectionCosines. Will be set to unit vector." );
return false;
}
}
return true;
}
return false;
}
std::vector<double> ImageHelper::GetDirectionCosinesValue(File const & f)
{
std::vector<double> dircos;
MediaStorage ms;
ms.SetFromFile(f);
const DataSet& ds = f.GetDataSet();
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
const Tag t1(0x5200,0x9229);
const Tag t2(0x5200,0x9230);
if( GetDirectionCosinesValueFromSequence(ds,t1, dircos)
|| GetDirectionCosinesValueFromSequence(ds, t2, dircos) )
{
gdcm_assert( dircos.size() == 6 );
return dircos;
}
else
{
dircos.resize( 6 );
bool b2 = ImageHelper::GetDirectionCosinesFromDataSet(ds, dircos);
if( b2 )
{
gdcmWarningMacro( "Image Orientation (Patient) cannot be stored here!. Continuing" );
}
else
{
gdcmErrorMacro( "Image Orientation (Patient) was not found" );
dircos[0] = 1;
dircos[1] = 0;
dircos[2] = 0;
dircos[3] = 0;
dircos[4] = 1;
dircos[5] = 0;
}
return dircos;
}
}
if( ms == MediaStorage::NuclearMedicineImageStorage )
{
const Tag t1(0x0054,0x0022);
if( ds.FindDataElement( t1 ) )
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( t1 ).GetValueAsSQ();
if( sqi && sqi->GetNumberOfItems() >= 1 )
{
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
dircos.resize( 6 );
bool b2 = ImageHelper::GetDirectionCosinesFromDataSet(subds, dircos);
if( b2 )
{
}
else
{
gdcmErrorMacro( "Image Orientation (Patient) was not found" );
dircos[0] = 1;
dircos[1] = 0;
dircos[2] = 0;
dircos[3] = 0;
dircos[4] = 1;
dircos[5] = 0;
}
return dircos;
}
}
}
dircos.resize( 6 );
if( (ms == MediaStorage::SecondaryCaptureImageStorage && !SecondaryCaptureImagePlaneModule) || !GetDirectionCosinesFromDataSet(ds, dircos) )
{
dircos[0] = 1;
dircos[1] = 0;
dircos[2] = 0;
dircos[3] = 0;
dircos[4] = 1;
dircos[5] = 0;
}
gdcm_assert( dircos.size() == 6 );
return dircos;
}
void ImageHelper::SetForceRescaleInterceptSlope(bool b)
{
ForceRescaleInterceptSlope = b;
}
bool ImageHelper::GetForceRescaleInterceptSlope()
{
return ForceRescaleInterceptSlope;
}
void ImageHelper::SetPMSRescaleInterceptSlope(bool b)
{
PMSRescaleInterceptSlope = b;
}
bool ImageHelper::GetPMSRescaleInterceptSlope()
{
return PMSRescaleInterceptSlope;
}
void ImageHelper::SetForcePixelSpacing(bool b)
{
ForcePixelSpacing = b;
}
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;
bool intercept = ds.FindDataElement(at1.GetTag());
if( intercept )
{
if( !ds.GetDataElement(at1.GetTag()).IsEmpty() )
{
at1.SetFromDataElement( ds.GetDataElement(at1.GetTag()) );
interceptslope[0] = at1.GetValue();
}
}
Attribute<0x0028,0x1053> at2;
bool slope = ds.FindDataElement(at2.GetTag());
if ( slope )
{
if( !ds.GetDataElement(at2.GetTag()).IsEmpty() )
{
at2.SetFromDataElement( ds.GetDataElement(at2.GetTag()) );
interceptslope[1] = at2.GetValue();
if( interceptslope[1] == 0 )
{
gdcmDebugMacro( "Cannot have slope == 0. Defaulting to 1.0 instead" );
interceptslope[1] = 1;
}
}
}
return intercept || slope;
}
PixelFormat ImageHelper::GetPixelFormatValue(const File& f)
{
PixelFormat pf;
const DataSet& ds = f.GetDataSet();
{
Attribute<0x0028,0x0100> at = { 0 };
at.SetFromDataSet( ds );
pf.SetBitsAllocated( at.GetValue() );
}
{
Attribute<0x0028,0x0101> at = { 0 };
at.SetFromDataSet( ds );
pf.SetBitsStored( at.GetValue() );
}
{
Attribute<0x0028,0x0102> at = { 0 };
at.SetFromDataSet( ds );
pf.SetHighBit( at.GetValue() );
}
{
Attribute<0x0028,0x0103> at = { 0 };
at.SetFromDataSet( ds );
pf.SetPixelRepresentation( at.GetValue() );
}
{
{
Attribute<0x0028,0x0002> at = { 1 };
at.SetFromDataSet( ds );
pf.SetSamplesPerPixel( at.GetValue() );
}
}
return pf;
}
std::vector<unsigned int> ImageHelper::GetDimensionsValue(const File& f)
{
DataSet const & ds = f.GetDataSet();
MediaStorage ms;
ms.SetFromFile(f);
std::vector<unsigned int> theReturn(3);
#if 0#endif
{
{
Attribute<0x0028,0x0011> at = { 0 }; at.SetFromDataSet( ds );
theReturn[0] = at.GetValue();
}
{
Attribute<0x0028,0x0010> at = { 0 }; at.SetFromDataSet( ds );
theReturn[1] = at.GetValue();
}
{
Attribute<0x0028,0x0008> at = { 0 };
at.SetFromDataSet( ds );
int numberofframes = at.GetValue();
theReturn[2] = 1;
if( numberofframes > 1 )
{
theReturn[2] = at.GetValue();
}
}
{
Attribute<0x0028,0x0005> at = { 0 };
if( ds.FindDataElement( at.GetTag() ) )
{
const DataElement &de = ds.GetDataElement( at.GetTag() );
if( at.GetVR().Compatible( de.GetVR() ) )
{
at.SetFromDataSet( ds );
int imagedimensions = at.GetValue();
if( imagedimensions == 3 )
{
Attribute<0x0028,0x0012> at2 = { 0 };
at2.SetFromDataSet( ds );
theReturn[2] = at2.GetValue();
}
}
else
{
gdcmWarningMacro( "Sorry cannot read attribute (wrong VR): " << at.GetTag() );
}
}
}
}
return theReturn;
}
void ImageHelper::SetDimensionsValue(File& f, const Pixmap & img)
{
const unsigned int *dims = img.GetDimensions();
MediaStorage ms;
ms.SetFromFile(f);
DataSet& ds = f.GetDataSet();
if (!MediaStorage::IsImage(ms)) {
gdcmWarningMacro("Wrong SOP Class");
}
{
Attribute<0x0028,0x0010> rows;
rows.SetValue( (uint16_t)dims[1] );
ds.Replace( rows.GetAsDataElement() );
Attribute<0x0028,0x0011> columns;
columns.SetValue( (uint16_t)dims[0] );
ds.Replace( columns.GetAsDataElement() );
Attribute<0x0028,0x0008> numframes = { 0 };
numframes.SetValue( dims[2] );
if( img.GetNumberOfDimensions() == 3 && dims[2] >= 1 )
{
if( ms.MediaStorage::GetModalityDimension() > 2 )
ds.Replace( numframes.GetAsDataElement() );
else if( ms.MediaStorage::GetModalityDimension() == 2 && dims[2] == 1 )
ds.Remove( numframes.GetTag() );
else
{
gdcmErrorMacro( "MediaStorage does not allow 3rd dimension. But value is: " << dims[2] );
gdcmAssertAlwaysMacro( "Could not set third dimension" );
}
}
else if( img.GetNumberOfDimensions() == 2 && dims[2] == 1 )
{
if (ms.MediaStorage::GetModalityDimension() > 2)
{
if( ms == MediaStorage::XRayAngiographicImageStorage )
{
ds.Remove(numframes.GetTag());
}
else
{
ds.Replace(numframes.GetAsDataElement());
}
}
else if( ms.MediaStorage::GetModalityDimension() == 2 )
ds.Remove( numframes.GetTag() );
}
else ds.Remove( numframes.GetTag() );
}
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
const Tag tfgs(0x5200,0x9230);
if( ds.FindDataElement( tfgs ) )
{
const DataElement &de = ds.GetDataElement( tfgs );
SmartPointer<SequenceOfItems> sqi = de.GetValueAsSQ();
gdcm_assert( sqi );
sqi->SetNumberOfItems( dims[2] );
{
DataElement dup(de.GetTag());
dup.SetVR(VR::SQ);
dup.SetValue(*sqi);
dup.SetVLToUndefined();
ds.Replace(dup);
}
}
}
}
static double fd2ds(const double d)
{
Element<VR::DS,VM::VM1> in = {{ 0 }};
in.SetValue( d );
std::stringstream ss;
in.Write( ss );
Element<VR::DS,VM::VM1> out = {{ 0 }};
out.Read( ss );
return out.GetValue();
}
std::vector<double> ImageHelper::GetRescaleInterceptSlopeValue(File const & f)
{
std::vector<double> interceptslope;
MediaStorage ms;
ms.SetFromFile(f);
const DataSet& ds = f.GetDataSet();
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
const Tag t1(0x5200,0x9229);
const Tag t2(0x5200,0x9230);
if( GetInterceptSlopeValueFromSequence(ds,t1, interceptslope)
|| GetInterceptSlopeValueFromSequence(ds,t2, interceptslope) )
{
gdcm_assert( interceptslope.size() == 2 );
return interceptslope;
}
if (ms == MediaStorage::XRay3DAngiographicImageStorage && ForceRescaleInterceptSlope)
{
const Tag t3(0x0018,0x9530);
if(ds.FindDataElement( t3 ))
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( t3 ).GetValueAsSQ();
if(sqi && sqi->GetNumberOfItems() > 0)
{
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
const Tag tpi(0x0028,0x1052);
const Tag tps(0x0028,0x1053);
if( subds.FindDataElement(tps) && subds.FindDataElement(tpi))
{
const DataElement &dei = subds.GetDataElement( tpi );
Attribute<0x0028,0x1052> ati;
ati.SetFromDataElement( dei );
interceptslope.push_back( ati.GetValue() );
const DataElement &des = subds.GetDataElement( tps );
Attribute<0x0028,0x1053> ats;
ats.SetFromDataElement( des );
interceptslope.push_back( ats.GetValue() );
return interceptslope;
}
}
}
}
}
interceptslope.resize( 2 );
interceptslope[0] = 0;
interceptslope[1] = 1;
if( ms == MediaStorage::CTImageStorage
|| ms == MediaStorage::ComputedRadiographyImageStorage
|| ms == MediaStorage::PETImageStorage
|| ms == MediaStorage::SecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ForceRescaleInterceptSlope
)
{
bool b = GetRescaleInterceptSlopeValueFromDataSet(ds, interceptslope);
if( !b )
{
gdcmDebugMacro( "No Modality LUT found (Rescale Intercept/Slope)" );
}
}
else if ( ms == MediaStorage::MRImageStorage )
{
#if 0#else
const PrivateTag tpriv_rescaleintercept( 0x2005,0x09,"Philips MR Imaging DD 005" );
const PrivateTag tpriv_rescaleslope( 0x2005,0x0a,"Philips MR Imaging DD 005" );
if( ds.FindDataElement( tpriv_rescaleintercept ) && ds.FindDataElement( tpriv_rescaleslope ) )
{
const DataElement &priv_rescaleintercept = ds.GetDataElement( tpriv_rescaleintercept );
const DataElement &priv_rescaleslope = ds.GetDataElement( tpriv_rescaleslope );
Element<VR::DS,VM::VM1> el_ri = {{ 0 }};
el_ri.SetFromDataElement( priv_rescaleintercept );
Element<VR::DS,VM::VM1> el_rs = {{ 1 }};
el_rs.SetFromDataElement( priv_rescaleslope );
if( PMSRescaleInterceptSlope )
{
interceptslope[0] = el_ri.GetValue();
interceptslope[1] = el_rs.GetValue();
if( interceptslope[1] == 0 )
interceptslope[1] = 1;
gdcmDebugMacro( "PMS Modality LUT loaded for MR Image Storage: [" << interceptslope[0] << "," << interceptslope[1] << "]" );
}
}
else
{
std::vector<double> dummy(2);
if( GetRescaleInterceptSlopeValueFromDataSet(ds, dummy) )
{
if(dummy[0] != 0 || dummy[1] != 1) {
interceptslope[0] = dummy[0];
interceptslope[1] = dummy[1];
gdcmDebugMacro( "Forcing Modality LUT used for MR Image Storage: [" << dummy[0] << "," << dummy[1] << "]" );
}
}
else
{
const Tag trwvms(0x0040,0x9096); if( ds.FindDataElement( trwvms ) )
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( trwvms ).GetValueAsSQ();
if( sqi )
{
const Tag trwvlutd(0x0040,0x9212); if( ds.FindDataElement( trwvlutd ) )
{
gdcmAssertAlwaysMacro(0); }
gdcmAssertAlwaysMacro( sqi->GetNumberOfItems() == 1 );
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
Attribute<0x0040,0x9224> at1 = {0};
at1.SetFromDataSet( subds );
Attribute<0x0040,0x9225> at2 = {1};
at2.SetFromDataSet( subds );
interceptslope[0] = fd2ds(at1.GetValue());
interceptslope[1] = fd2ds(at2.GetValue());
}
}
}
}
#endif
}
else if (
ms == MediaStorage::RTDoseStorage
)
{
Attribute<0x3004,0x000e> gridscaling = { 0 };
gridscaling.SetFromDataSet( ds );
interceptslope[0] = 0;
interceptslope[1] = gridscaling.GetValue();
if( interceptslope[1] == 0 )
{
gdcmWarningMacro( "Cannot have slope == 0. Defaulting to 1.0 instead" );
interceptslope[1] = 1;
}
}
gdcm_assert( interceptslope[1] != 0. );
return interceptslope;
}
Tag ImageHelper::GetSpacingTagFromMediaStorage(MediaStorage const &ms)
{
Tag t;
switch(ms)
{
case MediaStorage::EnhancedUSVolumeStorage:
case MediaStorage::CTImageStorage:
case MediaStorage::MRImageStorage:
case MediaStorage::RTDoseStorage:
case MediaStorage::NuclearMedicineImageStorage:
case MediaStorage::PETImageStorage:
case MediaStorage::GeneralElectricMagneticResonanceImageStorage:
case MediaStorage::PhilipsPrivateMRSyntheticImageStorage:
case MediaStorage::VLPhotographicImageStorage: case MediaStorage::VLMicroscopicImageStorage:
case MediaStorage::IVOCTForProcessing:
case MediaStorage::IVOCTForPresentation:
t = Tag(0x0028,0x0030);
break;
case MediaStorage::ComputedRadiographyImageStorage: case MediaStorage::DigitalXRayImageStorageForPresentation:
case MediaStorage::DigitalXRayImageStorageForProcessing:
case MediaStorage::DigitalMammographyImageStorageForPresentation:
case MediaStorage::DigitalMammographyImageStorageForProcessing:
case MediaStorage::DigitalIntraoralXrayImageStorageForPresentation:
case MediaStorage::DigitalIntraoralXRayImageStorageForProcessing:
case MediaStorage::XRayAngiographicImageStorage:
case MediaStorage::XRayRadiofluoroscopingImageStorage:
case MediaStorage::XRayAngiographicBiPlaneImageStorageRetired:
case MediaStorage::FujiPrivateMammoCRImageStorage:
t = Tag(0x0018,0x1164);
break;
case MediaStorage::RTImageStorage: t = Tag(0x3002,0x0011); break;
case MediaStorage::SecondaryCaptureImageStorage:
if( ImageHelper::SecondaryCaptureImagePlaneModule ) {
gdcmDebugMacro( "FIXME: Multiple tags can identify Secondary Capture spacing. This function should not be used for Secondary Capture data." );
t = Tag(0x0028,0x0030);
} else {
t = Tag(0x0018,0x2010);
}
break;
case MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage:
case MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage:
case MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage:
case MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage:
t = Tag(0x0018,0x2010);
break;
case MediaStorage::HardcopyGrayscaleImageStorage:
case MediaStorage::HardcopyColorImageStorage:
t = Tag(0x0018,0x2010); break;
case MediaStorage::GEPrivate3DModelStorage: case MediaStorage::Philips3D:
case MediaStorage::VideoEndoscopicImageStorage:
gdcmWarningMacro( "FIXME" );
t = Tag(0xffff,0xffff);
break;
case MediaStorage::UltrasoundMultiFrameImageStorage:
gdcmWarningMacro( "FIXME" );
t = Tag(0xffff,0xffff);
break;
case MediaStorage::UltrasoundImageStorage: case MediaStorage::UltrasoundImageStorageRetired:
case MediaStorage::UltrasoundMultiFrameImageStorageRetired:
t = Tag(0xffff,0xffff); t = Tag(0x0028,0x0034); break;
default:
gdcmDebugMacro( "Do not handle: " << ms );
t = Tag(0xffff,0xffff);
break;
}
if( ForcePixelSpacing && t == Tag(0xffff,0xffff) )
{
t = Tag(0x0028,0x0030);
}
return t;
}
Tag ImageHelper::GetZSpacingTagFromMediaStorage(MediaStorage const &ms)
{
Tag t;
switch(ms)
{
case MediaStorage::EnhancedUSVolumeStorage:
case MediaStorage::MRImageStorage:
case MediaStorage::NuclearMedicineImageStorage: case MediaStorage::GeneralElectricMagneticResonanceImageStorage:
t = Tag(0x0018,0x0088);
break;
case MediaStorage::PETImageStorage: case MediaStorage::CTImageStorage:
case MediaStorage::RTImageStorage:
case MediaStorage::ComputedRadiographyImageStorage: case MediaStorage::DigitalXRayImageStorageForPresentation:
case MediaStorage::DigitalXRayImageStorageForProcessing:
case MediaStorage::DigitalMammographyImageStorageForPresentation:
case MediaStorage::DigitalMammographyImageStorageForProcessing:
case MediaStorage::DigitalIntraoralXrayImageStorageForPresentation:
case MediaStorage::DigitalIntraoralXRayImageStorageForProcessing:
case MediaStorage::XRayAngiographicImageStorage:
case MediaStorage::XRayRadiofluoroscopingImageStorage:
case MediaStorage::XRayAngiographicBiPlaneImageStorageRetired:
case MediaStorage::UltrasoundImageStorage:
case MediaStorage::UltrasoundMultiFrameImageStorage:
case MediaStorage::UltrasoundImageStorageRetired:
case MediaStorage::UltrasoundMultiFrameImageStorageRetired:
case MediaStorage::SecondaryCaptureImageStorage:
if( ImageHelper::SecondaryCaptureImagePlaneModule ) {
t = Tag(0x0018,0x0088);
} else {
t = Tag(0xffff,0xffff);
}
break;
case MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage:
case MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage:
case MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage:
case MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage:
case MediaStorage::HardcopyGrayscaleImageStorage:
t = Tag(0xffff,0xffff);
break;
case MediaStorage::RTDoseStorage: t = Tag(0x3004,0x000c);
break;
case MediaStorage::GEPrivate3DModelStorage:
case MediaStorage::Philips3D:
case MediaStorage::VideoEndoscopicImageStorage:
gdcmWarningMacro( "FIXME" );
t = Tag(0xffff,0xffff);
break;
default:
gdcmDebugMacro( "Do not handle Z spacing for: " << ms );
t = Tag(0xffff,0xffff);
break;
}
if( ForcePixelSpacing && t == Tag(0xffff,0xffff) )
{
t = Tag(0x0018,0x0088);
}
return t;
}
std::vector<double> ImageHelper::GetSpacingValue(File const & f)
{
std::vector<double> sp;
sp.reserve(3);
MediaStorage ms;
ms.SetFromFile(f);
const DataSet& ds = f.GetDataSet();
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::OphthalmicTomographyImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage)
{
const Tag t1(0x5200,0x9229);
const Tag t2(0x5200,0x9230);
if( GetSpacingValueFromSequence(ds,t1, sp)
|| GetSpacingValueFromSequence(ds, t2, sp) )
{
gdcm_assert( sp.size() == 3 );
return sp;
}
sp.resize( 3 ); sp[0] = 1.;
sp[1] = 1.;
sp[2] = 1.;
gdcmWarningMacro( "Could not find Spacing" );
return sp;
}
else if( ms == MediaStorage::UltrasoundMultiFrameImageStorage || ms == MediaStorage::UltrasoundImageStorage )
{
if( GetUltraSoundSpacingValueFromSequence(ds, sp) )
{
sp.push_back( 1.0 );
return sp;
}
else
{
gdcmWarningMacro( "No spacing value found" );
sp.push_back( 1.0 );
sp.push_back( 1.0 );
sp.push_back( 1.0 );
return sp;
}
}
Tag spacingtag = Tag(0xffff,0xffff);
if( ms == MediaStorage::SecondaryCaptureImageStorage && SecondaryCaptureImagePlaneModule )
{
if( ds.FindDataElement( Tag(0x0028,0x0030) ) )
{
spacingtag = Tag(0x0028,0x0030);
}
else if( ds.FindDataElement( Tag(0x0018,0x2010) ) )
{
spacingtag = Tag(0x0018,0x2010);
}
}
else
{
spacingtag = GetSpacingTagFromMediaStorage(ms);
}
if( spacingtag != Tag(0xffff,0xffff) && ds.FindDataElement( spacingtag ) && !ds.GetDataElement( spacingtag ).IsEmpty() )
{
const DataElement& de = ds.GetDataElement( spacingtag );
const Global &g = GlobalInstance;
const Dicts &dicts = g.GetDicts();
const DictEntry &entry = dicts.GetDictEntry(de.GetTag());
const VR & vr = entry.GetVR();
gdcm_assert( vr.Compatible( de.GetVR() ) );
switch(vr)
{
case VR::DS:
{
Element<VR::DS,VM::VM1_n> el;
std::stringstream ss;
const ByteValue *bv = de.GetByteValue();
gdcm_assert( bv );
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
el.SetLength( entry.GetVM().GetLength() * entry.GetVR().GetSizeof() );
std::string::size_type found = s.find('\\');
if( found != std::string::npos )
{
el.Read( ss );
gdcm_assert( el.GetLength() == 2 );
for(unsigned int i = 0; i < el.GetLength(); ++i)
{
if( el.GetValue(i) )
{
sp.push_back( el.GetValue(i) );
}
else
{
gdcmWarningMacro( "Cannot have a spacing of 0" );
sp.push_back( 1.0 );
}
}
std::swap( sp[0], sp[1]);
}
else
{
double singleval;
ss >> singleval;
if( singleval == 0.0 )
{
singleval = 1.0;
}
sp.push_back( singleval );
sp.push_back( singleval );
}
gdcm_assert( sp.size() == (unsigned int)entry.GetVM() );
}
break;
case VR::IS:
{
Element<VR::IS,VM::VM1_n> el;
std::stringstream ss;
const ByteValue *bv = de.GetByteValue();
gdcm_assert( bv );
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
el.SetLength( entry.GetVM().GetLength() * entry.GetVR().GetSizeof() );
el.Read( ss );
for(unsigned int i = 0; i < el.GetLength(); ++i)
{
if( el.GetValue(i) )
sp.push_back( el.GetValue(i) );
else
{
gdcmWarningMacro( "Cannot have a spacing of 0" );
sp.push_back( 1.0 );
}
}
std::swap( sp[0], sp[1]);
gdcm_assert( sp.size() == (unsigned int)entry.GetVM() );
}
break;
default:
gdcm_assert(0);
break;
}
}
else
{
sp.push_back( 1.0 );
sp.push_back( 1.0 );
}
gdcm_assert( sp.size() == 2 );
std::vector<unsigned int> dims = ImageHelper::GetDimensionsValue( f );
Tag zspacingtag = ImageHelper::GetZSpacingTagFromMediaStorage(ms);
if( zspacingtag != Tag(0xffff,0xffff) && ds.FindDataElement( zspacingtag ) )
{
const DataElement& de = ds.GetDataElement( zspacingtag );
if( de.IsEmpty() )
{
sp.push_back( 1.0 );
}
else
{
const Global &g = GlobalInstance;
const Dicts &dicts = g.GetDicts();
const DictEntry &entry = dicts.GetDictEntry(de.GetTag());
const VR & vr = entry.GetVR();
gdcm_assert( de.GetVR() == vr || de.GetVR() == VR::INVALID || de.GetVR() == VR::UN );
if( entry.GetVM() == VM::VM1 )
{
switch(vr)
{
case VR::DS:
{
Element<VR::DS,VM::VM1_n> el;
std::stringstream ss;
const ByteValue *bv = de.GetByteValue();
gdcm_assert( bv );
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
el.SetLength( entry.GetVM().GetLength() * entry.GetVR().GetSizeof() );
el.Read( ss );
for(unsigned int i = 0; i < el.GetLength(); ++i)
{
const double value = el.GetValue(i);
sp.push_back( value );
}
}
break;
default:
gdcm_assert(0);
break;
}
}
else
{
gdcm_assert( entry.GetVM() == VM::VM2_n );
gdcm_assert( vr == VR::DS );
Attribute<0x28,0x8> numberoframes;
const DataElement& de1 = ds.GetDataElement( numberoframes.GetTag() );
numberoframes.SetFromDataElement( de1 );
Attribute<0x3004,0x000c> gridframeoffsetvector;
const DataElement& de2 = ds.GetDataElement( gridframeoffsetvector.GetTag() );
gridframeoffsetvector.SetFromDataElement( de2 );
double v1 = gridframeoffsetvector[0];
double v2 = gridframeoffsetvector[1];
sp.push_back( v2 - v1 );
}
}
}
else if( ds.FindDataElement( Tag(0x0028,0x0009) ) ) {
const DataElement& de = ds.GetDataElement( Tag(0x0028,0x0009) );
Attribute<0x0028,0x0009,VR::AT,VM::VM1> at;
at.SetFromDataElement( de );
gdcm_assert( ds.FindDataElement( at.GetTag() ) );
if( ds.FindDataElement( at.GetValue() ) )
{
const DataElement& de2 = ds.GetDataElement( at.GetValue() );
if( at.GetValue() == Tag(0x0018,0x1063) && at.GetNumberOfValues() == 1 )
{
Attribute<0x0018,0x1063> at2;
at2.SetFromDataElement( de2 );
if( dims[2] > 1 )
{
sp.push_back( at2.GetValue() );
}
else
{
if( at2.GetValue() != 0. )
{
gdcmErrorMacro( "Frame time for a single frame image should equal to 0, but found "<< at.GetValue() << ". Default to 1.0.");
}
sp.push_back( 1.0 );
}
}
else
{
gdcmWarningMacro( "Don't know how to handle spacing for: " << de );
sp.push_back( 1.0 );
}
}
else
{
gdcmErrorMacro( "Tag: " << at.GetTag() << " was found to point to missing"
"Tag: " << at.GetValue() << " default to 1.0." );
sp.push_back( 1.0 );
}
}
else
{
sp.push_back( 1.0 );
}
gdcm_assert( sp.size() == 3 );
gdcm_assert( sp[0] != 0. );
gdcm_assert( sp[1] != 0. );
return sp;
}
void ImageHelper::SetSpacingValue(DataSet & ds, const std::vector<double> & spacing)
{
MediaStorage ms;
ms.SetFromDataSet(ds);
if (!MediaStorage::IsImage(ms)) {
gdcmWarningMacro("Wrong SOP Class");
}
if( ms == MediaStorage::SecondaryCaptureImageStorage )
{
Tag pixelspacing(0x0028,0x0030);
Tag imagerpixelspacing(0x0018,0x1164);
Tag spacingbetweenslice(0x0018,0x0088);
}
gdcm_assert( spacing.size() == 3 );
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
{
const Tag tfgs(0x5200,0x9229);
SmartPointer<SequenceOfItems> sqi = InsertOrReplaceSQ( ds, tfgs );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item1 = sqi->GetItem(1);
item1.SetVLToUndefined();
DataSet &subds = item1.GetNestedDataSet();
const Tag tpms(0x0028,0x9110);
sqi = InsertOrReplaceSQ( subds, tpms );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item2 = sqi->GetItem(1);
item2.SetVLToUndefined();
DataSet &subds2 = item2.GetNestedDataSet();
Attribute<0x0018,0x0088> at2;
at2.SetValue( fabs(spacing[2]) );
Attribute<0x0028,0x0030> at1;
at1.SetValue( spacing[1], 0 );
at1.SetValue( spacing[0], 1 );
subds2.Replace( at1.GetAsDataElement() );
subds2.Replace( at2.GetAsDataElement() );
}
{
const Tag tfgs(0x5200,0x9230);
if( ds.FindDataElement( tfgs ) )
{
SmartPointer<SequenceOfItems> sqi = InsertOrReplaceSQ( ds, tfgs );
SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems();
for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0)
{
Item &item = sqi->GetItem(i0);
item.SetVLToUndefined();
DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0028,0x9110);
subds.Remove(tpms);
}
}
}
{
const Tag t1(0x0018,0x0088);
ds.Remove(t1);
const Tag t2(0x0028,0x0030);
ds.Remove(t2);
}
return;
}
else if( ms == MediaStorage::UltrasoundMultiFrameImageStorage || ms == MediaStorage::UltrasoundImageStorage )
{
SetUltraSoundSpacingValueFromSequence(ds, spacing);
return;
}
Tag spacingtag = GetSpacingTagFromMediaStorage(ms);
Tag zspacingtag = GetZSpacingTagFromMediaStorage(ms);
{
const Tag ¤tspacing = spacingtag;
if( currentspacing != Tag(0xffff,0xffff) )
{
DataElement de( currentspacing );
const Global &g = GlobalInstance;
const Dicts &dicts = g.GetDicts();
const DictEntry &entry = dicts.GetDictEntry(de.GetTag());
const VR & vr = entry.GetVR();
const VM & vm = entry.GetVM(); (void)vm;
gdcm_assert( de.GetVR() == vr || de.GetVR() == VR::INVALID );
switch(vr)
{
case VR::DS:
{
Element<VR::DS,VM::VM1_n> el;
el.SetLength( entry.GetVM().GetLength() * vr.GetSizeof() );
gdcm_assert( entry.GetVM() == VM::VM2 );
for( unsigned int i = 0; i < entry.GetVM().GetLength(); ++i)
{
el.SetValue( spacing[i], i );
}
el.SetValue( spacing[1], 0 );
el.SetValue( spacing[0], 1 );
std::stringstream os;
el.Write( os );
de.SetVR( VR::DS );
if( os.str().size() % 2 ) os << " ";
VL::Type osStrSize = (VL::Type)os.str().size();
de.SetByteValue( os.str().c_str(),osStrSize );
ds.Replace( de );
}
break;
case VR::IS:
{
Element<VR::IS,VM::VM1_n> el;
el.SetLength( entry.GetVM().GetLength() * vr.GetSizeof() );
gdcm_assert( entry.GetVM() == VM::VM2 );
for( unsigned int i = 0; i < entry.GetVM().GetLength(); ++i)
{
el.SetValue( (int)spacing[i], i );
}
std::stringstream os;
el.Write( os );
de.SetVR( VR::IS );
if( os.str().size() % 2 ) os << " ";
VL::Type osStrSize = (VL::Type)os.str().size();
de.SetByteValue( os.str().c_str(), osStrSize );
ds.Replace( de );
}
break;
default:
gdcm_assert(0);
}
}
}
{
const Tag ¤tspacing = zspacingtag;
if( currentspacing != Tag(0xffff,0xffff) )
{
DataElement de( currentspacing );
const Global &g = GlobalInstance;
const Dicts &dicts = g.GetDicts();
const DictEntry &entry = dicts.GetDictEntry(de.GetTag());
const VR & vr = entry.GetVR();
const VM & vm = entry.GetVM(); (void)vm;
gdcm_assert( de.GetVR() == vr || de.GetVR() == VR::INVALID );
if( entry.GetVM() == VM::VM2_n )
{
gdcm_assert( vr == VR::DS );
gdcm_assert( de.GetTag() == Tag(0x3004,0x000c) );
Attribute<0x28,0x8> numberoframes;
if( ds.FindDataElement( numberoframes.GetTag() ) )
{
const DataElement& de1 = ds.GetDataElement( numberoframes.GetTag() );
numberoframes.SetFromDataElement( de1 );
Element<VR::DS,VM::VM2_n> el;
el.SetLength( numberoframes.GetValue() * vr.GetSizeof() );
gdcm_assert( entry.GetVM() == VM::VM2_n );
double spacing_start = 0;
gdcm_assert( 0 < numberoframes.GetValue() );
for( int i = 0; i < numberoframes.GetValue(); ++i)
{
el.SetValue( spacing_start, i );
spacing_start += spacing[2];
}
std::stringstream os;
el.Write( os );
de.SetVR( VR::DS );
if( os.str().size() % 2 ) os << " ";
VL::Type osStrSize = (VL::Type)os.str().size();
de.SetByteValue( os.str().c_str(), osStrSize );
ds.Replace( de );
}
}
else
{
switch(vr)
{
case VR::DS:
{
Element<VR::DS,VM::VM1_n> el;
el.SetLength( entry.GetVM().GetLength() * vr.GetSizeof() );
gdcm_assert( entry.GetVM() == VM::VM1 );
for( unsigned int i = 0; i < entry.GetVM().GetLength(); ++i)
{
el.SetValue( spacing[i+2], i );
}
std::stringstream os;
el.Write( os );
de.SetVR( VR::DS );
if( os.str().size() % 2 ) os << " ";
VL::Type osStrSize = (VL::Type)os.str().size();
de.SetByteValue( os.str().c_str(), osStrSize );
ds.Replace( de );
}
break;
default:
gdcm_assert(0);
}
}
}
}
}
static void SetDataElementInSQAsItemNumber(DataSet & ds, DataElement const & de, Tag const & sqtag, unsigned int itemidx)
{
const Tag tfgs = sqtag; SmartPointer<SequenceOfItems> sqi = InsertOrReplaceSQ( ds, tfgs );
if( sqi->GetNumberOfItems() < itemidx )
{
Item item; sqi->AddItem( item );
}
Item &item1 = sqi->GetItem(itemidx);
item1.SetVLToUndefined();
DataSet &subds = item1.GetNestedDataSet();
const Tag tpms(0x0020,0x9113);
sqi = InsertOrReplaceSQ( subds, tpms );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item2 = sqi->GetItem(1);
item2.SetVLToUndefined();
DataSet &subds2 = item2.GetNestedDataSet();
subds2.Replace( de );
}
void ImageHelper::SetOriginValue(DataSet & ds, const Image & image)
{
const double *origin = image.GetOrigin();
MediaStorage ms;
ms.SetFromDataSet(ds);
if (!MediaStorage::IsImage(ms)) {
gdcmWarningMacro("Wrong SOP Class");
}
if( ms == MediaStorage::SecondaryCaptureImageStorage && !ImageHelper::SecondaryCaptureImagePlaneModule )
{
return;
}
if( ms != MediaStorage::CTImageStorage
&& ms != MediaStorage::MRImageStorage
&& ms != MediaStorage::RTDoseStorage
&& ms != MediaStorage::PETImageStorage
&& ms != MediaStorage::SegmentationStorage
&& ms != MediaStorage::SecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
&& ms != MediaStorage::XRay3DAngiographicImageStorage
&& ms != MediaStorage::XRay3DCraniofacialImageStorage
&& ms != MediaStorage::EnhancedMRImageStorage
&& ms != MediaStorage::EnhancedMRColorImageStorage
&& ms != MediaStorage::EnhancedPETImageStorage
&& ms != MediaStorage::EnhancedCTImageStorage
&& ms != MediaStorage::IVOCTForPresentation
&& ms != MediaStorage::IVOCTForProcessing
&& ms != MediaStorage::BreastTomosynthesisImageStorage
&& ms != MediaStorage::BreastProjectionXRayImageStorageForPresentation
&& ms != MediaStorage::BreastProjectionXRayImageStorageForProcessing
&& ms != MediaStorage::LegacyConvertedEnhancedMRImageStorage
&& ms != MediaStorage::LegacyConvertedEnhancedCTImageStorage
&& ms != MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
return;
}
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage)
{
const Tag tfgs(0x5200,0x9230);
Attribute<0x0020,0x0032> ipp = {{0,0,0}}; double zspacing = image.GetSpacing(2);
unsigned int dimz = image.GetDimension(2);
const double *cosines = image.GetDirectionCosines();
DirectionCosines dc( cosines );
double normal[3];
dc.Cross( normal );
DirectionCosines::Normalize(normal);
for(unsigned int i = 0; i < dimz; ++i )
{
double new_origin[3];
for (int j = 0; j < 3; j++)
{
new_origin[j] = origin[j] + normal[j] * i * zspacing;
}
ipp.SetValue( new_origin[0], 0);
ipp.SetValue( new_origin[1], 1);
ipp.SetValue( new_origin[2], 2);
SetDataElementInSQAsItemNumber(ds, ipp.GetAsDataElement(), tfgs, i+1);
}
{
const Tag tfgs0(0x5200,0x9229);
if( ds.FindDataElement( tfgs0 ) )
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs0 ).GetValueAsSQ();
gdcm_assert( sqi );
SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems();
for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0)
{
Item &item = sqi->GetItem(i0);
item.SetVLToUndefined();
DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0020,0x9113);
subds.Remove(tpms);
}
}
}
{
const Tag tiop(0x0020,0x0032);
ds.Remove(tiop);
}
if( ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage )
{
if( dimz > 1 ) {
Attribute<0x0028,0x0009> fip;
fip.SetNumberOfValues( 1 );
fip.SetValue( tfgs );
ds.Replace( fip.GetAsDataElement() );
}
}
return;
}
Attribute<0x0020,0x0032> ipp = {{0,0,0}}; ipp.SetValue( origin[0], 0);
ipp.SetValue( origin[1], 1);
ipp.SetValue( origin[2], 2);
ds.Replace( ipp.GetAsDataElement() );
}
void ImageHelper::SetDirectionCosinesValue(DataSet & ds, const std::vector<double> & dircos)
{
MediaStorage ms;
ms.SetFromDataSet(ds);
if (!MediaStorage::IsImage(ms)) {
gdcmWarningMacro("Wrong SOP Class");
}
if( ms == MediaStorage::SecondaryCaptureImageStorage && !ImageHelper::SecondaryCaptureImagePlaneModule )
{
return;
}
if( ms != MediaStorage::CTImageStorage
&& ms != MediaStorage::MRImageStorage
&& ms != MediaStorage::RTDoseStorage
&& ms != MediaStorage::PETImageStorage
&& ms != MediaStorage::SecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
&& ms != MediaStorage::SegmentationStorage
&& ms != MediaStorage::XRay3DAngiographicImageStorage
&& ms != MediaStorage::XRay3DCraniofacialImageStorage
&& ms != MediaStorage::EnhancedMRImageStorage
&& ms != MediaStorage::EnhancedMRColorImageStorage
&& ms != MediaStorage::EnhancedPETImageStorage
&& ms != MediaStorage::EnhancedCTImageStorage
&& ms != MediaStorage::IVOCTForPresentation
&& ms != MediaStorage::IVOCTForProcessing
&& ms != MediaStorage::BreastTomosynthesisImageStorage
&& ms != MediaStorage::BreastProjectionXRayImageStorageForPresentation
&& ms != MediaStorage::BreastProjectionXRayImageStorageForProcessing
&& ms != MediaStorage::LegacyConvertedEnhancedMRImageStorage
&& ms != MediaStorage::LegacyConvertedEnhancedCTImageStorage
&& ms != MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
return;
}
Attribute<0x0020,0x0037> iop = {{1,0,0,0,1,0}};
gdcm_assert( dircos.size() == 6 );
DirectionCosines dc( dircos.data() );
if( !dc.IsValid() )
{
gdcmWarningMacro( "Direction Cosines are not valid. Using default value (1\\0\\0\\0\\1\\0)" );
}
else
{
iop.SetValue( dircos[0], 0);
iop.SetValue( dircos[1], 1);
iop.SetValue( dircos[2], 2);
iop.SetValue( dircos[3], 3);
iop.SetValue( dircos[4], 4);
iop.SetValue( dircos[5], 5);
}
if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedMRColorImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
|| ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::SegmentationStorage
|| ms == MediaStorage::IVOCTForPresentation
|| ms == MediaStorage::IVOCTForProcessing
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
{
const Tag tfgs(0x5200,0x9229);
SmartPointer<SequenceOfItems> sqi = InsertOrReplaceSQ( ds, tfgs );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item1 = sqi->GetItem(1);
item1.SetVLToUndefined();
DataSet &subds = item1.GetNestedDataSet();
const Tag tpms(0x0020,0x9116);
sqi = InsertOrReplaceSQ( subds, tpms );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item2 = sqi->GetItem(1);
item2.SetVLToUndefined();
DataSet &subds2 = item2.GetNestedDataSet();
subds2.Replace( iop.GetAsDataElement() );
}
{
const Tag tfgs(0x5200,0x9230);
if( ds.FindDataElement( tfgs ) )
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
gdcm_assert( sqi );
SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems();
for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0)
{
Item &item = sqi->GetItem(i0);
item.SetVLToUndefined();
DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0020,0x9116);
subds.Remove(tpms);
}
}
}
{
const Tag tiop(0x0020,0x0037);
ds.Remove(tiop);
}
return;
}
ds.Replace( iop.GetAsDataElement() );
}
void ImageHelper::SetRescaleInterceptSlopeValue(File & f, const Image & img)
{
MediaStorage ms;
ms.SetFromFile(f);
if (!MediaStorage::IsImage(ms)) {
gdcmWarningMacro("Wrong SOP Class");
}
DataSet &ds = f.GetDataSet();
if( ms != MediaStorage::CTImageStorage
&& ms != MediaStorage::ComputedRadiographyImageStorage
&& ms != MediaStorage::MRImageStorage && ms != MediaStorage::PETImageStorage
&& ms != MediaStorage::RTDoseStorage
&& ms != MediaStorage::SecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage
&& ms != MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage
&& ms != MediaStorage::EnhancedMRImageStorage
&& ms != MediaStorage::EnhancedCTImageStorage
&& ms != MediaStorage::EnhancedPETImageStorage
&& ms != MediaStorage::XRay3DAngiographicImageStorage
&& ms != MediaStorage::XRay3DCraniofacialImageStorage
&& ms != MediaStorage::SegmentationStorage
&& ms != MediaStorage::IVOCTForPresentation
&& ms != MediaStorage::IVOCTForProcessing
&& ms != MediaStorage::BreastTomosynthesisImageStorage
&& ms != MediaStorage::BreastProjectionXRayImageStorageForPresentation
&& ms != MediaStorage::BreastProjectionXRayImageStorageForProcessing
&& ms != MediaStorage::LegacyConvertedEnhancedMRImageStorage
&& ms != MediaStorage::LegacyConvertedEnhancedCTImageStorage
&& ms != MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
if( img.GetIntercept() != 0. || img.GetSlope() != 1. )
{
gdcmErrorMacro( "Cannot have non-identity intercept/slope values." );
throw "Impossible"; }
return;
}
if( ms == MediaStorage::SegmentationStorage ) return; if( ms == MediaStorage::EnhancedCTImageStorage
|| ms == MediaStorage::EnhancedMRImageStorage
|| ms == MediaStorage::EnhancedPETImageStorage
|| ms == MediaStorage::XRay3DAngiographicImageStorage
|| ms == MediaStorage::XRay3DCraniofacialImageStorage
|| ms == MediaStorage::BreastTomosynthesisImageStorage
|| ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation
|| ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing
|| ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage
|| ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage )
{
{
const Tag tfgs(0x5200,0x9229);
SmartPointer<SequenceOfItems> sqi = InsertOrReplaceSQ( ds, tfgs );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item1 = sqi->GetItem(1);
item1.SetVLToUndefined();
DataSet &subds = item1.GetNestedDataSet();
const Tag tpms(0x0028,0x9145);
sqi = InsertOrReplaceSQ( subds, tpms );
if( !sqi->GetNumberOfItems() )
{
Item item; sqi->AddItem( item );
}
Item &item2 = sqi->GetItem(1);
item2.SetVLToUndefined();
DataSet &subds2 = item2.GetNestedDataSet();
Attribute<0x0028,0x1052> at1;
at1.SetValue( img.GetIntercept() );
subds2.Replace( at1.GetAsDataElement() );
Attribute<0x0028,0x1053> at2;
at2.SetValue( img.GetSlope() );
subds2.Replace( at2.GetAsDataElement() );
}
{
const Tag tfgs(0x5200,0x9230);
if( ds.FindDataElement( tfgs ) )
{
SmartPointer<SequenceOfItems> sqi = ds.GetDataElement( tfgs ).GetValueAsSQ();
gdcm_assert( sqi );
SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems();
for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0)
{
Item &item = sqi->GetItem(i0);
DataSet & subds = item.GetNestedDataSet();
const Tag tpms(0x0028,0x9145);
subds.Remove(tpms);
}
}
}
{
const Tag t1(0x0028,0x1052);
ds.Remove(t1);
const Tag t2(0x0028,0x1053);
ds.Remove(t2);
const Tag t3(0x0028,0x1053);
ds.Remove(t3);
}
return;
}
if( ms == MediaStorage::RTDoseStorage )
{
if( img.GetIntercept() != 0 )
{
gdcmErrorMacro( "Cannot have an intercept value for RTDOSE, only Scaling allowed" );
return;
}
Attribute<0x3004,0x00e> at2;
at2.SetValue( img.GetSlope() );
ds.Replace( at2.GetAsDataElement() );
Attribute<0x0028,0x0009> framePointer;
framePointer.SetNumberOfValues(1);
framePointer.SetValue( Tag(0x3004,0x000C) );
ds.Replace( framePointer.GetAsDataElement() );
return;
}
if( ms == MediaStorage::MRImageStorage )
{
#if 0#else
{
if( ForceRescaleInterceptSlope )
{
gdcmDebugMacro( "Forcing MR Image Storage / Modality LUT: [" << img.GetIntercept() << "," << img.GetSlope() );
Attribute<0x0028,0x1052> at1;
at1.SetValue( img.GetIntercept() );
ds.Replace( at1.GetAsDataElement() );
Attribute<0x0028,0x1053> at2;
at2.SetValue( img.GetSlope() );
ds.Replace( at2.GetAsDataElement() );
Attribute<0x0028,0x1054> at3; at3.SetValue( "US" ); ds.Replace( at3.GetAsDataElement() );
}
}
#endif
}
else
{
Attribute<0x0028,0x1052> at1;
at1.SetValue( img.GetIntercept() );
ds.Replace( at1.GetAsDataElement() );
Attribute<0x0028,0x1053> at2;
at2.SetValue( img.GetSlope() );
ds.Replace( at2.GetAsDataElement() );
Attribute<0x0028,0x1054> at3; at3.SetValue( "US" ); if( ms == MediaStorage::SecondaryCaptureImageStorage )
{
ds.Replace( at3.GetAsDataElement() );
}
else if( ms == MediaStorage::PETImageStorage )
{
ds.Remove( at3.GetTag() );
}
else
{
ds.ReplaceEmpty( at3.GetAsDataElement() );
}
}
}
bool ImageHelper::GetRealWorldValueMappingContent(File const & f, RealWorldValueMappingContent & ret)
{
MediaStorage ms;
ms.SetFromFile(f);
const DataSet& ds = f.GetDataSet();
if( ms == MediaStorage::MRImageStorage || ms == MediaStorage::NuclearMedicineImageStorage )
{
const Tag trwvms(0x0040,0x9096); if( ds.FindDataElement( trwvms ) )
{
SmartPointer<SequenceOfItems> sqi0 = ds.GetDataElement( trwvms ).GetValueAsSQ();
if( sqi0 )
{
const Tag trwvlutd(0x0040,0x9212); if( ds.FindDataElement( trwvlutd ) )
{
gdcmAssertAlwaysMacro(0); }
gdcmAssertAlwaysMacro( sqi0->GetNumberOfItems() == 1 );
const Item &item0 = sqi0->GetItem(1);
const DataSet & subds0 = item0.GetNestedDataSet();
{
Attribute<0x0040,0x9224> at1 = {0};
at1.SetFromDataSet( subds0 );
Attribute<0x0040,0x9225> at2 = {1};
at2.SetFromDataSet( subds0 );
ret.RealWorldValueIntercept = at1.GetValue();
ret.RealWorldValueSlope = at2.GetValue();
}
const Tag tmucs(0x0040,0x08ea); if( subds0.FindDataElement( tmucs ) )
{
SmartPointer<SequenceOfItems> sqi = subds0.GetDataElement( tmucs ).GetValueAsSQ();
if( sqi )
{
gdcmAssertAlwaysMacro( sqi->GetNumberOfItems() == 1 );
const Item &item = sqi->GetItem(1);
const DataSet & subds = item.GetNestedDataSet();
Attribute<0x0008,0x0100> at1;
at1.SetFromDataSet( subds );
Attribute<0x0008,0x0104> at2;
at2.SetFromDataSet( subds );
ret.CodeValue = at1.GetValue().Trim();
ret.CodeMeaning = at2.GetValue().Trim();
}
}
}
return true;
}
}
return false;
}
bool ImageHelper::ComputeSpacingFromImagePositionPatient(const std::vector<double> & imageposition, std::vector<double> & spacing)
{
if( imageposition.size() % 3 != 0 )
{
return false;
}
std::vector<double>::const_iterator it = imageposition.begin();
spacing[0] = spacing[1] = spacing[2] = 0.;
for( ; it != imageposition.end(); ++it)
{
const double x = *it++;
const double y = *it++;
const double z = *it;
spacing[0] += x;
spacing[1] += y;
spacing[2] += z;
}
size_t n = imageposition.size() / 3;
spacing[0] /= (double)n;
spacing[1] /= (double)n;
spacing[2] /= (double)n;
return true;
}
PhotometricInterpretation ImageHelper::GetPhotometricInterpretationValue(File const& f)
{
PixelFormat pf = GetPixelFormatValue(f);
const Tag tphotometricinterpretation(0x0028, 0x0004);
const ByteValue *photometricinterpretation =
ImageHelper::GetPointerFromElement(tphotometricinterpretation, f);
PhotometricInterpretation pi = PhotometricInterpretation::UNKNOWN;
if( photometricinterpretation )
{
std::string photometricinterpretation_str(
photometricinterpretation->GetPointer(),
photometricinterpretation->GetLength() );
pi = PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str() );
}
else
{
if( pf.GetSamplesPerPixel() == 1 )
{
gdcmWarningMacro( "No PhotometricInterpretation found, default to MONOCHROME2" );
pi = PhotometricInterpretation::MONOCHROME2;
}
else if( pf.GetSamplesPerPixel() == 3 )
{
gdcmWarningMacro( "No PhotometricInterpretation found, default to RGB" );
pi = PhotometricInterpretation::RGB;
}
else if( pf.GetSamplesPerPixel() == 4 )
{
gdcmWarningMacro( "No PhotometricInterpretation found, default to ARGB" );
pi = PhotometricInterpretation::ARGB;
}
}
bool isacrnema = false;
DataSet ds = f.GetDataSet();
const Tag trecognitioncode(0x0008,0x0010);
if( ds.FindDataElement( trecognitioncode ) && !ds.GetDataElement( trecognitioncode ).IsEmpty() )
{
gdcmDebugMacro( "Mixture of ACR NEMA and DICOM file" );
isacrnema = true;
}
if( !pf.GetSamplesPerPixel() || (pi.GetSamplesPerPixel() != pf.GetSamplesPerPixel()) )
{
if( pi != PhotometricInterpretation::UNKNOWN )
{
pf.SetSamplesPerPixel( pi.GetSamplesPerPixel() );
}
else if ( isacrnema )
{
assert ( pf.GetSamplesPerPixel() == 0 );
assert ( pi == PhotometricInterpretation::UNKNOWN );
pf.SetSamplesPerPixel( 1 );
pi = PhotometricInterpretation::MONOCHROME2;
}
else
{
gdcmWarningMacro( "Cannot recognize image type. Does not looks like ACR-NEMA and is missing both Sample Per Pixel AND PhotometricInterpretation. Please report" );
}
}
return pi;
}
unsigned int ImageHelper::GetPlanarConfigurationValue(const File& f)
{
const Tag planarconfiguration = Tag(0x0028, 0x0006);
PixelFormat pf = GetPixelFormatValue(f);
unsigned int pc = 0;
DataSet const & ds = f.GetDataSet();
if( ds.FindDataElement( planarconfiguration ) && !ds.GetDataElement( planarconfiguration ).IsEmpty() )
{
const DataElement& de = ds.GetDataElement( planarconfiguration );
Attribute<0x0028,0x0006> at = { 0 };
at.SetFromDataElement( de );
pc = at.GetValue();
if( pc && pf.GetSamplesPerPixel() != 3 )
{
gdcmDebugMacro( "Cannot have PlanarConfiguration=1, when Sample Per Pixel != 3" );
pc = 0;
}
}
return pc;
}
SmartPointer<LookupTable> ImageHelper::GetLUT(File const& f)
{
DataSet const & ds = f.GetDataSet();
PixelFormat pf = GetPixelFormatValue(f);
PhotometricInterpretation pi = GetPhotometricInterpretationValue(f);
bool modlut = ds.FindDataElement(Tag(0x0028,0x3000) );
if( modlut )
{
gdcmWarningMacro( "Modality LUT (0028,3000) are not handled. Image will not be displayed properly" );
}
bool lutdata = ds.FindDataElement(Tag(0x0028,0x3006) );
if( lutdata )
{
gdcmWarningMacro( "LUT Data (0028,3006) are not handled. Image will not be displayed properly" );
}
bool voilut = ds.FindDataElement(Tag(0x0028,0x3010) );
if( voilut )
{
gdcmWarningMacro( "VOI LUT (0028,3010) are not handled. Image will not be displayed properly" );
}
bool pixelpaddingvalue = ds.FindDataElement(Tag(0x0028,0x0120));
if(pixelpaddingvalue)
{
bool vizissue = true;
if( pf.GetPixelRepresentation() == 0 )
{
Element<VR::US,VM::VM1> ppv;
if( !ds.GetDataElement(Tag(0x0028,0x0120) ).IsEmpty() )
{
ppv.SetFromDataElement( ds.GetDataElement(Tag(0x0028,0x0120)) ); if( pi == PhotometricInterpretation::MONOCHROME2 && ppv.GetValue() == 0 )
{
vizissue = false;
}
}
}
else if( pf.GetPixelRepresentation() == 1 )
{
gdcmDebugMacro( "TODO" );
}
if( vizissue )
{
gdcmDebugMacro( "Pixel Padding Value (0028,0120) is not handled. Image will not be displayed properly" );
}
}
SmartPointer<LookupTable> lut = new LookupTable;
const Tag testseglut(0x0028, (0x1221 + 0));
if( ds.FindDataElement( testseglut ) )
{
lut = new SegmentedPaletteColorLookupTable;
}
lut->Allocate( pf.GetBitsAllocated() );
for(int i=0; i<3; ++i)
{
const Tag tdescriptor(0x0028, (uint16_t)(0x1101 + i));
Element<VR::US,VM::VM3> el_us3 = {{ 0, 0, 0}};
el_us3.SetFromDataElement( ds[tdescriptor] ); lut->InitializeLUT( LookupTable::LookupTableType(i),
el_us3[0], el_us3[1], el_us3[2] );
const Tag tlut(0x0028, (uint16_t)(0x1201 + i));
const Tag seglut(0x0028, (uint16_t)(0x1221 + i));
if( ds.FindDataElement( tlut ) )
{
const ByteValue *lut_raw = ds.GetDataElement( tlut ).GetByteValue();
if( lut_raw )
{
lut->SetLUT( LookupTable::LookupTableType(i),
(const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() );
}
else
{
lut->Clear();
}
unsigned long check =
(el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536)
* el_us3.GetValue(2) / 8;
gdcm_assert( !lut->Initialized() || check == lut_raw->GetLength() ); (void)check;
}
else if( ds.FindDataElement( seglut ) )
{
const ByteValue *lut_raw = ds.GetDataElement( seglut ).GetByteValue();
if( lut_raw )
{
lut->SetLUT( LookupTable::LookupTableType(i),
(const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() );
}
else
{
lut->Clear();
}
}
else
{
gdcm_assert(0);
}
}
if( ! lut->Initialized() ) {
gdcmDebugMacro("LUT was uninitialized!");
}
return lut;
}
const ByteValue* ImageHelper::GetPointerFromElement(Tag const &tag, const File& inF)
{
const DataSet &ds = inF.GetDataSet();
if( ds.FindDataElement( tag ) )
{
const DataElement &de = ds.GetDataElement( tag );
return de.GetByteValue();
}
return nullptr;
}
MediaStorage ImageHelper::ComputeMediaStorageFromModality(const char *modality,
unsigned int dimension, PixelFormat const & pixeltype,
PhotometricInterpretation const & pi,
double intercept , double slope
)
{
MediaStorage ms = MediaStorage::SecondaryCaptureImageStorage;
ms.GuessFromModality(modality, dimension );
if( dimension != 2 &&
(ms == MediaStorage::SecondaryCaptureImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage ) )
{
if( dimension == 3 &&
pixeltype.GetSamplesPerPixel() == 1 &&
pi == PhotometricInterpretation::MONOCHROME2 &&
pixeltype.GetBitsAllocated() == 8 &&
pixeltype.GetBitsStored() == 8 &&
pixeltype.GetHighBit() == 7 &&
pixeltype.GetPixelRepresentation() == 0
)
{
ms = MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage;
if( intercept != 0 || slope != 1 )
{
gdcmErrorMacro( "Cannot have shift/scale" );
return MediaStorage::MS_END;
}
}
else if( dimension == 3 &&
pixeltype.GetSamplesPerPixel() == 1 &&
pi == PhotometricInterpretation::MONOCHROME2 &&
pixeltype.GetBitsAllocated() == 1 &&
pixeltype.GetBitsStored() == 1 &&
pixeltype.GetHighBit() == 0 &&
pixeltype.GetPixelRepresentation() == 0
)
{
ms = MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage;
if( intercept != 0 || slope != 1 )
{
gdcmDebugMacro( "Cannot have shift/scale" );
return MediaStorage::MS_END;
}
}
else if( dimension == 3 &&
pixeltype.GetSamplesPerPixel() == 1 &&
pi == PhotometricInterpretation::MONOCHROME2 &&
pixeltype.GetBitsAllocated() == 16 &&
pixeltype.GetBitsStored() <= 16 && pixeltype.GetBitsStored() >= 9 &&
pixeltype.GetHighBit() == pixeltype.GetBitsStored() - 1 &&
pixeltype.GetPixelRepresentation() == 0
)
{
ms = MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage;
}
else if( dimension == 3 &&
pixeltype.GetSamplesPerPixel() == 3 &&
( pi == PhotometricInterpretation::RGB
|| pi == PhotometricInterpretation::YBR_RCT
|| pi == PhotometricInterpretation::YBR_ICT
|| pi == PhotometricInterpretation::YBR_PARTIAL_420
|| pi == PhotometricInterpretation::YBR_FULL
|| pi == PhotometricInterpretation::YBR_FULL_422 ) &&
pixeltype.GetBitsAllocated() == 8 &&
pixeltype.GetBitsStored() == 8 &&
pixeltype.GetHighBit() == 7 &&
pixeltype.GetPixelRepresentation() == 0
)
{
ms = MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage;
if( intercept != 0 || slope != 1 )
{
gdcmDebugMacro( "Cannot have shift/scale" );
return MediaStorage::MS_END;
}
}
else
{
gdcmDebugMacro( "Cannot handle Multi Frame image in SecondaryCaptureImageStorage" );
return MediaStorage::MS_END;
}
}
if( ms == MediaStorage::MRImageStorage )
{
if( intercept != 0.0 || slope != 1.0 )
{
if( !ForceRescaleInterceptSlope )
{
ms = MediaStorage::EnhancedMRImageStorage;
}
}
}
if( ms == MediaStorage::DigitalXRayImageStorageForPresentation )
{
if( intercept != 0.0 || slope != 1.0 )
{
ms = MediaStorage::XRay3DCraniofacialImageStorage;
}
}
return ms;
}
}