* 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
- *\TODO : may be we need one more bool,
- * to allow skipping the private elements while parsing the header
- * in order to save space
+ * during parsing, to save memory space
*/
gdcmHeader::gdcmHeader(const char *InFilename,
bool exception_on_error,
/**
* \ingroup gdcmHeader
- * \brief
+ * \brief Constructor
* @param exception_on_error
*/
gdcmHeader::gdcmHeader(bool exception_on_error) :
// see gdcmParser.cxx
//-----------------------------------------------------------------------------
// Public
+
/**
* \ingroup gdcmHeader
* \brief This predicate, based on hopefully reasonable heuristics,
if ( !GetHeaderEntryByNumber(0x0028, 0x0102) )
return false; // "High Bit"
if ( !GetHeaderEntryByNumber(0x0028, 0x0103) )
- return false; // "Pixel Representation"
+ return false; // "Pixel Representation" i.e. 'Sign'
return true;
}
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was already encountered
* and if it corresponds to a JPEGBaseLineProcess1 one.
- *
* @return True when JPEGBaseLineProcess1found. False in all other cases.
*/
bool gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(void) {
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was already encountered
* and if it corresponds to a JPEGExtendedProcess2-4 one.
- *
* @return True when JPEGExtendedProcess2-4 found. False in all other cases.
*/
bool gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(void) {
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was already encountered
* and if it corresponds to a JPEGExtendeProcess3-5 one.
- *
* @return True when JPEGExtendedProcess3-5 found. False in all other cases.
*/
bool gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(void) {
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was already encountered
* and if it corresponds to a JPEGSpectralSelectionProcess6-8 one.
- *
* @return True when JPEGSpectralSelectionProcess6-8 found. False in all
* other cases.
*/
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was already encountered
* and if it corresponds to a RLE Lossless one.
- *
* @return True when RLE Lossless found. False in all
* other cases.
*/
* \ingroup gdcmHeader
* \brief Determines if Transfer Syntax was already encountered
* and if it corresponds to a JPEG Lossless one.
- *
* @return True when RLE Lossless found. False in all
* other cases.
*/
/**
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was already encountered
- * and if it corresponds to a JPEG200 one.0
- *
+ * and if it corresponds to a JPEG2000 one
* @return True when JPEG2000 (Lossly or LossLess) found. False in all
* other cases.
*/
*/
bool gdcmHeader::IsDicomV3(void) {
// Checking if Transfert Syntax exists is enough
+ // Anyway, it's to late check if the 'Preamble' was found ...
+ // And ... would it be a rich idea to check ?
+ // (some 'no Preamble' DICOM images exist !)
return (GetHeaderEntryByNumber(0x0002, 0x0010) != NULL);
}
* \brief Retrieve the number of lines of image.
* \warning The defaulted value is 1 as opposed to gdcmHeader::GetXSize()
* @return The encountered size when found, 1 by default
- * (The file contains a Signal, not an Image).
+ * (The ACR-MEMA file contains a Signal, not an Image).
*/
int gdcmHeader::GetYSize(void) {
std::string StrSize = GetEntryByNumber(0x0028,0x0010);
* of frames of a multiframe.
* \warning When present we consider the "Number of Frames" as the third
* dimension. When absent we consider the third dimension as
- * being the "Planes" tag content.
+ * being the ACR-NEMA "Planes" tag content.
* @return The encountered size when found, 1 by default (single image).
*/
int gdcmHeader::GetZSize(void) {
if (StrSize != GDCM_UNFOUND)
return atoi(StrSize.c_str());
- // We then consider the "Planes" entry as the third dimension [we
- // cannot retrieve by name since "Planes tag is present both in
- // IMG (0028,0012) and OLY (6000,0012) sections of the dictionary].
+ // We then consider the "Planes" entry as the third dimension
StrSize = GetEntryByNumber(0x0028,0x0012);
if (StrSize != GDCM_UNFOUND)
return atoi(StrSize.c_str());
* \ingroup gdcmHeader
* \brief Retrieve the number of Bits Stored (actually used)
* (as opposite to number of Bits Allocated)
- *
* @return The encountered number of Bits Stored, 0 by default.
* 0 means the file is NOT USABLE. The caller has to check it !
*/
* \ingroup gdcmHeader
* \brief Retrieve the number of Bits Allocated
* (8, 12 -compacted ACR-NEMA files, 16, ...)
- *
* @return The encountered number of Bits Allocated, 0 by default.
* 0 means the file is NOT USABLE. The caller has to check it !
*/
-int gdcmHeader::GetBitsAllocated(void) { // TODO : move to gdcmFile
+int gdcmHeader::GetBitsAllocated(void) {
std::string StrSize = GetEntryByNumber(0x0028,0x0100);
if (StrSize == GDCM_UNFOUND)
return 0; // It's supposed to be mandatory
* \ingroup gdcmHeader
* \brief Retrieve the number of Samples Per Pixel
* (1 : gray level, 3 : RGB -1 or 3 Planes-)
- *
* @return The encountered number of Samples Per Pixel, 1 by default.
* (Gray level Pixels)
*/
-int gdcmHeader::GetSamplesPerPixel(void) { // TODO : move to gdcmFile
+int gdcmHeader::GetSamplesPerPixel(void) {
std::string StrSize = GetEntryByNumber(0x0028,0x0002);
if (StrSize == GDCM_UNFOUND)
return 1; // Well, it's supposed to be mandatory ...
- // but sometimes it's missing : we assume Gray pixels
+ // but sometimes it's missing : *we* assume Gray pixels
return atoi(StrSize.c_str());
}
* \ingroup gdcmHeader
* \brief Retrieve the Planar Configuration for RGB images
* (0 : RGB Pixels , 1 : R Plane + G Plane + B Plane)
- *
* @return The encountered Planar Configuration, 0 by default.
*/
int gdcmHeader::GetPlanarConfiguration(void) {
return 2;
if (PixelType == "32U" || PixelType == "32S")
return 4;
+ if (PixelType == "FD")
+ return 8;
dbg.Verbose(0, "gdcmHeader::GetPixelSize: Unknown pixel type");
return 0;
}
* - 16S signed 16 bit,
* - 32U unsigned 32 bit,
* - 32S signed 32 bit,
+ * - FD floating double 64 bits (Not kosher DICOM, but so usefull!)
* \warning 12 bit images appear as 16 bit.
* \ 24 bit images appear as 8 bit
* @return 0S if nothing found. NOT USABLE file. The caller has to check
dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
BitsAlloc = std::string("16");
}
+ if (BitsAlloc == "64") // )
+ return ("FD");
if (BitsAlloc == "12") // It will be unpacked
BitsAlloc = std::string("16");
else if (BitsAlloc == "24") // (in order no to be messed up
* \ingroup gdcmHeader
* \brief Recover the offset (from the beginning of the file)
* \ of *image* pixels (not *icone image* pixels, if any !)
+ * @return Pixel Offset
*/
size_t gdcmHeader::GetPixelOffset(void) {
//
* \warning Right now, 'Segmented xxx Palette Color Lookup Table Data'
* \ are NOT considered as LUT, since nobody knows
* \ how to deal with them
- * @return a Boolean
+ * \ Please warn me if you know sbdy that *does* know ... jprx
+ * @return true if LUT Descriptors and LUT Tables were found
*/
bool gdcmHeader::HasLUT(void) {
- // Check the presence of the LUT Descriptors
-
+ // Check the presence of the LUT Descriptors, and LUT Tables
// LutDescriptorRed
if ( !GetHeaderEntryByNumber(0x0028,0x1101) )
return false;
return false;
// LutDescriptorBlue
if ( !GetHeaderEntryByNumber(0x0028,0x1103) )
- return false;
-
- // It is not enough :
- // we check also
-
+ return false;
// Red Palette Color Lookup Table Data
if ( !GetHeaderEntryByNumber(0x0028,0x1201) )
return false;
* \brief gets the info from 0028,1101 : Lookup Table Desc-Red
* \ else 0
* @return Lookup Table number of Bits , 0 by default
- * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ * @ return bit number of each LUT item
*/
int gdcmHeader::GetLUTNbits(void) {
std::vector<std::string> tokens;
}
/**
- * \ingroup gdcmFile
+ * \ingroup gdcmHeader
* \brief Sets the Pixel Area size in the Header
* --> not-for-rats function
- *
- * \warning WARNING doit-etre etre publique ?
- * TODO : y aurait il un inconvenient à fusionner ces 2 fonctions
- *
* @param ImageDataSize new Pixel Area Size
* warning : nothing else is checked
*/
void gdcmHeader::SetImageDataSize(size_t ImageDataSize) {
std::string content1;
char car[20];
-
+
// Assumes HeaderEntry (GrPixel, NumPixel) is unique ...
// TODO deal with multiplicity (see gdcmData/icone.dcm)
sprintf(car,"%d",ImageDataSize);
SetEntryByNumber(content1, GrPixel, NumPixel);
}
-bool gdcmHeader::operator<(gdcmHeader &header)
-{
+
+/**
+ * \ingroup gdcmHeader
+ * \brief compares 2 Headers, according to DICOMDIR rules
+ * --> not-for-rats function
+ * \warning does NOT work with ACR-NEMA files
+ * \todo find a trick to solve the pb (use RET fields ?)
+ * @param header
+ * @return true if 'smaller'
+ */
+ bool gdcmHeader::operator<(gdcmHeader &header){
std::string s1,s2;
// Patient Name
// Constructor / Destructor
/**
* \ingroup gdcmHeaderHelper
- * \brief cstor
+ * \brief constructor
*/
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,
// 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.
*
*/
* - 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 ;-)
+ * 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
*/
std::string gdcmHeaderHelper::GetPixelType() {
}
}
+/**
+ *\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
return resInter;
}
-float gdcmHeaderHelper::GetRescaleSlope() {
+/**
+ *\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) {
// bug in the element 0x0028,0x1053
}
}
- return resSlope;
+ return resSlope;
}
/**
* \ingroup gdcmHeaderHelper
- * \brief This function is intended to user who doesn't whan
+ * \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;
return GetSamplesPerPixel();
}
-std::string gdcmHeaderHelper::GetStudyUID(){
+/**
+ *\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
}
-std::string gdcmHeaderHelper::GetSeriesUID(){
+/**
+ *\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
}
-std::string gdcmHeaderHelper::GetClassUID(){
+/**
+ *\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
}
-std::string gdcmHeaderHelper::GetInstanceUID(){
+/**
+ *\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)
// If not found (ACR-NEMA), we consider Slice Location (0020,1041)
// 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
+ * @return up-left image corner X position
*/
+
float gdcmHeaderHelper::GetXOrigin() {
float xImPos, yImPos, zImPos;
std::string StrImPos = GetEntryByNumber(0x0020,0x0032);
* \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
+ * @return up-left image corner Y position
*/
float gdcmHeaderHelper::GetYOrigin() {
float xImPos, yImPos, zImPos;
* \ 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;
/**
* \ingroup gdcmHeaderHelper
* \brief gets the info from 0008,0060 : Modality
- * @return ModalityType
+ * @return Modality Type
*/
ModalityType gdcmHeaderHelper::GetModality(void) {
std::string StrModality = GetEntryByNumber(0x0008,0x0060); //0008 0060 CS ID Modality
/**
* \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 ) {
/**
* \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() );
/**
* \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
+ * \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
}
}
-//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 :)
+/**
+ * \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() )
- {
+ if( ImagePositionPatientOrdering() ) {
return ;
}
- else if( ImageNumberOrdering() )
- {
+ else if( ImageNumberOrdering() ) {
return ;
- }
- else
- {
+ } else {
FileNameOrdering();
}
}
+/**
+ * \ingroup gdcmHeaderHelper
+ * \brief Gets the *coherent* File List
+ * @return the *coherent* File List
+*/
std::list<gdcmHeaderHelper*> &gdcmSerieHeaderHelper::GetGdcmFileList() {
return CoherentGdcmFileList;
}
// Private
/**
* \ingroup gdcmHeaderHelper
- * \brief
+ * \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
delete[] cosines;
return false;
}
-
distlist.push_back( dist );
return true;
}
-//Based on Image Number
+/**
+ * \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;
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;