Orfeo Toolbox  3.16
itkStimulateImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkStimulateImageIO.cxx,v $
5  Language: C++
6  Date: $Date: 2009-05-27 17:48:12 $
7  Version: $Revision: 1.27 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  Portions of this code are covered under the VTK copyright.
13  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
14 
15  This software is distributed WITHOUT ANY WARRANTY; without even
16  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17  PURPOSE. See the above copyright notices for more information.
18 
19 =========================================================================*/
20 #include "itkStimulateImageIO.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include <itksys/SystemTools.hxx>
24 #include <itksys/RegularExpression.hxx>
25 #include "itkByteSwapper.h"
26 
27 namespace itk
28 {
29 
31 {
32  this->SetNumberOfDimensions(4);
35  m_DisplayRange[0] = 0;
36  m_DisplayRange[1] = 0;
37 }
38 
40 {
41 }
42 
44  const char* filename)
45 
46 {
47  // Make sure that we have a file to
48  if ( *filename == 0 )
49  {
50  itkExceptionMacro(<<"A FileName must be specified.");
51  return false;
52  }
53 
54  // Close file from any previous image
55  if ( os.is_open() )
56  {
57  os.close();
58  }
59 
60  // Open the new file for reading
61  itkDebugMacro(<< "Initialize: opening file " << filename);
62 
63  // Actually open the file
64  os.open( filename, std::ios::in | std::ios::binary );
65 
66  if ( os.fail() )
67  {
68  return false;
69  }
70 
71  return true;
72 }
73 
74 
76  const char* filename)
77 
78 {
79  // Make sure that we have a file to
80  if ( *filename == 0 )
81  {
82  itkExceptionMacro(<<"A FileName must be specified.");
83  return false;
84  }
85 
86  // Close file from any previous image
87  if ( os.is_open() )
88  {
89  os.close();
90  }
91 
92  // Open the new file for writing
93  itkDebugMacro(<< "Initialize: opening file " << filename);
94 
95 #ifdef __sgi
96  // Create the file. This is required on some older sgi's
97  std::ofstream tFile(filename,std::ios::out);
98  tFile.close();
99 #endif
100 
101  // Actually open the file
102  os.open( filename, std::ios::out | std::ios::binary );
103 
104  if( os.fail() )
105  {
106  itkExceptionMacro(<< "Could not open file for writing: " << filename);
107  return false;
108  }
109 
110  return true;
111 }
112 
113 // This method will only test if the header looks like a
114 //Stimulate image file.
115 bool StimulateImageIO::CanReadFile(const char* filename)
116 {
117  std::ifstream file;
118  char buffer[256];
119  std::string fname(filename);
120 
121  if( fname == "" )
122  {
123  itkDebugMacro(<<"No filename specified.");
124  return false;
125  }
126 
127  bool extensionFound = false;
128  std::string::size_type sprPos = fname.rfind(".spr");
129  if ((sprPos != std::string::npos)
130  && (sprPos == fname.length() - 4))
131  {
132  extensionFound = true;
133  }
134 
135  if( !extensionFound )
136  {
137  itkDebugMacro(<<"The filename extension is not recognized");
138  return false;
139  }
140 
141  if ( ! this->OpenStimulateFileForReading(file, filename))
142  {
143  return false;
144  }
145 
146  // Check to see if its a spr file
147  file.getline(buffer,255);
148 
149  fname = buffer;
150 
151  if ( fname.find("numDim:") < fname.length() ||
152  fname.find("dim:") < fname.length() ||
153  fname.find("dataType:") < fname.length() )
154  {
155  return true;
156  }
157  else
158  {
159  return false;
160  }
161 }
162 
163 
164 void StimulateImageIO::Read(void* buffer)
165 {
166  std::ifstream file;
167 
168  //read header information file:
169  this->InternalReadImageInformation(file);
170 
171  //read data file
172  std::ifstream file_data;
173 
174  if( m_DataFileName == "" )
175  {
176  //if no data filename was specified try to guess one:
177  //based on filename.spr , options are:
178  //1: filename.spr.sdt
179  //2: filename.sdt
180 
181  //option 1:
183  m_DataFileName.replace(m_DataFileName.length(), 4, ".sdt" );
184 
185  // Actually open the file
186  file_data.open( m_DataFileName.c_str(), std::ios::in | std::ios::binary );
187  if ( file_data.fail() )
188  {
189  //option 2:
191  m_DataFileName.replace(m_DataFileName.length() - 3, 3, "sdt" );
192  file_data.open( m_DataFileName.c_str(), std::ios::in | std::ios::binary );
193  if ( file_data.fail() )
194  {
195  itkExceptionMacro(<<"No Data file was specified in header (spr) file and guessing file data name failed." );
196  return;
197  }
198  }
199  }//a filename was found for data file
200 
201  if( !OpenStimulateFileForReading( file_data, m_DataFileName.c_str()) )
202  {
203  itkExceptionMacro("StimulateImageIO could not open file: "
204  << m_DataFileName << " for reading."
205  << std::endl
206  << "Reason: "
207  << itksys::SystemTools::GetLastSystemError());
208  return;
209  }
210 
211  if( !this->ReadBufferAsBinary( file_data, buffer, this->GetImageSizeInBytes()) )
212  {
213  itkExceptionMacro(<<"Read failed: Wanted "
214  << this->GetImageSizeInBytes()
215  << " bytes, but read "
216  << file_data.gcount() << " bytes."
217  << " from file " << m_DataFileName );
218  }
219 
220  //byte swapping depending on pixel type:
221  switch (this->GetComponentType())
222  {
223  case CHAR:
224  ByteSwapper<char>::SwapRangeFromSystemToBigEndian((char *)buffer, static_cast<unsigned long>(this->GetImageSizeInComponents()) );
225  break;
226  case SHORT:
227  ByteSwapper<short>::SwapRangeFromSystemToBigEndian((short *)buffer, static_cast<unsigned long>(this->GetImageSizeInComponents()) );
228  break;
229  case INT:
230  ByteSwapper<int>::SwapRangeFromSystemToBigEndian((int *)buffer, static_cast<unsigned long>(this->GetImageSizeInComponents()) );
231  break;
232  case FLOAT:
233  ByteSwapper<float>::SwapRangeFromSystemToBigEndian((float *)buffer, static_cast<unsigned long>(this->GetImageSizeInComponents()) );
234  break;
235  case DOUBLE:
236  ByteSwapper<double>::SwapRangeFromSystemToBigEndian((double *)buffer, static_cast<unsigned long>(this->GetImageSizeInComponents()) );
237  break;
238  default:
239  break;
240  }
241 
242  //closing files:
243  file.close();
244  file_data.close();
245 }
246 
248 {
249  char line[255];
250  std::string text;
251 
252  //read .sdt file (header)
253 
254  if ( ! this->OpenStimulateFileForReading(file, m_FileName.c_str()) )
255  {
256  itkExceptionMacro("StimulateImageIO could not open sdt file: "
257  << m_FileName << " for reading."
258  << std::endl
259  << "Reason: "
260  << itksys::SystemTools::GetLastSystemError());
261  }
262 
263  // re open in ascii mode
264  file.close();
265  file.open( m_FileName.c_str(), std::ios::in );
266 
267  //extract dimensions, spacing, origin
268  unsigned int dim;
269  unsigned int dims[4];
270  float spacing[4];
271  float origin[4];
272  float fov[4];
273 
274  // set values in case we don't find them
275  this->SetNumberOfDimensions(4);
276  m_Spacing[0] = 1.0;
277  m_Spacing[1] = 1.0;
278  m_Spacing[2] = 1.0;
279  m_Spacing[3] = 1.0;
280 
281  m_Origin[0] = 0.0;
282  m_Origin[1] = 0.0;
283  m_Origin[2] = 0.0;
284  m_Origin[3] = 0.0;
285 
286  char pixelType[256];
287  float range[2];
288 
289  //char fidName[256] = "";
290  //char orient[256] = "";
291 
292  bool fov_specified = false;
293  bool origin_specified = false;
294  bool spacing_specified = false;
295  while((file.getline(line, 255), file.gcount() > 0))
296  {
297  text = line;
298 #ifdef __CYGWIN__
299  // If terminated with \r\n, getline only removes \n. Explictly
300  // strip \r.
301  if (text.size() > 0
302  && (text[text.size() - 1] == '\r'))
303  {
304  text.resize(text.size() - 1);
305  }
306 #endif
307 
308  if ( text.find("numDim") < text.length())
309  {
310  sscanf(line, "%*s %d", &dim);
311  this->SetNumberOfDimensions(dim);
312  }
313  else if ( text.find("dim") < text.length())
314  {
315  sscanf(line, "%*s %d %d %d %d", dims, dims+1, dims+2 , dims+3);
316  if ( m_NumberOfDimensions > 3 && dims[3] <= 1 )
317  {
318  this->SetNumberOfDimensions(3);
319  }
320  if ( m_NumberOfDimensions > 2 && dims[2] <= 1 )
321  {
322  this->SetNumberOfDimensions(2);
323  }
324  for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
325  {
326  m_Dimensions[i] = dims[i];
327  }
328  }
329  else if ( text.find("origin") < text.length())
330  {
331  //origin
332  //Position of the center of the first voxel. One value for each dimension. If
333  //the origin is not specified, but the fov is, then the image is assumed
334  //to be centered:
335 
336  sscanf(line, "%*s %f %f %f %f", origin, origin+1, origin+2 , origin+3);
337  for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
338  {
339  m_Origin[i] = origin[i];
340  }
341  origin_specified = true;
342  }
343  else if ( text.find("extent") < text.length())
344  {
345  //not documented
346  itkDebugMacro(<<"Extent was specified");
347  }
348  else if ( text.find("fov") < text.length())
349  {
350  //fov
351  //Field of view: The distance between the outside edges of the first and last
352  //voxel along each dimension; one value for each dimension. If the fov is not
353  //specified it is calculated according to: fov = interval * dim
354 
355  sscanf(line, "%*s %f %f %f %f", fov, fov+1, fov+2 , fov+3);
356  fov_specified = true;
357  }
358  else if ( text.find("interval") < text.length())
359  {
360  //interval
361  //The center to center distance between adjacent voxels along each dimension;
362  //one value for each dimension. If the interval is not specified it is
363  //calculated according to: interval = fov / dim
364 
365  sscanf(line, "%*s %f %f %f %f", spacing, spacing+1, spacing+2 , spacing+3);
366  for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
367  {
368  m_Spacing[i] = spacing[i];
369  }
370  spacing_specified = true;
371  }
372  else if ( text.find("dataType") < text.length())
373  {
374  sscanf(line, "%*s %s", pixelType);
375  text = pixelType;
377  if ( text.find("BYTE") < text.length() )
378  {
380  }
381  else if ( text.find("WORD") < text.length() )
382  {
384  }
385  else if ( text.find("LWORD") < text.length() )
386  {
388  }
389  else if ( text.find("REAL") < text.length() )
390  {
392  }
393  else if ( text.find("COMPLEX") < text.length() )
394  {
397  }
398  else
399  {
400  itkExceptionMacro(<<"Unrecognized type");
401  }
402  }//found scalars
403  else if ( text.find("displayRange") < text.length())
404  {
405  //displayRange:
406  //Two values giving the low_value and high_value. Voxel values below the
407  //low_value will be displayed as black and voxels with values above the
408  //high_value will be displayed as white. Voxels with values within the display
409  //range are displayed with a grey value that is scaled linearly between the
410  //low_value and high_value.
411 
412  sscanf(line, "%*s %f %f", range, range+1);
413  m_DisplayRange[0] = range[0];
414  m_DisplayRange[1] = range[1];
415  }
416  else if ( text.find("fidName") < text.length())
417  {
418  //Not well documented
419  //This is a bit tricky to get the value as there is sometime no white space
420  //only a ':' separate field from value, we assume there is no other ':'
421  char *pch;
422  pch = strchr(line,':');
423  sscanf(++pch, "%s", m_FidName); //delete any white space left
424  itkDebugMacro(<<"fidName was specified");
425  }
426  else if ( text.find("sdtOrient") < text.length())
427  {
428  //Not used now, but later when ITK Dictionary will be ready
429  //don't know for now the format in which to save this.
430  //This is a bit tricky to get the value as there is sometime no white space
431  //only a ':' separate field from value, we assume there is no other ':'
432  char *pch;
433  pch = strchr(line,':');
434  sscanf(++pch, "%s", m_SdtOrient); //delete any white space left
435  itkDebugMacro(<<"Orientation was specified");
436  }
437  else if ( text.find("dsplyThres") < text.length())
438  {
439  //not documented
440  itkDebugMacro(<<"Display threshold was specified");
441  }
442  else if ( text.find("endian") < text.length())
443  {
444  //BigEndian ieee-be / LittleEndian: ieee-le
445  if ( text.find("ieee-le") < text.length())
446  {
447  itkExceptionMacro(<<"Little Endian Stimulate files are not handled.");
448  }
449  }
450  else if ( text.find("mapParmFileName") < text.length())
451  {
452  //not documented
453  itkDebugMacro(<<"mapParmFileName was specified");
454  }
455  else if ( text.find("mapTypeName") < text.length())
456  {
457  //not documented
458  itkDebugMacro(<<"mapTypeName was specified");
459  }
460  else if ( text.find("stimFileName:") < text.length())
461  {
462  //file data name is explicitely specified
463  std::string datafilename;
464  // Remove leading and trailing blanks
465  itksys::RegularExpression regexp("stimFileName:[ ]*(.*)[ ]*$");
466  regexp.find(text);
467  datafilename = regexp.match(1);
468 
469  //if the data filename has a directory specified, use it as is,
470  //otherwise prepend the path of the .spr file.
471  std::string datafilenamePath =
472  ::itksys::SystemTools::GetFilenamePath (datafilename);
473  if (datafilenamePath == "")
474  {
475  std::string fileNamePath = ::itksys::SystemTools::GetFilenamePath (m_FileName.c_str());
476  m_DataFileName = fileNamePath + "/" + datafilename;
477  }
478  else
479  {
480  m_DataFileName = datafilename;
481  }
482  }
483  else if ( text.find("mapConf") < text.length())
484  {
485  //not documented
486  itkDebugMacro(<<"mapConf was specified");
487  }
488  else if ( text.find("periodStr") < text.length())
489  {
490  //not documented
491  itkDebugMacro(<<"periodStr was specified");
492  }
493  }
494 
495 
496  //compute any missing informations:
497  if( !spacing_specified && fov_specified)
498  {
499  for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
500  {
501  m_Spacing[i] = fov[i]/dims[i];
502  }
503  }
504  if( !origin_specified && fov_specified)
505  {
506  for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
507  {
508  m_Origin[i] = (m_Spacing[i] - fov[i])/2.;
509  }
510  }//otherwise default spacing & origin are used.
511 }
512 
514 {
515  std::ifstream file;
516  this->InternalReadImageInformation(file);
517 }
518 
519 
520 bool StimulateImageIO::CanWriteFile( const char* name )
521 {
522  std::string filename = name;
523 
524  if( filename == "" )
525  {
526  itkDebugMacro(<<"No filename specified.");
527  return false;
528  }
529 
530  bool extensionFound = false;
531  std::string::size_type sprPos = filename.rfind(".spr");
532  if ((sprPos != std::string::npos)
533  && (sprPos == filename.length() - 4))
534  {
535  extensionFound = true;
536  }
537 
538  if( !extensionFound )
539  {
540  itkDebugMacro(<<"The filename extension is not recognized");
541  return false;
542  }
543 
544  return true;
545 }
546 
547 void StimulateImageIO::Write(const void* buffer)
548 {
549  unsigned int i;
550 
551  std::ofstream file;
552  if ( ! this->OpenStimulateFileForWriting(file, m_FileName.c_str()) )
553  {
554  return;
555  }
556 
557  // Check the image region for proper dimensions, etc.
558  unsigned int numDims = this->GetNumberOfDimensions();
559  if ( numDims < 2 || numDims > 4 )
560  {
561  itkExceptionMacro(<<"Stimulate Writer can only write 2,3 or 4-dimensional images");
562  return;
563  }
564 
565  // Write the Stimulate header information
566  file << "numDim: " << this->GetNumberOfDimensions();
567 
568  // Write characteristics of the data
569  file << "\ndim:";
570  for(i=0; i < m_NumberOfDimensions; i++)
571  {
572  file << " " << m_Dimensions[i];
573  }
574 
575  file << "\norigin:";
576  for(i=0; i < m_NumberOfDimensions; i++)
577  {
578  file << " " << m_Origin[i];
579  }
580 
581  file << "\nfov:";
582  for(i=0; i < m_NumberOfDimensions; i++)
583  {
584  file << " " << m_Spacing[i]*m_Dimensions[i]; //fov = interval * dim
585  }
586 
587  file << "\ninterval:";
588  for(i=0; i < m_NumberOfDimensions; i++)
589  {
590  file << " " << m_Spacing[i];
591  }
592 
593  //preparation for writing buffer:
594  const unsigned long numberOfBytes = static_cast<unsigned long>(this->GetImageSizeInBytes());
595  const unsigned long numberOfComponents = static_cast<unsigned long>(this->GetImageSizeInComponents());
596 
597  file << "\ndataType: ";
598  {
599  char * tempmemory=new char[numberOfBytes];
600  memcpy(tempmemory,buffer,numberOfBytes);
601  switch(this->GetComponentType())
602  {
603  case CHAR:
604  file << "BYTE";
605  ByteSwapper<char>::SwapRangeFromSystemToBigEndian(reinterpret_cast<char *>(tempmemory), numberOfComponents );
606  break;
607  case SHORT:
608  file << "WORD";
609  ByteSwapper<short int>::SwapRangeFromSystemToBigEndian(reinterpret_cast<short int *>(tempmemory), numberOfComponents );
610  break;
611  case INT:
612  file << "LWORD";
613  ByteSwapper<int>::SwapRangeFromSystemToBigEndian(reinterpret_cast<int *>(tempmemory), numberOfComponents );
614  break;
615  case FLOAT:
616  file << "REAL";
617  ByteSwapper<float>::SwapRangeFromSystemToBigEndian(reinterpret_cast<float *>(tempmemory), numberOfComponents );
618  break;
619  case DOUBLE:
620  file << "COMPLEX";
621  ByteSwapper<double>::SwapRangeFromSystemToBigEndian(reinterpret_cast<double *>(tempmemory), numberOfComponents );
622  break;
623  default:
624  break;
625  }
626 
627  //add the data filename to the header
628  //determine datafile given the spr filename
630  m_DataFileName.replace(m_DataFileName.length() - 3, 3, "sdt" );
631  file << "\nstimFileName: " << m_DataFileName.c_str();
632 
633  //Last carrier return:
634  file << "\n";
635 
636  //actually read data file
637  std::ofstream file_data;
638 
639  if ( ! this->OpenStimulateFileForWriting(file_data, m_DataFileName.c_str()) )
640  {
641  return;
642  }
643 
644  // Write the actual pixel data
645  file_data.write( static_cast<const char *>(tempmemory) , numberOfBytes );
646  delete [] tempmemory;
647  file_data.close();
648  }
649  file.close();
650 }
651 
652 void StimulateImageIO::PrintSelf(std::ostream& os, Indent indent) const
653 {
654  Superclass::PrintSelf(os, indent);
655  os << indent << "\nDisplayRange: " << m_DisplayRange[0] << " " << m_DisplayRange[1];
656 }
657 
658 } // end namespace itk

Generated at Sun Feb 3 2013 00:09:10 for Orfeo Toolbox with doxygen 1.8.1.1