]> Creatis software - gdcm.git/commitdiff
Commenataires?
authorjpr <jpr>
Thu, 19 Dec 2002 10:58:02 +0000 (10:58 +0000)
committerjpr <jpr>
Thu, 19 Dec 2002 10:58:02 +0000 (10:58 +0000)
12 files changed:
src/gdcm.h
src/gdcmDict.cxx
src/gdcmDictEntry.cxx
src/gdcmDictSet.cxx
src/gdcmElValSet.cxx
src/gdcmElValue.cxx
src/gdcmFile.cxx
src/gdcmHeader.cxx
src/gdcmHeaderIdo.cxx
src/gdcmIdo.h
src/gdcmUtil.cxx
src/gdcmUtil.h

index 0c370c6603805560215bdffac716a8491519e851..c8bf4d046deaff68b79fe0ae34a51283a4748700 100644 (file)
@@ -1,9 +1,11 @@
+// gdcm.h
+
 // gdcmlib Intro:  
 // * gdcmlib is a library dedicated to reading and writing dicom files.
 // * LGPL for the license
 // * lightweigth as opposed to CTN or DCMTK wich come bundled which try
 //   to implement the full DICOM standard (networking...). gdcmlib concentrates
-//   on reading and 
+//   on reading and writing
 // * Formats: this lib should be able to read ACR-NEMA v1 and v2, Dicom v3 (as
 //   stated in part10). [cf dcmtk/dcmdata/docs/datadict.txt]
 // * Targeted plateforms: Un*xes and Win32/VC++6.0
@@ -26,6 +28,31 @@ using namespace std;  // string type lives in the std namespace on VC++
 #include <list>
 #include <map>
 
+                     // The requirement for the hash table (or map) that
+                      // we shall use:
+                      // 1/ First, next, last (iterators)
+                      // 2/ should be sortable (i.e. sorted by TagKey). This
+                      //    condition shall be droped since the Win32/VC++
+                      //    implementation doesn't look a sorted one. Pffff....
+                      // 3/ Make sure we can setup some default size value,
+                      //    which should be around 4500 entries which is the
+                      //    average dictionary size (said JPR)
+                      //
+                      // En fait, je disais que dans LE Directory Dicom (dans son etat 2002)
+                      // il y a 1600 entrees.
+                      // Une valeur raisonable pour un  majorant du nombre d'entrees
+                      // dans une entete DICOM d'une image semble semble etre 300
+                      // Si on 'decortique' les elements SQ (ce qui ne semble pas etre fait pour le moment)
+                      // on risque en fait de depasser ... un nombre non previsible dans le cas d'une entree SQ
+                      // contenant lui même un tres grand nombre d'entrees ?!?)
+                      // Quant au nombre d'entrees dans un DICOMDIR, c'est encore pire : il n'est limité
+                      // que par la taille d'un CD-ROM (les DVD-ROM ne sont pas encore pris en compte)
+                      // On peut s'attendre a 30 entrees par fichier dicom présent sur le CD-ROM
+                      // Remarque : il faudra se pencher sur le pb de la creation du DICOMDIR lorsqu'on voudra 
+                      // exporter des images lisibles par les consoles cliniques 
+                      // et pas seulement importables dans e-film. 
+
+
 #ifdef __GNUC__
 #include <stdint.h>
 #define guint16 uint16_t
@@ -43,6 +70,14 @@ typedef  unsigned int guint32;
 #define GDCM_EXPORT
 #endif
 
+
+//
+// ---------------------------------------------------- gdcmDictEntry
+//
+//     c'est une ligne du Dictionnaire Dicom
+//
+
+
 ////////////////////////////////////////////////////////////////////////////
 // Tag based hash tables.
 // We shall use as keys the strings (as the C++ type) obtained by
@@ -52,12 +87,13 @@ typedef  unsigned int guint32;
 // Then the corresponding TagKey shall be the string 0010|0010 (where
 // the | (pipe symbol) acts as a separator). Refer to 
 // gdcmDictEntry::TranslateToKey for this conversion function.
