]> Creatis software - gdcm.git/blobdiff - src/gdcm.h
* distutilsSwigCPlusPlus.py work around some swig portability
[gdcm.git] / src / gdcm.h
index 20e754130838cf96c8a8a59dfcda04d60a356197..735bd98c326ee678b33756a2d727c4a70bfc3aa7 100644 (file)
 // problems appears at loading of _gdcm.[so/dll]). So, simply uncomment
 // the declaration once you provided the definition of the method...
 
+#ifndef GDCM_H
+#define GDCM_H
+
 #include <string>
-#ifdef _MSC_VER
-using namespace std;  // string type lives in the std namespace on VC++
-#endif
+using namespace std;
 
 #include <iostream>
 #include <stddef.h>   // For size_t
 #include <stdio.h>    // FIXME For FILE on GCC only
 #include <list>
 #include <map>
+#include "gdcmException.h"
+
 
                      // The requirement for the hash table (or map) that
                       // we shall use:
@@ -38,8 +41,8 @@ using namespace std;  // string type lives in the std namespace on VC++
                       //    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.
+                      // En fait, je disais que dans LE Directory Dicom (dans son etat 2001)
+                      // 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)
@@ -52,7 +55,6 @@ using namespace std;  // string type lives in the std namespace on VC++
                       // exporter des images lisibles par les consoles cliniques 
                       // et pas seulement importables dans e-film. 
 
-
 #ifdef __GNUC__
 #include <stdint.h>
 #define guint16 uint16_t
@@ -70,14 +72,6 @@ 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
@@ -89,6 +83,7 @@ typedef  unsigned int   guint32;
 // gdcmDictEntry::TranslateToKey for this conversion function.
 
 typedef string TagKey;
