📄 gdcmfile.cxx
字号:
}
/**
* \brief Retrieve the number of columns of image.
* @return The encountered size when found, 0 by default.
* 0 means the file is NOT USABLE. The caller will have to check
*/
int File::GetXSize()
{
const std::string &strSize = GetEntryValue(0x0028,0x0011);
if ( strSize == GDCM_UNFOUND )
{
return 0;
}
return atoi( strSize.c_str() );
}
/**
* \brief Retrieve the number of lines of image.
* \warning The defaulted value is 1 as opposed to File::GetXSize()
* @return The encountered size when found, 1 by default
* (The ACR-NEMA file contains a Signal, not an Image).
*/
int File::GetYSize()
{
const std::string &strSize = GetEntryValue(0x0028,0x0010);
if ( strSize != GDCM_UNFOUND )
{
return atoi( strSize.c_str() );
}
if ( IsDicomV3() )
{
return 0;
}
// The Rows (0028,0010) entry was optional for ACR/NEMA.
// (at least some images didn't have it.)
// It might hence be a signal (1D image). So we default to 1:
return 1;
}
/**
* \brief Retrieve the number of planes of volume or the number
* of frames of a multiframe.
* \warning When present we consider the "Number of Frames" as the third
* dimension. When missing we consider the third dimension as
* being the ACR-NEMA "Planes" tag content.
* @return The encountered size when found, 1 by default (single image).
*/
int File::GetZSize()
{
// Both DicomV3 and ACR/Nema consider the "Number of Frames"
// as the third dimension.
const std::string &strSize = GetEntryValue(0x0028,0x0008);
if ( strSize != GDCM_UNFOUND )
{
return atoi( strSize.c_str() );
}
// We then consider the "Planes" entry as the third dimension
const std::string &strSize2 = GetEntryValue(0x0028,0x0012);
if ( strSize2 != GDCM_UNFOUND )
{
return atoi( strSize2.c_str() );
}
return 1;
}
// Special case:
// ts["1.2.840.10008.5.1.4.1.1.4.1"] = "Enhanced MR Image Storage";
bool File::GetSpacing(float &xspacing, float &yspacing, float &zspacing)
{
xspacing = yspacing = zspacing = 1.0;
TS *ts = Global::GetTS();
std::string sopclassuid_used;
// D 0002|0002 [UI] [Media Storage SOP Class UID]
const std::string &mediastoragesopclassuid_str = GetEntryValue(0x0002,0x0002);
const std::string &mediastoragesopclassuid = ts->GetValue(mediastoragesopclassuid_str);
//D 0008|0016 [UI] [SOP Class UID]
const std::string &sopclassuid_str = GetEntryValue(0x0008,0x0016);
const std::string &sopclassuid = ts->GetValue(sopclassuid_str);
if ( mediastoragesopclassuid == GDCM_UNFOUND && sopclassuid == GDCM_UNFOUND )
{
return false;
}
else
{
if( mediastoragesopclassuid == sopclassuid )
{
sopclassuid_used = mediastoragesopclassuid;
}
else
{
gdcmWarningMacro( "Inconsistant SOP Class UID: "
<< mediastoragesopclassuid << " and " << sopclassuid );
return false;
}
}
// ok we have now the correc SOP Class UID
if( sopclassuid_used == "Enhanced MR Image Storage" )
{
SeqEntry *PerframeFunctionalGroupsSequence = GetSeqEntry(0x5200,0x9230);
unsigned int n = PerframeFunctionalGroupsSequence->GetNumberOfSQItems();
if( !n ) return false;
SQItem *item1 = PerframeFunctionalGroupsSequence->GetFirstSQItem();
DocEntry *p = item1->GetDocEntry(0x0028,0x9110);
if( !p ) return false;
SeqEntry *seq = dynamic_cast<SeqEntry*>(p);
unsigned int n1 = seq->GetNumberOfSQItems();
if( !n1 ) return false;
SQItem *item2 = seq->GetFirstSQItem();
// D 0028|0030 [DS] [Pixel Spacing] [0.83333331346511\0.83333331346511 ]
DocEntry *p2 = item2->GetDocEntry(0x0028,0x0030);
if( !p2 ) return false;
ContentEntry *entry = dynamic_cast<ContentEntry *>(p2);
std::string spacing = entry->GetValue();
if ( sscanf( spacing.c_str(), "%f\\%f", &yspacing, &xspacing) != 2 )
{
xspacing = yspacing = 1.;
return false;
}
// D 0018|0050 [DS] [Slice Thickness] [1 ]
DocEntry *p3 = item2->GetDocEntry(0x0018,0x0050);
if( !p3 ) return false;
ContentEntry *entry2 = dynamic_cast<ContentEntry *>(p3);
std::string thickness = entry2->GetValue();
if ( sscanf( thickness.c_str(), "%f", &zspacing) != 1 )
{
zspacing = 1.;
return false;
}
return true;
}
return false;
}
/**
* \brief gets the info from 0018,1164 : ImagerPixelSpacing
* then 0028,0030 : Pixel Spacing
* else 1.0
* @return X dimension of a pixel
*/
float File::GetXSpacing()
{
float xspacing = 1.0;
float yspacing = 1.0;
float zspacing = 1.0;
int nbValues;
if ( GetSpacing(xspacing,yspacing,zspacing) )
{
return xspacing;
}
// else fallback
// To follow David Clunie's advice, we first check ImagerPixelSpacing
const std::string &strImagerPixelSpacing = GetEntryValue(0x0018,0x1164);
if ( strImagerPixelSpacing != GDCM_UNFOUND )
{
if ( ( nbValues = sscanf( strImagerPixelSpacing.c_str(),
"%f\\%f", &yspacing, &xspacing)) != 2 )
{
// if no values, xspacing is set to 1.0
if ( nbValues == 0 )
xspacing = 1.0;
// if single value is found, xspacing is defaulted to yspacing
if ( nbValues == 1 )
xspacing = yspacing;
if ( xspacing == 0.0 )
xspacing = 1.0;
}
return xspacing;
}
const std::string &strSpacing = GetEntryValue(0x0028,0x0030);
if ( strSpacing == GDCM_UNFOUND )
{
gdcmWarningMacro( "Unfound Pixel Spacing (0028,0030)" );
return 1.;
}
if ( ( nbValues = sscanf( strSpacing.c_str(),
"%f \\%f ", &yspacing, &xspacing)) != 2 )
{
// if no values, xspacing is set to 1.0
if ( nbValues == 0 )
xspacing = 1.0;
// if single value is found, xspacing is defaulted to yspacing
if ( nbValues == 1 )
xspacing = yspacing;
if ( xspacing == 0.0 )
xspacing = 1.0;
return xspacing;
}
// to avoid troubles with David Clunie's-like images (at least one)
if ( xspacing == 0.0 && yspacing == 0.0)
return 1.0;
if ( xspacing == 0.0)
{
gdcmWarningMacro("gdcmData/CT-MONO2-8-abdo.dcm-like problem");
// seems to be a bug in the header ...
nbValues = sscanf( strSpacing.c_str(), "%f \\0\\%f ", &yspacing, &xspacing);
gdcmAssertMacro( nbValues == 2 );
}
return xspacing;
}
/**
* \brief gets the info from 0018,1164 : ImagerPixelSpacing
* then from 0028,0030 : Pixel Spacing
* else 1.0
* @return Y dimension of a pixel
*/
float File::GetYSpacing()
{
float xspacing = 1., yspacing = 1.0, zspacing = 1.;
int nbValues;
if ( GetSpacing(xspacing,yspacing,zspacing) )
{
return yspacing;
}
// else fallback
// To follow David Clunie's advice, we first check ImagerPixelSpacing
const std::string &strImagerPixelSpacing = GetEntryValue(0x0018,0x1164);
if ( strImagerPixelSpacing != GDCM_UNFOUND )
{
nbValues = sscanf( strImagerPixelSpacing.c_str(), "%f", &yspacing);
// if sscanf cannot read any float value, it won't affect yspacing
if ( nbValues == 0 )
yspacing = 1.0;
if ( yspacing == 0.0 )
yspacing = 1.0;
return yspacing;
}
std::string strSpacing = GetEntryValue(0x0028,0x0030);
if ( strSpacing == GDCM_UNFOUND )
{
gdcmWarningMacro("Unfound Pixel Spacing (0028,0030)");
return 1.;
}
// if sscanf cannot read any float value, it won't affect yspacing
nbValues = sscanf( strSpacing.c_str(), "%f", &yspacing);
// if no values, yspacing is set to 1.0
if ( nbValues == 0 )
yspacing = 1.0;
if ( yspacing == 0.0 )
yspacing = 1.0;
return yspacing;
}
/**
* \brief gets the info from 0018,0088 : Space Between Slices
* else from 0018,0050 : Slice Thickness
* else 1.0
*
* When an element is missing, we suppose slices join together
* (no overlapping, no interslice gap) but we have no way to check it !
* For *Dicom* images, ZSpacing *should be* calculated using
* XOrigin, YOrigin, ZOrigin (of the top left image corner)
* of 2 consecutive images, and the Orientation
* Computing ZSpacing on a single image is not really meaningfull !
* @return Z dimension of a voxel-to be
*/
float File::GetZSpacing()
{
// There are still a lot of modality we are not dealing with, esp US
// There are tags like: D 3004|000c [DS] [Grid Frame Offset Vector] [0.0\2.00000003000000...]
// or D 0018|1065 [DS] [Frame Time Vector] [0.0\8.000000e+01\8.000000e+01\...
// That are perfeclty valid to be used
// Spacing Between Slices : distance between the middle of 2 slices
// Slices may be :
// jointives (Spacing between Slices = Slice Thickness)
// overlapping (Spacing between Slices < Slice Thickness)
// disjointes (Spacing between Slices > Slice Thickness)
// Slice Thickness : epaisseur de tissus sur laquelle est acquis le signal
// It only concerns the MRI guys, not people wanting to visualize volumes
// If Spacing Between Slices is missing,
// we suppose slices joint together
// --->
// ---> Warning :
// --->
//
// For *Dicom* images, ZSpacing should be calculated using
// XOrigin, YOrigin, ZOrigin (of the top left image corner)
// of 2 consecutive images, and the Orientation
//
// Computing ZSpacing on a single image is not really meaningfull !
float xspacing = 1.0;
float yspacing = 1.0;
float zspacing = 1.0;
if ( GetSpacing(xspacing,yspacing,zspacing) )
{
return zspacing;
}
const std::string &strSpacingBSlices = GetEntryValue(0x0018,0x0088);
if ( strSpacingBSlices == GDCM_UNFOUND )
{
gdcmWarningMacro("Unfound Spacing Between Slices (0018,0088)");
const std::string &strSliceThickness = GetEntryValue(0x0018,0x0050);
if ( strSliceThickness == GDCM_UNFOUND )
{
gdcmWarningMacro("Unfound Slice Thickness (0018,0050)");
return 1.0;
}
else
{
// if no 'Spacing Between Slices' is found,
// we assume slices join together
// (no overlapping, no interslice gap)
// if they don't, we're fucked up
return (float)atof( strSliceThickness.c_str() );
}
}
//else
float zsp = (float)atof( strSpacingBSlices.c_str());
if (zsp == 0.0) // last change not to break further computations ...
zsp = 1.0;
return zsp;
}
/**
* \brief gets the info from 0020,0032 : Image Position Patient
* else from 0020,0030 : Image Position (RET)
* else 0.
* @return up-left image corner X position
*/
float File::GetXOrigin()
{
float xImPos, yImPos, zImPos;
std::string strImPos = GetEntryValue(0x0020,0x0032);
if ( strImPos == GDCM_UNFOUND )
{
gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
strImPos = GetEntryValue(0x0020,0x0030); // For ACR-NEMA images
if ( strImPos == GDCM_UNFOUND )
{
gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
return 0.0;
}
}
if ( sscanf( strImPos.c_str(), "%f \\%f \\%f ", &xImPos, &yImPos, &zImPos) != 3 )
{
return 0.0;
}
return xImPos;
}
/**
* \brief gets the info from 0020,0032 : Image Position Patient
* else from 0020,0030 : Image Position (RET)
* else 0.
* @return up-left image corner Y position
*/
float File::GetYOrigin()
{
float xImPos, yImPos, zImPos;
std::string strImPos = GetEntryValue(0x0020,0x0032);
if ( strImPos == GDCM_UNFOUND)
{
gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
strImPos = GetEntryValue(0x0020,0x0030); // For ACR-NEMA images
if ( strImPos == GDCM_UNFOUND )
{
gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
return 0.;
}
}
if ( sscanf( strImPos.c_str(), "%f \\%f \\%f ", &xImPos, &yImPos, &zImPos) != 3 )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -