]> Creatis software - creaImageIO.git/blobdiff - src2/creaImageIOImageReader.cpp
Starting version 2
[creaImageIO.git] / src2 / creaImageIOImageReader.cpp
diff --git a/src2/creaImageIOImageReader.cpp b/src2/creaImageIOImageReader.cpp
new file mode 100644 (file)
index 0000000..2480a47
--- /dev/null
@@ -0,0 +1,505 @@
+#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