+
 typedef string TagKey;
 
 class GDCM_EXPORT gdcmDictEntry {
 private:
        guint16 group;    // e.g. 0x0010
-       guint16 element;  // e.g. 0x0010
+       guint16 element;  // e.g. 0x0103
        string  vr;       // Value Representation i.e. some clue about the nature
                          // of the data represented e.g. "FD" short for
                          // "Floating Point Double"
@@ -80,11 +116,19 @@ private:
        //         DcmDictRangeRestriction elementRestriction;
        //       };
 public:
+       
+       // fabrique une ligne de Dictionnaire Dicom à partir des parametres en entrée
+
+
        gdcmDictEntry(guint16 group, guint16 element,
                      string vr     = "Unknown",
                      string fourth = "Unknown",
                      string name   = "Unknown");
+                                         
+       // fabrique une 'clé' par concaténation du numGroupe et du numElement
+
        static TagKey TranslateToKey(guint16 group, guint16 element);
+       
        guint16 GetGroup(void)  { return group;};
        guint16 GetElement(void){return element;};
        string  GetVR(void)     {return vr; };
@@ -95,11 +139,22 @@ public:
        string  GetKey(void)    {return key;};
 };
   
+//
+// ---------------------------------------------------- gdcmDict
+// 
+//     c'est le Dictionnaire Dicom
+//
+
+  
 ////////////////////////////////////////////////////////////////////////////
 // A single DICOM dictionary i.e. a container for a collection of dictionary
 // entries. There should be a single public dictionary (THE dictionary of
 // the actual DICOM v3) but as many shadow dictionaries as imagers 
 // combined with all software versions...
+
+typedef map<TagKey, gdcmDictEntry*> TagHT;
+       // Table de Hachage  (group,Elem) --> ligne du Dictionnaire Dicom
+
 typedef map<TagKey, gdcmDictEntry*> TagHT;
 
 class GDCM_EXPORT gdcmDict {
@@ -107,18 +162,33 @@ class GDCM_EXPORT gdcmDict {
        string filename;
        TagHT entries;
 public:
+       // rempli le Dictionnaire Dicom à partir d'un fichier texte
        gdcmDict(const char* FileName);   // Read Dict from disk
+       
        // TODO Swig int AppendEntry(gdcmDictEntry* NewEntry);
+       
+       // renvoie une ligne de Dictionnaire Dicom à partir de (numGroup, numElement)
        gdcmDictEntry * GetTag(guint32 group, guint32 element);
        void Print(ostream&);
        TagHT & GetEntries(void) { return entries; }
 };
 
+
+//
+// ---------------------------------------------------- gdcmDictSet
+//
+//     Ensemble de Dictionnaires Dicom (le public + 'des' privés)
+//     Au cas ou l'on traiterait un jour les 'dictionnaires privés'
+//      - pratiquement un par constructeur, par machine, et par version du logiciel -
+//
+//
+
 ////////////////////////////////////////////////////////////////////////////
 // Container for managing a set of loaded dictionaries. Sharing dictionaries
 // should avoid :
 // * reloading an allready loaded dictionary,
 // * having many in memory representations of the same dictionary.
+
 typedef string DictKey;
 typedef map<DictKey, gdcmDict*> DictSetHT;
 
@@ -138,15 +208,29 @@ public:
        // TODO Swig int LoadDictFromName(string filename);
        // TODO Swig int LoadAllDictFromDirectory(string DirectoryName);
        // TODO Swig string* GetAllDictNames();
+       //
+       // Question : ne faudra-t-il pas mettre LE dictionnaire DICOM dans un Directory
+       // et les eventuels 'dictionnaires prives' dans un autre?
+       //
        int LoadDicomV3Dict(void);
        void Print(ostream&);
        gdcmDict* GetDict(DictKey DictName);
        gdcmDict* GetDefaultPublicDict(void);
 };
 
-////////////////////////////////////////////////////////////////////////////
+
+//
+// ---------------------------------------------------- ElValue
+//
+//     C'est un Element Dicom
+//     (ce qu'on a trouve dans l'entete de l'image
+//     + ce qu'on est allé chercher dans le Dictionnaire Dicom)
+//
+
+
 // The dicom header of a Dicom file contains a set of such ELement VALUES
 // (when successfuly parsed against a given Dicom dictionary)
