+ // 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;
+}
+
+/**
+ * \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;
+ int nbValues;
+
+ // 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. && yspacing == 0.)
+ return 1.;
+
+ if ( xspacing == 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 yspacing = 1.;
+ int nbValues;
+ // 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
+ * @return Z dimension of a voxel-to be
+ */
+float File::GetZSpacing()
+{
+ // 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
+
+ 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.;
+ }
+ 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
+ return (float)atof( strSpacingBSlices.c_str() );
+}
+
+/**
+ * \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 )