+typedef string TagName;
 
 class GDCM_EXPORT gdcmDictEntry {
 private:
@@ -116,74 +111,54 @@ private:
        //         DcmDictRangeRestriction elementRestriction;
        //       };
 public:
-       
-       // fabrique une ligne de Dictionnaire Dicom à partir des parametres en entrée
-
-       gdcmDictEntry(guint16 group, guint16 element,
+       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 GetGroup(void)  { return group; };
        guint16 GetElement(void){return element;};
-       string  GetVR(void)     {return vr; };
+       string  GetVR(void)     {return vr;     };
        void    SetVR(string);
+       void    SetKey(string k){ key = k;     }
        bool    IsVrUnknown(void);
        string  GetFourth(void) {return fourth;};
-       string  GetName(void)   {return name;};
-       string  GetKey(void)    {return key;};
+       string  GetName(void)   {return name;  };
+       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) --> pointeur vers une ligne du Dictionnaire Dicom
-
-typedef map<TagKey, gdcmDictEntry*> TagHT;
+typedef map<TagKey,  gdcmDictEntry*> TagKeyHT;
+typedef map<TagName, gdcmDictEntry*> TagNameHT;
 
 class GDCM_EXPORT gdcmDict {
        string name;
        string filename;
-       TagHT entries;
+       TagKeyHT  KeyHt;                // Both accesses with a TagKey or with a
+       TagNameHT NameHt;               // TagName are required.
 public:
-       // rempli le Dictionnaire Dicom à partir d'un fichier texte
-       gdcmDict(const char* FileName);   // Read Dict from disk
-       
-       // QUESTION :
-       // Ca doit ajouter une nouvelle entrée 'a la fin', ou 'a sa place' ?
-       //
-       // TODO Swig int AppendEntry(gdcmDictEntry* NewEntry);
-       
-       // renvoie une ligne de Dictionnaire Dicom à partir de (numGroup, numElement)
-       gdcmDictEntry * GetTag(guint32 group, guint32 element);
+       gdcmDict(const char* FileName);   // Reads Dict from ascii file
+       int AddNewEntry (gdcmDictEntry* NewEntry);
+       int ReplaceEntry(gdcmDictEntry* NewEntry);
+       int RemoveEntry (TagKey key);
+       int RemoveEntry (guint16 group, guint16 element);
+       gdcmDictEntry * GetTagByKey(guint16 group, guint16 element);
+       gdcmDictEntry * GetTagByName(TagName name);
        void Print(ostream&);
-       TagHT & GetEntries(void) { return entries; }
+       void PrintByKey(ostream&);
+       void PrintByName(ostream&);
+       TagKeyHT & GetEntries(void) { return KeyHt; }
 };
 
 
-//
-// ---------------------------------------------------- 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 :
@@ -195,13 +170,19 @@ typedef map<DictKey, gdcmDict*> DictSetHT;
 
 class GDCM_EXPORT gdcmDictSet {
 private:
-       string DictPath;      // Directory path to dictionaries
        DictSetHT dicts;
        int AppendDict(gdcmDict* NewDict);
-       int LoadDictFromFile(string filename, DictKey);
-       void SetDictPath(void);
+       void LoadDictFromFile(string filename, DictKey);
+private:
+       static string DictPath;      // Directory path to dictionaries
+       static string BuildDictPath(void);
+       static gdcmDict* DefaultPubDict;
 public:
-       gdcmDictSet(void);    // loads THE DICOM v3 dictionary
+       static list<string> * GetPubDictTagNames(void);
+       static map<string, list<string> >* GetPubDictTagNamesByCategory(void);
+       static gdcmDict* LoadDefaultPubDict(void);
+
+       gdcmDictSet(void);
        // TODO Swig int LoadDictFromFile(string filename);
    // QUESTION: the following function might not be thread safe !? Maybe
    //           we need some mutex here, to avoid concurent creation of
@@ -210,34 +191,14 @@ public:
        // 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);
+       gdcmDict* GetDefaultPubDict(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)
-//
-
-// QUESTION:
-//
-// Ne faudrait-il pas trouver un autre nom, qui preterait moins à confusion?
-// ElValue n'EST PAS la 'valeur d'un Element', mais la reunion d'infos
-// trouvees dans l'Entete du fichier ET 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;
@@ -246,37 +207,39 @@ private:
                               // elements happen to be implicit. Flag them here
                               // since we can't use the entry->vr without breaking
                               // the underlying dictionary.
-       // Might prove of some interest (see _ID_DCM_ELEM)
-       // int Swap;
 public:
-       string  value;     // used to be char * valeurElem
+       string  value;
        size_t Offset;     // Offset from the begining of file for direct user access
+       
        ElValue(gdcmDictEntry*);
        void SetDictEntry(gdcmDictEntry *NewEntry) { entry = NewEntry; };
-
        bool   IsVrUnknown(void) { return entry->IsVrUnknown(); };
-       void SetLength(guint32 l){ LgrElem = l; };
-       void SetValue(string val){ value = val; };
-       void SetOffset(size_t of){ Offset = of; };
        void SetImplicitVr(void) { ImplicitVr = true; };
        bool  IsImplicitVr(void) { return ImplicitVr; };
-       void    SetVR(string);
-       string  GetVR(void);
-       string  GetValue(void)   { return value;               };
-       guint32 GetLength(void)  { return LgrElem;             };
-       size_t  GetOffset(void)  { return Offset;              };
-       guint16 GetGroup(void)   { return entry->GetGroup();   };
-       guint16 GetElement(void) { return entry->GetElement(); };
-       string  GetKey(void)     { return entry->GetKey();     };
-       string  GetName(void)    { return entry->GetName();    };
-};
+       
+       guint16 GetGroup(void)   { return entry->GetGroup();  };
+       guint16 GetElement(void) { return entry->GetElement();};
+       string  GetKey(void)     { return entry->GetKey();    };
+       string  GetName(void)    { return entry->GetName();   };
+       string  GetVR(void)      { return entry->GetVR();     };
+       void    SetVR(string v)  { entry->SetVR(v);           }; 
+       void SetLength(guint32 l){ LgrElem = l;               };
+       guint32 GetLength(void)  { return LgrElem;            };
+       
+       // Question : SetLength est public 
+       // (sinon, on ne pourrait pas l'appeler dans ElValSet)
+       // alors que *personne* ne devrait s'en servir !
+       // c'est *forcément* la lgr de la string 'value', non?
 
+       void SetValue(string val){ value = val; };
+       string  GetValue(void)   { return value;};
+
+       void SetOffset(size_t of){ Offset = of; };
+       size_t  GetOffset(void)  { return Offset;};
+       // Question : SetOffset est public ...
+       // Quel utilisateur serait ammené à modifier l'Offset ?
+};
 
-//
-// ---------------------------------------------------- ElValSet
-//
-//     ... un ensemble d'Elements Dicom 
-//     ... le résultat de l'analyse d'une entete d'image, par exemple
 
 ////////////////////////////////////////////////////////////////////////////
 // Container for a set of successfully parsed ElValues.