+
 class GDCM_EXPORT ElValue {
 private:
        gdcmDictEntry *entry;
@@ -164,7 +248,7 @@ public:
        void SetDictEntry(gdcmDictEntry *NewEntry) { entry = NewEntry; };
 
        bool   IsVrUnknown(void) { return entry->IsVrUnknown(); };
-       void SetLength(guint32 l){LgrElem = l; };
+       void SetLength(guint32 l){ LgrElem = l; };
        void SetValue(string val){ value = val; };
        void SetOffset(size_t of){ Offset = of; };
        void SetImplicitVr(void) { ImplicitVr = true; };
@@ -180,6 +264,13 @@ public:
        string  GetName(void)    { return entry->GetName();};
 };
 
+
+//
+// ---------------------------------------------------- ElValSet
+//
+//     ... un ensemble d'Elements Dicom 
+//
+
 ////////////////////////////////////////////////////////////////////////////
 // Container for a set of succefully parsed ElValues.
 typedef map<TagKey, ElValue*> TagElValueHT;
@@ -200,9 +291,18 @@ public:
        TagElValueHT & GetTagHt(void);
 };
 
+
+//
+// ---------------------------------------------------- gdcmHeader
+//
+//     C'est le Dicom Header d'une image donnée
+//     (tous les elements Dicom qui la composent
+//     + des info 'de service')
+//
+
 ////////////////////////////////////////////////////////////////////////////
 // The typical usage of instances of class gdcmHeader is to classify a set of
-// dicom files according to header information e.g. to create a file hierachy
+// dicom files according to header information e.g. to create a file hierarchy
 // reflecting the Patient/Study/Serie informations, or extracting a given
 // SerieId. Accesing the content (image[s] or volume[s]) is beyond the
 // functionality of this class and belong to gdmcFile (see below).
@@ -212,9 +312,12 @@ public:
 // * the gdcmHeader::Set*Tag* family members cannot be defined as protected
 //   (Swig limitations for as Has_a dependency between gdcmFile and gdcmHeader)
  
+
 typedef string VRKey;
 typedef string VRAtr;
 typedef map<TagKey, VRAtr> VRHT;    // Value Representation Hash Table
