ITK  5.0.0
Insight Segmentation and Registration Toolkit
itkDCMTKFileReader.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkDCMTKFileReader_h
19 #define itkDCMTKFileReader_h
20 
21 #include "ITKIODCMTKExport.h"
22 #include <stack>
23 #include <vector>
24 #include "itkByteSwapper.h"
25 #include "itkIntTypes.h"
26 #include "vnl/vnl_vector.h"
27 #include "dcmtk/dcmdata/dcdict.h" // For DcmDataDictionary
28 #include "dcmtk/dcmdata/dcdicent.h"
29 #include "dcmtk/dcmdata/dcxfer.h"
30 #include "dcmtk/dcmdata/dcvrds.h"
31 #include "dcmtk/dcmdata/dcstack.h"
32 #include "dcmtk/dcmdata/dcdatset.h"
33 #include "dcmtk/dcmdata/dcitem.h"
34 #include "dcmtk/dcmdata/dcvrobow.h"
35 #include "dcmtk/dcmdata/dcsequen.h"
36 #include "itkMacro.h"
37 #include "itkImageIOBase.h"
38 
39 class DcmSequenceOfItems;
40 class DcmFileFormat;
41 class DcmDictEntry;
42 
43 // Don't print error messages if you're not throwing
44 // an exception
45 // std::cerr body;
46 #define DCMTKExceptionOrErrorReturn(body) \
47  { \
48  if(throwException) \
49  { \
50  itkGenericExceptionMacro(body); \
51  } \
52  else \
53  { \
54  return EXIT_FAILURE; \
55  } \
56  }
57 
58 namespace itk
59 {
60 // Forward reference because of circular dependencies
61 class ITK_FORWARD_EXPORT DCMTKSequence;
62 
63 class ITKIODCMTK_EXPORT DCMTKItem
64 {
65 public:
66  DCMTKItem() : m_DcmItem(nullptr)
67  {
68  }
69  void SetDcmItem(DcmItem *item);
70  int GetElementSQ(const unsigned short group,
71  const unsigned short entry,
72  DCMTKSequence &sequence,
73  const bool throwException = true) const;
74 
75 private:
76  DcmItem *m_DcmItem;
77 };
78 
79 class ITKIODCMTK_EXPORT DCMTKSequence
80 {
81 public:
82  DCMTKSequence() : m_DcmSequenceOfItems(nullptr) {}
83  void SetDcmSequenceOfItems(DcmSequenceOfItems *seq);
84  int card() const;
85  int GetSequence(unsigned long index,
86  DCMTKSequence &target,const bool throwException = true) const;
87  int GetStack(const unsigned short group,
88  const unsigned short element,
89  DcmStack &resultStack, const bool throwException = true) const;
90  int GetElementCS(const unsigned short group,
91  const unsigned short element,
92  std::string &target,
93  const bool throwException = true) const;
94 
95  int GetElementOB(const unsigned short group,
96  const unsigned short element,
97  std::string &target,
98  const bool throwException = true) const;
99 
100  int GetElementCSorOB(const unsigned short group,
101  const unsigned short element,
102  std::string &target,
103  const bool throwException = true) const;
104 
105  template <typename TType>
106  int GetElementDSorOB(const unsigned short group,
107  const unsigned short element,
108  TType &target,
109  const bool throwException = true) const
110  {
111  if(this->GetElementDS<TType>(group,element,1,&target,false) == EXIT_SUCCESS)
112  {
113  return EXIT_SUCCESS;
114  }
115  std::string val;
116  if(this->GetElementOB(group,element,val,throwException) != EXIT_SUCCESS)
117  {
118  DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex
119  << group << " " << std::hex
120  << element << std::dec);
121  }
122  const char *data = val.c_str();
123  const auto * fptr = reinterpret_cast<const TType *>(data);
124  target = *fptr;
125  return EXIT_SUCCESS;
126 
127  }
128 
129  template <typename TType>
130  int GetElementDSorOB(const unsigned short group,
131  const unsigned short element,
132  int count,
133  TType *target,
134  const bool throwException = true) const
135  {
136  if(this->GetElementDS<TType>(group,element,count,target,false) == EXIT_SUCCESS)
137  {
138  return EXIT_SUCCESS;
139  }
140  std::string val;
141  if(this->GetElementOB(group,element,val,throwException) != EXIT_SUCCESS)
142  {
143  DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex
144  << group << " " << std::hex
145  << element << std::dec);
146  }
147  const char *data = val.c_str();
148  const auto * fptr = reinterpret_cast<const TType *>(data);
149  for(int i = 0; i < count; ++i)
150  {
151  target[i] = fptr[i];
152  }
153  return EXIT_SUCCESS;
154  }
155 
156 
157  int GetElementFD(const unsigned short group,
158  const unsigned short element,
159  int count,
160  double *target,
161  const bool throwException = true) const;
162  int GetElementFD(const unsigned short group,
163  const unsigned short element,
164  double &target,
165  const bool throwException = true) const;
166  int GetElementDS(const unsigned short group,
167  const unsigned short element,
168  std::string &target,
169  const bool throwException = true) const;
170  int GetElementTM(const unsigned short group,
171  const unsigned short element,
172  std::string &target,
173  const bool throwException = true) const;
177  template <typename TType>
178  int GetElementDS(const unsigned short group,
179  const unsigned short element,
180  unsigned short count,
181  TType *target,
182  const bool throwException = true) const
183  {
184  DcmStack resultStack;
185  if(this->GetStack(group,element,resultStack,throwException) != EXIT_SUCCESS)
186  {
187  return EXIT_FAILURE;
188  }
189  auto * dsItem = dynamic_cast<DcmDecimalString *>(resultStack.top());
190  if(dsItem == nullptr)
191  {
192  DCMTKExceptionOrErrorReturn(<< "Can't get DecimalString Element at tag "
193  << std::hex << group << " "
194  << element << std::dec);
195  }
197 
198  OFVector<Float64> doubleVals;
199  if(dsItem->getFloat64Vector(doubleVals) != EC_Normal)
200  {
201  DCMTKExceptionOrErrorReturn(<< "Cant extract Array from DecimalString " << std::hex
202  << group << " " << std::hex
203  << element << std::dec);
204  }
205  if(doubleVals.size() != count)
206  {
207  DCMTKExceptionOrErrorReturn(<< "DecimalString " << std::hex
208  << group << " " << std::hex
209  << element << " expected "
210  << count << "items, but found "
211  << doubleVals.size() << std::dec);
212 
213  }
214  for(unsigned i = 0; i < count; i++)
215  {
216  target[i] = static_cast<TType>(doubleVals[i]);
217  }
218  return EXIT_SUCCESS;
219  }
220  int GetElementSQ(const unsigned short group,
221  const unsigned short element,
222  DCMTKSequence &target,
223  const bool throwException = true) const;
224  int GetElementItem(unsigned short itemIndex,
225  DCMTKItem &target,
226  const bool throwException = true) const;
227 
228  void print(std::ostream &out) const
229  {
230  this->m_DcmSequenceOfItems->print(out);
231  }
232 private:
233  DcmSequenceOfItems *m_DcmSequenceOfItems;
234 };
235 
236 class ITKIODCMTK_EXPORT DCMTKFileReader
237 {
238 public:
240 
241  DCMTKFileReader() : m_DFile(nullptr),
242  m_Dataset(nullptr),
243  m_Xfer(EXS_Unknown),
244  m_FrameCount(0),
245  m_FileNumber(-1L)
246  {}
247  ~DCMTKFileReader();
248 
249  void SetFileName(const std::string &fileName);
250 
251  const std::string &GetFileName() const;
252 
253  void LoadFile();
254 
255  int GetElementLO(const unsigned short group,
256  const unsigned short element,
257  std::string &target,
258  const bool throwException = true) const;
259  int GetElementLO(const unsigned short group,
260  const unsigned short element,
261  std::vector<std::string> &target,
262  const bool throwException = true) const;
263 
267  template <typename TType>
268  int GetElementDS(const unsigned short group,
269  const unsigned short element,
270  unsigned short count,
271  TType *target,
272  const bool throwException = true) const
273  {
274  DcmTagKey tagkey(group,element);
275  DcmElement *el;
276  if(this->m_Dataset->findAndGetElement(tagkey,el) != EC_Normal)
277  {
278  DCMTKExceptionOrErrorReturn(<< "Cant find tag " << std::hex
279  << group << " " << std::hex
280  << element << std::dec);
281  }
282  auto * dsItem = dynamic_cast<DcmDecimalString *>(el);
283  if(dsItem == nullptr)
284  {
285  DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex
286  << group << " " << std::hex
287  << element << std::dec);
288  }
289  OFVector<Float64> doubleVals;
290  if(dsItem->getFloat64Vector(doubleVals) != EC_Normal)
291  {
292  DCMTKExceptionOrErrorReturn(<< "Cant extract Array from DecimalString " << std::hex
293  << group << " " << std::hex
294  << element << std::dec);
295  }
296  if(doubleVals.size() != count)
297  {
298  DCMTKExceptionOrErrorReturn(<< "DecimalString " << std::hex
299  << group << " " << std::hex
300  << element << " expected "
301  << count << "items, but found "
302  << doubleVals.size() << std::dec);
304 
305  }
306  for(unsigned i = 0; i < count; i++)
307  {
308  target[i] = static_cast<TType>(doubleVals[i]);
309  }
310  return EXIT_SUCCESS;
311  }
312 
313  template <typename TType>
314  int GetElementDSorOB(const unsigned short group,
315  const unsigned short element,
316  TType &target,
317  const bool throwException = true) const
318  {
319  if(this->GetElementDS<TType>(group,element,1,&target,false) == EXIT_SUCCESS)
320  {
321  return EXIT_SUCCESS;
322  }
323  std::string val;
324  if(this->GetElementOB(group,element,val,throwException) != EXIT_SUCCESS)
325  {
326  DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex
327  << group << " " << std::hex
328  << element << std::dec);
329  }
330  const char *data = val.c_str();
331  const auto * fptr = reinterpret_cast<const TType *>(data);
332  target = *fptr;
333  switch(this->GetTransferSyntax())
334  {
335  case EXS_LittleEndianImplicit:
336  case EXS_LittleEndianExplicit:
338  break;
339  case EXS_BigEndianImplicit:
340  case EXS_BigEndianExplicit:
342  break;
343  default:
344  break;
345  }
346  return EXIT_SUCCESS;
347 
348  }
351  int GetElementDS(const unsigned short group,
352  const unsigned short element,
353  std::string &target,
354  const bool throwException = true) const;
355  int GetElementFD(const unsigned short group,
356  const unsigned short element,
357  double &target,
358  const bool throwException = true) const;
359  int GetElementFD(const unsigned short group,
360  const unsigned short element,
361  int count,
362  double * target,
363  const bool throwException = true) const;
364  int GetElementFL(const unsigned short group,
365  const unsigned short element,
366  float &target,
367  const bool throwException = true) const;
368  int GetElementFLorOB(const unsigned short group,
369  const unsigned short element,
370  float &target,
371  const bool throwException = true) const;
373 
374  int GetElementUS(const unsigned short group,
375  const unsigned short element,
376  unsigned short &target,
377  const bool throwException = true) const;
378  int GetElementUS(const unsigned short group,
379  const unsigned short element,
380  unsigned short *&target,
381  const bool throwException = true) const;
384  int GetElementCS(const unsigned short group,
385  const unsigned short element,
386  std::string &target,
387  const bool throwException = true) const;
388 
391  int GetElementPN(const unsigned short group,
392  const unsigned short element,
393  std::string &target,
394  const bool throwException = true) const;
395 
398  int GetElementIS(const unsigned short group,
399  const unsigned short element,
400  ::itk::int32_t &target,
401  const bool throwException = true) const;
402 
403  int GetElementSL(const unsigned short group,
404  const unsigned short element,
405  ::itk::int32_t &target,
406  const bool throwException = true) const;
407 
408  int GetElementISorOB(const unsigned short group,
409  const unsigned short element,
410  ::itk::int32_t &target,
411  const bool throwException = true) const;
412 
413  int GetElementCSorOB(const unsigned short group,
414  const unsigned short element,
415  std::string &target,
416  const bool throwException = true) const;
417 
420  int GetElementOB(const unsigned short group,
421  const unsigned short element,
422  std::string &target,
423  const bool throwException = true) const;
424 
425  int GetElementSQ(const unsigned short group,
426  unsigned short entry,
427  DCMTKSequence &sequence,
428  const bool throwException = true) const;
429 
430  int GetElementUI(const unsigned short group,
431  unsigned short entry,
432  std::string &target,
433  const bool throwException = true) const;
434 
435  int GetElementDA(const unsigned short group,
436  const unsigned short element,
437  std::string &target,
438  const bool throwException = true) const;
439 
440  int GetElementTM(const unsigned short group,
441  const unsigned short element,
442  std::string &target,
443  const bool throwException = true) const;
444 
445  int GetDirCosines(vnl_vector<double> &dir1,
446  vnl_vector<double> &dir2,
447  vnl_vector<double> &dir3) const;
448 
449  int GetDirCosArray(double * const dircos) const;
450 
451  int GetFrameCount() const;
452 
453  int GetSlopeIntercept(double &slope, double &intercept) const;
454 
455  int GetDimensions(unsigned short &rows, unsigned short &columns) const;
456 
457  ImageIOBase::IOComponentType GetImageDataType() const;
458  ImageIOBase::IOPixelType GetImagePixelType() const;
459 
460  int GetSpacing(double * const spacing) const;
461  int GetOrigin(double * const origin) const;
462 
463  bool HasPixelData() const;
464 
465  E_TransferSyntax GetTransferSyntax() const;
466 
467  long GetFileNumber() const;
468  static void
469  AddDictEntry(DcmDictEntry *entry);
470 
471  static bool CanReadFile(const std::string &filename);
472  static bool IsImageFile(const std::string &filename);
473 
474 private:
475 
476  std::string m_FileName;
477  DcmFileFormat* m_DFile;
478  DcmDataset * m_Dataset;
479  E_TransferSyntax m_Xfer;
480  Sint32 m_FrameCount;
482 };
483 
485 }
486 
487 #endif // itkDCMTKFileReader_h
static void SwapFromSystemToBigEndian(T *p)
int GetElementDSorOB(const unsigned short group, const unsigned short element, int count, TType *target, const bool throwException=true) const
int GetElementDSorOB(const unsigned short group, const unsigned short element, TType &target, const bool throwException=true) const
bool CompareDCMTKFileReaders(DCMTKFileReader *a, DCMTKFileReader *b)
int GetElementDS(const unsigned short group, const unsigned short element, unsigned short count, TType *target, const bool throwException=true) const
DcmSequenceOfItems * m_DcmSequenceOfItems
E_TransferSyntax m_Xfer
static void SwapFromSystemToLittleEndian(T *p)
int GetElementDSorOB(const unsigned short group, const unsigned short element, TType &target, const bool throwException=true) const
void print(std::ostream &out) const
::int32_t int32_t
Definition: itkIntTypes.h:32
#define DCMTKExceptionOrErrorReturn(body)
int GetElementDS(const unsigned short group, const unsigned short element, unsigned short count, TType *target, const bool throwException=true) const