@@ -284,34 +247,33 @@ typedef map<TagKey, ElValue*> TagElValueHT;
 typedef map<string, ElValue*> TagElValueNameHT;
 
 class GDCM_EXPORT ElValSet {
-               // We need both accesses with a TagKey and the Dictentry.Name
-
-       TagElValueHT tagHt;
-       TagElValueNameHT NameHt;
+       TagElValueHT tagHt;             // Both accesses with a TagKey or with a
+       TagElValueNameHT NameHt;        // the DictEntry.Name are required.
 public:        
        void Add(ElValue*);             
        void Print(ostream &);
        void PrintByName(ostream &);
+       int  Write(FILE *fp);
        ElValue* GetElementByNumber(guint32 group, guint32 element);
        ElValue* GetElementByName  (string);
        string   GetElValueByNumber(guint32 group, guint32 element);
        string   GetElValueByName  (string);
-       TagElValueHT & GetTagHt(void);
+       
+       TagElValueHT & GetTagHt(void);  
        
        int SetElValueByNumber(string content, guint32 group, guint32 element);
-       int SetElValueByName(string content, string TagName);
-};
-
+       int SetElValueByName  (string content, string TagName);
+       
+       int SetElValueLengthByNumber(guint32 l, guint32 group, guint32 element);
+       int SetElValueLengthByName  (guint32 l, string TagName);
 
-//
-// ---------------------------------------------------- gdcmHeader
-//
-//     C'est le Dicom Header d'une image donnée
-//     (tous les elements Dicom qui la composent
-//     + des info 'de service')
-//
+};
 
 ////////////////////////////////////////////////////////////////////////////
+// The purpous of an instance of gdcmHeader is to act as a container of
+// all the elements and their corresponding values (and additionaly the
+// corresponding DICOM dictionary entry) of the header of a DICOM file.
+//
 // 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 hierarchy
 // reflecting the Patient/Study/Serie informations, or extracting a given
@@ -322,27 +284,18 @@ public:
 //   be managed within a dictionary which is shared by all gdcmHeader instances
 // * 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;  // Ne devrait-elle pas etre utilisee dans la definition de VRHT ?
+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 ?        
+typedef map<VRKey, VRAtr> VRHT;    // Value Representation Hash Table
 
 class GDCM_EXPORT gdcmHeader {
        void SkipBytes(guint32);
 private:
        static VRHT *dicom_vr;
        // Dictionaries of data elements:
-       
-       // Question :
-       // Pourquoi mettre un pointeur statique vers le container des dictionnaires
-       // (qui est une H-table de pointeurs vers des dictionnaires)
-       // en plus des pointeurs vers chacun des dictionnaires ?
-       // Ces derniers n'auraient-ils pas suffit ?
-       //
-       static gdcmDictSet* Dicts;  // global dictionary container
+
+       gdcmDictSet* Dicts;         // global dictionary container
        gdcmDict* RefPubDict;       // public dictionary
        gdcmDict* RefShaDict;       // shadow dictionary (optional)
        // Parsed element values:
@@ -350,16 +303,6 @@ private:
        ElValSet ShaElVals;         // parsed with Shadow Dictionary
        string filename;            // refering underlying file
        FILE * fp;
-       // The tag Image Location ((0028,0200) containing the address of
-       // the pixels) is not allways present. Then we store this information
-       
-       // FIXME
-       
-       // Question :
-       // Qu'y a-t-il a corriger ?
-       //
-       // outside of the elements:
-       
        guint16 grPixel;
        guint16 numPixel;
        // Ne faudrait-il pas une indication sur la presence ou non
@@ -384,16 +327,26 @@ private:
        guint32 ReadInt32(void);
        guint16 SwapShort(guint16);
        guint32 SwapLong(guint32);
+       guint32 FindLengthOB(void);
        void Initialise(void);
        void CheckSwap(void);
+       void InitVRDict(void);
+       void SwitchSwapToBigEndian(void);
+       void AddAndDefaultElements(void);
+       void SetMaxSizeLoadElementValue(long);
+
+       gdcmDictEntry * GetDictEntryByKey(guint16, guint16);
+       gdcmDictEntry * GetDictEntryByName(string name);
+
+       // ElValue related utilities
+       ElValue * ReadNextElement(void);
+       ElValue * NewElValueByKey(guint16 group, guint16 element);
+       ElValue * NewElValueByName(string name);
        void FindLength(ElValue *);
-       guint32 FindLengthOB(void);
        void FindVR(ElValue *);
        void LoadElementValue(ElValue *);
        void LoadElementValueSafe(ElValue *);
        void SkipElementValue(ElValue *);
-       void InitVRDict(void);
-       void SwitchSwapToBigEndian(void);
        void FixFoundLength(ElValue*, guint32);
        bool IsAnInteger(ElValue *);
        
@@ -405,15 +358,7 @@ private:
        bool IsJPEGExtendedProcess2_4TransferSyntax(void);      
        bool IsJPEGExtendedProcess3_5TransferSyntax(void);
        bool IsJPEGSpectralSelectionProcess6_8TransferSyntax(void);     
-//
-// Euhhhhhhh
-// Il y en a encore DIX-SEPT, comme ça.
-// Il faudrait trouver qq chose + rusé ...
-//     
                
-       void SetMaxSizeLoadElementValue(long);
-       ElValue       * ReadNextElement(void);
-       gdcmDictEntry * IsInDicts(guint32, guint32);
 protected:
        enum FileType {
                Unknown = 0,
@@ -427,8 +372,10 @@ protected:
        int anonymize(ostream&);  // FIXME : anonymize should be a friend ?
 public:
        void LoadElements(void);
-       virtual void ParseHeader(void);
-       gdcmHeader(const char* filename);
+       virtual void ParseHeader(bool exception_on_error = false)
+         throw(gdcmFormatError);
+       gdcmHeader(const char *filename, bool exception_on_error = false)
+         throw(gdcmFileError);
        virtual ~gdcmHeader();
        
        size_t GetPixelOffset(void);
@@ -440,14 +387,7 @@ public:
        // an additional specific dictionary to access extra information.
        // TODO Swig int SetShaDict(string filename);
 
-       // Retrieve all potentially available tag [tag = (group, element)] names
-       // from the standard (or public) dictionary. Typical usage: enable the
-       // user of a GUI based interface to select his favorite fields for sorting
-       // or selecting.
-       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);
 
@@ -460,7 +400,7 @@ public:
 
        TagElValueHT & GetPubElVal(void) { return PubElVals.GetTagHt(); };
        void   PrintPubElVal(ostream & os = cout);
-       void   PrintPubDict(ostream &);
+       void   PrintPubDict(ostream & os = cout);
          
        // Same thing with the shadow :
        // TODO Swig string* GetShaTagNames(); 
@@ -479,24 +419,25 @@ public:
 
        int SetPubElValByName(string content, string TagName);
        int SetPubElValByNumber(string content, guint16 group, guint16 element);
-       // TODO Swig int SetShaElValByName(string content, string ShadowTagName);
-       // TODO Swig int SetShaElValByNumber(string content, guint16 group, guint16 element);
+       int SetShaElValByName(string content, string ShadowTagName);
+       int SetShaElValByNumber(string content, guint16 group, guint16 element);
 
+       ElValSet GetPubElVals() { return(PubElVals); }
 };
 
 //
 // ---------------------------------------------------- gdcmFile
 //
 //     un fichier EST_UNE entete, ou A_UNE entete ?
