]> Creatis software - gdcm.git/blob - src/gdcmParser.h
2004-03-23 Jean-Pierre Roux
[gdcm.git] / src / gdcmParser.h
1 // gdcmParser.h
2 //-----------------------------------------------------------------------------
3 #ifndef GDCMPARSER_H
4 #define GDCMPARSER_H
5
6 #include "gdcmCommon.h"
7 #include "gdcmVR.h"
8 #include "gdcmTS.h"
9 #include "gdcmException.h"
10 #include "gdcmDictSet.h"
11 #include "gdcmHeaderEntry.h"
12
13 #include <map>
14 #include <list>       // for linking together *all* the Dicom Elements
15
16 //-----------------------------------------------------------------------------
17 typedef std::string VRKey;
18 typedef std::string VRAtr;
19 typedef std::map<VRKey, VRAtr> VRHT;    // Value Representation Hash Table
20
21 typedef std::multimap<TagKey, gdcmHeaderEntry *> TagHeaderEntryHT;
22 typedef std::pair<TagKey, gdcmHeaderEntry *> PairHT;
23 typedef std::pair<TagHeaderEntryHT::iterator,TagHeaderEntryHT::iterator> IterHT; 
24
25 typedef std::list<gdcmHeaderEntry *> ListTag; // for linking together the Elements
26
27 typedef std::string GroupKey;
28 typedef std::map<GroupKey, int> GroupHT;
29
30 //-----------------------------------------------------------------------------
31 /*
32  * \defgroup gdcmParser
33  * \brief used by both gdcmHeader and gdcmDicomDir
34  */
35 class GDCM_EXPORT gdcmParser
36 {
37 public:
38
39 // Print
40    /**
41     * \ingroup gdcmParser
42     * \brief   Sets the print level for the Dicom Header 
43     * \note    0 for Light Print; 1 for 'medium' Print, 2 for Heavy
44     */
45    void SetPrintLevel(int level) 
46       { printLevel = level; };
47    /**
48     * \ingroup gdcmParser
49     * \brief   canonical Printer 
50     * \sa    SetPrintLevel
51     */   
52    virtual void Print        (std::ostream &os = std::cout) 
53       {PrintEntry(os);};
54    virtual void PrintEntry   (std::ostream &os = std::cout);
55    virtual void PrintPubDict (std::ostream &os = std::cout);
56    virtual void PrintShaDict (std::ostream &os = std::cout);
57
58 // Standard values
59    /**
60     * \ingroup gdcmParser
61     * \brief   Gets the external File Name 
62     */
63    inline std::string GetFileName(void) 
64       {return filename;}
65
66 // Dictionnaries
67    gdcmDict *GetPubDict(void);
68    gdcmDict *GetShaDict(void);
69    bool SetShaDict(gdcmDict *dict);
70    bool SetShaDict(DictKey dictName);
71
72 // Informations contained in the parser
73    virtual bool IsReadable(void);
74    bool IsImplicitVRLittleEndianTransferSyntax(void);
75    bool IsExplicitVRLittleEndianTransferSyntax(void);
76    bool IsDeflatedExplicitVRLittleEndianTransferSyntax(void);
77    bool IsExplicitVRBigEndianTransferSyntax(void);
78    FileType GetFileType(void);
79
80 // Entries
81    /**
82     * \ingroup gdcmHeader
83     * \brief   returns a ref to the Dicom Header H table (multimap)
84     * return the Dicom Header H table
85     */
86    inline TagHeaderEntryHT &GetEntry(void) { return tagHT; };
87
88    /**
89     * \ingroup gdcmHeader
90     * \brief   returns a ref to the Dicom Header chained list
91     * return the Dicom Header chained list
92     */
93    inline ListTag &GetListEntry(void) { return listEntries; };
94
95 // Read (used in gdcmFile, gdcmDicomDir)
96    FILE *OpenFile(bool exception_on_error = false) throw(gdcmFileError);
97    bool CloseFile(void);
98
99 // Write (used in gdcmFile, gdcmDicomDir)
100    virtual bool Write(FILE *, FileType);
101
102    gdcmHeaderEntry * ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint16 Elem);
103    gdcmHeaderEntry * ReplaceOrCreateByNumber(     char  *Value, guint16 Group, guint16 Elem);
104    bool ReplaceIfExistByNumber (     char  *Value, guint16 Group, guint16 Elem);
105
106 // System access
107    /**
108     * \ingroup gdcmHeader
109     * \brief   returns the 'swap code' 
110     *          (Big Endian, Little Endian, 
111     *          Bad Big Endian, Bad Little Endian)
112     *          according to the processor Endianity and what's written on disc
113     * return 
114     */
115    inline int GetSwapCode(void) { return sw; }
116    
117    guint16 SwapShort(guint16);   // needed by gdcmFile
118    guint32 SwapLong(guint32);    // needed by gdcmFile
119    guint16 UnswapShort(guint16); // needed by gdcmFile
120    guint32 UnswapLong(guint32);  // needed by gdcmFile
121
122 protected:
123 // constructor and destructor are protected to forbid end user 
124 // to instanciate class gdcmParser 
125 // (only gdcmHeader and gdcmDicomDir are meaningfull)
126    gdcmParser(bool exception_on_error  = false);
127    gdcmParser(const char *inFilename, 
128               bool  exception_on_error = false, 
129               bool  enable_sequences   = false,
130               bool  ignore_shadow      = false);
131    virtual ~gdcmParser(void);
132 // Entry
133    int CheckIfEntryExistByNumber(guint16 Group, guint16 Elem ); // int !
134    virtual std::string GetEntryByName    (std::string tagName);
135    virtual std::string GetEntryVRByName  (std::string tagName);
136    virtual std::string GetEntryByNumber  (guint16 group, guint16 element);
137    virtual std::string GetEntryVRByNumber(guint16 group, guint16 element);
138    virtual int     GetEntryLengthByNumber(guint16 group, guint16 element);
139
140    virtual bool SetEntryByName  (std::string content, std::string tagName);
141    virtual bool SetEntryByNumber(std::string content,  guint16 group, guint16 element);
142    virtual bool SetEntryLengthByNumber(guint32 length, guint16 group, guint16 element);
143
144    virtual size_t GetEntryOffsetByNumber  (guint16 Group, guint16 Elem);
145    virtual void  *GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem);   
146    virtual void  *LoadEntryVoidArea       (guint16 Group, guint16 Element);
147    virtual bool   SetEntryVoidAreaByNumber(void *a, guint16 Group, guint16 Elem);
148
149    virtual void UpdateShaEntries(void);
150
151 // Header entry
152    gdcmHeaderEntry *GetHeaderEntryByNumber  (guint16 group, guint16 element); 
153    gdcmHeaderEntry *GetHeaderEntryByName    (std::string Name);
154    IterHT           GetHeaderEntrySameNumber(guint16 group, guint16 element); 
155 // IterHT           GetHeaderEntrySameName  (std::string Name); 
156
157    void LoadHeaderEntrySafe(gdcmHeaderEntry *);
158
159    void UpdateGroupLength(bool SkipSequence = false, FileType type = ImplicitVR);
160    void WriteEntry(gdcmHeaderEntry *tag,FILE *_fp,FileType type);
161    void WriteEntries(FILE *_fp,FileType type);
162    void WriteEntriesDeprecated(FILE *_fp,FileType type); // JPR
163
164    void AddHeaderEntry       (gdcmHeaderEntry *);
165    
166    /**
167     * \ingroup gdcmParser
168     * \brief   Set the external File Name 
169     */
170    inline void SetFileName(char* fileName) 
171       {filename = fileName;}
172       
173 // Variables
174    /**
175    * \brief File Pointer, open during Header parsing
176    */
177    FILE *fp;
178    /**
179    * \brief ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown
180    */
181    FileType filetype;  
182
183 /// after opening the file, we read HEADER_LENGTH_TO_READ bytes.
184    static const unsigned int HEADER_LENGTH_TO_READ; 
185 /// Elements whose value is longer than MAX_SIZE_LOAD_ELEMENT_VALUE are NOT loaded
186    static const unsigned int MAX_SIZE_LOAD_ELEMENT_VALUE;
187 /// Elements whose value is longer than  MAX_SIZE_PRINT_ELEMENT_VALUE are NOT printed  
188    static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE;
189
190 protected:
191    /**
192    * \brief H Table (multimap), to provide fast access
193    */
194    TagHeaderEntryHT tagHT; 
195    /**
196    * \brief chained list, to keep the 'spacial' ordering
197    */
198    ListTag listEntries; 
199    /**
200    * \brief will be set 1 if user asks to 'go inside' the 'sequences' (VR = "SQ")
201    */    
202    int enableSequences;
203    /**
204    * \brief amount of printed details for each Header Entry (Dicom Element)
205    *  0 : the least 
206    */    
207    int printLevel;
208    
209    /** 
210    * \brief For some ACR-NEMA images, it's *not* 7fe0 ... 
211    */   
212    guint16 GrPixel;
213    
214    /** 
215    * \brief For some ACR-NEMA images, it's *not* 0010 ... 
216    */    
217    guint16 NumPixel;
218    /**
219    * \brief some files may contain icons; GrPixel,NumPixel appears several times
220    * Let's remember how many times!
221    */
222    int countGrPixel;
223    /**
224    * \brief = true when the 'pixel Element' is reached during writting process
225    */   
226    bool itsTimeToWritePixels;
227       
228 private:
229    // Read
230    bool ParseHeader(bool exception_on_error = false) throw(gdcmFormatError);
231
232    void LoadHeaderEntries    (void);
233    void LoadHeaderEntry      (gdcmHeaderEntry *);
234    void FindHeaderEntryLength(gdcmHeaderEntry *);
235    void FindHeaderEntryVR    (gdcmHeaderEntry *);
236    bool CheckHeaderEntryVR   (gdcmHeaderEntry *, VRKey);
237
238    std::string GetHeaderEntryValue  (gdcmHeaderEntry *);
239    std::string GetHeaderEntryUnvalue(gdcmHeaderEntry *);
240
241    void SkipHeaderEntry          (gdcmHeaderEntry *);
242    void FixHeaderEntryFoundLength(gdcmHeaderEntry *, guint32);
243    bool IsHeaderEntryAnInteger   (gdcmHeaderEntry *);
244
245    guint32 FindHeaderEntryLengthOB(void);
246
247    guint16 ReadInt16(void);
248    guint32 ReadInt32(void);
249    void    SkipBytes(guint32);
250
251    void Initialise(void);
252    bool CheckSwap(void);
253    void SwitchSwapToBigEndian(void);
254    void SetMaxSizeLoadEntry(long);
255    void SetMaxSizePrintEntry(long);
256
257    // DictEntry  related utilities
258    gdcmDictEntry *GetDictEntryByName  (std::string Name);
259    gdcmDictEntry *GetDictEntryByNumber(guint16, guint16);
260    gdcmDictEntry *NewVirtualDictEntry(guint16 group, 
261                                       guint16 element,
262                                       std::string vr     = "unkn",
263                                       std::string fourth = "unkn",
264                                       std::string name   = "unkn");
265    //gdcmDictEntry *NewVirtualDictEntry(gdcmHeaderEntry *); // never defined
266    
267    // HeaderEntry related utilities
268    
269    gdcmHeaderEntry *ReadNextHeaderEntry   (void);
270    gdcmHeaderEntry *NewHeaderEntryByNumber(guint16 group, 
271                                            guint16 element);
272    gdcmHeaderEntry *NewHeaderEntryByName  (std::string Name);
273    
274    // Deprecated (Not used) --> commented out
275    //gdcmHeaderEntry *NewManualHeaderEntryToPubDict(std::string NewTagName,
276    //                                               std::string VR);
277    
278    guint32 GenerateFreeTagKeyInGroup(guint16 group);
279
280    /**
281    * \brief Refering underlying filename.
282    */
283    std::string filename; 
284
285    /**
286    * \brief Public dictionary used to parse this header
287    */
288    gdcmDict *RefPubDict;
289    
290    /**
291    * \brief Optional "shadow dictionary" (private elements) used to parse this header
292    */
293    gdcmDict *RefShaDict;
294
295    /**
296    * \brief = 1 if a gdcmHeaderEntry was added post parsing 
297    */   
298    int wasUpdated;
299    
300    /**
301    * \brief =1 if user wants to skip shadow groups while parsing (to save space)
302    */
303    int ignoreShadow;
304    
305    /**
306    * \brief Swap code e.g. little, big, bad-big, bad-little endian). 
307    * \warning : this code is not fixed during header parsing.      
308    */
309    int sw;
310    /**
311    * \brief Size threshold above which an element value will NOT be loaded in 
312    *       memory (to avoid loading the image/volume itself). By default,
313    *       this upper bound is fixed to 1024 bytes (which might look reasonable
314    *       when one considers the definition of the various VR contents).
315    */
316    guint32 MaxSizeLoadEntry;
317    
318    /**
319    * \brief Size threshold above which an element value will NOT be *printed* in
320    *        order no to polute the screen output. 
321    *        By default, this upper bound is fixed to 64 bytes.
322    */   
323    guint32 MaxSizePrintEntry;
324    
325 };
326
327 //-----------------------------------------------------------------------------
328 #endif