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