// 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:
// 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)
// exporter des images lisibles par les consoles cliniques
// et pas seulement importables dans e-film.
-
#ifdef __GNUC__
#include <stdint.h>
#define guint16 uint16_t
#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
// gdcmDictEntry::TranslateToKey for this conversion function.
typedef string TagKey;
+typedef string TagName;
class GDCM_EXPORT gdcmDictEntry {
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 :
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
// 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;
// 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.
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
// 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:
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
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 *);
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,
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);
// 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);
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();
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 !
// 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
// 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);
};
//
//class gdcmMultiFrame : gdcmFile;
+#endif // #ifndef GDCM_H