X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmHeaderHelper.cxx;h=c8647471ceef57b6e3fc129fe8213291906c44ac;hb=46c9c13ea7d5b2a2fec304f12b3db77c8028caea;hp=05ade1c54c6e64685a3cb951e2192327f73d4d77;hpb=d44cb38c3275dc302d9b523c17d346810f0e6644;p=gdcm.git diff --git a/src/gdcmHeaderHelper.cxx b/src/gdcmHeaderHelper.cxx index 05ade1c5..c8647471 100644 --- a/src/gdcmHeaderHelper.cxx +++ b/src/gdcmHeaderHelper.cxx @@ -1,106 +1,75 @@ -// $Header: /cvs/public/gdcm/src/Attic/gdcmHeaderHelper.cxx,v 1.5 2003/09/18 09:32:15 regrain Exp $ - -//This is needed when compiling in debug mode -#ifdef _MSC_VER -#pragma warning ( disable : 4800 ) -// 'identifier' : class 'type' needs to have dll-interface to be used by -// clients of class 'type2' -#pragma warning ( disable : 4251 ) -// 'identifier' : identifier was truncated to 'number' characters in the -// debug information -#pragma warning ( disable : 4786 ) -#endif //_MSC_VER - +// gdcmHeaderHelper.cxx +//----------------------------------------------------------------------------- #include "gdcmHeaderHelper.h" -#include "gdcmUtil.h" //for debug +#include "gdcmDirList.h" + +#include "gdcmDebug.h" #include #include -#include //for bzero -using namespace std; - -//directory manipulation (os indep). -//cygwin ???? -> _WIN32 ?? -#ifdef _MSC_VER -#include -int GetDir(string dPath, list &filenames) -{ - //For now dPath should have an ending "\" - WIN32_FIND_DATA FileData; - HANDLE hFile; - hFile = FindFirstFile((dPath+"*").c_str(), &FileData); - if ( hFile == INVALID_HANDLE_VALUE ) - { - //No files ! - return false; - } - - if( strncmp(FileData.cFileName, ".", 1) != 0 ) - filenames.push_back( dPath+FileData.cFileName ); - while( FindNextFile(hFile, &FileData ) != 0) - { - if( strncmp(FileData.cFileName, ".", 1) != 0 ) - filenames.push_back( dPath+FileData.cFileName ); - } - return true; -} - -#else -#include - -int GetDir(string dPath, list &filenames) -{ - DIR *dir = opendir( dPath.c_str() ); - struct dirent *entry; - while((entry = readdir(dir)) != NULL) - { -// if( strncmp(entry->d_name, ".", 1) != 0 && strncmp(entry->d_name, "..", 2) != 0) - if( strncmp(entry->d_name, ".", 1) != 0 ) - { - filenames.push_back( dPath + "/" + entry->d_name ); - } - } - closedir(dir); - return true; -} +#include -#endif - -//---------------------------------------------------------------------------- +//----------------------------------------------------------------------------- /** * \ingroup gdcmHeaderHelper - * \brief cstor + * \brief constructor */ -gdcmHeaderHelper::gdcmHeaderHelper() : gdcmHeader( ) -{ +gdcmHeaderHelper::gdcmHeaderHelper() : gdcmHeader( ) { + } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper - * \brief cstor + * \brief constructor + * @param InFilename Name of the file to deal with + * @param exception_on_error + * @param enable_sequences = true to allow the header + * to be parsed *inside* the SeQuences, + * when they have an actual length + * @param ignore_shadow = true if user wants to skip shadow groups + * during parsing, to save memory space */ gdcmHeaderHelper::gdcmHeaderHelper(const char *InFilename, - bool exception_on_error) : gdcmHeader( InFilename , exception_on_error) + bool exception_on_error, + bool enable_sequences, + bool ignore_shadow) + : gdcmHeader( InFilename, + exception_on_error, + enable_sequences, + ignore_shadow) { } -//---------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Print + +//----------------------------------------------------------------------------- +// Public /** * \ingroup gdcmHeaderHelper - * \brief Return the size (in bytes) of a single pixel of data. + * \brief Returns the size (in bytes) of a single pixel of data. * @return The size in bytes of a single pixel of data. * */ int gdcmHeaderHelper::GetPixelSize() { - string PixelType = GetPixelType(); + + // 0028 0100 US IMG Bits Allocated + // (in order no to be messed up by old RGB images) + if (gdcmHeader::GetEntryByNumber(0x0028,0x0100) == "24") + return 3; + + std::string PixelType = GetPixelType(); if (PixelType == "8U" || PixelType == "8S") return 1; if (PixelType == "16U" || PixelType == "16S") return 2; if (PixelType == "32U" || PixelType == "32S") return 4; + if (PixelType == "FD") // to help unfortunate users to manage DOUBLE + return 8; dbg.Verbose(0, "gdcmHeader::GetPixelSize: Unknown pixel type"); return 0; } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief Build the Pixel Type of the image. @@ -111,87 +80,96 @@ int gdcmHeaderHelper::GetPixelSize() { * - 16S signed 16 bit, * - 32U unsigned 32 bit, * - 32S signed 32 bit, + * - FD Double, * \warning 12 bit images appear as 16 bit. + * 24 bit images appear as 8 bit + * 64 bit means 'DOUBLE' images + * (no DOUBLE images in kosher DICOM, + * but so usefull for people that miss them ;-) * @return */ -string gdcmHeaderHelper::GetPixelType() { - string BitsAlloc; - BitsAlloc = GetElValByName("Bits Allocated"); - if (BitsAlloc == GDCM_UNFOUND) { +std::string gdcmHeaderHelper::GetPixelType() { + std::string BitsAlloc; + BitsAlloc = GetEntryByNumber(0x0028, 0x0100); + if (BitsAlloc == GDCM_UNFOUND) { // Bits Allocated dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated"); - BitsAlloc = string("16"); + BitsAlloc = std::string("16"); } - if (BitsAlloc == "12") - BitsAlloc = string("16"); - - string Signed; - Signed = GetElValByName("Pixel Representation"); - if (Signed == GDCM_UNFOUND) { + if (BitsAlloc == "12") // It will be unpacked + BitsAlloc = std::string("16"); + else if (BitsAlloc == "24") // (in order no to be messed up + BitsAlloc = std::string("8"); // by old RGB images) + + std::string Signed; + Signed = GetEntryByNumber(0x0028, 0x0103); + if (Signed == GDCM_UNFOUND) { // "Pixel Representation" dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Pixel Representation"); - BitsAlloc = string("0"); + BitsAlloc = std::string("0"); } + if (BitsAlloc == "64") // to help users that want to deal with DOUBLE + return("FD"); + if (Signed == "0") - Signed = string("U"); + Signed = std::string("U"); else - Signed = string("S"); + Signed = std::string("S"); return( BitsAlloc + Signed); } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0028,0030 : Pixel Spacing - * \ else 1. + * else 1.0 * @return X dimension of a pixel */ float gdcmHeaderHelper::GetXSpacing() { float xspacing, yspacing; - string StrSpacing = GetPubElValByNumber(0x0028,0x0030); - - if (StrSpacing == GDCM_UNFOUND) { - dbg.Verbose(0, "gdcmHeader::GetXSpacing: unfound Pixel Spacing (0028,0030)"); - return 1.; - } - if( sscanf( StrSpacing.c_str(), "%f\\%f", &xspacing, &yspacing) != 2) - return 0.; - //else - return xspacing; + std::string StrSpacing = GetEntryByNumber(0x0028,0x0030); + + if (StrSpacing == GDCM_UNFOUND) { + dbg.Verbose(0, "gdcmHeader::GetXSpacing: unfound Pixel Spacing (0028,0030)"); + return 1.; + } + int nbValues; + if( (nbValues = sscanf( StrSpacing.c_str(), "%f\\%f", &yspacing, &xspacing)) != 2) { + if (nbValues==1) // if single value is found, xspacing is defaulted to yspacing + return yspacing; + } + if (xspacing == 0.) { + dbg.Verbose(0, "gdcmHeader::GetYSpacing: gdcmData/CT-MONO2-8-abdo.dcm problem"); + // seems to be a bug in the header ... + sscanf( StrSpacing.c_str(), "%f\\0\\%f", &yspacing, &xspacing); + } + return xspacing; } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0028,0030 : Pixel Spacing - * \ else 1. + * else 1.0 * @return Y dimension of a pixel */ float gdcmHeaderHelper::GetYSpacing() { - float xspacing, yspacing; - string StrSpacing = GetPubElValByNumber(0x0028,0x0030); + float yspacing; + std::string StrSpacing = GetEntryByNumber(0x0028,0x0030); if (StrSpacing == GDCM_UNFOUND) { dbg.Verbose(0, "gdcmHeader::GetYSpacing: unfound Pixel Spacing (0028,0030)"); return 1.; } - if( sscanf( StrSpacing.c_str(), "%f\\%f", &xspacing, &yspacing) != 2) - return 0.; - if (yspacing == 0.) { - dbg.Verbose(0, "gdcmHeader::GetYSpacing: gdcmData/CT-MONO2-8-abdo.dcm problem"); - // seems to be a bug in the header ... - sscanf( StrSpacing.c_str(), "%f\\0\\%f", &xspacing, &yspacing); - } + sscanf( StrSpacing.c_str(), "%f", &yspacing); return yspacing; } -//---------------------------------------------------------------------------- /** *\ingroup gdcmHeaderHelper *\brief gets the info from 0018,0088 : Space Between Slices - *\ else from 0018,0050 : Slice Thickness - *\ else 1. + * else from 0018,0050 : Slice Thickness + * else 1.0 * @return Z dimension of a voxel-to be */ float gdcmHeaderHelper::GetZSpacing() { - // TODO : translate into English // Spacing Between Slices : distance entre le milieu de chaque coupe // Les coupes peuvent etre : // jointives (Spacing between Slices = Slice Thickness) @@ -202,11 +180,11 @@ float gdcmHeaderHelper::GetZSpacing() { // Si le Spacing Between Slices est absent, // on suppose que les coupes sont jointives - string StrSpacingBSlices = GetPubElValByNumber(0x0018,0x0088); + std::string StrSpacingBSlices = GetEntryByNumber(0x0018,0x0088); if (StrSpacingBSlices == GDCM_UNFOUND) { dbg.Verbose(0, "gdcmHeader::GetZSpacing: unfound StrSpacingBSlices"); - string StrSliceThickness = GetPubElValByNumber(0x0018,0x0050); + std::string StrSliceThickness = GetEntryByNumber(0x0018,0x0050); if (StrSliceThickness == GDCM_UNFOUND) return 1.; else @@ -220,7 +198,140 @@ float gdcmHeaderHelper::GetZSpacing() { } } -//---------------------------------------------------------------------------- +/** + *\ingroup gdcmHeaderHelper + *\brief gets the info from 0028,1052 : Rescale Intercept + * @return Rescale Intercept + */ +float gdcmHeaderHelper::GetRescaleIntercept() { + float resInter = 0.; + std::string StrRescInter = GetEntryByNumber(0x0028,0x1052); //0028 1052 DS IMG Rescale Intercept + if (StrRescInter != GDCM_UNFOUND) { + if( sscanf( StrRescInter.c_str(), "%f", &resInter) != 1) { + dbg.Verbose(0, "gdcmHeader::GetRescaleIntercept: Rescale Slope is empty"); + // bug in the element 0x0028,0x1052 + } + } + return resInter; +} + +/** + *\ingroup gdcmHeaderHelper + *\brief gets the info from 0028,1053 : Rescale Slope + * @return Rescale Slope + */ + float gdcmHeaderHelper::GetRescaleSlope() { + float resSlope = 1.; + std::string StrRescSlope = GetEntryByNumber(0x0028,0x1053); //0028 1053 DS IMG Rescale Slope + if (StrRescSlope != GDCM_UNFOUND) { + if( sscanf( StrRescSlope.c_str(), "%f", &resSlope) != 1) { + dbg.Verbose(0, "gdcmHeader::GetRescaleSlope: Rescale Slope is empty"); + // bug in the element 0x0028,0x1053 + } + } + return resSlope; +} + +/** + * \ingroup gdcmHeaderHelper + * \brief This function is intended to user who doesn't want + * to have to manage a LUT and expects to get an RBG Pixel image + * (or a monochrome one ...) + * \warning to be used with GetImagePixels() + * @return 1 if Gray level, 3 if Color (RGB, YBR or PALETTE COLOR) + */ +int gdcmHeaderHelper::GetNumberOfScalarComponents() { + if (GetSamplesPerPixel() ==3) + return 3; + + // 0028 0100 US IMG Bits Allocated + // (in order no to be messed up by old RGB images) + if (gdcmHeader::GetEntryByNumber(0x0028,0x0100) == "24") + return 3; + + std::string PhotometricInterpretation = + gdcmHeader::GetEntryByNumber(0x0028,0x0004); + + if ( ( PhotometricInterpretation == "PALETTE COLOR ") ) { + if (HasLUT()) // PALETTE COLOR is NOT enough + return 3; + else + return 1; + } + + //beware of trailing space at end of string + if (PhotometricInterpretation.find(GDCM_UNFOUND) < + PhotometricInterpretation.length() || + PhotometricInterpretation.find("MONOCHROME1") < + PhotometricInterpretation.length() || + PhotometricInterpretation.find("MONOCHROME2") < + PhotometricInterpretation.length() ) + return 1; + else + // we assume that *all* kinds of YBR are dealt with + return 3; +} + +/** + * \ingroup gdcmHeaderHelper + * \brief This function is intended to user that DOESN'T want + * to get RGB pixels image when it's stored as a PALETTE COLOR image + * - the (vtk) user is supposed to know how deal with LUTs - + * \warning to be used with GetImagePixelsRaw() + * @return 1 if Gray level, 3 if Color (RGB or YBR - NOT 'PALETTE COLOR' -) + */ +int gdcmHeaderHelper::GetNumberOfScalarComponentsRaw() { + + // 0028 0100 US IMG Bits Allocated + // (in order no to be messed up by old RGB images) + if (gdcmHeader::GetEntryByNumber(0x0028,0x0100) == "24") + return 3; + + // we assume that *all* kinds of YBR are dealt with + return GetSamplesPerPixel(); +} + +/** + *\ingroup gdcmHeaderHelper + *\brief gets the info from 0020,000d : Study Instance UID + *\todo ? : return the ACR-NEMA element value if DICOM one is not found + * @return Study Instance UID + */ + std::string gdcmHeaderHelper::GetStudyUID(){ + return GetEntryByNumber(0x0020,0x000d); //0020 000d UI REL Study Instance UID +} + +/** + *\ingroup gdcmHeaderHelper + *\brief gets the info from 0020,000e : Series Instance UID + *\todo ? : return the ACR-NEMA element value if DICOM one is not found + * @return Series Instance UID + */ + std::string gdcmHeaderHelper::GetSeriesUID(){ + return GetEntryByNumber(0x0020,0x000e); //0020 000e UI REL Series Instance UID +} + +/** + *\ingroup gdcmHeaderHelper + *\brief gets the info from 0008,0016 : SOP Class UID + *\todo ? : return the ACR-NEMA element value if DICOM one is not found + * @return SOP Class UID + */ + std::string gdcmHeaderHelper::GetClassUID(){ + return GetEntryByNumber(0x0008,0x0016); //0008 0016 UI ID SOP Class UID +} + +/** + *\ingroup gdcmHeaderHelper + *\brief gets the info from 0008,0018 : SOP Instance UID + *\todo ? : return the ACR-NEMA element value if DICOM one is not found + * @return SOP Instance UID + */ + std::string gdcmHeaderHelper::GetInstanceUID(){ + return GetEntryByNumber(0x0008,0x0018); //0008 0018 UI ID SOP Instance UID +} +// +// -------------- Remember ! ---------------------------------- // // Image Position Patient (0020,0032): // If not found (ACR_NEMA) we try Image Position (0020,0030) @@ -231,21 +342,25 @@ float gdcmHeaderHelper::GetZSpacing() { // TODO : find a way to inform the caller nothing was found // TODO : How to tell the caller a wrong number of values was found? +// +// --------------------------------------------------------------- +// /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0020,0032 : Image Position Patient - *\ else from 0020,0030 : Image Position (RET) - *\ else 0. - * @return up-left image corner position + * else from 0020,0030 : Image Position (RET) + * else 0. + * @return up-left image corner X position */ + float gdcmHeaderHelper::GetXOrigin() { float xImPos, yImPos, zImPos; - string StrImPos = GetPubElValByNumber(0x0020,0x0032); + std::string StrImPos = GetEntryByNumber(0x0020,0x0032); if (StrImPos == GDCM_UNFOUND) { dbg.Verbose(0, "gdcmHeader::GetXImagePosition: unfound Image Position Patient (0020,0032)"); - StrImPos = GetPubElValByNumber(0x0020,0x0030); // For ACR-NEMA images + StrImPos = GetEntryByNumber(0x0020,0x0030); // For ACR-NEMA images if (StrImPos == GDCM_UNFOUND) { dbg.Verbose(0, "gdcmHeader::GetXImagePosition: unfound Image Position (RET) (0020,0030)"); // How to tell the caller nothing was found ? @@ -256,21 +371,21 @@ float gdcmHeaderHelper::GetXOrigin() { return 0.; return xImPos; } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0020,0032 : Image Position Patient - * \ else from 0020,0030 : Image Position (RET) - * \ else 0. - * @return up-left image corner position + * else from 0020,0030 : Image Position (RET) + * else 0. + * @return up-left image corner Y position */ float gdcmHeaderHelper::GetYOrigin() { float xImPos, yImPos, zImPos; - string StrImPos = GetPubElValByNumber(0x0020,0x0032); + std::string StrImPos = GetEntryByNumber(0x0020,0x0032); if (StrImPos == GDCM_UNFOUND) { dbg.Verbose(0, "gdcmHeader::GetYImagePosition: unfound Image Position Patient (0020,0032)"); - StrImPos = GetPubElValByNumber(0x0020,0x0030); // For ACR-NEMA images + StrImPos = GetEntryByNumber(0x0020,0x0030); // For ACR-NEMA images if (StrImPos == GDCM_UNFOUND) { dbg.Verbose(0, "gdcmHeader::GetYImagePosition: unfound Image Position (RET) (0020,0030)"); // How to tell the caller nothing was found ? @@ -281,7 +396,7 @@ float gdcmHeaderHelper::GetYOrigin() { return 0.; return yImPos; } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0020,0032 : Image Position Patient @@ -289,11 +404,11 @@ float gdcmHeaderHelper::GetYOrigin() { * \ else from 0020,1041 : Slice Location * \ else from 0020,0050 : Location * \ else 0. - * @return up-left image corner position + * @return up-left image corner Z position */ float gdcmHeaderHelper::GetZOrigin() { float xImPos, yImPos, zImPos; - string StrImPos = GetPubElValByNumber(0x0020,0x0032); + std::string StrImPos = GetEntryByNumber(0x0020,0x0032); if (StrImPos != GDCM_UNFOUND) { if( sscanf( StrImPos.c_str(), "%f\\%f\\%f", &xImPos, &yImPos, &zImPos) != 3) { dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Image Position Patient (0020,0032)"); @@ -302,7 +417,7 @@ float gdcmHeaderHelper::GetZOrigin() { return zImPos; } } - StrImPos = GetPubElValByNumber(0x0020,0x0030); // For ACR-NEMA images + StrImPos = GetEntryByNumber(0x0020,0x0030); // For ACR-NEMA images if (StrImPos != GDCM_UNFOUND) { if( sscanf( StrImPos.c_str(), "%f\\%f\\%f", &xImPos, &yImPos, &zImPos) != 3) { dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Image Position (RET) (0020,0030)"); @@ -311,7 +426,7 @@ float gdcmHeaderHelper::GetZOrigin() { return zImPos; } } - string StrSliceLocation = GetPubElValByNumber(0x0020,0x1041);// for *very* old ACR-NEMA images + std::string StrSliceLocation = GetEntryByNumber(0x0020,0x1041);// for *very* old ACR-NEMA images if (StrSliceLocation != GDCM_UNFOUND) { if( sscanf( StrSliceLocation.c_str(), "%f", &zImPos) !=1) { dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Slice Location (0020,1041)"); @@ -321,7 +436,7 @@ float gdcmHeaderHelper::GetZOrigin() { } } dbg.Verbose(0, "gdcmHeader::GetZImagePosition: unfound Slice Location (0020,1041)"); - string StrLocation = GetPubElValByNumber(0x0020,0x0050); + std::string StrLocation = GetEntryByNumber(0x0020,0x0050); if (StrLocation != GDCM_UNFOUND) { if( sscanf( StrLocation.c_str(), "%f", &zImPos) !=1) { dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Location (0020,0050)"); @@ -333,7 +448,7 @@ float gdcmHeaderHelper::GetZOrigin() { dbg.Verbose(0, "gdcmHeader::GetYImagePosition: unfound Location (0020,0050)"); return 0.; // Hopeless } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0020,0013 : Image Number @@ -346,20 +461,20 @@ int gdcmHeaderHelper::GetImageNumber() { //binary conversion rules. This may be preferable to sscanf() since atoi() is a much smaller, // simpler and faster function. sscanf() can do all possible conversions whereas atoi() can //only do single decimal integer conversions. - string StrImNumber = GetPubElValByNumber(0x0020,0x0013); //0020 0013 IS REL Image Number + std::string StrImNumber = GetEntryByNumber(0x0020,0x0013); //0020 0013 IS REL Image Number if (StrImNumber != GDCM_UNFOUND) { return atoi( StrImNumber.c_str() ); } return 0; //Hopeless } -//---------------------------------------------------------------------------- + /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0008,0060 : Modality - * @return ModalityType + * @return Modality Type */ ModalityType gdcmHeaderHelper::GetModality(void) { - string StrModality = GetPubElValByNumber(0x0008,0x0060); //0008 0060 CS ID Modality + std::string StrModality = GetEntryByNumber(0x0008,0x0060); //0008 0060 CS ID Modality if (StrModality != GDCM_UNFOUND) { if ( StrModality.find("AU") < StrModality.length()) return AU; else if ( StrModality.find("AS") < StrModality.length()) return AS; @@ -390,10 +505,10 @@ ModalityType gdcmHeaderHelper::GetModality(void) { else if ( StrModality.find("PT") < StrModality.length()) return PT; else if ( StrModality.find("RF") < StrModality.length()) return RF; else if ( StrModality.find("RG") < StrModality.length()) return RG; - else if ( StrModality.find("RTDOSE") < StrModality.length()) return RTDOSE; - else if ( StrModality.find("RTIMAGE") < StrModality.length()) return RTIMAGE; - else if ( StrModality.find("RTPLAN") < StrModality.length()) return RTPLAN; - else if ( StrModality.find("RTSTRUCT") < StrModality.length()) return RTSTRUCT; + else if ( StrModality.find("RTDOSE") < StrModality.length()) return RTDOSE; + else if ( StrModality.find("RTIMAGE") < StrModality.length()) return RTIMAGE; + else if ( StrModality.find("RTPLAN") < StrModality.length()) return RTPLAN; + else if ( StrModality.find("RTSTRUCT")< StrModality.length()) return RTSTRUCT; else if ( StrModality.find("SM") < StrModality.length()) return SM; else if ( StrModality.find("ST") < StrModality.length()) return ST; else if ( StrModality.find("TG") < StrModality.length()) return TG; @@ -412,49 +527,10 @@ ModalityType gdcmHeaderHelper::GetModality(void) { return Unknow; } -//---------------------------------------------------------------------------- -string gdcmHeaderHelper::GetStudyUID() -{ - return GetPubElValByNumber(0x0020,0x000d); //!0020 000d UI REL Study Instance UID -} -//---------------------------------------------------------------------------- -string gdcmHeaderHelper::GetSeriesUID() -{ - return GetPubElValByNumber(0x0020,0x000e); //!0020 000e UI REL Series Instance UID -} -//---------------------------------------------------------------------------- -string gdcmHeaderHelper::GetClassUID() -{ - return GetPubElValByNumber(0x0008,0x0016); //!0008 0016 UI ID SOP Class UID -} -//---------------------------------------------------------------------------- -string gdcmHeaderHelper::GetInstanceUID() -{ - return GetPubElValByNumber(0x0008,0x0018); //!0008 0018 UI ID SOP Instance UID -} - - - - - - - - - -gdcmSerieHeaderHelper::~gdcmSerieHeaderHelper() -{ - //! \todo - for (list::iterator it = CoherentGdcmFileList.begin(); - it != CoherentGdcmFileList.end(); it++) - { - delete *it; - } - CoherentGdcmFileList.clear(); -} -//---------------------------------------------------------------------------- /** * \ingroup gdcmHeaderHelper * \brief gets the info from 0020,0037 : Image Orientation Patient + * @param iop adress of the (6)float aray to receive values * @return cosines of image orientation patient */ void gdcmHeaderHelper::GetImageOrientationPatient( float* iop ) { @@ -462,7 +538,7 @@ void gdcmHeaderHelper::GetImageOrientationPatient( float* iop ) { //iop is supposed to be float[6] iop[0] = iop[1] = iop[2] = iop[3] = iop[4] = iop[5] = 0; - string StrImOriPat = GetPubElValByNumber(0x0020,0x0037); // 0020 0037 DS REL Image Orientation (Patient) + std::string StrImOriPat = GetEntryByNumber(0x0020,0x0037); // 0020 0037 DS REL Image Orientation (Patient) if (StrImOriPat != GDCM_UNFOUND) { if( sscanf( StrImOriPat.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6) { @@ -474,7 +550,7 @@ void gdcmHeaderHelper::GetImageOrientationPatient( float* iop ) { } //For ACR-NEMA - StrImOriPat = GetPubElValByNumber(0x0020,0x0035); //0020 0035 DS REL Image Orientation (RET) + StrImOriPat = GetEntryByNumber(0x0020,0x0035); //0020 0035 DS REL Image Orientation (RET) if (StrImOriPat != GDCM_UNFOUND) { if( sscanf( StrImOriPat.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6) { @@ -486,72 +562,113 @@ void gdcmHeaderHelper::GetImageOrientationPatient( float* iop ) { } } -//---------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Protected + +//----------------------------------------------------------------------------- +// Private + +//----------------------------------------------------------------------------- + + + +//----------------------------------------------------------------------------- +// gdcmSerieHeaderHelper +//----------------------------------------------------------------------------- +// Constructor / Destructor +gdcmSerieHeaderHelper::~gdcmSerieHeaderHelper(){ + //! \todo + for (std::list::iterator it = CoherentGdcmFileList.begin(); + it != CoherentGdcmFileList.end(); it++) + { + delete *it; + } + CoherentGdcmFileList.clear(); +} + +//----------------------------------------------------------------------------- +// Print + +//----------------------------------------------------------------------------- +// Public /** - * \ingroup gdcmHeaderHelper - * \brief add a gdcmFile to the list based on file name - */ -void gdcmSerieHeaderHelper::AddFileName(string filename) -{ + * \ingroup gdcmHeaderHelper + * \brief add a gdcmFile to the list based on file name + * @param filename Name of the file to deal with + */ +void gdcmSerieHeaderHelper::AddFileName(std::string filename) { gdcmHeaderHelper *GdcmFile = new gdcmHeaderHelper( filename.c_str() ); this->CoherentGdcmFileList.push_back( GdcmFile ); } -//---------------------------------------------------------------------------- + /** - * \ingroup gdcmHeaderHelper - * \brief add a gdcmFile to the list - */ -void gdcmSerieHeaderHelper::AddGdcmFile(gdcmHeaderHelper *file) -{ + * \ingroup gdcmHeaderHelper + * \brief add a gdcmFile to the list + * @param file gdcmHeaderHelper to add + */ +void gdcmSerieHeaderHelper::AddGdcmFile(gdcmHeaderHelper *file){ this->CoherentGdcmFileList.push_back( file ); } -//---------------------------------------------------------------------------- + /** - * \ingroup gdcmHeaderHelper - * \brief \todo - */ -void gdcmSerieHeaderHelper::SetDirectory(string dir) -{ - list filenames_list; - GetDir(dir, filenames_list); //OS specific + * \ingroup gdcmHeaderHelper + * \brief Sets the Directory + * @param dir Name of the directory to deal with + */ +void gdcmSerieHeaderHelper::SetDirectory(std::string dir){ + gdcmDirList filenames_list(dir); //OS specific - for(list::iterator it = filenames_list.begin(); it != - filenames_list.end(); it++) + for(gdcmDirList::iterator it = filenames_list.begin(); + it !=filenames_list.end(); it++) { gdcmHeaderHelper *file = new gdcmHeaderHelper( it->c_str() ); this->CoherentGdcmFileList.push_back( file ); } } -//---------------------------------------------------------------------------- -//This could be implemented in a 'Strategy Pattern' approach -//But as I don't know how to do it, I leave it this way -//BTW, this is also a Strategy, I don't know this is the best approcah :) -void gdcmSerieHeaderHelper::OrderGdcmFileList() -{ - if( ImagePositionPatientOrdering() ) - { + +/** + * \ingroup gdcmHeaderHelper + * \brief Sorts the File List + * \warning This could be implemented in a 'Strategy Pattern' approach + * But as I don't know how to do it, I leave it this way + * BTW, this is also a Strategy, I don't know this is the best approach :) +*/ +void gdcmSerieHeaderHelper::OrderGdcmFileList(){ + if( ImagePositionPatientOrdering() ) { return ; } - else if( ImageNumberOrdering() ) - { + else if( ImageNumberOrdering() ) { return ; - } - else - { + } else { FileNameOrdering(); } } -//---------------------------------------------------------------------------- + /** - * \ingroup gdcmHeaderHelper - * \brief - We may order, considering : - -# Image Number - -# Image Position Patient - -# More to come :) + * \ingroup gdcmHeaderHelper + * \brief Gets the *coherent* File List + * @return the *coherent* File List */ -//based on Jolinda's algorithm +std::list &gdcmSerieHeaderHelper::GetGdcmFileList() { + return CoherentGdcmFileList; +} + +//----------------------------------------------------------------------------- +// Protected + +//----------------------------------------------------------------------------- +// Private +/** + * \ingroup gdcmHeaderHelper + * \brief sorts the images, according to their Patient Position + * We may order, considering : + * -# Image Number + * -# Image Position Patient + * -# More to come :) + * @return false only if the header is bugged ! + */ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() +//based on Jolinda's algorithm { //iop is calculated based on the file file float *cosines = new float[6]; @@ -561,10 +678,10 @@ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() float min, max; bool first = true; int n=0; - vector distlist; + std::vector distlist; //!\todo rewrite this for loop. - for (list::iterator it = CoherentGdcmFileList.begin(); + for (std::list::iterator it = CoherentGdcmFileList.begin(); it != CoherentGdcmFileList.end(); it++) { if(first) { @@ -610,7 +727,6 @@ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() delete[] cosines; return false; } - distlist.push_back( dist ); @@ -623,7 +739,7 @@ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() //Then I order the slices according to the value "dist". Finally, once //I've read in all the slices, I calculate the z-spacing as the difference //between the "dist" values for the first two slices. - vector CoherentGdcmFileVector(n); + std::vector CoherentGdcmFileVector(n); //CoherentGdcmFileVector.reserve( n ); CoherentGdcmFileVector.resize( n ); //assert( CoherentGdcmFileVector.capacity() >= n ); @@ -633,7 +749,7 @@ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() n = 0; //VC++ don't understand what scope is !! it -> it2 - for (list::iterator it2 = CoherentGdcmFileList.begin(); + for (std::list::iterator it2 = CoherentGdcmFileList.begin(); it2 != CoherentGdcmFileList.end(); it2++, n++) { //2*n sort algo !! @@ -646,7 +762,7 @@ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only //VC++ don't understand what scope is !! it -> it3 - for (vector::iterator it3 = CoherentGdcmFileVector.begin(); + for (std::vector::iterator it3 = CoherentGdcmFileVector.begin(); it3 != CoherentGdcmFileVector.end(); it3++) { CoherentGdcmFileList.push_back( *it3 ); @@ -658,15 +774,19 @@ bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering() return true; } -//---------------------------------------------------------------------------- -//Based on Image Number -bool gdcmSerieHeaderHelper::ImageNumberOrdering() -{ + +/** + * \ingroup gdcmHeaderHelper + * \brief sorts the images, according to their Image Number + * @return false only if the header is bugged ! + */ + +bool gdcmSerieHeaderHelper::ImageNumberOrdering() { int min, max, pos; - int n = 0;//CoherentGdcmFileList.size(); //O(N) operation !! + int n = 0;//CoherentGdcmFileList.size() is a O(N) operation !! unsigned char *partition; - list::iterator it = CoherentGdcmFileList.begin(); + std::list::iterator it = CoherentGdcmFileList.begin(); min = max = (*it)->GetImageNumber(); for (; it != CoherentGdcmFileList.end(); it++, n++) @@ -681,10 +801,10 @@ bool gdcmSerieHeaderHelper::ImageNumberOrdering() partition = new unsigned char[n]; memset(partition, 0, n); - vector CoherentGdcmFileVector(n); + std::vector CoherentGdcmFileVector(n); //VC++ don't understand what scope is !! it -> it2 - for (list::iterator it2 = CoherentGdcmFileList.begin(); + for (std::list::iterator it2 = CoherentGdcmFileList.begin(); it2 != CoherentGdcmFileList.end(); it2++) { pos = (*it2)->GetImageNumber(); @@ -692,7 +812,7 @@ bool gdcmSerieHeaderHelper::ImageNumberOrdering() partition[pos - min]++; } - unsigned char mult; + unsigned char mult = 1; for(int i=0; i it3 CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only - for (vector::iterator it3 = CoherentGdcmFileVector.begin(); + for (std::vector::iterator it3 = CoherentGdcmFileVector.begin(); it3 != CoherentGdcmFileVector.end(); it3++) { CoherentGdcmFileList.push_back( *it3 ); @@ -708,18 +828,19 @@ bool gdcmSerieHeaderHelper::ImageNumberOrdering() CoherentGdcmFileVector.clear(); delete[] partition; - return mult; + return (mult!=0); } -//---------------------------------------------------------------------------- -bool gdcmSerieHeaderHelper::FileNameOrdering() -{ + + +/** + * \ingroup gdcmHeaderHelper + * \brief sorts the images, according to their File Name + * @return false only if the header is bugged ! + */ + bool gdcmSerieHeaderHelper::FileNameOrdering() { //using the sort //sort(CoherentGdcmFileList.begin(), CoherentGdcmFileList.end()); return true; } -//---------------------------------------------------------------------------- -list &gdcmSerieHeaderHelper::GetGdcmFileList() -{ - return CoherentGdcmFileList; -} -//---------------------------------------------------------------------------- + +//-----------------------------------------------------------------------------