fw4spl
fwDcmtkIO/include/fwDcmtkIO/reader/main/ImageReader.hpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #pragma once
8 
9 #include "fwDcmtkIO/config.hpp"
10 
11 #include <fwMedData/DicomSeries.hpp>
12 
13 #include <dcmtk/config/osconfig.h>
14 #include <dcmtk/dcmdata/dcdeftag.h>
15 #include <dcmtk/dcmdata/dcfilefo.h>
16 #include <dcmtk/dcmdata/dcistrmb.h>
17 #include <dcmtk/dcmimgle/dcmimage.h>
18 #include <dcmtk/dcmnet/diutil.h>
19 
20 namespace fwDcmtkIO
21 {
22 namespace reader
23 {
24 namespace main
25 {
26 
30 class FWDCMTKIO_CLASS_API ImageReader
31 {
32 public:
33  typedef ::fwMedData::DicomSeries::DicomContainerType DicomContainerType;
34 
47  static void fillImageBuffer(unsigned int rows, unsigned int columns,
48  unsigned int depth,
49  DicomContainerType& instances,
50  void* destination, double rescaleSlope,
51  double rescaleIntercept,
52  unsigned short pixelRepresentation, ::fwTools::Type imageType)
53  {
54  if (pixelRepresentation == 0)
55  {
56  // Use unsigned char
57  if(imageType.sizeOf() == 1)
58  {
59  ::fwDcmtkIO::reader::main::ImageReader::fillImageBuffer< Uint8 >(
60  rows, columns, depth, instances, destination, rescaleSlope, rescaleIntercept, imageType);
61  }
62  // Use unsigned short
63  else
64  {
65  ::fwDcmtkIO::reader::main::ImageReader::fillImageBuffer< Uint16 >(
66  rows, columns, depth, instances, destination, rescaleSlope, rescaleIntercept, imageType);
67  }
68  }
69  else
70  {
71  // Use signed char
72  if(imageType.sizeOf() == 1)
73  {
74  ::fwDcmtkIO::reader::main::ImageReader::fillImageBuffer< Sint8 >(
75  rows, columns, depth, instances, destination, rescaleSlope, rescaleIntercept, imageType);
76  }
77  // Use signed short
78  else
79  {
80  ::fwDcmtkIO::reader::main::ImageReader::fillImageBuffer< Sint16 >(
81  rows, columns, depth, instances, destination, rescaleSlope, rescaleIntercept, imageType);
82  }
83  }
84  }
85 
94  template< typename T >
95  static T* createTemporaryBuffer(unsigned int rows, unsigned int columns,
96  unsigned int depth,
97  DicomContainerType& instances)
98  {
99  OFCondition status;
100  DcmDataset* dataset;
101 
102  T* tempoBuffer = new T[rows*columns*depth];
103  uint32_t sliceSize = rows*columns;
104 
105  uint32_t copySize;
106  if(instances.size() == 1 )
107  {
108  copySize = rows*columns*depth;
109  }
110  else
111  {
112  copySize = rows*columns;
113  }
114 
115  // Slice index
116  unsigned short z = 0;
117 
118  // Read every instances
119  for(const auto& item : instances)
120  {
121  const ::fwMemory::BufferObject::sptr bufferObj = item.second;
122  const size_t buffSize = bufferObj->getSize();
123  const std::string dicomPath = bufferObj->getStreamInfo().fsFile.string();
124  ::fwMemory::BufferObject::Lock lock(bufferObj);
125  char* buffer = static_cast< char* >( lock.getBuffer() );
126 
127  DcmInputBufferStream is;
128  is.setBuffer(buffer, offile_off_t(buffSize));
129  is.setEos();
130 
131  DcmFileFormat fileFormat;
132  fileFormat.transferInit();
133  if (!fileFormat.read(is).good())
134  {
135  FW_RAISE("Unable to read Dicom file '"<< dicomPath <<"' "<<
136  "(slice: '" << item.first << "')");
137  }
138 
139  fileFormat.loadAllDataIntoMemory();
140  fileFormat.transferEnd();
141 
142  dataset = fileFormat.getDataset();
143 
144  // Decompress data set if compressed
145  dataset->chooseRepresentation(EXS_LittleEndianExplicit, nullptr);
146 
147  const Uint16* pixelData;
148  dataset->findAndGetUint16Array(DCM_PixelData, pixelData);
149 
150  if(pixelData)
151  {
152  //Add the slice to the temporary buffer
153  memcpy(tempoBuffer+z*sliceSize, pixelData, copySize*sizeof(T));
154  ++z;
155  }
156  else
157  {
158  SLM_WARN("There is no pixel data in file \"" + dicomPath + "\".");
159  }
160 
161  }
162 
163  return tempoBuffer;
164  }
165 
166 protected:
167 
180  template< typename T >
181  static void fillImageBuffer(unsigned int rows, unsigned int columns,
182  unsigned int depth,
183  DicomContainerType& instances,
184  void* destination, double rescaleSlope,
185  double rescaleIntercept,
186  ::fwTools::Type imageType)
187  {
188  T* tempoBuffer = ::fwDcmtkIO::reader::main::ImageReader::createTemporaryBuffer<T>(
189  rows, columns, depth, instances);
190 
191  //Copy the temporary buffer to the final buffer
192  if (imageType == ::fwTools::Type::s_INT8)
193  {
194  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::int8_t >(
195  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
196  rescaleIntercept);
197  }
198  else if (imageType == ::fwTools::Type::s_INT16)
199  {
200  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::int16_t >(
201  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
202  rescaleIntercept);
203  }
204  else if (imageType == ::fwTools::Type::s_INT32)
205  {
206  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::int32_t >(
207  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
208  rescaleIntercept);
209  }
210  else if (imageType == ::fwTools::Type::s_INT64)
211  {
212  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::int64_t >(
213  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
214  rescaleIntercept);
215  }
216  else if (imageType == ::fwTools::Type::s_UINT8)
217  {
218  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::uint8_t >(
219  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
220  rescaleIntercept);
221  }
222  else if (imageType == ::fwTools::Type::s_UINT16)
223  {
224  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::uint16_t >(
225  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
226  rescaleIntercept);
227  }
228  else if (imageType == ::fwTools::Type::s_UINT32)
229  {
230  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::uint32_t >(
231  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
232  rescaleIntercept);
233  }
234  else if (imageType == ::fwTools::Type::s_UINT64)
235  {
236  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< std::uint64_t >(
237  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
238  rescaleIntercept);
239  }
240  else if (imageType == ::fwTools::Type::s_FLOAT)
241  {
242  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< float >(
243  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
244  rescaleIntercept);
245  }
246  else if (imageType == ::fwTools::Type::s_DOUBLE)
247  {
248  ::fwDcmtkIO::reader::main::ImageReader::copyBuffer< double >(
249  rows, columns, depth, tempoBuffer, destination, rescaleSlope,
250  rescaleIntercept);
251  }
252 
253  delete tempoBuffer;
254  }
255 
268  template< typename T, typename U >
269  static void copyBuffer(unsigned int rows, unsigned int columns,
270  unsigned int depth,
271  U* source,
272  void* destination,
273  double rescaleSlope, double rescaleIntercept)
274  {
275  T* arrayBuffer = static_cast< T* >(destination);
276  unsigned short x, y, z;
277  unsigned int frameSize = columns*rows;
278  x = y = z = 0;
279  for(x = 0; x < columns; ++x)
280  {
281  for(y = 0; y < rows; ++y)
282  {
283  unsigned int yshift = x*rows;
284 
285  for(z = 0; z < depth; ++z)
286  {
287  unsigned int position = y + yshift + z*frameSize;
288  T value = (T)source[position];
289  value = static_cast< T >(rescaleSlope * value + rescaleIntercept);
290  arrayBuffer[position] = value;
291  }
292  }
293  }
294  }
295 
296 };
297 
298 } //main
299 } //reader
300 } //fwDcmtkIO
static T * createTemporaryBuffer(unsigned int rows, unsigned int columns, unsigned int depth, DicomContainerType &instances)
Create the signed short or unsigned short temporary buffer used to fill the image buffer The template...
base class for BufferObject Lock
#define SLM_WARN(message)
Definition: spyLog.hpp:261
static void fillImageBuffer(unsigned int rows, unsigned int columns, unsigned int depth, DicomContainerType &instances, void *destination, double rescaleSlope, double rescaleIntercept, unsigned short pixelRepresentation,::fwTools::Type imageType)
Fill the buffer of an image.
LockBase< T >::BufferType getBuffer() const
Returns BufferObject&#39;s buffer pointer.
static void fillImageBuffer(unsigned int rows, unsigned int columns, unsigned int depth, DicomContainerType &instances, void *destination, double rescaleSlope, double rescaleIntercept,::fwTools::Type imageType)
Fill the buffer of an image The template T is used to determine if we must use signed or unsigned sho...
This class is used to read the buffer of a DICOM image in DIRECT mode.
static void copyBuffer(unsigned int rows, unsigned int columns, unsigned int depth, U *source, void *destination, double rescaleSlope, double rescaleIntercept)
Copy the temporary buffer to the image buffer The template T is used to determine the type of the fin...
Class describing an elementary C++ type aka unsigned char, signed char, .... int, float...
Definition: Type.hpp:32
fwDcmtkIO contains classes used to pull Dicom images from a pacs using dcmtk library.
Definition: Codec.hpp:12
FWTOOLS_API unsigned char sizeOf() const
Return the sizeof of the type.
Definition: Type.cpp:168