--- /dev/null
+#include <creaImageIOImageReader.h>
+#include <creaImageIOTreeAttributeDescriptor.h>
+
+
+#include <vtkImageReader2.h>
+#include <vtkPNGReader.h>
+#include <vtkTIFFReader.h>
+#include <vtkJPEGReader.h>
+#include <vtkBMPReader.h>
+#include <vtkSLCReader.h>
+#include <vtkMetaImageReader.h>
+//#include <vtkGESignalReader.h>
+
+#include <gdcmFile.h>
+#include <vtkGdcmReader.h>
+
+
+#include "boost/filesystem/path.hpp"
+
+namespace creaImageIO
+{
+
+ //========================================================================
+ std::string irclean(const std::string& str)
+ {
+ if (str == "GDCM::Unfound")
+ {
+ return "----";
+ }
+ if (str[str.size()-1]==' ')
+ {
+ return str.substr(0,str.size()-1);
+ }
+ if (str[str.size()-1]==0)
+ {
+ return str.substr(0,str.size()-1);
+ }
+
+ return str;
+ }
+ //========================================================================
+
+ void IRSplitString ( const std::string& str,
+ const std::string& delimiters,
+ std::vector<std::string>& tokens)
+ {
+ // Skip delimiters at beginning.
+ std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+ // Find first delimiter.
+ std::string::size_type pos = str.find_first_of(delimiters, lastPos);
+
+ while (std::string::npos != pos || std::string::npos != lastPos)
+ {
+ // Found a token, add it to the vector.
+ // SPECIFIC : REMOVE INITIAL DOT (lastPos + 1)
+ tokens.push_back(str.substr(lastPos+1, pos - lastPos));
+ // Skip delimiters. Note the "not_of"
+ lastPos = str.find_first_not_of(delimiters, pos);
+ // Find next delimiter
+ pos = str.find_first_of(delimiters, lastPos);
+ }
+
+ }
+
+
+ //=====================================================================
+ class SpecificImageReader
+ {
+ public:
+ SpecificImageReader() {}
+ virtual ~SpecificImageReader() {}
+
+ void SetName(const std::string& s) { mName = s; }
+ const std::string& GetName() const { return mName; }
+
+ virtual void PushBackExtensions(std::vector<std::string>&) {}
+
+ virtual bool CanRead(const std::string& filename) { return false; }
+ virtual vtkImageData* ReadImage(const std::string& filename) { return 0; }
+ virtual void ReadAttributes(const std::string& filename,
+ std::map<std::string,std::string>& attr) {}
+
+ private:
+ std::string mName;
+ };
+ //=====================================================================
+
+ //=====================================================================
+ class SpecificVtkReader : public SpecificImageReader
+ {
+ public:
+ //=====================================================================
+ SpecificVtkReader(vtkImageReader2* r,
+ const std::string& name = "",
+ const std::string& extensions = "")
+ : mVTKReader(r), mExtensions(extensions)
+ {
+ if (name.size() == 0)
+ {
+ SetName ( mVTKReader->GetDescriptiveName() );
+ }
+ else
+ {
+ SetName ( name );
+ }
+ };
+ //=====================================================================
+ ~SpecificVtkReader()
+ {
+ mVTKReader->Delete();
+ }
+ //=====================================================================
+ bool CanRead(const std::string& filename)
+ {
+ // std::cout << "## Reader "<<GetName()
+ //<<" ::CanRead("<<filename<<")"
+ // <<std::endl;
+ return (mVTKReader->CanReadFile(filename.c_str())!=0);
+ }
+ //=====================================================================
+
+ //=====================================================================
+ vtkImageData* ReadImage(const std::string& filename)
+ {
+ // std::cout << "## Reader "<<GetName()
+ //<<" ::Read("<<filename<<")"
+ // <<std::endl;
+ vtkImageData* im = 0;
+ try
+ {
+ mVTKReader->SetFileName(filename.c_str());
+ mVTKReader->Update();
+ im = vtkImageData::New();
+ im->ShallowCopy(mVTKReader->GetOutput());
+ }
+ catch (...)
+ {
+ if (im!=0) im->Delete();
+ im = 0;
+ }
+ return im;
+ }
+ //=====================================================================
+
+ //=====================================================================
+ void PushBackExtensions(std::vector<std::string>& v)
+ {
+ std::string ext = mExtensions;
+ if (ext.size()==0) ext = mVTKReader->GetFileExtensions ();
+
+ IRSplitString(ext," ",v);
+ }
+ //=====================================================================
+
+ //=====================================================================
+ void ReadAttributes(const std::string& filename,
+ std::map<std::string,std::string>& attr)
+ {
+ // std::cout << "SpecificVtkReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
+ // Get image dimensions
+ // How to get the image info without loading it in vtk ?
+ mVTKReader->SetFileName(filename.c_str());
+ mVTKReader->Update(); //OpenFile();
+ int ext[6];
+ mVTKReader->GetDataExtent(ext);
+ // Columns
+ char cols[128];
+ sprintf(cols,"%i",ext[1]-ext[0]);
+ // Rows
+ char rows[128];
+ sprintf(rows,"%i",ext[3]-ext[2]);
+ // Planes
+ char planes[128];
+ sprintf(planes,"%i",ext[5]-ext[4]);
+
+ //
+ std::map<std::string,std::string>::iterator i;
+ if ( (i = attr.find("Full File Name")) != attr.end())
+ {
+ boost::filesystem::path full_path(filename);
+ std::string f = full_path.leaf();
+ i->second = f;
+ }
+ if ( (i = attr.find("Columns")) != attr.end())
+ {
+ i->second = cols;
+ }
+ if ( (i = attr.find("Rows")) != attr.end())
+ {
+ i->second = rows;
+ }
+ if ( (i = attr.find("Planes")) != attr.end())
+ {
+ i->second = planes;
+ }
+ }
+ //=====================================================================
+ private:
+ vtkImageReader2* mVTKReader;
+ std::string mExtensions;
+ };
+ //=====================================================================
+
+ //=====================================================================
+ /*
+ void IRFillFields(DicomNode* node,
+ GDCM_NAME_SPACE::File* gdcmFile)
+ {
+ const DicomNodeTypeDescription::FieldDescriptionMapType& dm
+ = node->GetTypeDescription().GetFieldDescriptionMap();
+ DicomNodeTypeDescription::FieldDescriptionMapType::const_iterator i;
+
+
+ DicomNode::FieldValueMapType& vm = node->GetFieldValueMap();
+ for (i=dm.begin(); i!=dm.end(); ++i)
+ {
+ if ( (i->second.flags==0) &&
+ (i->second.group!=0) &&
+ (i->second.element!=0) )
+ {
+ uint16_t gr = i->second.group;
+ uint16_t el = i->second.element;
+
+ std::string val = gdcmFile->GetEntryString(gr,el);
+
+ vm[i->first] = irclean(val);
+ }
+ else
+ {
+ vm[i->first] = "";
+ }
+ }
+ }
+ */
+ //=====================================================================
+
+ //=====================================================================
+ class DicomReader : public SpecificImageReader
+ {
+ public:
+ //=====================================================================
+ DicomReader()
+ {
+ mReader = vtkGdcmReader::New();
+ SetName ( "Dicom" );
+ };
+ //=====================================================================
+ ~DicomReader()
+ {
+ mReader->Delete();
+ }
+ //=====================================================================
+ bool CanRead(const std::string& filename)
+ {
+ // std::cout << "## Reader "<<GetName()
+ //<<" ::CanRead("<<filename<<")"
+ // <<std::endl;
+ // return true;
+
+
+ // GDCM_NAME_SPACE
+ // std::cout << "GDCM_NAME_SPACE = '" << STRINGIFY_SYMBOL(GDCM_NAME_SPACE)
+ // << "'"
+ // <<std::endl;
+
+ GDCM_NAME_SPACE::File* file = GDCM_NAME_SPACE::File::New();
+ file->SetLoadMode( GDCM_NAME_SPACE::LD_ALL);
+ file->SetFileName(filename.c_str());
+ file->Load();
+ bool ok = file->IsReadable();
+ file->Delete();
+ return ok;
+ }
+ //=====================================================================
+ vtkImageData* ReadImage(const std::string& filename)
+ {
+ // std::cout << "## Reader "<<GetName()
+ //<<" ::Read("<<filename<<")"
+ // <<std::endl;
+
+ vtkImageData* im = 0;
+ try
+ {
+ mReader->SetFileName(filename.c_str());
+ mReader->Update();
+ im = vtkImageData::New();
+ im->ShallowCopy(mReader->GetOutput());
+ }
+ catch (...)
+ {
+ if (im!=0) im->Delete();
+ im = 0;
+ }
+ return im;
+ }
+ //=====================================================================
+ void PushBackExtensions(std::vector<std::string>& v)
+ {
+ v.push_back("dcm");
+ v.push_back("");
+ }
+ //=====================================================================
+
+ //=====================================================================
+ //=====================================================================
+ void ReadAttributes(const std::string& filename,
+ std::map<std::string,std::string>& attr)
+ {
+ // std::cout << "DicomReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
+ GDCM_NAME_SPACE::File* file = GDCM_NAME_SPACE::File::New();
+ file->SetLoadMode( GDCM_NAME_SPACE::LD_ALL);
+ file->SetFileName(filename.c_str());
+ file->Load();
+ if (file->IsReadable())
+ {
+
+ std::map<std::string,std::string>::iterator i;
+ for (i=attr.begin();i!=attr.end();++i)
+ {
+ if ( i->first == "Full File Name" )
+ {
+ boost::filesystem::path full_path(filename);
+ std::string f = full_path.leaf();
+ i->second = f;
+ }
+ else
+ {
+ tree::AttributeDescriptor a(i->first);
+ uint16_t gr = a.GetGroup();
+ uint16_t el = a.GetElement();
+ if ( ( gr!=0 ) && ( el!=0 ) )
+ {
+ std::string val = file->GetEntryString(gr,el);
+ i->second = irclean(val);
+ }
+ }
+ }
+ }
+ file->Delete();
+ }
+
+
+ private:
+ vtkGdcmReader* mReader;
+ };
+ //=====================================================================
+
+
+
+
+
+ //=====================================================================
+ ImageReader::ImageReader()
+ :
+ mUnreadableImage(0),
+ mLastFilename("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"),
+ mLastReader(0)
+
+ {
+ // std::cout << "#### ImageReader::ImageReader()"<<std::endl;
+ if (mUnreadableImage!=0) return;
+
+ Register(new SpecificVtkReader(vtkPNGReader::New()));
+ Register(new SpecificVtkReader(vtkTIFFReader::New()));
+ Register(new SpecificVtkReader(vtkJPEGReader::New()));
+ Register(new SpecificVtkReader(vtkBMPReader::New()));
+ Register(new SpecificVtkReader(vtkSLCReader::New()));
+ Register(new SpecificVtkReader(vtkMetaImageReader::New(),"MHD",".mhd"));
+ // Register(new SpecificVtkReader(vtkGESignalReader::New()));
+ Register(new DicomReader);
+
+ /*
+ std::cout << "## Registered file extensions : "<<std::endl;
+ std::vector<std::string>::const_iterator i;
+ for (i=GetKnownExtensions().begin();
+ i!=GetKnownExtensions().end();
+ i++)
+ {
+ std::cout << "'"<<(*i)<<"'"<<std::endl;
+ }
+ */
+ //
+ mUnreadableImage = vtkImageData::New();
+ int dim[3];
+ dim[0] = dim[1] = 128;
+ dim[2] = 1;
+ mUnreadableImage->SetDimensions ( dim );
+ mUnreadableImage->SetScalarTypeToUnsignedChar();
+ mUnreadableImage->AllocateScalars();
+ for (int i=0;i<dim[0];i++)
+ for (int j=0;j<dim[1];j++)
+ mUnreadableImage->SetScalarComponentFromFloat(i,j,0,0,0);
+ for (int i=0;i<dim[0];i++)
+ {
+ mUnreadableImage->SetScalarComponentFromFloat(i,i,0,0,255);
+ mUnreadableImage->SetScalarComponentFromFloat(dim[0]-1-i,i,0,0,255);
+ }
+
+
+
+ }
+ //=====================================================================
+
+ //=====================================================================
+ ImageReader::~ImageReader()
+ {
+ // std::cout << "#### ImageReader::~ImageReader()"<<std::endl;
+ std::vector<SpecificImageReader*>::iterator i;
+ for (i=mReader.begin(); i!=mReader.end(); i++)
+ {
+ // std::cout << "#### ImageReader::UnRegister("
+ // << (*i)->GetName()<<")"<<std::endl;
+ delete (*i);
+ }
+ mReader.clear();
+ if (mUnreadableImage!=0)
+ {
+ mUnreadableImage->Delete();
+ mUnreadableImage = 0;
+ }
+ }
+ //=====================================================================
+
+ //=====================================================================
+ void ImageReader::Register(SpecificImageReader* r)
+ {
+ // std::cout << "#### ImageReader::Register("<<r->GetName()<<")"<<std::endl;
+ mReader.push_back(r);
+ r->PushBackExtensions(mKnownExtensions);
+ }
+ //=====================================================================
+
+ //=====================================================================
+ // Returns true iff the file is readable
+ bool ImageReader::CanRead( const std::string& filename,
+ const std::string& exclude )
+ {
+ // std::cout << "## ImageReader::CanRead("<<filename<<")"<<std::endl;
+ bool ok = false;
+ std::vector<SpecificImageReader*>::iterator i;
+ for (i=mReader.begin(); i!=mReader.end(); i++)
+ {
+ if ((*i)->GetName()==exclude) continue;
+ ok = (*i)->CanRead(filename);
+ if (ok)
+ {
+ mLastFilename = filename;
+ mLastReader = *i;
+ break;
+ }
+ }
+ return ok;
+ }
+ //=====================================================================
+
+ //=====================================================================
+ // Reads the file (CanRead must be called before : no test here)
+ vtkImageData* ImageReader::ReadImage( const std::string& filename,
+ const std::string& exclude )
+ {
+ // std::cout << "## ImageReader::Read("<<filename<<")"<<std::endl;
+ if (mLastFilename!=filename)
+ {
+ if (!CanRead(filename,exclude))
+ {
+ // std::cout << " -- Cannot read image "<<std::endl;
+ vtkImageData* im = vtkImageData::New();
+ im->ShallowCopy(mUnreadableImage);
+ return im;
+ }
+ }
+ vtkImageData* i = mLastReader->ReadImage(mLastFilename);
+ // std::cout << "i="<<i<<std::endl;
+ if (i==0)
+ {
+ // std::cout << "i=UNREAD"<<i<<std::endl;
+ i = vtkImageData::New();
+ i->ShallowCopy(mUnreadableImage);
+ }
+ // std::cout << "i="<<i<<std::endl;
+ return i;
+ }
+ //=====================================================================
+
+
+ //=====================================================================
+ void ImageReader::ReadAttributes(const std::string& filename,
+ std::map<std::string,std::string>& attr)
+ {
+ // std::cout << "ImageReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
+ // std::cout << "## ImageReader::Read("<<filename<<")"<<std::endl;
+ if (mLastFilename!=filename)
+ {
+ if (!CanRead(filename))
+ {
+ return;
+ }
+ }
+ mLastReader->ReadAttributes(mLastFilename,attr);
+ }
+ //=====================================================================
+
+
+
+} // namespace creaImageIO