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