]> Creatis software - gdcm.git/blobdiff - dcmlib.h
* ChangeLog added --- Frog
[gdcm.git] / dcmlib.h
index 7f43acb9ad16cacaf0bf4e669509c6ccd2d66a9c..942870abafbf54e6d270d5518ebf0e3e86cdfc13 100644 (file)
--- a/dcmlib.h
+++ b/dcmlib.h
-// Terminology : 
-// * in DCMlib     tag = (group, element, name, value representation) e.g.
-//   (0x0010, 0x0010, "Patient_Name",    _ID_Patient_Name
-//   group   = 16 bit integer
-//   element = 16 bit integer
-//   name    = char * ("Patient_Name")
-//   value representation  (e.g. "AE" = "Application Entity",
-//         "FD", "Floating Point Double")
-// * in DCMTK  tag = (group, element) but they are many more fields in
-//   the implementation (see below). What are the relevant ones ?
-//      struct DBI_SimpleEntry {
-//         Uint16 group;
-//         Uint16 element;
-//         Uint16 upperGroup;
-//         Uint16 upperElement;
-//         DcmEVR evr;
-//         const char* tagName;
-//         int vmMin;
-//         int vmMax;
-//         const char* standardVersion;
-//         DcmDictRangeRestriction groupRestriction;
-//         DcmDictRangeRestriction elementRestriction;
-//       };
-//
-//       static const DBI_SimpleEntry simpleBuiltinDict[] = {
-//           { 0x0000, 0x0000, 0x0000, 0x0000,
-//             EVR_UL, "CommandGroupLength", 1, 1, "dicom98",
-//             DcmDictRange_Unspecified, DcmDictRange_Unspecified },...}
+// 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 
+// * 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
 
-//
-// Open questions:
-// * in libido a dictionary entry goes :
-//   {0x0018,0x1251,"SH","ACQ","Transmitting Coil"}. What does the fourth
-//   entry refer to ? 
-// * what type of Dicom files can this library read ? ACR/NEMA/Dicom v2
-//   or v3 part10 ? dcmtk/dcmdata/docs/datadict.txt mentions :all
-//   standard DICOM tags (including those found in supplements 1, 2, 3, 4, 5,
-//   6, 7, 8, 9, 10), obsolete ACR/NEMA version 2 tags, obsolete SPI tags, and
-//   the tags used by Papyrus version 3...
-//   Note en DCMTK the dictionary contains a standard version entry, like
-//   "dicom98", dicom99", "ACR/NEMA2"
-// * the convertion from VR to native types depends on native types of
-//   target language (Python, Tcl a priori don't share the same native
-//   representations). Where should this go ?
-// * the dcmHeader::Set*Tag* family members cannot be defined as protected
-//   (Swig limitations for as Has_a dependency between dcmFile and dcmHeader)
-//   
-// Plateforms: Un*xes and Win32/VC++6.0 or Win32/Cygwin
+#include <string>
+#include <stddef.h>    // For size_t
 
+// 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)
+#include <map>
+
+// Tag based hash tables.
+// We shall use as keys the strings (as the C++ type) obtained by
+// concatenating the group value and the element value (both of type
+// unsigned 16 bit integers in Dicom) expressed in hexadecimal.
+// Example: consider the tag given as (group, element) = (0x0010, 0x0010).
+// Then the corresponding TagKey shall be the string 00100010 (or maybe
+// 0x00100x0010, we need some checks here).
+typedef string TagKey;
+typedef map<TagKey, char*> TagHT;
 
-#include <stddef.h>    // For size_t
 // Dummy declaration for the time being
