DGtal 1.4.0
Loading...
Searching...
No Matches
ITKDicomReader.ih
1/**
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 **/
16
17/**
18 * @file ITKDicomReader.ih
19 * @author Boris Mansencal (\c boris.mansencal@labri.fr )
20 * LaBRI (CNRS, UMR 5800, University of Bordeaux, Bordeaux-INP, France
21 *
22 * @date 2019/02/05
23 *
24 * Header file for module ITKDicomReader.cpp
25 *
26 * This file is part of the DGtal library.
27 */
28
29#include "DGtal/images/ConstImageAdapter.h"
30#include "DGtal/io/readers/ITKReader.h"
31#if defined(__GNUG__)
32#pragma GCC diagnostic push
33#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
34#endif
35#if defined(__clang__)
36#pragma clang diagnostic push
37#pragma clang diagnostic ignored "-Wdocumentation"
38#endif
39#include <itkImageSeriesReader.h>
40#include <itkGDCMImageIO.h>
41#if defined(__clang__)
42#pragma clang diagnostic pop
43#endif
44#if defined(__GNUG__)
45#pragma GCC diagnostic pop
46#endif
47
48namespace DGtal {
49
50 template <typename I>
51 template <typename TFunctor>
52 I ITKDicomReader<I>::importDICOM( const std::vector<std::string> & filenames,
53 const TFunctor & aFunctor )
54 {
55 (void)ITK_IO_IMAGE_EXT; //To avoid compiler "not used" warning
56 //when building only this reader.
57
58 if ( filenames.empty() )
59 {
60 trace.error() << "[ITKDicomReader] empty filenames vector passed.";
61 throw IOException();
62 }
63
64 typedef typename Image::Domain Domain;
65 typedef itk::ImageIOBase::IOComponentType IOComponentType;
66 BOOST_CONCEPT_ASSERT( (concepts::CUnaryFunctor<TFunctor, ValueOut, Value>));
67 const IOComponentType componentType =
68 ITKReader<I>::getITKComponentType( filenames[0] );
69 // We suppose all file have the same 'componentType'.
70
71 switch ( componentType )
72 {
73
74 default:
75 case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:
76 {
77 trace.error()
78 << "[ITKDicomReader] Unknown and unsupported component type!";
79 throw IOException();
80 }
81 case itk::ImageIOBase::UCHAR:
82 {
83 typedef ImageContainerByITKImage<Domain, unsigned char> DGtalITKImage;
84 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
85 }
86 case itk::ImageIOBase::CHAR:
87 {
88 typedef ImageContainerByITKImage<Domain, char> DGtalITKImage;
89 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
90 }
91 case itk::ImageIOBase::USHORT:
92 {
93 typedef ImageContainerByITKImage<Domain, unsigned short> DGtalITKImage;
94 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
95 }
96 case itk::ImageIOBase::SHORT:
97 {
98 typedef ImageContainerByITKImage<Domain, short> DGtalITKImage;
99 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
100 }
101 case itk::ImageIOBase::UINT:
102 {
103 typedef ImageContainerByITKImage<Domain, unsigned int> DGtalITKImage;
104 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
105 }
106 case itk::ImageIOBase::INT:
107 {
108 typedef ImageContainerByITKImage<Domain, int> DGtalITKImage;
109 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
110 }
111 case itk::ImageIOBase::ULONG:
112 {
113 typedef ImageContainerByITKImage<Domain, unsigned long> DGtalITKImage;
114 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
115 }
116 case itk::ImageIOBase::LONG:
117 {
118 typedef ImageContainerByITKImage<Domain, long> DGtalITKImage;
119 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
120 }
121#if (ITK_VERSION_MAJOR > 4)\
122 || (ITK_VERSION_MAJOR == 4 && ITK_VERSION_MINOR >= 13)
123 case itk::ImageIOBase::ULONGLONG:
124 {
125 typedef ImageContainerByITKImage<Domain, unsigned long long>
126 DGtalITKImage;
127 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
128 }
129 case itk::ImageIOBase::LONGLONG:
130 {
131 typedef ImageContainerByITKImage<Domain, long long> DGtalITKImage;
132 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
133 }
134#endif
135 case itk::ImageIOBase::FLOAT:
136 {
137 typedef ImageContainerByITKImage<Domain, float> DGtalITKImage;
138 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
139 }
140 case itk::ImageIOBase::DOUBLE:
141 {
142 typedef ImageContainerByITKImage<Domain, double> DGtalITKImage;
143 return readDGtalImageFromITKtypes<DGtalITKImage>( filenames, aFunctor );
144 }
145 }
146 }
147
148
149 template <typename I>
150 template <typename Domain, typename PixelType>
151 inline
152 ImageContainerByITKImage<Domain, PixelType>
153 ITKDicomReader<I>::
154 importDicomFiles(const std::vector<std::string> & filenames)
155 {
156 typedef ImageContainerByITKImage<Domain, PixelType> ImageContainer;
157
158 const unsigned int dimension = Domain::dimension;
159 typedef itk::Image<PixelType, dimension> ItkImage;
160 typedef itk::ImageSeriesReader<ItkImage> ItkReader;
161
162 //typedef itk::GDCMImageIO ItkImageIO;
163
164 typedef typename ImageContainer::ITKImagePointer ITKImagePointer;
165 ITKImagePointer itkImage = nullptr;
166
167 try
168 {
169 typename ItkReader::Pointer reader = ItkReader::New();
170 //ItkImageIO::Pointer dicomIO = ItkImageIO::New();
171 //reader->SetImageIO( dicomIO );
172
173 reader->SetFileNames( filenames );
174 reader->Update();
175
176 itkImage = reader->GetOutput();
177 }
178 catch ( itk::ExceptionObject & e )
179 {
180 trace.error() << e;
181 throw IOException();
182 }
183 catch( ... )
184 {
185 trace.error() << "ITKDicomReader: can't read " << filenames.size()
186 << " files"<<std::endl;
187 throw IOException();
188 }
189
190 const typename ItkImage::SizeType& inputSize =
191 itkImage->GetLargestPossibleRegion().GetSize();
192 const unsigned int width = inputSize[0];
193 const unsigned int height = inputSize[1];
194 const unsigned int depth = inputSize[2];
195 if ( !height || !width || !depth )
196 {
197 trace.error() << "ITKDicomReader: one dimension is null (w=" << width
198 << ", h=" << height << ", d=" << depth << ")" << std::endl;
199 throw IOException();
200 }
201
202 const ImageContainer image( itkImage );
203
204 return image;
205 }
206
207
208 template <typename I>
209 template <typename Image, typename Domain, typename OrigValue,
210 typename TFunctor, typename Value>
211 Image
212 ITKDicomReader<I>::Aux<Image, Domain, OrigValue, TFunctor, Value>::
213 readDGtalImageFromITKtypes( const std::vector<std::string> & filenames,
214 const TFunctor & aFunctor )
215 {
216 typedef ImageContainerByITKImage<Domain, OrigValue> TypeDGtalImage;
217 TypeDGtalImage dgtalItkImage =
218 importDicomFiles<Domain, OrigValue>( filenames );
219
220 const Domain& domain = dgtalItkImage.domain();
221
222 typedef ConstImageAdapter<TypeDGtalImage, Domain, functors::Identity,
223 Value, TFunctor>
224 AdaptedImage;
225 const functors::Identity identityFunctor{};
226 const AdaptedImage adapted( dgtalItkImage, domain, identityFunctor,
227 aFunctor);
228
229 Image image( domain );
230 std::copy( adapted.constRange().begin(), adapted.constRange().end(),
231 image.range().outputIterator() );
232
233 return image;
234 }
235
236
237
238 //specialization
239 template <typename I>
240 template <typename Domain, typename OrigValue, typename TFunctor,
241 typename Value>
242 ImageContainerByITKImage<Domain, Value>
243 ITKDicomReader<I>::Aux<ImageContainerByITKImage<Domain, Value>, Domain,
244 OrigValue, TFunctor, Value>::
245 readDGtalImageFromITKtypes( const std::vector<std::string> & filenames,
246 const TFunctor & aFunctor )
247 {
248 typedef ImageContainerByITKImage<Domain, Value> Image;
249
250 typedef ImageContainerByITKImage<Domain, OrigValue> TypeDGtalImage;
251 TypeDGtalImage dgtalItkImage =
252 importDicomFiles<Domain, OrigValue>( filenames );
253
254 const Domain& domain = dgtalItkImage.domain();
255
256 typedef ConstImageAdapter<TypeDGtalImage, Domain, functors::Identity,
257 Value, TFunctor>
258 AdaptedImage;
259 const functors::Identity identityFunctor{};
260 const AdaptedImage adapted( dgtalItkImage, domain, identityFunctor,
261 aFunctor);
262
263 Image image( domain );
264 std::copy( adapted.constRange().begin(), adapted.constRange().end(),
265 image.range().outputIterator() );
266
267 //copy ITKImage spatial parameters
268 image.getITKImagePointer()->SetOrigin(
269 dgtalItkImage.getITKImagePointer()->GetOrigin() );
270 image.getITKImagePointer()->SetSpacing(
271 dgtalItkImage.getITKImagePointer()->GetSpacing() );
272 image.getITKImagePointer()->SetDirection(
273 dgtalItkImage.getITKImagePointer()->GetDirection() );
274
275 return image;
276 }
277
278
279 template <typename I>
280 template <typename TypeDGtalImage, typename TFunctor>
281 typename ITKDicomReader<I>::Image ITKDicomReader<I>::
282 readDGtalImageFromITKtypes( const std::vector<std::string> & filenames,
283 const TFunctor & aFunctor )
284 {
285 typedef typename Image::Domain Domain;
286 typedef typename TypeDGtalImage::Value OrigValue;
287
288 return Aux<Image, Domain, OrigValue, TFunctor, Value>::
289 readDGtalImageFromITKtypes( filenames, aFunctor );
290 }
291
292}//namespace