]> Creatis software - creaImageIO.git/blob - src/creaImageIOImageReader.cpp
no message
[creaImageIO.git] / src / creaImageIOImageReader.cpp
1 #include <creaImageIOImageReader.h>
2 //#include <creaImageIOUtilities.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   // Static members
67   /*
68   std::vector<SpecificImageReader*> ImageReader::mReader;
69   std::vector<std::string>ImageReader::mKnownExtensions;
70   vtkImageData* ImageReader::mUnreadableImage = 0;
71   std::string ImageReader::mLastFilename("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
72   SpecificImageReader* ImageReader::mLastReader = 0;
73   //=====================================================================  
74   // Global instance : automatic init / destr
75   ImageReader GlobalImageReader;
76   //=====================================================================  
77   */
78
79   //=====================================================================
80   class SpecificImageReader 
81   {
82   public:
83     SpecificImageReader() {}
84     virtual ~SpecificImageReader() {}
85     void SetName(const std::string& s) { mName = s; }
86     const std::string& GetName() const { return mName; }
87     virtual bool CanRead(const std::string& filename) { return false; }
88     virtual vtkImageData* Read(const std::string& filename) { return 0; }
89     virtual void PushBackExtensions(std::vector<std::string>&) {}
90     virtual void ReadDicomInfo(const std::string& filename, 
91                                DicomNode* image) {}
92   private:
93     std::string mName;
94   };
95   //=====================================================================
96   
97   //=====================================================================
98   class SpecificVtkReader : public SpecificImageReader          
99   {                                                                     
100   public:                                                               
101     SpecificVtkReader(vtkImageReader2* r, 
102                       const std::string& name = "",
103                       const std::string& extensions = "")
104       : mVTKReader(r), mExtensions(extensions)
105     {
106       if (name.size() == 0) 
107         {
108           SetName ( mVTKReader->GetDescriptiveName() );
109         }
110       else 
111         {
112           SetName ( name );
113         }
114     };
115     ~SpecificVtkReader()
116     {
117       mVTKReader->Delete();
118     }
119     bool CanRead(const std::string& filename)
120     { 
121       //      std::cout << "## Reader "<<GetName()
122       //<<" ::CanRead("<<filename<<")"
123       //                <<std::endl;
124       return (mVTKReader->CanReadFile(filename.c_str())!=0);
125     }
126     vtkImageData* Read(const std::string& filename)
127     {
128       //      std::cout << "## Reader "<<GetName()
129       //<<" ::Read("<<filename<<")"
130       //                <<std::endl;
131       vtkImageData* im = 0;
132       try
133         {
134           mVTKReader->SetFileName(filename.c_str());
135           mVTKReader->Update();
136           im = vtkImageData::New();
137           im->ShallowCopy(mVTKReader->GetOutput());
138         }
139       catch (...)
140         {
141           if (im!=0) im->Delete();
142           im = 0;
143         }
144       return im;
145     }
146
147     void PushBackExtensions(std::vector<std::string>& v)
148     {
149       std::string ext = mExtensions;
150       if (ext.size()==0) ext = mVTKReader->GetFileExtensions ();
151       
152       IRSplitString(ext," ",v);
153     }
154      
155     void ReadDicomInfo(const std::string& filename, 
156                        DicomNode* image) 
157     {
158       //      std::cout << "SpecificVtkReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
159       boost::filesystem::path full_path(filename);
160       std::string f = full_path.leaf();
161         //Utilities::GetFileName(filename));
162       // file name 
163       image->SetFieldValue("A0004_1500",irclean(f));
164       // Does not work : 
165       // How to get the image info without loading it in vtk ?
166       
167       mVTKReader->SetFileName(filename.c_str());
168       mVTKReader->Update(); //OpenFile();
169       int ext[6];
170       mVTKReader->GetDataExtent(ext);
171       // Columns
172       char str[128];
173       sprintf(str,"%i",ext[1]-ext[0]);
174       //      std::cout << "col="<<str<<std::endl;
175       image->SetFieldValue("A0028_0011",str);
176       // Rows
177       sprintf(str,"%i",ext[3]-ext[2]);
178       //      std::cout << "row="<<str<<std::endl;
179       image->SetFieldValue("A0028_0010",str);
180       // Planes == frames
181       sprintf(str,"%i",ext[5]-ext[4]);
182       //      std::cout << "frames="<<str<<std::endl;
183       image->SetFieldValue("A0028_0008",str);
184             
185     }
186   private:
187     vtkImageReader2* mVTKReader;
188     std::string mExtensions;
189   };
190   //=====================================================================
191  
192   //===================================================================== 
193   void IRFillFields(DicomNode* node, 
194                   GDCM_NAME_SPACE::File* gdcmFile)
195   {
196     const DicomNodeTypeDescription::FieldDescriptionMapType& dm
197       = node->GetTypeDescription().GetFieldDescriptionMap();
198     DicomNodeTypeDescription::FieldDescriptionMapType::const_iterator i;
199     
200         
201     DicomNode::FieldValueMapType& vm = node->GetFieldValueMap();
202     for (i=dm.begin(); i!=dm.end(); ++i)
203       {
204         if ( (i->second.flags==0) && 
205              (i->second.group!=0) && 
206              (i->second.element!=0) )
207           {
208                 uint16_t gr = i->second.group;
209                 uint16_t el = i->second.element;
210
211                 std::string val = gdcmFile->GetEntryString(gr,el);
212
213             vm[i->first] = irclean(val);
214           }
215         else 
216           {
217             vm[i->first] = "";
218           }
219       }
220   }
221   //=====================================================================
222
223   //=====================================================================
224   class DicomReader : public SpecificImageReader                
225   {                                                                     
226   public:                                                               
227     DicomReader()
228     {
229       mReader = vtkGdcmReader::New();
230       SetName ( "Dicom" );
231     };
232     ~DicomReader()
233     {
234       mReader->Delete();
235     }
236     bool CanRead(const std::string& filename)
237     { 
238       //      std::cout << "## Reader "<<GetName()
239       //<<" ::CanRead("<<filename<<")"
240       //                <<std::endl;
241       //      return true;
242
243       
244       //      GDCM_NAME_SPACE
245       //  std::cout << "GDCM_NAME_SPACE = '" << STRINGIFY_SYMBOL(GDCM_NAME_SPACE)
246       // << "'" 
247       // <<std::endl;
248       
249       GDCM_NAME_SPACE::File* file = GDCM_NAME_SPACE::File::New();
250       file->SetLoadMode( GDCM_NAME_SPACE::LD_ALL);
251       file->SetFileName(filename.c_str());
252       file->Load();
253       bool ok = file->IsReadable();
254       file->Delete();
255       return ok;
256     }
257     vtkImageData* Read(const std::string& filename)
258     {
259       //      std::cout << "## Reader "<<GetName()
260       //<<" ::Read("<<filename<<")"
261       //                <<std::endl;
262
263       vtkImageData* im = 0;
264       try
265         {
266           mReader->SetFileName(filename.c_str());
267           mReader->Update();
268           im = vtkImageData::New();
269           im->ShallowCopy(mReader->GetOutput());
270         }
271       catch (...)
272         {
273           if (im!=0) im->Delete();
274           im = 0;
275         }
276       return im;
277     }
278
279     void PushBackExtensions(std::vector<std::string>& v)
280     {
281       v.push_back("dcm");
282       v.push_back("");
283     }
284
285     void ReadDicomInfo(const std::string& filename,
286                        DicomNode* image)
287     { 
288       //    std::cout << "DicomReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
289       GDCM_NAME_SPACE::File* file = GDCM_NAME_SPACE::File::New();
290       file->SetLoadMode( GDCM_NAME_SPACE::LD_ALL);
291       file->SetFileName(filename.c_str());
292       file->Load();
293       if (file->IsReadable())
294         {
295           
296           DicomNode* cur = image;
297           do 
298             {
299               IRFillFields(cur,file);
300               cur = cur->GetParent();
301             }
302           while (cur);
303           // File name and full file name
304           image->SetFieldValue("FullFileName",filename);
305           
306           boost::filesystem::path full_path(filename);
307           
308           image->SetFieldValue("A0004_1500",full_path.leaf());
309                                //Utilities::GetFileName(filename));
310         }
311       file->Delete();
312     }
313   
314
315   private:
316     vtkGdcmReader* mReader;
317   };
318   //=====================================================================
319  
320
321
322
323
324   //=====================================================================
325   ImageReader::ImageReader()
326     :   
327     mUnreadableImage(0),
328     mLastFilename("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"),
329     mLastReader(0)
330
331   {
332     //    std::cout << "#### ImageReader::ImageReader()"<<std::endl;
333     if (mUnreadableImage!=0) return;
334
335     Register(new SpecificVtkReader(vtkPNGReader::New()));
336     Register(new SpecificVtkReader(vtkTIFFReader::New()));
337     Register(new SpecificVtkReader(vtkJPEGReader::New()));
338     Register(new SpecificVtkReader(vtkBMPReader::New()));
339     Register(new SpecificVtkReader(vtkSLCReader::New()));
340     Register(new SpecificVtkReader(vtkMetaImageReader::New(),"MHD",".mhd"));
341     //   Register(new SpecificVtkReader(vtkGESignalReader::New()));
342     Register(new DicomReader);
343
344     /*
345     std::cout << "## Registered file extensions : "<<std::endl;
346     std::vector<std::string>::const_iterator i;
347     for (i=GetKnownExtensions().begin();
348          i!=GetKnownExtensions().end();
349          i++)
350       {
351         std::cout << "'"<<(*i)<<"'"<<std::endl;
352       }
353     */
354     // 
355     mUnreadableImage = vtkImageData::New();
356     int dim[3];
357     dim[0] = dim[1] = 128; 
358     dim[2] = 1; 
359     mUnreadableImage->SetDimensions ( dim );
360     mUnreadableImage->SetScalarTypeToUnsignedChar();
361     mUnreadableImage->AllocateScalars();    
362     for (int i=0;i<dim[0];i++) 
363       for (int j=0;j<dim[1];j++) 
364         mUnreadableImage->SetScalarComponentFromFloat(i,j,0,0,0);
365     for (int i=0;i<dim[0];i++) 
366       {
367         mUnreadableImage->SetScalarComponentFromFloat(i,i,0,0,255);
368         mUnreadableImage->SetScalarComponentFromFloat(dim[0]-1-i,i,0,0,255);
369       }
370
371
372     
373   }
374   //=====================================================================
375
376   //=====================================================================
377   ImageReader::~ImageReader()
378   {
379     //    std::cout << "#### ImageReader::~ImageReader()"<<std::endl;
380     std::vector<SpecificImageReader*>::iterator i;
381     for (i=mReader.begin(); i!=mReader.end(); i++)
382       {
383         //      std::cout << "#### ImageReader::UnRegister("
384         //                << (*i)->GetName()<<")"<<std::endl;
385         delete (*i);
386       }
387     mReader.clear();
388     if (mUnreadableImage!=0) 
389       {
390         mUnreadableImage->Delete();
391         mUnreadableImage = 0;
392       }
393   }
394   //=====================================================================
395
396   //=====================================================================
397   void ImageReader::Register(SpecificImageReader* r)
398   {
399     //    std::cout << "#### ImageReader::Register("<<r->GetName()<<")"<<std::endl;
400     mReader.push_back(r);
401     r->PushBackExtensions(mKnownExtensions);
402   }
403   //=====================================================================
404
405   //=====================================================================
406   // Returns true iff the file is readable
407   bool ImageReader::CanRead( const std::string& filename, 
408                              const std::string& exclude )
409   {
410     //    std::cout << "## ImageReader::CanRead("<<filename<<")"<<std::endl;
411     bool ok = false;
412     std::vector<SpecificImageReader*>::iterator i;
413     for (i=mReader.begin(); i!=mReader.end(); i++)
414       {
415         if ((*i)->GetName()==exclude) continue;
416         ok = (*i)->CanRead(filename);
417         if (ok) 
418           {
419             mLastFilename = filename;
420             mLastReader = *i;
421             break;
422           }
423       }
424     return ok;
425   }
426   //=====================================================================
427
428   //=====================================================================
429   // Reads the file (CanRead must be called before : no test here)
430   vtkImageData*  ImageReader::Read( const std::string& filename, 
431                                     const std::string& exclude )
432   {
433     //    std::cout << "## ImageReader::Read("<<filename<<")"<<std::endl;
434     if (mLastFilename!=filename)
435       {
436         if (!CanRead(filename,exclude)) 
437           { 
438             //      std::cout << "  -- Cannot read image "<<std::endl;
439             vtkImageData* im = vtkImageData::New();
440             im->ShallowCopy(mUnreadableImage);
441             return im;
442           }
443       }
444     vtkImageData* i = mLastReader->Read(mLastFilename);
445     //    std::cout << "i="<<i<<std::endl;
446     if (i==0) 
447       {
448         //      std::cout << "i=UNREAD"<<i<<std::endl;
449         i = vtkImageData::New();
450         i->ShallowCopy(mUnreadableImage);
451       }
452     //    std::cout << "i="<<i<<std::endl;
453     return i;
454   }
455   //=====================================================================
456
457
458   //=====================================================================
459    void ImageReader::ReadDicomInfo(const std::string& filename, 
460                                    DicomNode* image)
461    {
462      // std::cout << "ImageReader::ReadDicomInfo '"<<filename<<"'"<<std::endl;
463     //    std::cout << "## ImageReader::Read("<<filename<<")"<<std::endl;
464     if (mLastFilename!=filename)
465       {
466         if (!CanRead(filename)) 
467           { 
468             return;
469           }
470       }
471     mLastReader->ReadDicomInfo(mLastFilename,image);
472    }
473   //=====================================================================
474
475
476
477 } // namespace creaImageIO