-typedef int Dict;
-typedef int gint16;    // We shall need glib.h !
+typedef int guint16;    // We shall need glib.h !
+
+class DictEntry {
+private:
+////// QUESTION: it is not sure that we need to store the group and
+//////           and the element within a DictEntry. What is the point
+//////           of storing the equivalent of a TagKey within the information
+//////           accessed through that TagKey !?
+       guint16 group;          // e.g. 0x0010
+       guint16 element;        // e.g. 0x0010
+       string  name;           // e.g. "Patient_Name"
+       string  ValRep; // Value Representation i.e. some clue about the nature
+                                                       // of the data represented e.g. "FD" short for
+                                                       // "Floating Point Double"
+       // DCMTK has many fields for handling a DictEntry (see below). What are the
+       // relevant ones for gdcmlib ?
+       //      struct DBI_SimpleEntry {
+       //         Uint16 group;
+       //         Uint16 element;
+       //         Uint16 upperGroup;
+       //         Uint16 upperElement;
+       //         DcmEVR evr;
+       //         const char* tagName;
+       //         int vmMin;
+       //         int vmMax;
+       //         const char* standardVersion;
+       //         DcmDictRangeRestriction groupRestriction;
+       //         DcmDictRangeRestriction elementRestriction;
+       //       };
+public:
+       DictEntry();
+       DictEntry(guint16 group, guint16 element, string  name, string  VR);
+};
+
+// 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...
+class Dict {
+       string name;
+       string filename;
+       TagHT entries;
+public:
+       Dict();
+       Dict(string filename);  // Read Dict from disk
+       int AppendEntry(DictEntry* NewEntry);
+};
+
+// 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 int DictId;
+class DictSet {
+private:
+       map<DictId, Dict*> dicts;
+       int AppendDict(Dict* NewDict);
+public:
+       DictSet();              // Default constructor loads THE DICOM v3 dictionary
+       int LoadDictFromFile(string filename);
+///// QUESTION: the following function might not be thread safe !? Maybe
+/////           we need some mutex here, to avoid concurent creation of
+/////           the same dictionary !?!?!
+       int LoadDictFromName(string filename);
+       int LoadAllDictFromDirectory(string directorynanme);
+       string* GetAllDictNames();
+       Dict* GetDict(string DictName);
+};
+
+// The dicom header of a Dicom file contains a set of such ELement VALUES
+// (when successfuly parsed against a given Dicom dictionary)
+class ElValue {
+       DictEntry entry;
+       string  value;
+};
+
+// Container for a set of succefully parsed ElValues.
+typedef map<TagKey, char*> TagHT;
+class ElValSet {
+       // We need both accesses with a TagKey and the Dicentry.Name
+////// QUESTION: this leads to a double storage of a single ElValue
+       map<TagKey, ElValue> tagHt;
+       map<srting, ElValue> NameHt;
+public:
+       int Add(ElValue);
+};
 
 // The typical usage of objects of this class is to classify a set of
 // dicom files according to header information e.g. to create a file hierachy
 // 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 (see dmcFile below).