+               // Cette Table de Hachage ne devrait servir qu'a determiner
+               // si deux caractères correspondent à une VR existante ?        
 
 class GDCM_EXPORT gdcmHeader {
        void SkipBytes(guint32);
@@ -235,6 +338,7 @@ private:
        // outside of the elements:
        guint16 grPixel;
        guint16 numPixel;
+       
        // Swap code (little, big, big-bad endian): this code is not fixed
        // during parsing.FIXME sw should be an enum e.g.
        //enum EndianType {
@@ -243,6 +347,7 @@ private:
                //BigEndian, 
                //BadBigEndian};
        int sw;
+
        // Only the elements whose size are below this bound shall be loaded.
        // By default, this upper bound is limited to 1024 (which looks reasonable
        // when one considers the definition of the various VR contents).
@@ -268,7 +373,6 @@ private:
        void SetMaxSizeLoadElementValue(long);
        ElValue       * ReadNextElement(void);
        gdcmDictEntry * IsInDicts(guint32, guint32);
-       size_t GetPixelOffset(void);
 protected:
        enum FileType {
                Unknown = 0,
@@ -285,9 +389,13 @@ public:
        virtual void ParseHeader(void);
        gdcmHeader(const char* filename);
        virtual ~gdcmHeader();
+       
+       size_t GetPixelOffset(void);
+       void   GetPixels(size_t, void *);
+       int    GetSwapCode(void) { return sw; }
 
        // TODO Swig int SetPubDict(string filename);
-       // When some proprietary shadow groups are disclosed, whe can set
+       // When some proprietary shadow groups are disclosed, we can set
        // up an additional specific dictionary to access extra information.
        // TODO Swig int SetShaDict(string filename);
 
@@ -298,13 +406,17 @@ public:
        list<string> * GetPubTagNames(void);
        map<string, list<string> > * GetPubTagNamesByCategory(void);
        // Get the element values themselves:
+       
        string GetPubElValByName(string TagName);
        string GetPubElValByNumber(guint16 group, guint16 element);
+
        // Getting the element value representation (VR) might be needed by caller
        // to convert the string typed content to caller's native type (think
        // of C/C++ vs Python).
+
        string GetPubElValRepByName(string TagName);
        string GetPubElValRepByNumber(guint16 group, guint16 element);
+
        TagElValueHT & GetPubElVal(void) { return PubElVals.GetTagHt(); };
        void   PrintPubElVal(ostream & os = cout);
        void   PrintPubDict(ostream &);
@@ -332,6 +444,14 @@ public:
        // TODO Swig int GetSwapCode();
 };
 
+//
+// ---------------------------------------------------- gdcmFile
+//
+//     un fichier EST_UNE entete, ou A_UNE entete ?
+//
+//
+
+
 ////////////////////////////////////////////////////////////////////////////
 // In addition to Dicom header exploration, this class is designed
 // for accessing the image/volume content. One can also use it to
@@ -339,6 +459,7 @@ public:
 ////// QUESTION: this looks still like an open question wether the
 //////           relationship between a gdcmFile and gdcmHeader is of
 //////           type IS_A or HAS_A !
+
 class GDCM_EXPORT gdcmFile: gdcmHeader
 {
 private:
@@ -355,8 +476,10 @@ public:
        //    the DICOM header is post-poned to first header information access.
        //    This avoid a double parsing of public part of the header when
        //    one sets an a posteriori shadow dictionary (efficiency can be
-       //    seen a a side effect).
+       //    seen as a side effect).
+       
        gdcmFile(string & filename);
+       
        // For promotion (performs a deepcopy of pointed header object)
        // TODO Swig gdcmFile(gdcmHeader* header);
        // TODO Swig ~gdcmFile();
@@ -369,12 +492,15 @@ public:
        // Allocates necessary memory, copies the data (image[s]/volume[s]) to
        // newly allocated zone and return a pointer to it:
        // TODO Swig void * GetImageData();
+       
        // Returns size (in bytes) of required memory to contain data
        // represented in this file.
        // TODO Swig size_t GetImageDataSize();
+       
        // Copies (at most MaxSize bytes) of data to caller's memory space.
        // Returns an error code on failure (if MaxSize is not big enough)
        // TODO Swig int PutImageDataHere(void* destination, size_t MaxSize );
+       
        // Allocates ExpectedSize bytes of memory at this->Data and copies the
        // pointed data to it.
        // TODO Swig int SetImageData(void * Data, size_t ExpectedSize);
@@ -382,5 +508,22 @@ public:
        // TODO Swig int Write();
 };
 
+//
+// ---------------------------------------------------- gdcmSerie
+//
+//     une serie EST_UN fichier ????
+//
+//
+
 //class gdcmSerie : gdcmFile;
+
+//
+// ---------------------------------------------------- gdcmMultiFrame
+//
+//     un fichierMultiFrame EST_UN fichier 
+//
+//
+
 //class gdcmMultiFrame : gdcmFile;
+
+
index 3514749ecbbc4dee8eb260bfbb0e3e49377379ed..32cc12467410975dd91ebb1ae9c0f8dd8fa22977 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmDict.cxx
+
 #include <fstream>
 #include "gdcm.h"
 #include "gdcmUtil.h"
@@ -37,6 +39,8 @@ void gdcmDict::Print(ostream& os) {
     }
 }
 
