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