-//
-//
+// 
+//     On dit 'EST_UNE' ...
 
 
 ////////////////////////////////////////////////////////////////////////////
 // In addition to Dicom header exploration, this class is designed
 // for accessing the image/volume content. One can also use it to
 // write Dicom files.
-////// QUESTION: this looks still like an open question wether the
+////// QUESTION: this looks still like an open question whether the
 //////           relationship between a gdcmFile and gdcmHeader is of
 //////           type IS_A or HAS_A !
 
@@ -553,11 +494,23 @@ public:
        // Copies (at most MaxSize bytes) of data to caller's memory space.
        // Returns an error code on failure (if MaxSize is not big enough)
        
-       int PutImageDataHere(void* destination, size_t MaxSize );
+       int GetImageDataIntoVector(void* destination, size_t MaxSize );
+       
+       // Question :
+       //
+       //      GetImageData et GetImageDataIntoVector
+       // Get et Put pour 2 fonctions qui font presque la meme chose :-(
+       //
        
        // Allocates ExpectedSize bytes of memory at this->Data and copies the
        // pointed data to it.
+       
+       // Question :
+       // Pourquoi dupliquer les pixels, alors qu'on les a deja en mémoire,
+       // et que Data (dans le gdcmHeader) est un pointeur ?
+       
        // TODO Swig int SetImageData(void * Data, size_t ExpectedSize);
+       
        // Push to disk.
        // A NE PAS OUBLIER : que fait-on en cas de Transfert Syntax (dans l'entete)
        // incohérente avec l'ordre des octets en mémoire  
@@ -565,9 +518,10 @@ public:
        
        // Ecrit sur disque les pixels d'UNE image
        // Aucun test n'est fait sur l'"Endiannerie" du processeur.
-       // C'est à l'utilisateur d'appeler son Reader correctement
+       // Ca sera à l'utilisateur d'appeler son Reader correctement
                
        int WriteRawData (string nomFichier);
+       int WriteDcm     (string nomFichier);
 };
 
 //
@@ -589,3 +543,4 @@ public:
 //class gdcmMultiFrame : gdcmFile;
 
 
+#endif // #ifndef GDCM_H