Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
mitkToFNrrdImageWriter.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 // mitk includes
13 #include <mitkToFNrrdImageWriter.h>
14 
15 // itk includes
16 #include "itksys/SystemTools.hxx"
17 #include "itkNrrdImageIO.h"
18 
19 namespace mitk
20 {
21  ToFNrrdImageWriter::ToFNrrdImageWriter(): ToFImageWriter(),
22  m_DistanceOutfile(), m_AmplitudeOutfile(), m_IntensityOutfile()
23  {
24  m_Extension = std::string(".nrrd");
25  }
26 
27  ToFNrrdImageWriter::~ToFNrrdImageWriter()
28  {
29  }
30 
32  {
37 
39  this->m_ToFImageSizeInBytes = this->m_ToFPixelNumber * sizeof(float);
40 
42  this->m_RGBImageSizeInBytes = this->m_RGBPixelNumber * sizeof(unsigned char) * 3;
43 
44  if (this->m_DistanceImageSelected)
45  {
46  this->OpenStreamFile( this->m_DistanceOutfile, this->m_DistanceImageFileName);
47  }
48  if (this->m_AmplitudeImageSelected)
49  {
50  this->OpenStreamFile(this->m_AmplitudeOutfile, this->m_AmplitudeImageFileName);
51  }
52  if (this->m_IntensityImageSelected)
53  {
54  this->OpenStreamFile(this->m_IntensityOutfile, this->m_IntensityImageFileName);
55  }
56  if (this->m_RGBImageSelected)
57  {
58  this->OpenStreamFile(this->m_RGBOutfile, this->m_RGBImageFileName);
59  }
60  this->m_NumOfFrames = 0;
61  }
62 
64  {
65  if (this->m_DistanceImageSelected)
66  {
67  this->CloseStreamFile(this->m_DistanceOutfile, this->m_DistanceImageFileName);
68  }
69  if (this->m_AmplitudeImageSelected)
70  {
71  this->CloseStreamFile(this->m_AmplitudeOutfile, this->m_AmplitudeImageFileName);
72  }
73  if (this->m_IntensityImageSelected)
74  {
75  this->CloseStreamFile(this->m_IntensityOutfile, this->m_IntensityImageFileName);
76  }
77  if (this->m_RGBImageSelected)
78  {
79  this->CloseStreamFile(this->m_RGBOutfile, this->m_RGBImageFileName);
80  }
81  }
82 
83  void ToFNrrdImageWriter::Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData, unsigned char* rgbData)
84  {
85  if (this->m_DistanceImageSelected)
86  {
87  this->m_DistanceOutfile.write( (char*) distanceFloatData, this->m_ToFImageSizeInBytes);
88  }
89  if (this->m_AmplitudeImageSelected)
90  {
91  this->m_AmplitudeOutfile.write( (char*)amplitudeFloatData, this->m_ToFImageSizeInBytes);
92  }
93  if (this->m_IntensityImageSelected)
94  {
95  this->m_IntensityOutfile.write(( char* )intensityFloatData, this->m_ToFImageSizeInBytes);
96  }
97  if (this->m_RGBImageSelected)
98  {
99  this->m_RGBOutfile.write(( char* )rgbData, this->m_RGBImageSizeInBytes);
100  }
101  this->m_NumOfFrames++;
102  }
103 
104  void ToFNrrdImageWriter::OpenStreamFile( std::ofstream &outfile, std::string outfileName )
105  {
106  outfile.open(outfileName.c_str(), std::ofstream::binary);
107  if(!outfile.is_open())
108  {
109  MITK_ERROR << "Error opening outfile: " << outfileName;
110  throw std::logic_error("Error opening outfile.");
111  return;
112  }
113  }
114 
115  void ToFNrrdImageWriter::CloseStreamFile( std::ofstream &outfile, std::string fileName )
116  {
117  if (this->m_NumOfFrames == 0)
118  {
119  outfile.close();
120  throw std::logic_error("File is empty.");
121  return;
122  }
123 
124  // flush the last data to the file and convert the stream data to nrrd file
125  outfile.flush();
126  this->ConvertStreamToNrrdFormat( fileName );
127  outfile.close();
128  }
129 
130  void ToFNrrdImageWriter::ConvertStreamToNrrdFormat( std::string fileName )
131  {
132  int CaptureWidth = 0;
133  int CaptureHeight = 0;
134  int PixelNumber = 0;
135 
136  if (fileName==this->m_RGBImageFileName)
137  {
138  CaptureWidth = this->m_RGBCaptureWidth;
139  CaptureHeight = this->m_RGBCaptureHeight;
140  PixelNumber = this->m_RGBPixelNumber;
141  }
142  else
143  {
144  CaptureWidth = this->m_ToFCaptureWidth;
145  CaptureHeight = this->m_ToFCaptureHeight;
146  PixelNumber = this->m_ToFPixelNumber;
147  }
148  Image::Pointer imageTemplate = Image::New();
149  unsigned int dimension;
150  unsigned int* dimensions;
152  {
153  dimension = 4;
154  dimensions = new unsigned int[dimension];
155  dimensions[0] = CaptureWidth;
156  dimensions[1] = CaptureHeight;
157  dimensions[2] = 1;
158  dimensions[3] = this->m_NumOfFrames;
159  }
160  else if( m_ToFImageType == ToFImageType3D)
161  {
162  dimension = 3;
163  dimensions = new unsigned int[dimension];
164  dimensions[0] = CaptureWidth;
165  dimensions[1] = CaptureHeight;
166  dimensions[2] = this->m_NumOfFrames;
167  }
168  else
169  {
170  throw std::logic_error("No image type set, please choose between 2D+t and 3D!");
171  }
172  float* floatData = nullptr;
173  unsigned char* rgbData = nullptr;
174  if (fileName==this->m_RGBImageFileName)
175  {
176  rgbData = new unsigned char[PixelNumber*3];
177  for(int i=0; i<PixelNumber*3; i++)
178  {
179  rgbData[i] = i + 0.0;
180  }
181  mitk::PixelType RGBType = MakePixelType<unsigned char, itk::RGBPixel<unsigned char>, 3>();
182  imageTemplate->Initialize( RGBType,dimension, dimensions, 1);
183  imageTemplate->SetSlice(rgbData, 0, 0, 0);
184  }
185  else
186  {
187  floatData = new float[PixelNumber];
188  for(int i=0; i<PixelNumber; i++)
189  {
190  floatData[i] = i + 0.0;
191  }
192  mitk::PixelType FloatType = MakeScalarPixelType<float>();
193  imageTemplate->Initialize( FloatType,dimension, dimensions, 1);
194  imageTemplate->SetSlice(floatData, 0, 0, 0);
195  }
196 
197  itk::NrrdImageIO::Pointer nrrdWriter = itk::NrrdImageIO::New();
198  nrrdWriter->SetNumberOfDimensions(dimension);
199  nrrdWriter->SetPixelType( imageTemplate->GetPixelType().GetPixelType());
200  nrrdWriter->SetComponentType( (itk::ImageIOBase::IOComponentType) imageTemplate->GetPixelType().GetComponentType());
201  if(imageTemplate->GetPixelType().GetNumberOfComponents() > 1)
202  {
203  nrrdWriter->SetNumberOfComponents(imageTemplate->GetPixelType().GetNumberOfComponents());
204  }
205 
206  itk::ImageIORegion ioRegion( dimension );
207  mitk::Vector3D spacing = imageTemplate->GetGeometry()->GetSpacing();
208  mitk::Point3D origin = imageTemplate->GetGeometry()->GetOrigin();
209 
210  for(unsigned int i = 0; i < dimension; i++)
211  {
212  nrrdWriter->SetDimensions(i,dimensions[i]);
213  nrrdWriter->SetSpacing(i,spacing[i]);
214  nrrdWriter->SetOrigin(i,origin[i]);
215 
216  mitk::Vector3D direction;
217  direction.SetVnlVector(imageTemplate->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
218  vnl_vector< double > axisDirection(dimension);
219 
220  for(unsigned int j = 0; j < dimension; j++)
221  {
222  axisDirection[j] = direction[j]/spacing[i];
223  }
224  nrrdWriter->SetDirection( i, axisDirection );
225 
226  ioRegion.SetSize(i, imageTemplate->GetLargestPossibleRegion().GetSize(i) );
227  ioRegion.SetIndex(i, imageTemplate->GetLargestPossibleRegion().GetIndex(i) );
228  }
229 
230  nrrdWriter->SetIORegion(ioRegion);
231  nrrdWriter->SetFileName(fileName);
232  nrrdWriter->SetUseStreamedWriting(true);
233 
234  std::ifstream stream(fileName.c_str(), std::ifstream::binary);
235  if (fileName==m_RGBImageFileName)
236  {
237  unsigned int size = PixelNumber*3 * this->m_NumOfFrames;
238  unsigned int sizeInBytes = size * sizeof(unsigned char);
239  unsigned char* data = new unsigned char[size];
240  stream.read((char*)data, sizeInBytes);
241  nrrdWriter->Write(data);
242  stream.close();
243  delete[] data;
244  }
245  else
246  {
247  unsigned int size = PixelNumber * this->m_NumOfFrames;
248  unsigned int sizeInBytes = size * sizeof(float);
249  float* data = new float[size];
250  stream.read((char*)data, sizeInBytes);
251  try
252  {
253  nrrdWriter->Write(data);
254  }
255  catch (itk::ExceptionObject* e)
256  {
257  MITK_ERROR<< e->what();
258  return;
259  }
260 
261  stream.close();
262  delete[] data;
263  }
264 
265  delete[] dimensions;
266  if (fileName==m_RGBImageFileName)
267  {
268  delete[] rgbData;
269  }
270  else
271  {
272  delete[] floatData;
273  }
274  }
275 
276 } // end namespace mitk
void Add(float *distanceFloatData, float *amplitudeFloatData, float *intensityFloatData, unsigned char *rgbData=nullptr) override
Add new data to file.
int m_RGBImageSizeInBytes
size of the image to save in bytes
bool m_AmplitudeImageSelected
flag indicating if amplitude image should be recorded
int m_NumOfFrames
number of frames written to the image. Used for pic header.
bool m_IntensityImageSelected
flag indicating if intensity image should be recorded
void CheckForFileExtension(std::string &fileName)
Checks file name if file extension exists. If not an error message is returned.
#define MITK_ERROR
Definition: mitkLogMacros.h:20
bool m_DistanceImageSelected
flag indicating if distance image should be recorded
DataCollection - Class to facilitate loading/accessing structured data.
int m_RGBPixelNumber
number of pixels (widht*height) of the images to record
int m_ToFCaptureWidth
width (x-dimension) of the images to record.
int m_ToFCaptureHeight
height (y-dimension) of the images to record.
int m_RGBCaptureHeight
height (y-dimension) of the images to record.
std::string m_IntensityImageFileName
file name for saving the intensity image
bool m_RGBImageSelected
flag indicating if RGB image should be recorded
std::string m_AmplitudeImageFileName
file name for saving the amplitude image
int m_ToFPixelNumber
number of pixels (widht*height) of the images to record
std::string m_Extension
file extension used for saving images
std::string m_DistanceImageFileName
file name for saving the distance image
static Pointer New()
int m_ToFImageSizeInBytes
size of the image to save in bytes
std::string m_RGBImageFileName
file name for saving the RGB image
ToFImageWriter::ToFImageType m_ToFImageType
type of image to be recorded: ToFImageType3D (0) or ToFImageType2DPlusT (1)
int m_RGBCaptureWidth
width (x-dimension) of the images to record.
void Close() override
Close file(s) add .pic header and write.
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
void Open() override
Open file(s) for writing.