Slicer 5.13
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
Loading...
Searching...
No Matches
itkDCMTKFileReader.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
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 * https://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// Vendored copy: define the ITKIODCMTK export macros as no-ops so the
22// reader builds directly into the consuming module (parity with
23// SlicerExt PETDICOMExtension/SUVFactorCalculatorCLI). Sourced from ITK
24// Modules/IO/DCMTK/src after ITK commit db492d9b09 made the header private.
25#ifndef ITKIODCMTK_EXPORT
26# define ITKIODCMTK_EXPORT
27#endif
28#include <stack>
29#include <vector>
30#include "itkByteSwapper.h"
31#include "itkIntTypes.h"
32#include "vnl/vnl_vector.h"
33#include "dcmtk/dcmdata/dcdict.h" // For DcmDataDictionary
34#include "dcmtk/dcmdata/dcdicent.h"
35#include "dcmtk/dcmdata/dcxfer.h"
36#include "dcmtk/dcmdata/dcvrds.h"
37#include "dcmtk/dcmdata/dcstack.h"
38#include "dcmtk/dcmdata/dcdatset.h"
39#include "dcmtk/dcmdata/dcitem.h"
40#include "dcmtk/dcmdata/dcvrobow.h"
41#include "dcmtk/dcmdata/dcsequen.h"
42#include "itkMacro.h"
43#include "itkImageIOBase.h"
44#include "itkMetaDataDictionary.h"
45
46class DcmSequenceOfItems;
47class DcmFileFormat;
48class DcmDictEntry;
49
50// Don't print error messages if you're not throwing
51// an exception
52// std::cerr body;
53#define DCMTKExceptionOrErrorReturn(body) \
54 { \
55 if (throwException) \
56 { \
57 itkGenericExceptionMacro(body); \
58 } \
59 else \
60 { \
61 return EXIT_FAILURE; \
62 } \
63 }
64
65namespace itk
66{
67// Forward reference because of circular dependencies
68class ITK_FORWARD_EXPORT DCMTKSequence;
69
71{
72public:
73 DCMTKItem() = default;
74
75 void SetDcmItem(DcmItem* item);
76 int GetElementSQ(const unsigned short group, const unsigned short entry, DCMTKSequence& sequence, const bool throwException = true) const;
77
78private:
79 DcmItem* m_DcmItem{ nullptr };
80};
81
83{
84public:
85 DCMTKSequence() = default;
86 void SetDcmSequenceOfItems(DcmSequenceOfItems* seq);
87 int card() const;
88 int GetSequence(unsigned long index, DCMTKSequence& target, const bool throwException = true) const;
89 int GetStack(const unsigned short group, const unsigned short element, DcmStack& resultStack, const bool throwException = true) const;
90 int GetElementCS(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
91
92 int GetElementOB(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
93
94 int GetElementCSorOB(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
95
96 template <typename TType>
97 int GetElementDSorOB(const unsigned short group, const unsigned short element, TType& target, const bool throwException = true) const
98 {
99 if (this->GetElementDS<TType>(group, element, 1, &target, false) == EXIT_SUCCESS)
100 {
101 return EXIT_SUCCESS;
102 }
103 std::string val;
104 if (this->GetElementOB(group, element, val, throwException) != EXIT_SUCCESS)
105 {
106 DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex << group << ' ' << std::hex << element << std::dec);
107 }
108 const char* data = val.c_str();
109 const auto* fptr = reinterpret_cast<const TType*>(data);
110 target = *fptr;
111 return EXIT_SUCCESS;
112 }
113
114 template <typename TType>
115 int GetElementDSorOB(const unsigned short group, const unsigned short element, int count, TType* target, const bool throwException = true) const
116 {
117 if (this->GetElementDS<TType>(group, element, count, target, false) == EXIT_SUCCESS)
118 {
119 return EXIT_SUCCESS;
120 }
121 std::string val;
122 if (this->GetElementOB(group, element, val, throwException) != EXIT_SUCCESS)
123 {
124 DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex << group << ' ' << std::hex << element << std::dec);
125 }
126 const char* data = val.c_str();
127 const auto* fptr = reinterpret_cast<const TType*>(data);
128 for (int i = 0; i < count; ++i)
129 {
130 target[i] = fptr[i];
131 }
132 return EXIT_SUCCESS;
133 }
134
135 int GetElementFD(const unsigned short group, const unsigned short element, int count, double* target, const bool throwException = true) const;
136 int GetElementFD(const unsigned short group, const unsigned short element, double& target, const bool throwException = true) const;
137 int GetElementDS(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
138 int GetElementTM(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
142 template <typename TType>
143 int GetElementDS(const unsigned short group, const unsigned short element, unsigned short count, TType* target, const bool throwException = true) const
144 {
145 DcmStack resultStack;
146 if (this->GetStack(group, element, resultStack, throwException) != EXIT_SUCCESS)
147 {
148 return EXIT_FAILURE;
149 }
150 auto* dsItem = dynamic_cast<DcmDecimalString*>(resultStack.top());
151 if (dsItem == nullptr)
152 {
153 DCMTKExceptionOrErrorReturn(<< "Can't get DecimalString Element at tag " << std::hex << group << ' ' << element << std::dec);
154 }
155
156 OFVector<Float64> doubleVals;
157 if (dsItem->getFloat64Vector(doubleVals) != EC_Normal)
158 {
159 DCMTKExceptionOrErrorReturn(<< "Cant extract Array from DecimalString " << std::hex << group << ' ' << std::hex << element << std::dec);
160 }
161 if (doubleVals.size() != count)
162 {
163 DCMTKExceptionOrErrorReturn(<< "DecimalString " << std::hex << group << ' ' << std::hex << element << " expected " << count << "items, but found " << doubleVals.size()
164 << std::dec);
165 }
166 for (unsigned int i = 0; i < count; ++i)
167 {
168 target[i] = static_cast<TType>(doubleVals[i]);
169 }
170 return EXIT_SUCCESS;
171 }
172 int GetElementSQ(const unsigned short group, const unsigned short element, DCMTKSequence& target, const bool throwException = true) const;
173 int GetElementItem(unsigned short itemIndex, DCMTKItem& target, const bool throwException = true) const;
174
175 void print(std::ostream& out) const { this->m_DcmSequenceOfItems->print(out); }
176
177private:
178 DcmSequenceOfItems* m_DcmSequenceOfItems{ nullptr };
179};
180
182{
183public:
185
186 DCMTKFileReader() = default;
188
189 void SetFileName(const std::string& fileName);
190
191 const std::string& GetFileName() const;
192
193 void LoadFile();
194
195 int GetElementLO(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
196 int GetElementLO(const unsigned short group, const unsigned short element, std::vector<std::string>& target, const bool throwException = true) const;
197
201 template <typename TType>
202 int GetElementDS(const unsigned short group, const unsigned short element, unsigned short count, TType* target, const bool throwException = true) const
203 {
204 DcmTagKey tagkey(group, element);
205 DcmElement* el;
206 if (this->m_Dataset->findAndGetElement(tagkey, el) != EC_Normal)
207 {
208 DCMTKExceptionOrErrorReturn(<< "Cant find tag " << std::hex << group << ' ' << std::hex << element << std::dec);
209 }
210 auto* dsItem = dynamic_cast<DcmDecimalString*>(el);
211 if (dsItem == nullptr)
212 {
213 DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex << group << ' ' << std::hex << element << std::dec);
214 }
215 OFVector<Float64> doubleVals;
216 if (dsItem->getFloat64Vector(doubleVals) != EC_Normal)
217 {
218 DCMTKExceptionOrErrorReturn(<< "Cant extract Array from DecimalString " << std::hex << group << ' ' << std::hex << element << std::dec);
219 }
220 if (doubleVals.size() != count)
221 {
222 DCMTKExceptionOrErrorReturn(<< "DecimalString " << std::hex << group << ' ' << std::hex << element << " expected " << count << "items, but found " << doubleVals.size()
223 << std::dec);
224 }
225 for (unsigned int i = 0; i < count; ++i)
226 {
227 target[i] = static_cast<TType>(doubleVals[i]);
228 }
229 return EXIT_SUCCESS;
230 }
231
232 template <typename TType>
233 int GetElementDSorOB(const unsigned short group, const unsigned short element, TType& target, const bool throwException = true) const
234 {
235 if (this->GetElementDS<TType>(group, element, 1, &target, false) == EXIT_SUCCESS)
236 {
237 return EXIT_SUCCESS;
238 }
239 std::string val;
240 if (this->GetElementOB(group, element, val, throwException) != EXIT_SUCCESS)
241 {
242 DCMTKExceptionOrErrorReturn(<< "Cant find DecimalString element " << std::hex << group << ' ' << std::hex << element << std::dec);
243 }
244 const char* data = val.c_str();
245 const auto* fptr = reinterpret_cast<const TType*>(data);
246 target = *fptr;
247 switch (this->GetTransferSyntax())
248 {
249 case EXS_LittleEndianImplicit:
250 case EXS_LittleEndianExplicit: itk::ByteSwapper<TType>::SwapFromSystemToLittleEndian(&target); break;
251 case EXS_BigEndianImplicit:
252 case EXS_BigEndianExplicit: itk::ByteSwapper<TType>::SwapFromSystemToBigEndian(&target); break;
253 default: break;
254 }
255 return EXIT_SUCCESS;
256 }
257
259 int GetElementDS(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
260 int GetElementFD(const unsigned short group, const unsigned short element, double& target, const bool throwException = true) const;
261 int GetElementFD(const unsigned short group, const unsigned short element, int count, double* target, const bool throwException = true) const;
262 int GetElementFL(const unsigned short group, const unsigned short element, float& target, const bool throwException = true) const;
263 int GetElementFLorOB(const unsigned short group, const unsigned short element, float& target, const bool throwException = true) const;
264
265 int GetElementUS(const unsigned short group, const unsigned short element, unsigned short& target, const bool throwException = true) const;
266 int GetElementUS(const unsigned short group, const unsigned short element, unsigned short*& target, const bool throwException = true) const;
269 int GetElementCS(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
270
273 int GetElementPN(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
274
277 int GetElementIS(const unsigned short group, const unsigned short element, itk::int32_t& target, const bool throwException = true) const;
278
279 int GetElementSL(const unsigned short group, const unsigned short element, itk::int32_t& target, const bool throwException = true) const;
280
281 int GetElementISorOB(const unsigned short group, const unsigned short element, itk::int32_t& target, const bool throwException = true) const;
282
283 int GetElementCSorOB(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
284
287 int GetElementOB(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
288
289 int GetElementSQ(const unsigned short group, unsigned short entry, DCMTKSequence& sequence, const bool throwException = true) const;
290
291 int GetElementUI(const unsigned short group, unsigned short entry, std::string& target, const bool throwException = true) const;
292
294 int GetElementAsString(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
295
296 int GetElementDA(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
297
298 int GetElementTM(const unsigned short group, const unsigned short element, std::string& target, const bool throwException = true) const;
299
300 int GetDirCosines(vnl_vector<double>& dir1, vnl_vector<double>& dir2, vnl_vector<double>& dir3) const;
301
302 int GetDirCosArray(double* const dircos) const;
303
304 int GetFrameCount() const;
305
306 int GetSlopeIntercept(double& slope, double& intercept) const;
307
308 int GetDimensions(unsigned short& rows, unsigned short& columns) const;
309
310 IOComponentEnum GetImageDataType() const;
311 IOPixelEnum GetImagePixelType() const;
312
313 int GetSpacing(double* const spacing) const;
314 int GetOrigin(double* const origin) const;
315
316 bool HasPixelData() const;
317
318 E_TransferSyntax GetTransferSyntax() const;
319
320 long GetFileNumber() const;
321 static void AddDictEntry(DcmDictEntry* entry);
322
323 static bool CanReadFile(const std::string& filename);
324 static bool IsImageFile(const std::string& filename);
325
326 void PopulateMetaDataDictionary(MetaDataDictionary& dict) const;
327
328private:
329 std::string m_FileName;
330 DcmFileFormat* m_DFile{ nullptr };
331 DcmDataset* m_Dataset{ nullptr };
332 E_TransferSyntax m_Xfer{ EXS_Unknown };
333 Sint32 m_FrameCount{ 0 };
334 long m_FileNumber{ -1L };
335};
336
338} // namespace itk
339
340#endif // itkDCMTKFileReader_h
int GetFrameCount() const
static void AddDictEntry(DcmDictEntry *entry)
int GetElementSQ(const unsigned short group, unsigned short entry, DCMTKSequence &sequence, const bool throwException=true) const
int GetDirCosines(vnl_vector< double > &dir1, vnl_vector< double > &dir2, vnl_vector< double > &dir3) const
int GetElementIS(const unsigned short group, const unsigned short element, itk::int32_t &target, const bool throwException=true) const
int GetElementUI(const unsigned short group, unsigned short entry, std::string &target, const bool throwException=true) const
void SetFileName(const std::string &fileName)
int GetElementISorOB(const unsigned short group, const unsigned short element, itk::int32_t &target, const bool throwException=true) const
int GetDimensions(unsigned short &rows, unsigned short &columns) const
int GetElementDA(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
E_TransferSyntax GetTransferSyntax() const
int GetElementLO(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetElementUS(const unsigned short group, const unsigned short element, unsigned short &target, const bool throwException=true) const
int GetElementFD(const unsigned short group, const unsigned short element, double &target, const bool throwException=true) const
int GetElementFD(const unsigned short group, const unsigned short element, int count, double *target, const bool throwException=true) const
int GetElementSL(const unsigned short group, const unsigned short element, itk::int32_t &target, const bool throwException=true) const
int GetElementPN(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
DCMTKFileReader()=default
int GetElementCS(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
static bool CanReadFile(const std::string &filename)
int GetElementLO(const unsigned short group, const unsigned short element, std::vector< std::string > &target, const bool throwException=true) const
int GetOrigin(double *const origin) const
int GetElementFL(const unsigned short group, const unsigned short element, float &target, const bool throwException=true) const
int GetElementTM(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetDirCosArray(double *const dircos) const
int GetElementDSorOB(const unsigned short group, const unsigned short element, TType &target, const bool throwException=true) const
const std::string & GetFileName() const
static bool IsImageFile(const std::string &filename)
bool HasPixelData() const
int GetElementDS(const unsigned short group, const unsigned short element, unsigned short count, TType *target, const bool throwException=true) const
int GetSlopeIntercept(double &slope, double &intercept) const
int GetElementUS(const unsigned short group, const unsigned short element, unsigned short *&target, const bool throwException=true) const
int GetElementCSorOB(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetSpacing(double *const spacing) const
int GetElementFLorOB(const unsigned short group, const unsigned short element, float &target, const bool throwException=true) const
long GetFileNumber() const
void PopulateMetaDataDictionary(MetaDataDictionary &dict) const
int GetElementAsString(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetElementDS(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetElementOB(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
IOComponentEnum GetImageDataType() const
IOPixelEnum GetImagePixelType() const
DCMTKItem()=default
int GetElementSQ(const unsigned short group, const unsigned short entry, DCMTKSequence &sequence, const bool throwException=true) const
void SetDcmItem(DcmItem *item)
int GetElementDS(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
void SetDcmSequenceOfItems(DcmSequenceOfItems *seq)
int GetElementCSorOB(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetElementFD(const unsigned short group, const unsigned short element, int count, double *target, const bool throwException=true) const
int GetElementCS(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetSequence(unsigned long index, DCMTKSequence &target, const bool throwException=true) const
int GetElementDSorOB(const unsigned short group, const unsigned short element, TType &target, const bool throwException=true) const
int GetElementItem(unsigned short itemIndex, DCMTKItem &target, const bool throwException=true) const
int GetElementTM(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
DCMTKSequence()=default
void print(std::ostream &out) const
int GetStack(const unsigned short group, const unsigned short element, DcmStack &resultStack, const bool throwException=true) const
int card() const
int GetElementOB(const unsigned short group, const unsigned short element, std::string &target, const bool throwException=true) const
int GetElementDS(const unsigned short group, const unsigned short element, unsigned short count, TType *target, const bool throwException=true) const
int GetElementSQ(const unsigned short group, const unsigned short element, DCMTKSequence &target, const bool throwException=true) const
int GetElementDSorOB(const unsigned short group, const unsigned short element, int count, TType *target, const bool throwException=true) const
int GetElementFD(const unsigned short group, const unsigned short element, double &target, const bool throwException=true) const
#define ITKIODCMTK_EXPORT
#define DCMTKExceptionOrErrorReturn(body)
Simplified inverse ITK transforms.
bool CompareDCMTKFileReaders(DCMTKFileReader *a, DCMTKFileReader *b)