12 #include <boost/lexical_cast.hpp> 15 #include <itkByteSwapper.h> 16 #include <itkIOCommon.h> 17 #include <itkExceptionObject.h> 20 #include <fwCore/Exception.hpp> 22 #include "inr2itk/itkInrImageIO.hpp" 24 #define max(a,b) ((a) > (b) ? (a) : (b)) 25 #define min(a,b) ((a) <= (b) ? (a) : (b)) 30 InrImageIO::InrImageIO()
32 this->SetNumberOfDimensions(3);
39 InrImageIO::~InrImageIO()
46 void InrImageIO::PrintSelf(std::ostream& os, Indent indent)
const 48 Superclass::PrintSelf(os, indent);
49 os << indent <<
"PixelType " << m_PixelType <<
"\n";
50 os << indent <<
"ComponentType " << m_ComponentType <<
"\n";
58 gzFile inputFile = gzopen(FileNameToRead,
"rb");
66 gzgets(inputFile, firstLine, 256);
70 std::string
const magic(
"#INRIMAGE-4#{\n");
85 gzFile inputFile = gzopen(this->GetFileName(),
"rb");
89 ExceptionObject exception(__FILE__, __LINE__);
90 std::stringstream errorMessage;
91 errorMessage <<
"File " << GetFileName() <<
" could not be read";
92 exception.SetDescription(errorMessage.str());
96 const int lineBufSize = 256;
97 char linebuf[lineBufSize];
98 std::map<std::string, std::string> headerValues;
100 while( gzgets(inputFile, linebuf, lineBufSize) && !gzeof(inputFile) )
102 std::string line(linebuf);
104 m_headerSize += line.length();
106 std::string::size_type
const endOfLine = line.find(
'\n');
107 line = line.substr(0, endOfLine);
119 else if(line[0]==
'#')
126 std::string::const_iterator delimiter = std::find(line.begin(), line.end(),
'=');
127 if(delimiter==line.end())
131 ExceptionObject exception(__FILE__, __LINE__);
132 std::stringstream errorMessage;
133 errorMessage <<
"Invalid INR file.\n" <<
"Offending line : " << line;
134 exception.SetDescription(errorMessage.str());
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())
145 ExceptionObject exception(__FILE__, __LINE__);
147 std::stringstream errorMessage;
148 errorMessage <<
"Invalid INR file.\n" <<
"Duplicate key : " << key;
149 exception.SetDescription(errorMessage.str());
154 headerValues[key] = value;
162 for(std::map<std::string, std::string>::const_iterator it = headerValues.begin(); it!=headerValues.end(); ++it)
164 if(it->first==
"XDIM")
166 int xdim = ::boost::lexical_cast<
int>( it->second );
167 this->SetDimensions(0, xdim);
169 else if(it->first==
"YDIM")
171 int ydim = ::boost::lexical_cast<
int>( it->second );
172 this->SetDimensions(1, ydim);
174 else if(it->first==
"ZDIM")
176 int zdim = ::boost::lexical_cast<
int>( it->second );
177 this->SetDimensions(2, zdim);
179 else if(it->first==
"VDIM")
181 int vdim = ::boost::lexical_cast<
int>( it->second );
184 SetPixelType(SCALAR);
188 SetPixelType(VECTOR);
190 SetNumberOfComponents(vdim);
192 else if(it->first==
"VX")
194 float vx = ::boost::lexical_cast<
float >( it->second );
195 this->SetSpacing(0, vx);
197 else if(it->first==
"VY")
199 float vy = ::boost::lexical_cast<
float >( it->second );
200 this->SetSpacing(1, vy);
202 else if(it->first==
"VZ")
204 float vz = ::boost::lexical_cast<
float >( it->second );
205 this->SetSpacing(2, vz);
207 else if(it->first==
"TYPE")
209 std::map<std::string, std::string>::const_iterator pixsize_it = headerValues.find(
"PIXSIZE");
210 if(pixsize_it==headerValues.end())
213 ExceptionObject exception(__FILE__, __LINE__);
214 std::stringstream errorMessage;
215 errorMessage <<
"Invalid INR file.\n" <<
"PIXSIZE key not found.";
216 exception.SetDescription(errorMessage.str());
219 std::string type = it->second;
220 std::string pixsize = pixsize_it->second;
221 if(type==
"unsigned fixed")
223 if(pixsize==
"8 bits")
225 m_ComponentType = UCHAR;
227 else if(pixsize==
"16 bits")
229 m_ComponentType = USHORT;
231 else if(pixsize==
"32 bits")
233 if ( 4 ==
sizeof(
unsigned int) )
235 m_ComponentType = UINT;
237 else if ( 4 ==
sizeof(
unsigned long) )
239 m_ComponentType = ULONG;
243 ExceptionObject exception(__FILE__, __LINE__);
244 std::stringstream errorMessage;
245 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
246 exception.SetDescription(errorMessage.str());
250 else if(pixsize==
"64 bits")
252 if ( 8 ==
sizeof(
unsigned int) )
254 m_ComponentType = UINT;
256 else if ( 8 ==
sizeof(
unsigned long) )
258 m_ComponentType = ULONG;
262 ExceptionObject exception(__FILE__, __LINE__);
263 std::stringstream errorMessage;
264 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
265 exception.SetDescription(errorMessage.str());
271 ExceptionObject exception(__FILE__, __LINE__);
272 std::stringstream errorMessage;
273 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
274 exception.SetDescription(errorMessage.str());
278 else if(type==
"signed fixed")
280 if(pixsize==
"8 bits")
282 m_ComponentType = CHAR;
284 else if(pixsize==
"16 bits")
286 m_ComponentType = SHORT;
288 else if(pixsize==
"32 bits")
290 if ( 4 ==
sizeof(
int) )
292 m_ComponentType = INT;
294 else if ( 4 ==
sizeof(
long) )
296 m_ComponentType = LONG;
300 ExceptionObject exception(__FILE__, __LINE__);
301 std::stringstream errorMessage;
302 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
303 exception.SetDescription(errorMessage.str());
307 else if(pixsize==
"64 bits")
309 if ( 8 ==
sizeof(
int) )
311 m_ComponentType = INT;
313 else if ( 8 ==
sizeof(
long) )
315 m_ComponentType = LONG;
319 ExceptionObject exception(__FILE__, __LINE__);
320 std::stringstream errorMessage;
321 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
322 exception.SetDescription(errorMessage.str());
328 ExceptionObject exception(__FILE__, __LINE__);
329 std::stringstream errorMessage;
330 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
331 exception.SetDescription(errorMessage.str());
335 else if(type==
"float")
345 if(pixsize==
"32 bits")
347 m_ComponentType = FLOAT;
349 else if(pixsize==
"64 bits")
351 m_ComponentType = DOUBLE;
355 ExceptionObject exception(__FILE__, __LINE__);
356 std::stringstream errorMessage;
357 errorMessage <<
"Invalid INR file.\n" <<
"Invalid PIXSIZE.";
358 exception.SetDescription(errorMessage.str());
364 ExceptionObject exception(__FILE__, __LINE__);
365 std::stringstream errorMessage;
366 errorMessage <<
"Invalid INR file.\n" <<
"Invalid TYPE.";
367 exception.SetDescription(errorMessage.str());
371 else if(it->first==
"PIXSIZE")
375 else if(it->first==
"SCALE")
379 else if(it->first==
"CPU")
382 if(it->second==
"sun" || it->second==
"sgi")
386 m_ByteOrder = BigEndian;
389 else if(it->second==
"pc" || it->second==
"alpha" || it->second==
"decm")
393 m_ByteOrder = LittleEndian;
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());
411 gzFile file = gzopen(GetFileName(),
"rb");
415 ExceptionObject exception(__FILE__, __LINE__);
416 std::stringstream errorMessage;
417 errorMessage <<
"INR file " << GetFileName() <<
" could not be read";
418 exception.SetDescription(errorMessage.str());
423 int bytesSkipped = gzseek(file, m_headerSize, SEEK_CUR);
424 if(bytesSkipped!=m_headerSize)
426 ExceptionObject exception(__FILE__, __LINE__);
427 std::stringstream errorMessage;
428 errorMessage <<
"INR file " << GetFileName() <<
" could not be read (header size : " << bytesSkipped <<
"/" <<
430 exception.SetDescription(errorMessage.str());
442 ( (GetImageSizeInBytes()>1024*1024*10) ? ( GetImageSizeInBytes() / nbStep ) + 1 : GetImageSizeInBytes() );
446 while ( bytesRead < GetImageSizeInBytes() && step < nbStep )
449 UpdateProgress( ((
float)bytesRead)/GetImageSizeInBytes() );
450 bytesRead += gzread( file, ((
char *)buffer)+bytesRead, min(size, GetImageSizeInBytes() - bytesRead) );
458 UpdateProgress( 1.0 );
461 if(bytesRead!=GetImageSizeInBytes())
464 ExceptionObject exception(__FILE__, __LINE__);
465 std::stringstream errorMessage;
466 errorMessage <<
"INR file " << GetFileName() <<
" could not be read";
467 exception.SetDescription(errorMessage.str());
472 if ( m_ByteOrder == LittleEndian )
474 switch(m_ComponentType)
477 ByteSwapper<char>::SwapRangeFromSystemToLittleEndian((
char*)buffer, GetImageSizeInComponents() );
480 ByteSwapper<unsigned char>::SwapRangeFromSystemToLittleEndian((
unsigned char*)buffer,
481 GetImageSizeInComponents() );
484 ByteSwapper<short>::SwapRangeFromSystemToLittleEndian((
short*)buffer, GetImageSizeInComponents() );
487 ByteSwapper<unsigned short>::SwapRangeFromSystemToLittleEndian((
unsigned short*)buffer,
488 GetImageSizeInComponents() );
491 ByteSwapper<int>::SwapRangeFromSystemToLittleEndian((
int*)buffer, GetImageSizeInComponents() );
494 ByteSwapper<unsigned int>::SwapRangeFromSystemToLittleEndian((
unsigned int*)buffer,
495 GetImageSizeInComponents() );
498 ByteSwapper<long>::SwapRangeFromSystemToLittleEndian((
long*)buffer, GetImageSizeInComponents() );
501 ByteSwapper<unsigned long>::SwapRangeFromSystemToLittleEndian((
unsigned long*)buffer,
502 GetImageSizeInComponents() );
505 ByteSwapper<float>::SwapRangeFromSystemToLittleEndian((
float*)buffer, GetImageSizeInComponents() );
508 ByteSwapper<double>::SwapRangeFromSystemToLittleEndian((
double*)buffer, GetImageSizeInComponents() );
512 ExceptionObject exception(__FILE__, __LINE__);
513 exception.SetDescription(
"Pixel Type Unknown");
517 else if ( m_ByteOrder == BigEndian )
519 switch(m_ComponentType)
522 ByteSwapper<char>::SwapRangeFromSystemToBigEndian((
char*)buffer, GetImageSizeInComponents() );
525 ByteSwapper<unsigned char>::SwapRangeFromSystemToBigEndian((
unsigned char*)buffer,
526 GetImageSizeInComponents() );
529 ByteSwapper<short>::SwapRangeFromSystemToBigEndian((
short*)buffer, GetImageSizeInComponents() );
532 ByteSwapper<unsigned short>::SwapRangeFromSystemToBigEndian((
unsigned short*)buffer,
533 GetImageSizeInComponents() );
536 ByteSwapper<int>::SwapRangeFromSystemToBigEndian((
int*)buffer, GetImageSizeInComponents() );
539 ByteSwapper<unsigned int>::SwapRangeFromSystemToBigEndian((
unsigned int*)buffer,
540 GetImageSizeInComponents() );
543 ByteSwapper<long>::SwapRangeFromSystemToBigEndian((
long*)buffer, GetImageSizeInComponents() );
546 ByteSwapper<unsigned long>::SwapRangeFromSystemToBigEndian((
unsigned long*)buffer,
547 GetImageSizeInComponents() );
550 ByteSwapper<float>::SwapRangeFromSystemToBigEndian((
float*)buffer, GetImageSizeInComponents() );
553 ByteSwapper<double>::SwapRangeFromSystemToBigEndian((
double*)buffer, GetImageSizeInComponents() );
557 ExceptionObject exception(__FILE__, __LINE__);
558 exception.SetDescription(
"Pixel Type Unknown");
571 std::string
const filename(FileNameToWrite);
573 std::string::size_type index = filename.rfind(
".inr");
574 if(index==filename.length() - std::string(
".inr").length())
579 index = filename.rfind(
".inr.gz");
580 if(index==filename.length() - std::string(
".inr.gz").length())
592 std::stringstream headerStream;
595 headerStream <<
"#INRIMAGE-4#{" <<
"\n";
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";
601 headerStream <<
"VDIM=" << GetNumberOfComponents() <<
"\n";
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";
607 headerStream <<
"SCALE=2**0" <<
"\n";
609 headerStream <<
"CPU=" << (itk::ByteSwapper<char>::SystemIsLE() ?
"pc" :
"sgi") <<
"\n";
612 if(m_ComponentType==UCHAR || m_ComponentType==USHORT || m_ComponentType==UINT || m_ComponentType==ULONG)
614 type =
"unsigned fixed";
616 else if(m_ComponentType==CHAR || m_ComponentType==SHORT || m_ComponentType==INT || m_ComponentType==LONG)
618 type =
"signed fixed";
620 else if(m_ComponentType==FLOAT || m_ComponentType==DOUBLE)
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());
634 headerStream <<
"TYPE=" << type <<
"\n";
637 if(m_ComponentType==UCHAR || m_ComponentType==CHAR)
639 pixelSize =
sizeof(char);
641 else if(m_ComponentType==USHORT || m_ComponentType==SHORT)
643 pixelSize =
sizeof(short);
645 else if(m_ComponentType==UINT || m_ComponentType==INT)
647 pixelSize =
sizeof(int);
649 else if(m_ComponentType==ULONG || m_ComponentType==LONG)
651 pixelSize =
sizeof(long);
653 else if(m_ComponentType==FLOAT)
655 pixelSize =
sizeof(float);
657 else if(m_ComponentType==DOUBLE)
659 pixelSize =
sizeof(double);
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());
673 headerStream <<
"PIXSIZE=" << pixelSize <<
" bits" <<
"\n";
675 int const padding = 256 - headerStream.str().length() - std::string(
"##}\n").length();
676 for(
int i = 0; i<padding; ++i)
678 headerStream <<
"\n";
680 headerStream <<
"##}\n";
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());
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");
696 if(index==filename.length() - std::string(
".inr.gz").length())
698 gzFile outputFile = gzopen(this->GetFileName(),
"wb9");
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());
708 std::string
const headerString = headerStream.str();
709 gzwrite( outputFile, const_cast<char*>(headerString.c_str()), headerString.length() );
714 FILE* outputFile = fopen(this->GetFileName(),
"wb");
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());
725 std::string
const headerString = headerStream.str();
726 fwrite( headerString.c_str(),
sizeof(char), headerString.length(), outputFile);
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())
741 gzFile outputFile = gzopen(this->GetFileName(),
"ab");
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());
757 ( (GetImageSizeInBytes()>1024*1024*10) ? ( GetImageSizeInBytes() / 10 ) + 1 : GetImageSizeInBytes() );
760 while ( written < GetImageSizeInBytes() )
762 UpdateProgress( ((
float)written)/GetImageSizeInBytes() );
764 gzwrite( outputFile, ((
char *)buffer)+written, min(size, GetImageSizeInBytes() - written) );
773 UpdateProgress( 1.0 );
780 FILE* outputFile = fopen(this->GetFileName(),
"ab");
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());
796 ( (GetImageSizeInBytes()>1024*1024*10) ? ( GetImageSizeInBytes() / 10 ) + 1 : GetImageSizeInBytes() );
799 while ( written < GetImageSizeInBytes() )
801 UpdateProgress( ((
float)written)/GetImageSizeInBytes() );
803 fwrite( ((
char *)buffer)+written, 1, min(size, GetImageSizeInBytes() - written), outputFile);
811 UpdateProgress( 1.0 );
virtual void WriteImageInformation() override
virtual void Read(void *buffer) override
#define OSLM_TRACE(message)
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