From a9a9c2b27a6a015496a66506c09065b8ebb2cfbd Mon Sep 17 00:00:00 2001 From: malaterre Date: Tue, 16 Nov 2004 05:03:35 +0000 Subject: [PATCH] ENH: 1. Finish merging JMR patch for writting DICOM from scratch 2. Fix -hopefully- bug with MONOCHROME and space vs null character 3. Use const ref when possible 4. Add a new function InitializeDefaultHeader, which create a template DICOM header (CT image for now) 5. A few more comments 6. CreateUniqueUID can now be called without parameter --- src/gdcmFile.cxx | 7 +-- src/gdcmHeader.cxx | 106 ++++++++++++++++++++++++++++++++++++++++----- src/gdcmHeader.h | 12 ++++- src/gdcmUtil.h | 6 +-- 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index b5de832e..2cf2c255 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmFile.cxx,v $ Language: C++ - Date: $Date: 2004/11/16 02:54:35 $ - Version: $Revision: 1.155 $ + Date: $Date: 2004/11/16 05:03:35 $ + Version: $Revision: 1.156 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -18,6 +18,7 @@ #include "gdcmFile.h" #include "gdcmDebug.h" +#include "gdcmUtil.h" #include namespace gdcm @@ -346,7 +347,7 @@ uint8_t* File::GetImageData() if ( HeaderInternal->HasLUT() ) { // The LUT interpretation failed - std::string photometricInterpretation = "MONOCHROME1 "; + std::string photometricInterpretation = Util::DicomString("MONOCHROME1"); HeaderInternal->SetEntryByNumber( photometricInterpretation, 0x0028, 0x0004 ); PixelRead = 0; // no PixelRaw diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index bf44c55c..a950ddbb 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmHeader.cxx,v $ Language: C++ - Date: $Date: 2004/11/10 18:27:23 $ - Version: $Revision: 1.200 $ + Date: $Date: 2004/11/16 05:03:35 $ + Version: $Revision: 1.201 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -79,11 +79,12 @@ Header::Header( std::string const & filename ): } /** - * \brief Constructor + * \brief Constructor used when we want to generate dicom files from scratch */ Header::Header() :Document() { + InitializeDefaultHeader(); } /** @@ -93,7 +94,6 @@ Header::~Header () { } - /** * \brief Performs some consistency checking on various 'File related' * (as opposed to 'DicomDir related') entries @@ -463,8 +463,8 @@ int Header::GetNumberOfScalarComponents() // beware of trailing space at end of string // DICOM tags are never of odd length if ( strPhotometricInterpretation == GDCM_UNFOUND || - strPhotometricInterpretation == "MONOCHROME1 " || - strPhotometricInterpretation == "MONOCHROME2 " ) + Util::DicomStringEqual(strPhotometricInterpretation, "MONOCHROME1") || + Util::DicomStringEqual(strPhotometricInterpretation, "MONOCHROME2") ) { return 1; } @@ -822,7 +822,7 @@ int Header::GetBitsAllocated() */ int Header::GetSamplesPerPixel() { - std::string strSize = GetEntryByNumber(0x0028,0x0002); + const std::string& strSize = GetEntryByNumber(0x0028,0x0002); if ( strSize == GDCM_UNFOUND ) { dbg.Verbose(0, "Header::GetBitsStored: this is supposed to " @@ -840,9 +840,9 @@ int Header::GetSamplesPerPixel() */ bool Header::IsMonochrome() { - std::string PhotometricInterp = GetEntryByNumber( 0x0028, 0x0004 ); - if ( PhotometricInterp == "MONOCHROME1 " - || PhotometricInterp == "MONOCHROME2 " ) + const std::string& PhotometricInterp = GetEntryByNumber( 0x0028, 0x0004 ); + if ( Util::DicomStringEqual(PhotometricInterp, "MONOCHROME1") + || Util::DicomStringEqual(PhotometricInterp, "MONOCHROME2") ) { return true; } @@ -1302,6 +1302,92 @@ void Header::GetImageOrientationPatient( float iop[6] ) } } +/** + * \brief Initialize a default DICOM header that should contain all the + * field require by other reader. DICOM standart does not + * explicitely defines thoses fields, heuristic has been choosen. + * This is not perfect as we are writting a CT image... + */ +void Header::InitializeDefaultHeader() +{ + typedef struct + { + const char *value; + uint16_t group; + uint16_t elem; + } DICOM_DEFAULT_VALUE; + + const char *date = Util::GetCurrentDate().c_str(); + const char *time = Util::GetCurrentTime().c_str(); + const char *uid = Util::CreateUniqueUID().c_str(); + + static DICOM_DEFAULT_VALUE defaultvalue[] = { + "76", 0x0002, 0x0000, // MetaElementGroup Length // FIXME: how to recompute ? + "1.2.840.10008.5.1.4.1.1.2", 0x0002, 0x0002, // MediaStorageSOPInstanceUID (CT Image Storage) + uid, 0x0002, 0x0012, // META Implementation Class UID + "ISO_IR 100", 0x0008, 0x0005, // Specific Character Set + "DERIVED\\SECONDARY\\OTHER\\GDCM", 0x0008, 0x0008, // Image Type + "1.2.840.10008.5.1.4.1.1.2", 0x0008, 0x0016, // SOP Class UID + "", 0x0008, 0x0050, // Accession Number + "GDCM", 0x0008, 0x0070, // Manufacturer + "GDCM", 0x0008, 0x0080, // Institution Name + "http://www-creatis.insa-lyon.fr/Public/Gdcm/", 0x0008, 0x0081, // Institution Address + "", 0x0008, 0x0090, // Refering Physician Name + "", 0x0008, 0x1030, // Study Description + "", 0x0008, 0x1050, // Performing Physician's Name + "", 0x0008, 0x1060, // Name of Physician(s) Reading Study + "", 0x0010, 0x0040, // Patient's Sex + uid, 0x0020, 0x000d, // StudyInstanceUID + uid, 0x0020, 0x000e, // SeriesInstanceUID + "", 0x0020, 0x0011, // AcquisitionNumber + "1\\0\\0\\0\\1\\0", 0x0020, 0x0037, // Image Orientation Patient + "1", 0x0028, 0x0002, // Samples per pixel 1 or 3 + "MONOCHROME2", 0x0028, 0x0004, // photochromatic interpretation + +// Date and time + + date, 0x0008, 0x0012, // Instance Creation Date + time, 0x0008, 0x0013, // Instance Creation Time + date, 0x0008, 0x0020, // Study Date + date, 0x0008, 0x0022, // Acquisition Date + date, 0x0008, 0x0023, // Content Date + time, 0x0008, 0x0030, // Study Time + "CT", 0x0008, 0x0060, // Modality + "GDCM", 0x0010, 0x0010, // Patient's Name + "GDCMID", 0x0010, 0x0020, // Patient ID + "1", 0x0020, 0x0010, // StudyID + "1", 0x0020, 0x0011, // SeriesNumber + "1.0", 0x0018, 0x0050, // slice Thickness + "1.0", 0x0018, 0x0088, // space between slices + "1.0\\1.0", 0x0028, 0x0030, // pixelSpacing + "64", 0x0028, 0x0010, // nbRows + "64", 0x0028, 0x0011, // nbCols + "16", 0x0028, 0x0100, // BitsAllocated 8 or 16 + "12", 0x0028, 0x0101, // BitsStored 8 or 12 + "11", 0x0028, 0x0102, // HighBit 7 or 11 + "0", 0x0028, 0x0103, // Pixel Representation 0(unsigned) or 1(signed) + "1000.0", 0x0028, 0x1051, // Window Width + "500.0", 0x0028, 0x1050, // Window Center + 0, 0, 0 + }; + + // default value + // Special case this is the image (not a string) + GrPixel = 0x7fe0; + NumPixel = 0x0010; + ReplaceOrCreateByNumber(0, 0, GrPixel, NumPixel); + + // All remaining strings: + unsigned int i = 0; + DICOM_DEFAULT_VALUE current = defaultvalue[i]; + while( current.value ) + { + std::string value = Util::DicomString( current.value ); //pad the string properly + ReplaceOrCreateByNumber(value, current.group, current.elem); + current = defaultvalue[++i]; + } +} + //----------------------------------------------------------------------------- // Private diff --git a/src/gdcmHeader.h b/src/gdcmHeader.h index 13a5d398..d7d7d870 100644 --- a/src/gdcmHeader.h +++ b/src/gdcmHeader.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmHeader.h,v $ Language: C++ - Date: $Date: 2004/10/28 03:10:58 $ - Version: $Revision: 1.92 $ + Date: $Date: 2004/11/16 05:03:35 $ + Version: $Revision: 1.93 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -160,6 +160,7 @@ public: bool HasLUT(); int GetLUTNbits(); + /// Return the Transfer Syntax as a string std::string GetTransfertSyntaxName(); /// Accessor to \ref Header::GrPixel @@ -172,9 +173,16 @@ public: void SetImageDataSize(size_t expectedSize); void Write(std::ofstream* fp, FileType filetype); + + /// Initialize DICOM header when none + void InitializeDefaultHeader(); protected: + /// Replace patient's specific information by 'anonymous' bool AnonymizeHeader(); + + /// Helper function needed to organize DICOM files based on + /// their x,y,z position void GetImageOrientationPatient( float iop[6] ); private: diff --git a/src/gdcmUtil.h b/src/gdcmUtil.h index bf897015..6893f4d2 100644 --- a/src/gdcmUtil.h +++ b/src/gdcmUtil.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmUtil.h,v $ Language: C++ - Date: $Date: 2004/11/16 02:54:35 $ - Version: $Revision: 1.44 $ + Date: $Date: 2004/11/16 05:03:35 $ + Version: $Revision: 1.45 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -54,7 +54,7 @@ public: static std::string DicomString(const char* s, size_t l); static std::string DicomString(const char* s); static bool DicomStringEqual(const std::string& s1, const char *s2); - static std::string CreateUniqueUID(const std::string& root); + static std::string CreateUniqueUID(const std::string& root = ""); private: static std::string GetIPAddress(); //Do not expose this method -- 2.48.1