-class dcmHeader {
+// Notes:
+// * the gdcmHeader::Set*Tag* family members cannot be defined as protected
+//   (Swig limitations for as Has_a dependency between gdcmFile and gdcmHeader)
+class gdcmHeader {
 private:
-       Dict* PubDict;          // Public Dictionary
-       Dict* ShaDict;    // Shadow Dictionary (optional)
+       static DictSet* Dicts;  // Global dictionary container
+       Dict* RefPubDict;                       // Public Dictionary
+       Dict* RefShaDict;                       // Shadow Dictionary (optional)
        int swapcode;
+       ElValSet PubElVals;             // Element Values parsed with Public Dictionary
+       ElValSet ShaElVals;             // Element Values parsed with Shadow Dictionary
+protected:
+///// QUESTION: Maybe Print is a better name than write !?
+       int write(ostream&);   
+///// QUESTION: Maybe anonymize should be a friend function !?!?
+/////           See below for an example of how anonymize might be implemented.
+       int anonymize(ostream&);
 public:
-       dcmHeader();
-       dcmHeader(char* filename);
-       ~dcmHeader();
+       gdcmHeader();
+       gdcmHeader(string filename);
+       ~gdcmHeader();
+
+       int SetPubDict(string filename);
+       // When some proprietary shadow groups are disclosed, whe can set
+       // up an additional specific dictionary to access extra information.
+       int SetShaDict(string filename);
 
        // Retrieve all potentially available tag [tag = (group, element)] names
        // from the standard (or public) dictionary (hence static). Typical usage:
        // enable the user of a GUI based interface to select his favorite fields
        // for sorting or selection.
-       static char ** GetDcmTagNames();
-       char*   GetDcmTag(char* TagName);
-       // 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).
-       char*   GetDcmTagValRep(char* TagName);
+       string* GetPubTagNames();
+       // Get the element values themselves:
+       string GetPubElValByName(string TagName);
+       string GetPubElValByNumber(guint16 group, guint16 element);
+       // Get 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);
+         
+       // Same thing with the shadow :
+       string* GetShaTagNames(); 
+       string GetShaElValByName(string TagName);
+       string GetShaElValByNumber(guint16 group, guint16 element);
+       string GetShaElValRepByName(string TagName);
+       string GetShaElValRepByNumber(guint16 group, guint16 element);
+
+       // Wrappers of the above (both public and shadow) to avoid bugging the
+       // caller with knowing if ElVal is from the public or shadow dictionary.
+       string GetElValByName(string TagName);
+       string GetElValByNumber(guint16 group, guint16 element);
+       string GetElValRepByName(string TagName);
+       string GetElValRepByNumber(guint16 group, guint16 element);
+
+       int SetPubElValByName(string content, string TagName);
+       int SetPubElValByNumber(string content, guint16 group, guint16 element);
+       int SetShaElValByName(string content, string ShadowTagName);
+       int SetShaElValByNumber(string content, guint16 group, guint16 element);
 
-       // When some proprietary shadow groups are disclosed, whe can set
-       // up an additional specific dictionary to access extra information.
-       int SetShadowDict(char* filename);
-       int SetShadowDict(char** dictionary);  //????????
-       int AddShadowDict(char* filename);     //????????              
-       int DelShadowDict();
-
-       // Retrieve all potentially available shadowed tag names
-       char** GetShadowTagNames(); 
-       char*  GetShadowTag(char* TagName);
-
-       int SetTag(char* content, gint16 group, gint16 element);
-       int SetTagByName(char* content, char* TagName);
-       int SetShadowTag(char* content, gint16 group, gint16 element);
-       int SetShadowTagByName(char* content, char* ShadowTagName);
-
-       // Enable caller's low-level manual access to shadowed info
-       char*   GetDcmTagByNumber(gint16 group, gint16 element);
-       // Does this make ANY sense ?
-       char*   GetDcmTagByNumberValRep(char* TagName);
        int GetSwapCode();
 };
 
 // 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.
-class dcmFile
+////// 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 gdcmFile: gdcmHeader
 {
 private:
-       dcmHeader* Header;
        void* Data;
-       int Parsed;            // weather allready parsed
-       char* OrigalFileName;  // To avoid file overwrite
+       int Parsed;                             // weather allready parsed
+       string OrigFileName;    // To avoid file overwrite
 public:
        // Constructor dedicated to writing a new DICOMV3 part10 compliant
        // file (see SetFileName, SetDcmTag and Write)
-       dcmFile();
+       gdcmFile();
        // Opens (in read only and when possible) an existing file and checks
        // for DICOM compliance. Returns NULL on failure.
        // Note: the in-memory representation of all available tags found in
@@ -123,15 +209,15 @@ public:
        //    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).
-       dcmFile(char* filename);
+       gdcmFile(string filename);
        // For promotion (performs a deepcopy of pointed header object)
-       dcmFile(dcmHeader* header);
-       ~dcmFile();
+       gdcmFile(gdcmHeader* header);
+       ~gdcmFile();
 
        // On writing purposes. When instance was created through
-       // dcmFile(char* filename) then the filename argument MUST be different
+       // gdcmFile(string filename) then the filename argument MUST be different
        // from the constructor's one (no overwriting aloud).
-       int SetFileName(char* filename);
+       int SetFileName(string filename);
 
        // Allocates necessary memory, copies the data (image[s]/volume[s]) to
        // newly allocated zone and return a pointer to it:
@@ -141,26 +227,33 @@ public:
        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)
-       int GetImageDataHere(void* destination, size_t MaxSize );
+       int PutImageDataHere(void* destination, size_t MaxSize );
        // Allocates ExpectedSize bytes of memory at this->Data and copies the
        // pointed data to it.
        int SetImageData(void * Data, size_t ExpectedSize);
        // Push to disk.
        int Write();
-
-///// Repeat here all the dcmHeader public members !!!
 };
 
-//class dcmSerie : dcmFile;
-//class dcmMultiFrame : dcmFile;
+//class gdcmSerie : gdcmFile;
+//class gdcmMultiFrame : gdcmFile;
 
 //
 //Examples:
-// * dcmFile WriteDicom;
+// * gdcmFile WriteDicom;
 //   WriteDicom.SetFileName("MyDicomFile.dcm");
-//     string * AllTags = dcmHeader.GetDcmTagNames();
+//     string * AllTags = gdcmHeader.GetDcmTagNames();
 //   WriteDicom.SetDcmTag(AllTags[5], "253");
 //   WriteDicom.SetDcmTag("Patient Name", "bozo");
 //   WriteDicom.SetDcmTag("Patient Name", "bozo");
 //     WriteDicom.SetImageData(Image);
 //   WriteDicom.Write();
+//
+//
+//   Anonymize(ostream& output) {
+//   a = gdcmFile("toto1");
+//   a.SetPubValueByName("Patient Name", "");
+//   a.SetPubValueByName("Date", "");
+//   a.SetPubValueByName("Study Date", "");
+//   a.write(output);
+//   }