]> Creatis software - gdcm.git/blob - src/gdcmTS.cxx
ENH: Fix nasty bug. Thanks to bcc55 for actually doing optimization
[gdcm.git] / src / gdcmTS.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmTS.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/10/25 17:51:17 $
7   Version:   $Revision: 1.51 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmTS.h"
20 #include "gdcmDebug.h"
21 #include "gdcmUtil.h"
22 #include "gdcmDictSet.h"
23
24 #include <fstream>
25 #include <string>
26 #include <iostream>
27 #include <ctype.h> // for isdigit
28
29 // TODO
30 // a lot of troubles expected with TS : 1.2.840.113619.5.2
31 // Implicit VR - Big Endian
32 // http://www.gemedicalsystemseurope.com/euen/it_solutions/pdf/lsqxi_rev2.pdf
33 // 
34
35 namespace gdcm 
36 {
37 //-----------------------------------------------------------------------------
38 /// \brief Transfer Syntaxes gdcm deals with (internal use only)
39 static const char *SpecialStrings[] =  {
40   // Implicit VR Little Endian
41   "1.2.840.10008.1.2",
42   // Implicit VR Big Endian DLX (G.E Private)
43   "1.2.840.113619.5.2",
44   // Explicit VR Little Endian
45   "1.2.840.10008.1.2.1",
46   // Deflated Explicit VR Little Endian
47   "1.2.840.10008.1.2.1.99",
48   // Explicit VR Big Endian
49   "1.2.840.10008.1.2.2",
50   // JPEG Baseline (Process 1)
51   "1.2.840.10008.1.2.4.50",
52   // JPEG Extended (Process 2 & 4)
53   "1.2.840.10008.1.2.4.51",
54   // JPEG Extended (Process 3 & 5)
55   "1.2.840.10008.1.2.4.52",
56   // JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)
57   "1.2.840.10008.1.2.4.53",
58   // JPEG Full Progression, Non-Hierarchical (Process 10 & 12)
59   "1.2.840.10008.1.2.4.55",
60   // JPEG Lossless, Non-Hierarchical (Process 14)
61   "1.2.840.10008.1.2.4.57",
62   // JPEG Lossless, Hierarchical, First-Order Prediction (Process 14,
63   //                                                       [Selection Value 1])
64   "1.2.840.10008.1.2.4.70",
65   // JPEG-LS Lossless Image Compression
66   "1.2.840.10008.1.2.4.80",
67   // JPEG-LS Lossy (Near-Lossless) Image Compression
68   "1.2.840.10008.1.2.4.81",
69   // JPEG 2000 Lossless
70   "1.2.840.10008.1.2.4.90",
71   // JPEG 2000
72   "1.2.840.10008.1.2.4.91",
73   // RLE Lossless
74   "1.2.840.10008.1.2.5",
75   // MPEG2 Main Profile @ Main Level
76   "1.2.840.10008.1.2.4.100",
77   // Unknown
78   "Unknown Transfer Syntax", // Pretty sure we never use this case...
79   NULL // Compilers have no obligation to finish by NULL, do it ourself
80 };
81
82 //-----------------------------------------------------------------------------
83 /// \brief auto generated function, to fill up the Dicom Dictionnary,
84 ///       if relevant file is not found on user's disk
85 void FillDefaultTSDict(TSHT &ts);
86
87 //-----------------------------------------------------------------------------
88 // Constructor / Destructor
89 TS::TS() 
90 {
91    std::string filename = DictSet::BuildDictPath() + DICT_TS;
92    std::ifstream from(filename.c_str());
93    if ( !from )
94    {
95       gdcmWarningMacro("Can't open dictionary" << filename.c_str());
96       FillDefaultTSDict( TsMap );
97    }
98    else
99    {
100       TSKey key;
101       TSAtr name;
102
103       while (!from.eof())
104       {
105          from >> key;
106          from >> std::ws;
107          std::getline(from, name);
108
109          if (key != "")
110          {
111             TsMap[key] = name;
112          }
113       }
114       from.close();
115    }
116 }
117
118 TS::~TS() 
119 {
120    TsMap.clear();
121 }
122
123 //-----------------------------------------------------------------------------
124 // Public
125
126 /// \brief returns occurence number of the given key
127 int TS::Count(TSKey const &key) 
128 {
129    return TsMap.count(key);
130 }
131
132 /// \brief returns the human readable value of a Transfer Syntax string 
133 TSAtr const &TS::GetValue(TSKey const &key) 
134 {
135    // First thing clean up the string 
136    // (sometimes the transfer syntax is padded with spaces)
137    std::string copy = key;
138    while ( copy.size() && !isdigit((unsigned char)copy[copy.size()-1]) )
139    {
140       copy.erase(copy.size()-1, 1);
141    }
142
143    TSHT::const_iterator it = TsMap.find(copy);
144    if (it == TsMap.end())
145    {
146       return GDCM_UNFOUND;
147    }
148    return it->second;
149 }
150 /**
151  * \brief   Determines if the key passed corresponds to a 'Transfer Syntax'
152  *          as defined in DICOM (and stored in gdcm::TS class)
153  * @return  True when key is an actual 'Transfer Syntax'. 
154  *          False in all other cases.
155  */
156 bool TS::IsTransferSyntax(TSKey const &key)
157 {
158    TSHT::const_iterator it = TsMap.find(key);
159    return it != TsMap.end();
160 }
161
162 /**
163  * \brief   Determines if the Transfer Syntax was already encountered
164  *          and if it corresponds to a Run Length Encoding Lossless one
165  * @return  True when Run Length Encoding Lossless found. 
166  *          False in all other cases.
167  */
168 bool TS::IsRLELossless(TSKey const &key)
169 {
170    bool r = false;
171    // First check this is an actual transfer syntax
172    if ( IsTransferSyntax(key) )
173    {
174       if ( key == SpecialStrings[RLELossless] )
175       {
176          r = true;
177       }
178    }
179    return r;
180 }
181
182 /**
183  * \brief   Determines if the Transfer Syntax was already encountered
184  *          and if it corresponds to a 'classical' JPEG Lossless one
185  * @return  True when 'classical' Lossless found. 
186  *          False in all other cases.
187  */
188 bool TS::IsJPEGLossless(TSKey const &key)
189 {
190    bool r = false;
191    // First check this is an actual transfer syntax
192    if ( IsTransferSyntax(key) )
193    {
194       if ( key == SpecialStrings[JPEGFullProgressionProcess10_12]
195         || key == SpecialStrings[JPEGLosslessProcess14]
196         || key == SpecialStrings[JPEGLosslessProcess14_1] )
197       {
198          r = true;
199       }
200    }
201    return r;
202 }
203
204 /**
205  * \brief   Determines if the Transfer Syntax was already encountered
206  *          and if it corresponds to a 'classical' JPEG Lossy one
207  * @return  True when 'classical' Lossy found. 
208  *          False in all other cases.
209  */
210 bool TS::IsJPEGLossy(TSKey const &key)
211 {
212    bool r = false;
213    // First check this is an actual transfer syntax
214    if ( IsTransferSyntax(key) )
215    {
216       if ( key == SpecialStrings[JPEGBaselineProcess1]
217         || key == SpecialStrings[JPEGExtendedProcess2_4]
218         || key == SpecialStrings[JPEGExtendedProcess3_5]
219         || key == SpecialStrings[JPEGSpectralSelectionProcess6_8] )
220       {
221          r = true;
222       }
223    }
224    return r;
225 }
226
227 /**
228  * \brief   Determines if the Transfer Syntax was already encountered
229  *          and if it corresponds to a JPEG2000 one
230  * @return  True when JPEG2000 (Lossly or LossLess) found. 
231  *          False in all other cases.
232  */
233 bool TS::IsJPEG2000(TSKey const &key)
234 {
235    bool r = false;
236    // First check this is an actual transfer syntax
237    if ( IsTransferSyntax(key) )
238    {
239       if ( key == SpecialStrings[JPEG2000Lossless]
240         || key == SpecialStrings[JPEG2000] )
241       {
242          r = true;
243       }
244    }
245    return r;
246 }
247
248 /**
249  * \brief   Determines if the Transfer Syntax corresponds to 
250  *          'classical' Jpeg Lossless or Jpeg lossy.
251  * @return  True when any form of JPEG found. False otherwise.
252  */
253 bool TS::IsJPEG(TSKey const &key)
254 {
255    bool r = false;
256    // First check this is an actual transfer syntax
257    if ( IsTransferSyntax(key) )
258    {
259       if ( IsJPEGLossy( key )
260         || IsJPEGLossless( key )
261         || IsJPEG2000( key )
262         || IsJPEGLS( key )
263          )
264       {
265          r = true;
266       }
267    }
268    return r;
269 }
270
271 /**
272  * \brief   Determines if the Transfer Syntax corresponds to any form
273  *          of Jpeg-LS encoded Pixel data.
274  * @return  True when any form of JPEG-LS found. False otherwise.
275  */
276 bool TS::IsJPEGLS(TSKey const &key)
277 {
278    bool r = false;
279    // First check this is an actual transfer syntax
280    if ( IsTransferSyntax(key) )
281    {
282       if ( key == SpecialStrings[JPEGLSLossless]
283         || key == SpecialStrings[JPEGLSNearLossless] ) 
284       {
285          r = true;
286       }
287    }
288    return r;
289 }
290
291 /**
292  * \brief   Determines if the Transfer Syntax corresponds to any form
293  *          of MPEG encoded Pixel data.
294  * @return  True when any form of MPEG found. False otherwise.
295  */
296 bool TS::IsMPEG(TSKey const &key)
297 {
298    bool r = false;
299    // First check this is an actual transfer syntax
300    if ( IsTransferSyntax(key) )
301    {
302       if ( key == SpecialStrings[MPEG2MainProfile] ) 
303       {
304          r = true;
305       }
306    }
307    return r;
308 }
309
310 /**
311  * \brief   GetSpecialTransferSyntax ??
312  * @param  key TSKey const &key ??
313  * @return  TS::SpecialType ??.
314  */
315 TS::SpecialType TS::GetSpecialTransferSyntax(TSKey const &key)
316 {
317    for (int i = 0; SpecialStrings[i] != NULL; i++)
318    {
319       if ( SpecialStrings[i] == key )
320       {
321          return SpecialType(i);
322       }
323    }
324    return UnknownTS;
325 }
326
327 /**
328  * \brief   GetSpecialTransferSyntax ??
329  * @param  t SpecialType t ??
330  * @return  char* TS : SpecialStrings[t] ??.
331  */
332 const char* TS::GetSpecialTransferSyntax(SpecialType t)
333 {
334    return SpecialStrings[t];
335 }
336
337 //-----------------------------------------------------------------------------
338 // Protected
339
340 //-----------------------------------------------------------------------------
341 // Private
342
343 //-----------------------------------------------------------------------------
344 // Print
345 /**
346  * \brief   Print all 
347  * @param   os The output stream to be written to.
348  */
349 void TS::Print(std::ostream &os) 
350 {
351    std::ostringstream s;
352
353    for (TSHT::const_iterator it = TsMap.begin(); it != TsMap.end(); ++it)
354    {
355       s << "TS : " << it->first << " = " << it->second << std::endl;
356    }
357    os << s.str();
358 }
359
360 //-----------------------------------------------------------------------------
361 } // end namespace gdcm