]> Creatis software - creaImageIO.git/blob - src2/creaImageIOImageReader.cpp
Starting version 2
[creaImageIO.git] / src2 / creaImageIOImageReader.cpp
1 #include <creaImageIOImageReader.h>
2 #include <creaImageIOTreeAttributeDescriptor.h>
3
4
5 #include <vtkImageReader2.h>
6 #include <vtkPNGReader.h>
7 #include <vtkTIFFReader.h>
8 #include <vtkJPEGReader.h>
9 #include <vtkBMPReader.h>
10 #include <vtkSLCReader.h>
11 #include <vtkMetaImageReader.h>
12 //#include <vtkGESignalReader.h>
13
14 #include <gdcmFile.h> 
15 #include <vtkGdcmReader.h>
16
17
18 #include "boost/filesystem/path.hpp"
19
20 namespace creaImageIO
21 {
22   
23   //========================================================================
24   std::string irclean(const std::string& str)
25   {
26     if (str == "GDCM::Unfound") 
27       {
28         return "----";
29       }
30     if (str[str.size()-1]==' ')
31       {
32         return str.substr(0,str.size()-1);
33       }
34     if (str[str.size()-1]==0)
35       {
36         return str.substr(0,str.size()-1);
37       }
38     
39     return str;
40   }
41   //========================================================================
42
43   void IRSplitString ( const std::string& str, 
44                        const std::string& delimiters, 
45                        std::vector<std::string>& tokens)
46   {
47     // Skip delimiters at beginning.
48     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
49     // Find first delimiter.
50     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
51     
52     while (std::string::npos != pos || std::string::npos != lastPos)
53       {
54         // Found a token, add it to the vector.
55         // SPECIFIC : REMOVE INITIAL DOT (lastPos + 1)
56         tokens.push_back(str.substr(lastPos+1, pos - lastPos));
57         // Skip delimiters.  Note the "not_of"
58         lastPos = str.find_first_not_of(delimiters, pos);
59         // Find next delimiter
60         pos = str.find_first_of(delimiters, lastPos);
61       }
62     
63     }
64   
65
66   //=====================================================================
67   class SpecificImageReader 
68   {
69   public:
70     SpecificImageReader() {}
71     virtual ~SpecificImageReader() {}
72
73     void SetName(const std::string& s) { mName = s; }
74     const std::string& GetName() const { return mName; }
75
76     virtual void PushBackExtensions(std::vector<std::string>&) {}
77
78     virtual bool CanRead(const std::string& filename) { return false; }
79     virtual vtkImageData* ReadImage(const std::string& filename) { return 0; }
80     virtual void ReadAttributes(const std::string& filename, 
81                                 std::map<std::string,std::string>& attr) {}
82
83   private:
84     std::string mName;
85   };
86   //=====================================================================
87   
88   //=====================================================================
89   class SpecificVtkReader : public SpecificImageReader          
90   {                                                                     
91   public:                                                               
92     //=====================================================================
93     SpecificVtkReader(vtkImageReader2* r, 
94                       const std::string& name = "",
95                       const std::string& extensions = "")
96       : mVTKReader(r), mExtensions(extensions)
97     {
98       if (name.size() == 0) 
99         {
100           SetName ( mVTKReader->GetDescriptiveName() );
101         }
102       else 
103         {
104           SetName ( name );
105         }
106     };
107     //=====================================================================
108     ~SpecificVtkReader()
109     {
110       mVTKReader->Delete();
111     }
112     //=====================================================================
113     bool CanRead(const std::string& filename)
114     { 
115       //      std::cout << "## Reader "<<GetName()
116       //<<" ::CanRead("<<filename<<")"
117       //                <<std::endl;
118       return (mVTKReader->CanReadFile(filename.c_str())!=0);
119     }
120     //=====================================================================
121
122     //=====================================================================
123     vtkImageData* ReadImage(const std::string& filename)
124     {
125       //      std::cout << "## Reader "<<GetName()
126       //<<" ::Read("<<filename<<")"
127       //                <<std::endl;
128       vtkImageData* im = 0;
129       try
130         {
131           mVTKReader->SetFileName(filename.c_str());
132           mVTKReader->Update();
133           im = vtkImageData::New();
134           im->ShallowCopy(mVTKReader->GetOutput());
135         }
136       catch (...)
137         {
138           if (im!=0) im->Delete();
139           im = 0;
140         }
141       return im;
142     }
143     //=====================================================================
144
145     //=====================================================================
146     void PushBackExtensions(std::vector<std::string>& v)
147     {
148       std::string ext = mExtensions;
149       if (ext.size()==0) ext = mVTKReader->GetFileExtensions ();
150       
151       IRSplitString(ext," ",v);
152     }
153     //=====================================================================
154     
155     //=====================================================================
156     void ReadAttributes(const std::string& filename, 
157                         std::map<std::string,std::string>& attr)
158     {
159       //      std::cout << "SpecificVtkReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
160       // Get image dimensions
161       // How to get the image info without loading it in vtk ?
162       mVTKReader->SetFileName(filename.c_str());
163       mVTKReader->Update(); //OpenFile();
164       int ext[6];
165       mVTKReader->GetDataExtent(ext);
166       // Columns
167       char cols[128];
168       sprintf(cols,"%i",ext[1]-ext[0]);
169       // Rows
170       char rows[128];
171       sprintf(rows,"%i",ext[3]-ext[2]);
172       // Planes 
173       char planes[128];
174       sprintf(planes,"%i",ext[5]-ext[4]);
175       
176       // 
177       std::map<std::string,std::string>::iterator i;
178       if ( (i = attr.find("Full File Name")) != attr.end())
179         {
180           boost::filesystem::path full_path(filename);
181           std::string f = full_path.leaf();
182           i->second = f;
183         }
184       if ( (i = attr.find("Columns")) != attr.end())
185         {
186           i->second = cols;
187         }
188       if ( (i = attr.find("Rows")) != attr.end())
189         {
190           i->second = rows;
191         }
192       if ( (i = attr.find("Planes")) != attr.end())
193         {
194           i->second = planes;
195         }
196     }
197     //=====================================================================
198   private:
199     vtkImageReader2* mVTKReader;
200     std::string mExtensions;
201   };
202   //=====================================================================
203  
204   //===================================================================== 
205   /*
206   void IRFillFields(DicomNode* node, 
207                   GDCM_NAME_SPACE::File* gdcmFile)
208   {
209     const DicomNodeTypeDescription::FieldDescriptionMapType& dm
210       = node->GetTypeDescription().GetFieldDescriptionMap();
211     DicomNodeTypeDescription::FieldDescriptionMapType::const_iterator i;
212     
213         
214     DicomNode::FieldValueMapType& vm = node->GetFieldValueMap();
215     for (i=dm.begin(); i!=dm.end(); ++i)
216       {
217         if ( (i->second.flags==0) && 
218              (i->second.group!=0) && 
219              (i->second.element!=0) )
220           {
221                 uint16_t gr = i->second.group;
222                 uint16_t el = i->second.element;
223
224                 std::string val = gdcmFile->GetEntryString(gr,el);
225
226             vm[i->first] = irclean(val);
227           }
228         else 
229           {
230             vm[i->first] = "";
231           }
232       }
233   }
234   */
235   //=====================================================================
236
237   //=====================================================================
238   class DicomReader : public SpecificImageReader                
239   {                                                                     
240   public:                                                               
241     //=====================================================================
242     DicomReader()
243     {
244       mReader = vtkGdcmReader::New();
245       SetName ( "Dicom" );
246     };
247     //=====================================================================
248     ~DicomReader()
249     {
250       mReader->Delete();
251     }
252     //=====================================================================
253     bool CanRead(const std::string& filename)
254     { 
255       //      std::cout << "## Reader "<<GetName()
256       //<<" ::CanRead("<<filename<<")"
257       //                <<std::endl;
258       //      return true;
259
260       
261       //      GDCM_NAME_SPACE
262       //  std::cout << "GDCM_NAME_SPACE = '" << STRINGIFY_SYMBOL(GDCM_NAME_SPACE)
263       // << "'" 
264       // <<std::endl;
265       
266       GDCM_NAME_SPACE::File* file = GDCM_NAME_SPACE::File::New();
267       file->SetLoadMode( GDCM_NAME_SPACE::LD_ALL);
268       file->SetFileName(filename.c_str());
269       file->Load();
270       bool ok = file->IsReadable();
271       file->Delete();
272       return ok;
273     }
274     //=====================================================================
275     vtkImageData* ReadImage(const std::string& filename)
276     {
277       //      std::cout << "## Reader "<<GetName()
278       //<<" ::Read("<<filename<<")"
279       //                <<std::endl;
280
281       vtkImageData* im = 0;
282       try
283         {
284           mReader->SetFileName(filename.c_str());
285           mReader->Update();
286           im = vtkImageData::New();
287           im->ShallowCopy(mReader->GetOutput());
288         }
289       catch (...)
290         {
291           if (im!=0) im->Delete();
292           im = 0;
293         }
294       return im;
295     }
296     //=====================================================================
297     void PushBackExtensions(std::vector<std::string>& v)
298     {
299       v.push_back("dcm");
300       v.push_back("");
301     }
302     //=====================================================================
303
304     //=====================================================================
305    //=====================================================================
306     void ReadAttributes(const std::string& filename, 
307                         std::map<std::string,std::string>& attr)
308     {
309       //    std::cout << "DicomReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
310       GDCM_NAME_SPACE::File* file = GDCM_NAME_SPACE::File::New();
311       file->SetLoadMode( GDCM_NAME_SPACE::LD_ALL);
312       file->SetFileName(filename.c_str());
313       file->Load();
314       if (file->IsReadable())
315         {
316           
317           std::map<std::string,std::string>::iterator i;
318           for (i=attr.begin();i!=attr.end();++i)
319             {
320               if ( i->first == "Full File Name" )
321                 {
322                   boost::filesystem::path full_path(filename);
323                   std::string f = full_path.leaf();
324                   i->second = f;
325                 }
326               else
327                 {
328                   tree::AttributeDescriptor a(i->first);
329                   uint16_t gr = a.GetGroup();
330                   uint16_t el = a.GetElement();
331                   if ( ( gr!=0 ) && ( el!=0 ) )
332                     {
333                       std::string val = file->GetEntryString(gr,el);
334                       i->second = irclean(val);
335                     }
336                 }
337             }
338         }
339       file->Delete();
340     }
341   
342
343   private:
344     vtkGdcmReader* mReader;
345   };
346   //=====================================================================
347  
348
349
350
351
352   //=====================================================================
353   ImageReader::ImageReader()
354     :   
355     mUnreadableImage(0),
356     mLastFilename("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"),
357     mLastReader(0)
358
359   {
360     //    std::cout << "#### ImageReader::ImageReader()"<<std::endl;
361     if (mUnreadableImage!=0) return;
362
363     Register(new SpecificVtkReader(vtkPNGReader::New()));
364     Register(new SpecificVtkReader(vtkTIFFReader::New()));
365     Register(new SpecificVtkReader(vtkJPEGReader::New()));
366     Register(new SpecificVtkReader(vtkBMPReader::New()));
367     Register(new SpecificVtkReader(vtkSLCReader::New()));
368     Register(new SpecificVtkReader(vtkMetaImageReader::New(),"MHD",".mhd"));
369     //   Register(new SpecificVtkReader(vtkGESignalReader::New()));
370     Register(new DicomReader);
371
372     /*
373     std::cout << "## Registered file extensions : "<<std::endl;
374     std::vector<std::string>::const_iterator i;
375     for (i=GetKnownExtensions().begin();
376          i!=GetKnownExtensions().end();
377          i++)
378       {
379         std::cout << "'"<<(*i)<<"'"<<std::endl;
380       }
381     */
382     // 
383     mUnreadableImage = vtkImageData::New();
384     int dim[3];
385     dim[0] = dim[1] = 128; 
386     dim[2] = 1; 
387     mUnreadableImage->SetDimensions ( dim );
388     mUnreadableImage->SetScalarTypeToUnsignedChar();
389     mUnreadableImage->AllocateScalars();    
390     for (int i=0;i<dim[0];i++) 
391       for (int j=0;j<dim[1];j++) 
392         mUnreadableImage->SetScalarComponentFromFloat(i,j,0,0,0);
393     for (int i=0;i<dim[0];i++) 
394       {
395         mUnreadableImage->SetScalarComponentFromFloat(i,i,0,0,255);
396         mUnreadableImage->SetScalarComponentFromFloat(dim[0]-1-i,i,0,0,255);
397       }
398
399
400     
401   }
402   //=====================================================================
403
404   //=====================================================================
405   ImageReader::~ImageReader()
406   {
407     //    std::cout << "#### ImageReader::~ImageReader()"<<std::endl;
408     std::vector<SpecificImageReader*>::iterator i;
409     for (i=mReader.begin(); i!=mReader.end(); i++)
410       {
411         //      std::cout << "#### ImageReader::UnRegister("
412         //                << (*i)->GetName()<<")"<<std::endl;
413         delete (*i);
414       }
415     mReader.clear();
416     if (mUnreadableImage!=0) 
417       {
418         mUnreadableImage->Delete();
419         mUnreadableImage = 0;
420       }
421   }
422   //=====================================================================
423
424   //=====================================================================
425   void ImageReader::Register(SpecificImageReader* r)
426   {
427     //    std::cout << "#### ImageReader::Register("<<r->GetName()<<")"<<std::endl;
428     mReader.push_back(r);
429     r->PushBackExtensions(mKnownExtensions);
430   }
431   //=====================================================================
432
433   //=====================================================================
434   // Returns true iff the file is readable
435   bool ImageReader::CanRead( const std::string& filename, 
436                              const std::string& exclude )
437   {
438     //    std::cout << "## ImageReader::CanRead("<<filename<<")"<<std::endl;
439     bool ok = false;
440     std::vector<SpecificImageReader*>::iterator i;
441     for (i=mReader.begin(); i!=mReader.end(); i++)
442       {
443         if ((*i)->GetName()==exclude) continue;
444         ok = (*i)->CanRead(filename);
445         if (ok) 
446           {
447             mLastFilename = filename;
448             mLastReader = *i;
449             break;
450           }
451       }
452     return ok;
453   }
454   //=====================================================================
455
456   //=====================================================================
457   // Reads the file (CanRead must be called before : no test here)
458   vtkImageData*  ImageReader::ReadImage( const std::string& filename, 
459                                          const std::string& exclude )
460   {
461     //    std::cout << "## ImageReader::Read("<<filename<<")"<<std::endl;
462     if (mLastFilename!=filename)
463       {
464         if (!CanRead(filename,exclude)) 
465           { 
466             //      std::cout << "  -- Cannot read image "<<std::endl;
467             vtkImageData* im = vtkImageData::New();
468             im->ShallowCopy(mUnreadableImage);
469             return im;
470           }
471       }
472     vtkImageData* i = mLastReader->ReadImage(mLastFilename);
473     //    std::cout << "i="<<i<<std::endl;
474     if (i==0) 
475       {
476         //      std::cout << "i=UNREAD"<<i<<std::endl;
477         i = vtkImageData::New();
478         i->ShallowCopy(mUnreadableImage);
479       }
480     //    std::cout << "i="<<i<<std::endl;
481     return i;
482   }
483   //=====================================================================
484
485
486   //=====================================================================
487    void ImageReader::ReadAttributes(const std::string& filename, 
488                                     std::map<std::string,std::string>& attr)
489    {
490      // std::cout << "ImageReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
491     //    std::cout << "## ImageReader::Read("<<filename<<")"<<std::endl;
492     if (mLastFilename!=filename)
493       {
494         if (!CanRead(filename)) 
495           { 
496             return;
497           }
498       }
499     mLastReader->ReadAttributes(mLastFilename,attr);
500    }
501   //=====================================================================
502
503
504
505 } // namespace creaImageIO