fw4spl
itkInrImageIO.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2015.
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 #include <algorithm>
8 #include <map>
9 #include <utility>
10 #include <cstdio>
11 
12 #include <boost/lexical_cast.hpp>
13 
14 #include <itk_zlib.h>
15 #include <itkByteSwapper.h>
16 #include <itkIOCommon.h>
17 #include <itkExceptionObject.h>
18 
19 #include <fwCore/spyLog.hpp>
20 #include <fwCore/Exception.hpp>
21 
22 #include "inr2itk/itkInrImageIO.hpp"
23 
24 #define max(a,b) ((a) > (b) ? (a) : (b))
25 #define min(a,b) ((a) <= (b) ? (a) : (b))
26 
27 namespace itk
28 {
29 
30 InrImageIO::InrImageIO()
31 {
32  this->SetNumberOfDimensions(3);
33  m_PixelType = SCALAR;
34  //m_swapBytes = false;
35 }
36 
37 //------------------------------------------------------------------------------
38 
39 InrImageIO::~InrImageIO()
40 {
41  // Nothing to do.
42 }
43 
44 //------------------------------------------------------------------------------
45 
46 void InrImageIO::PrintSelf(std::ostream& os, Indent indent) const
47 {
48  Superclass::PrintSelf(os, indent);
49  os << indent << "PixelType " << m_PixelType << "\n";
50  os << indent << "ComponentType " << m_ComponentType << "\n";
51 }
52 
53 //------------------------------------------------------------------------------
54 
55 bool InrImageIO::CanReadFile( const char* FileNameToRead )
56 {
57  // Do not perform extension checking, magic number in the header is better.
58  gzFile inputFile = gzopen(FileNameToRead, "rb");
59  if(inputFile == 0)
60  {
61  return false;
62  }
63 
64  char firstLine[256];
65 
66  gzgets(inputFile, firstLine, 256);
67 
68  gzclose(inputFile);
69 
70  std::string const magic("#INRIMAGE-4#{\n");
71  if(firstLine!=magic)
72  {
73  return false;
74  }
75  else
76  {
77  return true;
78  }
79 }
80 
81 //------------------------------------------------------------------------------
82 
84 {
85  gzFile inputFile = gzopen(this->GetFileName(), "rb");
86  if(inputFile==NULL)
87  {
88  gzclose(inputFile);
89  ExceptionObject exception(__FILE__, __LINE__);
90  std::stringstream errorMessage;
91  errorMessage << "File " << GetFileName() << " could not be read";
92  exception.SetDescription(errorMessage.str());
93  throw exception;
94  }
95 
96  const int lineBufSize = 256;
97  char linebuf[lineBufSize];
98  std::map<std::string, std::string> headerValues;
99  m_headerSize = 0;
100  while( gzgets(inputFile, linebuf, lineBufSize) && !gzeof(inputFile) )
101  {
102  std::string line(linebuf);
103  // Count the number of characters we just read : length of the line
104  m_headerSize += line.length();
105  // Remove eventual trailing '\n'
106  std::string::size_type const endOfLine = line.find('\n');
107  line = line.substr(0, endOfLine);
108 
109  if(line=="##}")
110  {
111  // End of header : get outta here
112  break;
113  }
114 
115  if(line.empty())
116  {
117  // Empty line, nothing to do
118  }
119  else if(line[0]=='#')
120  {
121  // Comment line, nothing to do
122  }
123  else
124  {
125  // Look for key=value
126  std::string::const_iterator delimiter = std::find(line.begin(), line.end(), '=');
127  if(delimiter==line.end())
128  {
129  // invalid line : missing '='
130  gzclose(inputFile);
131  ExceptionObject exception(__FILE__, __LINE__);
132  std::stringstream errorMessage;
133  errorMessage << "Invalid INR file.\n" << "Offending line : " << line;
134  exception.SetDescription(errorMessage.str());
135  throw exception;
136  }
137 
138  // Tokenize [KEY] = [VALUE] and store it in map
139  std::string key = line.substr(0, delimiter-line.begin());
140  std::string value = line.substr(delimiter-line.begin()+1, std::string::npos);
141  OSLM_TRACE("[" << key << "] = [" << value << "]");
142  if(headerValues.find(key)!=headerValues.end())
143  {
144  // duplicate key
145  ExceptionObject exception(__FILE__, __LINE__);
146  gzclose(inputFile);
147  std::stringstream errorMessage;
148  errorMessage << "Invalid INR file.\n" << "Duplicate key : " << key;
149  exception.SetDescription(errorMessage.str());
150  throw exception;
151  }
152  else
153  {
154  headerValues[key] = value;
155  }
156  }
157  }
158  // We have finished reading the header
159  gzclose(inputFile);
160 
161  // Process headerValue map
162  for(std::map<std::string, std::string>::const_iterator it = headerValues.begin(); it!=headerValues.end(); ++it)
163  {
164  if(it->first=="XDIM")
165  {
166  int xdim = ::boost::lexical_cast<int>( it->second );
167  this->SetDimensions(0, xdim);
168  }
169  else if(it->first=="YDIM")
170  {
171  int ydim = ::boost::lexical_cast<int>( it->second );
172  this->SetDimensions(1, ydim);
173  }
174  else if(it->first=="ZDIM")
175  {
176  int zdim = ::boost::lexical_cast<int>( it->second );
177  this->SetDimensions(2, zdim);
178  }
179  else if(it->first=="VDIM")
180  {
181  int vdim = ::boost::lexical_cast<int>( it->second );
182  if(vdim == 1)
183  {
184  SetPixelType(SCALAR);
185  }
186  else
187  {
188  SetPixelType(VECTOR);
189  }
190  SetNumberOfComponents(vdim);
191  }
192  else if(it->first=="VX")
193  {
194  float vx = ::boost::lexical_cast< float >( it->second );
195  this->SetSpacing(0, vx);
196  }
197  else if(it->first=="VY")
198  {
199  float vy = ::boost::lexical_cast< float >( it->second );
200  this->SetSpacing(1, vy);
201  }
202  else if(it->first=="VZ")
203  {
204  float vz = ::boost::lexical_cast< float >( it->second );
205  this->SetSpacing(2, vz);
206  }
207  else if(it->first=="TYPE")
208  {
209  std::map<std::string, std::string>::const_iterator pixsize_it = headerValues.find("PIXSIZE");
210  if(pixsize_it==headerValues.end())
211  {
212  // Missing pixsize
213  ExceptionObject exception(__FILE__, __LINE__);
214  std::stringstream errorMessage;
215  errorMessage << "Invalid INR file.\n" << "PIXSIZE key not found.";
216  exception.SetDescription(errorMessage.str());
217  throw exception;
218  }
219  std::string type = it->second;
220  std::string pixsize = pixsize_it->second;
221  if(type=="unsigned fixed")
222  {
223  if(pixsize=="8 bits")
224  {
225  m_ComponentType = UCHAR;
226  }
227  else if(pixsize=="16 bits")
228  {
229  m_ComponentType = USHORT;
230  }
231  else if(pixsize=="32 bits")
232  {
233  if ( 4 == sizeof(unsigned int) )
234  {
235  m_ComponentType = UINT;
236  }
237  else if ( 4 == sizeof(unsigned long) )
238  {
239  m_ComponentType = ULONG;
240  }
241  else
242  {
243  ExceptionObject exception(__FILE__, __LINE__);
244  std::stringstream errorMessage;
245  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
246  exception.SetDescription(errorMessage.str());
247  throw exception;
248  }
249  }
250  else if(pixsize=="64 bits")
251  {
252  if ( 8 == sizeof(unsigned int) )
253  {
254  m_ComponentType = UINT;
255  }
256  else if ( 8 == sizeof(unsigned long) )
257  {
258  m_ComponentType = ULONG;
259  }
260  else
261  {
262  ExceptionObject exception(__FILE__, __LINE__);
263  std::stringstream errorMessage;
264  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
265  exception.SetDescription(errorMessage.str());
266  throw exception;
267  }
268  }
269  else
270  {
271  ExceptionObject exception(__FILE__, __LINE__);
272  std::stringstream errorMessage;
273  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
274  exception.SetDescription(errorMessage.str());
275  throw exception;
276  }
277  }
278  else if(type=="signed fixed")
279  {
280  if(pixsize=="8 bits")
281  {
282  m_ComponentType = CHAR;
283  }
284  else if(pixsize=="16 bits")
285  {
286  m_ComponentType = SHORT;
287  }
288  else if(pixsize=="32 bits")
289  {
290  if ( 4 == sizeof(int) )
291  {
292  m_ComponentType = INT;
293  }
294  else if ( 4 == sizeof(long) )
295  {
296  m_ComponentType = LONG;
297  }
298  else
299  {
300  ExceptionObject exception(__FILE__, __LINE__);
301  std::stringstream errorMessage;
302  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
303  exception.SetDescription(errorMessage.str());
304  throw exception;
305  }
306  }
307  else if(pixsize=="64 bits")
308  {
309  if ( 8 == sizeof(int) )
310  {
311  m_ComponentType = INT;
312  }
313  else if ( 8 == sizeof(long) )
314  {
315  m_ComponentType = LONG;
316  }
317  else
318  {
319  ExceptionObject exception(__FILE__, __LINE__);
320  std::stringstream errorMessage;
321  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
322  exception.SetDescription(errorMessage.str());
323  throw exception;
324  }
325  }
326  else
327  {
328  ExceptionObject exception(__FILE__, __LINE__);
329  std::stringstream errorMessage;
330  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
331  exception.SetDescription(errorMessage.str());
332  throw exception;
333  }
334  }
335  else if(type=="float")
336  {
337  /*
338  if(pixsize=="8 bits")
339  {
340  }
341  else if(pixsize=="16 bits")
342  {
343  }
344  */
345  /*else*/ if(pixsize=="32 bits")
346  {
347  m_ComponentType = FLOAT;
348  }
349  else if(pixsize=="64 bits")
350  {
351  m_ComponentType = DOUBLE;
352  }
353  else
354  {
355  ExceptionObject exception(__FILE__, __LINE__);
356  std::stringstream errorMessage;
357  errorMessage << "Invalid INR file.\n" << "Invalid PIXSIZE.";
358  exception.SetDescription(errorMessage.str());
359  throw exception;
360  }
361  }
362  else
363  {
364  ExceptionObject exception(__FILE__, __LINE__);
365  std::stringstream errorMessage;
366  errorMessage << "Invalid INR file.\n" << "Invalid TYPE.";
367  exception.SetDescription(errorMessage.str());
368  throw exception;
369  }
370  } // TYPE
371  else if(it->first=="PIXSIZE")
372  {
373  // nothing to do, processed with "TYPE"
374  }
375  else if(it->first=="SCALE")
376  {
377  // For fixed point arithmetic only. We don't use it.
378  }
379  else if(it->first=="CPU")
380  {
381  // Big endian are : sun, sgi
382  if(it->second=="sun" || it->second=="sgi")
383  {
384  // File is big-endian, swap if system is little endian.
385  //m_swapBytes = itk::ByteSwapper<char>::SystemIsLE();
386  m_ByteOrder = BigEndian;
387  }
388  // Little endian are : pc, alpha, decm
389  else if(it->second=="pc" || it->second=="alpha" || it->second=="decm")
390  {
391  // File is little-endian, swap if system is big-endian.
392  //m_swapBytes = itk::ByteSwapper<char>::SystemIsBE();
393  m_ByteOrder = LittleEndian;
394  }
395  else
396  {
397  ExceptionObject exception(__FILE__, __LINE__);
398  std::stringstream errorMessage;
399  errorMessage << "Invalid INR file.\n" << "Unknown CPU value : " << it->second;
400  exception.SetDescription(errorMessage.str());
401  throw exception;
402  }
403  }
404  }
405 }
406 
407 //------------------------------------------------------------------------------
408 
409 void InrImageIO::Read(void * buffer)
410 {
411  gzFile file = gzopen(GetFileName(), "rb");
412 
413  if(file == NULL)
414  {
415  ExceptionObject exception(__FILE__, __LINE__);
416  std::stringstream errorMessage;
417  errorMessage << "INR file " << GetFileName() << " could not be read";
418  exception.SetDescription(errorMessage.str());
419  throw exception;
420  }
421 
422  // Skip the header
423  int bytesSkipped = gzseek(file, m_headerSize, SEEK_CUR);
424  if(bytesSkipped!=m_headerSize)
425  {
426  ExceptionObject exception(__FILE__, __LINE__);
427  std::stringstream errorMessage;
428  errorMessage << "INR file " << GetFileName() << " could not be read (header size : " << bytesSkipped << "/" <<
429  m_headerSize <<").";
430  exception.SetDescription(errorMessage.str());
431  throw exception;
432  }
433 
434  // And read the buffer
435 
436  // Replace this line :
437  //int bytesRead = gzread(file, buffer, GetImageSizeInBytes());
438  // by
439  int bytesRead = 0;
440  int nbStep = 10;
441  long long int size =
442  ( (GetImageSizeInBytes()>1024*1024*10) ? ( GetImageSizeInBytes() / nbStep ) + 1 : GetImageSizeInBytes() );
443  int step = 0;
444  try
445  {
446  while ( bytesRead < GetImageSizeInBytes() && step < nbStep )
447  {
448  step++;
449  UpdateProgress( ((float)bytesRead)/GetImageSizeInBytes() );
450  bytesRead += gzread( file, ((char *)buffer)+bytesRead, min(size, GetImageSizeInBytes() - bytesRead) );
451  }
452  }
453  catch(::fwCore::Exception &e) // catch progress bar cancel exception
454  {
455  gzclose(file);
456  throw;
457  }
458  UpdateProgress( 1.0 );
459  // End replace
460 
461  if(bytesRead!=GetImageSizeInBytes())
462  {
463  gzclose(file);
464  ExceptionObject exception(__FILE__, __LINE__);
465  std::stringstream errorMessage;
466  errorMessage << "INR file " << GetFileName() << " could not be read";
467  exception.SetDescription(errorMessage.str());
468  throw exception;
469  }
470 
471  // Swap bytes if necessary
472  if ( m_ByteOrder == LittleEndian )
473  {
474  switch(m_ComponentType)
475  {
476  case CHAR:
477  ByteSwapper<char>::SwapRangeFromSystemToLittleEndian((char*)buffer, GetImageSizeInComponents() );
478  break;
479  case UCHAR:
480  ByteSwapper<unsigned char>::SwapRangeFromSystemToLittleEndian((unsigned char*)buffer,
481  GetImageSizeInComponents() );
482  break;
483  case SHORT:
484  ByteSwapper<short>::SwapRangeFromSystemToLittleEndian((short*)buffer, GetImageSizeInComponents() );
485  break;
486  case USHORT:
487  ByteSwapper<unsigned short>::SwapRangeFromSystemToLittleEndian((unsigned short*)buffer,
488  GetImageSizeInComponents() );
489  break;
490  case INT:
491  ByteSwapper<int>::SwapRangeFromSystemToLittleEndian((int*)buffer, GetImageSizeInComponents() );
492  break;
493  case UINT:
494  ByteSwapper<unsigned int>::SwapRangeFromSystemToLittleEndian((unsigned int*)buffer,
495  GetImageSizeInComponents() );
496  break;
497  case LONG:
498  ByteSwapper<long>::SwapRangeFromSystemToLittleEndian((long*)buffer, GetImageSizeInComponents() );
499  break;
500  case ULONG:
501  ByteSwapper<unsigned long>::SwapRangeFromSystemToLittleEndian((unsigned long*)buffer,
502  GetImageSizeInComponents() );
503  break;
504  case FLOAT:
505  ByteSwapper<float>::SwapRangeFromSystemToLittleEndian((float*)buffer, GetImageSizeInComponents() );
506  break;
507  case DOUBLE:
508  ByteSwapper<double>::SwapRangeFromSystemToLittleEndian((double*)buffer, GetImageSizeInComponents() );
509  break;
510  default:
511  gzclose(file);
512  ExceptionObject exception(__FILE__, __LINE__);
513  exception.SetDescription("Pixel Type Unknown");
514  throw exception;
515  }
516  }
517  else if ( m_ByteOrder == BigEndian )
518  {
519  switch(m_ComponentType)
520  {
521  case CHAR:
522  ByteSwapper<char>::SwapRangeFromSystemToBigEndian((char*)buffer, GetImageSizeInComponents() );
523  break;
524  case UCHAR:
525  ByteSwapper<unsigned char>::SwapRangeFromSystemToBigEndian((unsigned char*)buffer,
526  GetImageSizeInComponents() );
527  break;
528  case SHORT:
529  ByteSwapper<short>::SwapRangeFromSystemToBigEndian((short*)buffer, GetImageSizeInComponents() );
530  break;
531  case USHORT:
532  ByteSwapper<unsigned short>::SwapRangeFromSystemToBigEndian((unsigned short*)buffer,
533  GetImageSizeInComponents() );
534  break;
535  case INT:
536  ByteSwapper<int>::SwapRangeFromSystemToBigEndian((int*)buffer, GetImageSizeInComponents() );
537  break;
538  case UINT:
539  ByteSwapper<unsigned int>::SwapRangeFromSystemToBigEndian((unsigned int*)buffer,
540  GetImageSizeInComponents() );
541  break;
542  case LONG:
543  ByteSwapper<long>::SwapRangeFromSystemToBigEndian((long*)buffer, GetImageSizeInComponents() );
544  break;
545  case ULONG:
546  ByteSwapper<unsigned long>::SwapRangeFromSystemToBigEndian((unsigned long*)buffer,
547  GetImageSizeInComponents() );
548  break;
549  case FLOAT:
550  ByteSwapper<float>::SwapRangeFromSystemToBigEndian((float*)buffer, GetImageSizeInComponents() );
551  break;
552  case DOUBLE:
553  ByteSwapper<double>::SwapRangeFromSystemToBigEndian((double*)buffer, GetImageSizeInComponents() );
554  break;
555  default:
556  gzclose(file);
557  ExceptionObject exception(__FILE__, __LINE__);
558  exception.SetDescription("Pixel Type Unknown");
559  throw exception;
560  }
561  }
562 
563  gzclose(file);
564 }
565 
566 //------------------------------------------------------------------------------
567 
568 bool InrImageIO::CanWriteFile(const char * FileNameToWrite)
569 {
570  // Extension must be .inr or .inr.gz
571  std::string const filename(FileNameToWrite);
572 
573  std::string::size_type index = filename.rfind(".inr");
574  if(index==filename.length() - std::string(".inr").length())
575  {
576  return true;
577  }
578 
579  index = filename.rfind(".inr.gz");
580  if(index==filename.length() - std::string(".inr.gz").length())
581  {
582  return true;
583  }
584 
585  return false;
586 }
587 
588 //------------------------------------------------------------------------------
589 
591 {
592  std::stringstream headerStream;
593 
594  // Magic
595  headerStream << "#INRIMAGE-4#{" << "\n";
596  // Dimensions : always write a 3D InrImage
597  headerStream << "XDIM=" << ((GetDimensions(0)<1) ? 1 : GetDimensions(0)) << "\n";
598  headerStream << "YDIM=" << ((GetDimensions(1)<1) ? 1 : GetDimensions(1)) << "\n";
599  headerStream << "ZDIM=" << ((GetDimensions(2)<1) ? 1 : GetDimensions(2)) << "\n";
600  // Number of components per pixel
601  headerStream << "VDIM=" << GetNumberOfComponents() << "\n";
602  // Spacing : if it's 0, put it to one instead
603  headerStream << "VX=" << ((GetSpacing(0)==0.0) ? 1.0 : GetSpacing(0)) << "\n";
604  headerStream << "VY=" << ((GetSpacing(1)==0.0) ? 1.0 : GetSpacing(1)) << "\n";
605  headerStream << "VZ=" << ((GetSpacing(2)==0.0) ? 1.0 : GetSpacing(2)) << "\n";
606  // Scale
607  headerStream << "SCALE=2**0" << "\n";
608  // Endianness
609  headerStream << "CPU=" << (itk::ByteSwapper<char>::SystemIsLE() ? "pc" : "sgi") << "\n";
610  // Point type
611  std::string type;
612  if(m_ComponentType==UCHAR || m_ComponentType==USHORT || m_ComponentType==UINT || m_ComponentType==ULONG)
613  {
614  type = "unsigned fixed";
615  }
616  else if(m_ComponentType==CHAR || m_ComponentType==SHORT || m_ComponentType==INT || m_ComponentType==LONG)
617  {
618  type = "signed fixed";
619  }
620  else if(m_ComponentType==FLOAT || m_ComponentType==DOUBLE)
621  {
622  type = "float";
623  }
624  else
625  {
626  // Unknown/incorrect component type
627  ExceptionObject exception(__FILE__, __LINE__);
628  std::stringstream errorMessage;
629  errorMessage << "File " << GetFileName()
630  << " could not be written : unknown pixel type.";
631  exception.SetDescription(errorMessage.str());
632  throw exception;
633  }
634  headerStream << "TYPE=" << type << "\n";
635  // PixelSize
636  int pixelSize;
637  if(m_ComponentType==UCHAR || m_ComponentType==CHAR)
638  {
639  pixelSize = sizeof(char);
640  }
641  else if(m_ComponentType==USHORT || m_ComponentType==SHORT)
642  {
643  pixelSize = sizeof(short);
644  }
645  else if(m_ComponentType==UINT || m_ComponentType==INT)
646  {
647  pixelSize = sizeof(int);
648  }
649  else if(m_ComponentType==ULONG || m_ComponentType==LONG)
650  {
651  pixelSize = sizeof(long);
652  }
653  else if(m_ComponentType==FLOAT)
654  {
655  pixelSize = sizeof(float);
656  }
657  else if(m_ComponentType==DOUBLE)
658  {
659  pixelSize = sizeof(double);
660  }
661  else
662  {
663  // Unknown/incorrect component type
664  ExceptionObject exception(__FILE__, __LINE__);
665  std::stringstream errorMessage;
666  errorMessage << "File " << GetFileName()
667  << " could not be written : unknown pixel type.";
668  exception.SetDescription(errorMessage.str());
669  throw exception;
670  }
671 
672  pixelSize *= 8;
673  headerStream << "PIXSIZE=" << pixelSize << " bits" << "\n";
674 
675  int const padding = 256 - headerStream.str().length() - std::string("##}\n").length();
676  for(int i = 0; i<padding; ++i)
677  {
678  headerStream << "\n";
679  }
680  headerStream << "##}\n";
681  if(!headerStream)
682  {
683  // Something could not be written to headerStream
684  ExceptionObject exception(__FILE__, __LINE__);
685  std::stringstream errorMessage;
686  errorMessage << "File " << GetFileName()
687  << " could not be written : error while writing to headerStream.";
688  exception.SetDescription(errorMessage.str());
689  throw exception;
690  }
691 
692  std::string const header = headerStream.str();
693  std::string const filename(this->GetFileName());
694  std::string::size_type const index = filename.rfind(".inr.gz");
695 
696  if(index==filename.length() - std::string(".inr.gz").length())
697  {
698  gzFile outputFile = gzopen(this->GetFileName(), "wb9");
699  if(outputFile == 0)
700  {
701  ExceptionObject exception(__FILE__, __LINE__);
702  std::stringstream errorMessage;
703  errorMessage << "File " << GetFileName()
704  << " could not be written : error writing header.";
705  exception.SetDescription(errorMessage.str());
706  throw exception;
707  }
708  std::string const headerString = headerStream.str();
709  gzwrite( outputFile, const_cast<char*>(headerString.c_str()), headerString.length() );
710  gzclose(outputFile);
711  }
712  else
713  {
714  FILE* outputFile = fopen(this->GetFileName(), "wb");
715  if(outputFile == 0)
716  {
717  ExceptionObject exception(__FILE__, __LINE__);
718  std::stringstream errorMessage;
719  errorMessage << "File " << GetFileName()
720  << " could not be written : error writing header.";
721  exception.SetDescription(errorMessage.str());
722  throw exception;
723  }
724 
725  std::string const headerString = headerStream.str();
726  fwrite( headerString.c_str(), sizeof(char), headerString.length(), outputFile);
727  fclose(outputFile);
728  }
729 }
730 
731 //------------------------------------------------------------------------------
732 
733 void InrImageIO::Write(const void* buffer)
734 {
735  this->WriteImageInformation();
736  std::string const filename(GetFileName());
737  std::string const suffix(".inr.gz");
738  std::string::size_type const index = filename.rfind(suffix);
739  if(index==filename.length() - suffix.length())
740  {
741  gzFile outputFile = gzopen(this->GetFileName(), "ab");
742  if(outputFile == 0)
743  {
744  ExceptionObject exception(__FILE__, __LINE__);
745  std::stringstream errorMessage;
746  errorMessage << "File " << GetFileName()
747  << " could not be written : error writing buffer.";
748  exception.SetDescription(errorMessage.str());
749  throw exception;
750  }
751 
752  // Replace this line :
753  // gzwrite(outputFile, const_cast<void*>(buffer), GetImageSizeInBytes());
754  // by
755  int written = 0;
756  long long int size =
757  ( (GetImageSizeInBytes()>1024*1024*10) ? ( GetImageSizeInBytes() / 10 ) + 1 : GetImageSizeInBytes() );
758  try
759  {
760  while ( written < GetImageSizeInBytes() )
761  {
762  UpdateProgress( ((float)written)/GetImageSizeInBytes() );
763  written +=
764  gzwrite( outputFile, ((char *)buffer)+written, min(size, GetImageSizeInBytes() - written) );
765 
766  }
767  }
768  catch(::fwCore::Exception &e) // catch progress bar cancel exception
769  {
770  gzclose(outputFile);
771  throw;
772  }
773  UpdateProgress( 1.0 );
774  // End replace
775 
776  gzclose(outputFile);
777  }
778  else
779  {
780  FILE* outputFile = fopen(this->GetFileName(), "ab");
781  if(outputFile == 0)
782  {
783  ExceptionObject exception(__FILE__, __LINE__);
784  std::stringstream errorMessage;
785  errorMessage << "File " << GetFileName()
786  << " could not be written : error writing buffer.";
787  exception.SetDescription(errorMessage.str());
788  throw exception;
789  }
790 
791  // Replace this line :
792  // fwrite(buffer, 1, GetImageSizeInBytes(), outputFile);
793  // by :
794  int written = 0;
795  long long int size =
796  ( (GetImageSizeInBytes()>1024*1024*10) ? ( GetImageSizeInBytes() / 10 ) + 1 : GetImageSizeInBytes() );
797  try
798  {
799  while ( written < GetImageSizeInBytes() )
800  {
801  UpdateProgress( ((float)written)/GetImageSizeInBytes() );
802  written +=
803  fwrite( ((char *)buffer)+written, 1, min(size, GetImageSizeInBytes() - written), outputFile);
804  }
805  }
806  catch(::fwCore::Exception &e) // catch progress bar cancel exception
807  {
808  fclose(outputFile);
809  throw;
810  }
811  UpdateProgress( 1.0 );
812  // End replace
813 
814  fclose(outputFile);
815  }
816 }
817 
818 } // namespace itk
virtual void WriteImageInformation() override
virtual void Read(void *buffer) override
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
virtual void ReadImageInformation() override
virtual bool CanWriteFile(const char *FileNameToWrite) override
virtual void Write(const void *buffer) override
This file defines SpyLog macros. These macros are used to log messages to a file or to the console du...
virtual Superclass bool CanReadFile(const char *FileNameToRead) override