+// renvoie une ligne de Dictionnaire Dicom à partir de (numGroup, numElement)
+
 gdcmDictEntry * gdcmDict::GetTag(guint32 group, guint32 element) {
        TagKey key = gdcmDictEntry::TranslateToKey(group, element);
        if ( ! entries.count(key))
index 0294d7b56a57a166f97fec85f7c89c57978c983d..c9b1ca0c687943e563402b8ce861d2818e3257f3 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmDict.cxx
+
 #include "gdcm.h"
 #include "gdcmUtil.h"
 
index 3e0cc03678c6a58a993b25629a54cd2752d4d899..1c3c0a7781af7f43b6126bb75acd3754b3854010 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmDictEntry
+
 #include <fstream>
 #include <stdlib.h>  // For getenv
 #include "gdcm.h"
index b74b475e3f38a92a3d5846fda9abfdae6a632c9a..71f76056f3a5ebf3ce2a7aeeed2dff61e3fba39f 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmElValSet.cxx
+
 #include "gdcm.h"
 #include "gdcmUtil.h"
 
index bbcf731c7679d6f509b4f2218beb017e2dc15182..060ffb99eb767cb911d69a9fe936f0fbb43abc8d 100644 (file)
@@ -1,7 +1,9 @@
+// gdcmElValue.cxx
+
 #include "gdcm.h"
 
 void   ElValue::SetVR(string ValRep) { entry->SetVR(ValRep); }
-string ElValue::GetVR(void)   { return entry->GetVR(); }
+string ElValue::GetVR(void)          { return entry->GetVR(); }
 
 ElValue::ElValue(gdcmDictEntry* in) {
        ImplicitVr = false;
index cb69387531a50ab4b7529af62f59cc5c4ecbdb94..d5a85294a273a84c6cbeeb003b3f20e322339962 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmFile.cxx
+
 #include "gdcm.h"
 
 gdcmFile::gdcmFile(string & filename)
index 6722b122dbcc787438b4893811e6721aa9200289..3107da2ff3bf31765a6245aedcf5dcc9181e8854 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmHeader.cxx
+
 #include "gdcm.h"
 #include <stdio.h>
 // For nthos:
@@ -11,7 +13,7 @@
 #include <sstream>
 #include "gdcmUtil.h"
 
-#define HEADER_LENGHT_TO_READ 256 // on ne lit plus que le debut
+#define HEADER_LENGTH_TO_READ 256 // on ne lit plus que le debut
 
 namespace Error {
        struct FileReadError {
@@ -88,8 +90,9 @@ void gdcmHeader::InitVRDict (void) {
 
 /**
  * \ingroup gdcmHeader
- * \brief   Discover what the swap code is (among little endian, big endian, 
+ * \brief   Discover what the swap code is (among little endian, big endian,
  *          bad little endian, bad big endian).
+ *
  */
 void gdcmHeader::CheckSwap()
 {
@@ -103,7 +106,7 @@ void gdcmHeader::CheckSwap()
         
        int lgrLue;
        char * entCur;
-       char deb[HEADER_LENGHT_TO_READ];
+       char deb[HEADER_LENGTH_TO_READ];
         
        // First, compare HostByteOrder and NetworkByteOrder in order to
        // determine if we shall need to swap bytes (i.e. the Endian type).
@@ -114,7 +117,7 @@ void gdcmHeader::CheckSwap()
        
        // The easiest case is the one of a DICOM header, since it possesses a
        // file preamble where it suffice to look for the sting "DICM".
-       lgrLue = fread(deb, 1, HEADER_LENGHT_TO_READ, fp);
+       lgrLue = fread(deb, 1, HEADER_LENGTH_TO_READ, fp);
        
        entCur = deb + 128;
        if(memcmp(entCur, "DICM", (size_t)4) == 0) {
@@ -200,7 +203,7 @@ void gdcmHeader::CheckSwap()
                return;
        default :
                dbg.Verbose(0, "gdcmHeader::CheckSwap:",
-                              "ACE/NEMA unfound swap info (time to raise bets)");
+                              "ACR/NEMA unfound swap info (time to raise bets)");
        }
 
        // We are out of luck. It is not a DicomV3 nor a 'clean' ACR/NEMA file.
@@ -233,6 +236,13 @@ void gdcmHeader::SwitchSwapToBigEndian(void) {
                sw = 3412;
 }
 
+void gdcmHeader::GetPixels(size_t lgrTotale, void* Pixels) {
+       size_t pixelsOffset; 
+       pixelsOffset = GetPixelOffset();
+       fseek(fp, pixelsOffset, SEEK_SET);
+       fread(Pixels, 1, lgrTotale, fp);
+}
+
 /**
  * \ingroup   gdcmHeader
  * \brief     Find the value representation of the current tag.
@@ -270,7 +280,7 @@ void gdcmHeader::FindVR( ElValue *ElVal) {
        // a tag where we expect reading a VR but are in fact we read the
        // first to bytes of the length. Then we will interogate (through find)
        // the dicom_vr dictionary with oddities like "\004\0" which crashes
-       // both GCC and VC++ implentations of the STL map. Hence when the
+       // both GCC and VC++ implementations of the STL map. Hence when the
        // expected VR read happens to be non-ascii characters we consider
        // we hit falsely explicit VR tag.
 
@@ -431,7 +441,7 @@ void gdcmHeader::FindLength(ElValue * ElVal) {
                // endian encoding". When this is the case, chances are we got our
                // hands on a big endian encoded file: we switch the swap code to
                // big endian and proceed...
-               if ( (element  == 0) && (length16 == 1024) ) {
+               if ( (element  == 0x000) && (length16 == 0x0400) ) {
                        if ( ! IsBigEndianTransferSyntax() )
                                throw Error::FileReadError(fp, "gdcmHeader::FindLength");
                        length16 = 4;
@@ -550,6 +560,12 @@ void gdcmHeader::LoadElementValue(ElValue * ElVal) {
        fseek(fp, (long)ElVal->GetOffset(), SEEK_SET);
        
        // Sequences not treated yet !
+       //
+       // Ne faudrait-il pas au contraire trouver immediatement
+       // une maniere 'propre' de traiter les sequences (vr = SQ)
+       // car commencer par les ignorer risque de conduire a qq chose
+       // qui pourrait ne pas etre generalisable
+       //
        if( vr == "SQ" )
                SkipLoad = true;
 
@@ -579,6 +595,10 @@ void gdcmHeader::LoadElementValue(ElValue * ElVal) {
        }
 
        // Values bigger than specified are not loaded.
+       //
+       // En fait, c'est les elements dont la longueur est superieure 
+       // a celle fixee qui ne sont pas charges
+       //
        if (length > MaxSizeLoadElementValue) {
                ostringstream s;
                s << "gdcm::NotLoaded.";
@@ -733,6 +753,23 @@ bool gdcmHeader::IsAnInteger(ElValue * ElVal) {
        if ( (group == 0x0028) && (element == 0x0005) )
                // This tag is retained from ACR/NEMA
                // CHECKME Why should "Image Dimensions" be a single integer ?
+               //
+               // "Image Dimensions", c'est en fait le 'nombre de dimensions'
+               // de l'objet ACR-NEMA stocké
+               // 1 : Signal
+               // 2 : Image
+               // 3 : Volume
+               // 4 : Sequence
+               //
+               // DICOM V3 ne retient pas cette information
+               // Par defaut, tout est 'Image',
+               // C'est a l'utilisateur d'explorer l'ensemble des entetes
+               // pour savoir à quoi il a a faire
+               //
+               // Le Dicom Multiframe peut etre utilise pour stocker,
+               // dans un seul fichier, une serie temporelle (cardio vasculaire GE, p.ex)
+               // ou un volume (medecine Nucleaire, p.ex)
+               //
                return true;
        
        if ( (group == 0x0028) && (element == 0x0200) )
@@ -776,6 +813,10 @@ size_t gdcmHeader::GetPixelOffset(void) {
 }
 
 gdcmDictEntry * gdcmHeader::IsInDicts(guint32 group, guint32 element) {
+       //
+       // Y a-t-il une raison de lui passer des guint32
+       // alors que group et element sont des guint16?
+       //
        gdcmDictEntry * found = (gdcmDictEntry*)0;
        if (!RefPubDict && !RefShaDict) {
                //FIXME build a default dictionary !
index 97035dc664a5a2f180e7d01c889d55f02110c0bd..32edd1d938da504fe9e6089855a18b3131405e38 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmHeaderIdo.cxx
+
 #include "gdcmIdo.h"
 #include "gdcmUtil.h"
 
index af006f764dc57406927646d39ad68b2348a38730..61796397ee884a17b2feee32db3da04dd10112a6 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmIdo.h
+
 #include "gdcm.h"
 
 class gdcmHeaderIdo: protected gdcmHeader {
index 78bcff738034e44448562b9ef22a2a1a154849bb..840d6f242cc186ad91b7b77c12268a55bc4fcd5e 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmUtil.cxx
+
 #include <ctype.h>   // For isspace
 #include "gdcmUtil.h"
 
index 4f19b3ae23966d62b26d944794c4fdef200105ce..32f68172b2576a8fb58f541a8e969ea7fef2420e 100644 (file)
@@ -1,3 +1,5 @@
+// gdcmUtil.h
+
 #include <iostream>
 using namespace std;