]> Creatis software - creaImageIO.git/blob - src2/creaImageIOGimmickView.cpp
Added GetImages to obtain images from a given file list.
[creaImageIO.git] / src2 / creaImageIOGimmickView.cpp
1 #include <creaImageIOGimmickView.h>
2 #include <creaImageIOSystem.h>
3
4 #include "boost/filesystem.hpp"
5
6 namespace fs = boost::filesystem;
7
8 namespace creaImageIO
9 {
10
11         ///Class used to represent the actual state of the image selected and to perform comparisons on its values
12   class ImageExtent
13   {
14   public:
15     ImageExtent(const std::string& x, const std::string& y, const std::string& z, const std::string& t)
16         {
17                  sscanf(x.c_str(),"%d",&mExtent[0]);
18                  sscanf(y.c_str(),"%d",&mExtent[1]);
19                  sscanf(z.c_str(),"%d",&mExtent[2]);
20                  sscanf(t.c_str(),"%d",&mExtent[3]);
21                  if(x==""){mExtent[0]=1;}
22              if(y==""){mExtent[1]=1;}
23              if(z==""){mExtent[2]=1;}
24                  if(t==""){mExtent[3]=1;}
25
26                  if (mExtent[3]>1) mDim=4;
27                  else if (mExtent[2]>1) mDim=3;
28              else if (mExtent[1]>1) mDim=2;
29              else if (mExtent[0]>1) mDim=1;
30                  else mDim=0;
31         }
32         
33
34         ///Clears the extent
35     void Clear() { mExtent[0] = mExtent[1] = mExtent[2] = mExtent[3] = 1; }
36
37         ///Returns true if the two extents are compatible
38     bool IsCompatible( const ImageExtent& );
39
40         ///Adds the extent passed as a parameter to the current extent
41     void Add ( const ImageExtent& );
42                 
43         ///Returns the ieth position of the extent
44     int Get(int i) { return mExtent[i]; }
45     
46         ///Returns the dimension of the current image
47     void SetDimension(int dim) { mDim=dim; }
48
49         ///Returns the dimension of the current image
50     int GetDimension() { return mDim; }
51
52   private:
53     int mExtent[4];
54     int mDim;
55   };
56
57   //======================================================================
58
59   //======================================================================
60   // CTor
61   GimmickView::GimmickView(Gimmick* gimmick, int threads)
62     : mGimmick(gimmick),
63           mReader(threads)
64   {
65     GimmickDebugMessage(1,"GimmickView::GimmickView"
66                         <<std::endl);
67         // Anciently started the threads ...
68     // Threads now automatically start at first image request
69     //mReader.Start();
70         
71   }
72   //======================================================================
73
74   //======================================================================
75   /// Destructor
76   GimmickView::~GimmickView()
77   {
78     GimmickDebugMessage(1,"GimmickView::~GimmickView"
79                         <<std::endl);
80   }
81    //======================================================================
82  
83   //======================================================================  
84   /// Initializes the view : 
85   /// Creates the TreeViews for all the TreeHandler of the Controller
86   /// 
87   void GimmickView::Initialize()
88   {
89         mImageExtent=0;
90         mReaderStarted=false;
91   }
92   //======================================================================
93   
94   //======================================================================
95   /// Finalize 
96   void GimmickView::Finalize()
97   {
98   }
99
100   //======================================================================
101
102   //======================================================================
103   /// Create the tree views 
104   void GimmickView::CreateTreeViews()
105   {
106     GimmickMessage(2,"Creating the tree views"<<std::endl);
107     Gimmick::TreeHandlerMapType::const_iterator i;
108     for (i = mGimmick->GetTreeHandlerMap().begin();
109          i!= mGimmick->GetTreeHandlerMap().end();
110          ++i)
111       {
112         this->CreateTreeView(i->second);
113       }
114   }
115   //======================================================================
116
117   //======================================================================
118   /// Updates the TreeView of given name from level l to bottom
119   /// (calls the virtual method TreeView::Update())
120   void GimmickView::UpdateTreeViewLevel(const std::string& t, int l)
121   {
122     TreeViewMapType::iterator i;
123     i = GetTreeViewMap().find(t);
124     if ( i == GetTreeViewMap().end() )
125       {
126         GimmickError("INTERNAL ERROR : GimmickView::UpdateTreeView : '"
127                      <<t<<"' is not in TreeViewMap");
128       }
129     i->second->UpdateLevel(l);    
130   }
131   //======================================================================
132   /// Clears the status and begins a new selection process
133   void GimmickView::ResetExtent()
134   {
135           if(mImageExtent!=0)
136           {
137           mImageExtent=0;
138           }
139           valid=true;
140   }
141
142
143   //======================================================================
144   
145   //======================================================================
146   bool ImageExtent::IsCompatible(const ImageExtent& ie)
147   {
148           bool compatible=true;
149           ImageExtent * extent= (ImageExtent*)&ie;
150           if((*extent).Get(0)!=Get(0)
151                  || (*extent).Get(1)!=Get(1))
152           {
153                   compatible=false;
154           }
155           return compatible;
156   }
157
158   //======================================================================
159   
160   //======================================================================
161   void ImageExtent::Add(const ImageExtent& ie)
162   {
163           ImageExtent * extent= (ImageExtent*)&ie;
164           mExtent[2]+=(*extent).Get(2);
165           SetDimension(3);
166   }
167
168   //======================================================================
169   ///Validates the dimension compliance of the images with the maximum and 
170   ///minimum given, and between their sizes
171   bool GimmickView::ValidateSelected (tree::Node* sel, int min_dim, int max_dim)
172   {
173         GimmickDebugMessage(2,"Validating selected"<<std::endl);
174         std::string mMessage;
175         
176         if(sel==0)
177         {
178                 mMessage="Cannot have 0 images selected!";
179                 valid=false;
180         }
181         else
182         {
183         ImageExtent* ie=new ImageExtent((*sel).GetAttribute("D0028_0010"),
184                                                  (*sel).GetAttribute("D0028_0011"),
185                                                                          (*sel).GetAttribute("D0028_0012"), 
186                                                                          "");
187         if(mImageExtent==0)
188         {
189                 mImageExtent=ie;
190                 if((mImageExtent->Get(min_dim-1)<2)||(mImageExtent->Get(max_dim)>1))
191                 {
192                         valid=false;
193                 }
194                 else
195                 {
196                         std::stringstream out;
197                         out << mImageExtent->GetDimension() << "D image " << mImageExtent->Get(0) << "x"<< mImageExtent->Get(1) << "x"<< mImageExtent->Get(2) <<" selected";
198                 mMessage = out.str();
199                         mImageExtent->SetDimension(2);
200                         valid=true;
201                 }
202         }
203         else
204         {
205                 if(mImageExtent->IsCompatible(*ie))
206                 {
207                         if(mImageExtent->GetDimension()==max_dim && mImageExtent->Get(max_dim)>2)
208                         {
209                                 std::stringstream out;
210                                 out<<"Cannot add this image to selection : would result in a "<<mImageExtent->GetDimension()+1<<"D image!";
211                                 mMessage=out.str();
212                                 valid=false;
213                         }
214                         else if(max_dim<3)
215                         {
216                                 std::stringstream out;
217                                 out<<"Selecting "<<mImageExtent->GetDimension()<<"D images is not allowed !";
218                                 mMessage=out.str();
219                                 valid=false;
220                         }
221                         else if(min_dim==3 && (ie->Get(2)+mImageExtent->Get(2))<2)
222                         {
223                                 std::stringstream out;
224                                 out << "Cannot build the selection as it would result in a ";
225                                 out << mImageExtent->GetDimension();
226                                 out << "D image, and the minimum is ";
227                                 out << min_dim;
228                                 out << "D!";
229                                 mMessage=out.str();
230                                 valid=false;
231                         }
232                         else
233                         {
234             mImageExtent->Add(*ie);
235                         std::stringstream out;
236                         out << mImageExtent->GetDimension() << "D image " << mImageExtent->Get(0) << "x"<< mImageExtent->Get(1) << "x"<< mImageExtent->Get(2) <<" selected";
237                 mMessage = out.str();
238                         }
239                         
240                 }
241                 else
242                 {
243                         mMessage="The selected images are not compatible.";
244                         valid=false;
245                 }
246         }
247         }
248
249         
250         mValidationSignal(valid);
251         SetMessage(mMessage);
252         return valid;
253   }
254
255 //======================================================================
256
257    //======================================================================
258   ///Reads Images (Non Threaded)
259   void GimmickView::ReadImagesNotThreaded(std::vector<vtkImageData*>& s,std::vector<std::string> im, int dimension)
260   {
261           
262         // Create the output data
263         if (im.size()==1) 
264       {
265                   
266                 // Only one image : give it
267                 vtkImageData* out = vtkImageData::New();
268                 GimmickDebugMessage(3, "State Check: Full Filename: "
269                                                 <<im.front()
270                                                 <<std::endl);
271                 out->ShallowCopy(mReader.GetImage(im.front()));
272                 s.push_back( out );
273       }
274           
275     else if (im.size()>1)
276       {
277         vtkImageData* first = mReader.GetImage( im.front());
278         if (dimension==2) 
279           {     
280             // n2D to 3D
281             vtkImageData* out = vtkImageData::New();
282             out->CopyStructure(first);  
283             out->SetScalarType(first->GetScalarType());
284             int ext[6];
285             first->GetExtent(ext);
286             ext[5] = im.size();
287             out->SetExtent(ext);
288             // LG : TODO : Z Spacing  ?
289             
290             out->AllocateScalars();
291             
292             //first->Print(std::cout);
293             //      out->Print(std::cout);
294             
295             int dim[3];
296             first->GetDimensions(dim);
297             unsigned long imsize = 
298               ( (unsigned long)first->GetScalarPointer(0,1,0)
299                 - (unsigned long)first->GetScalarPointer(0,0,0))
300               *dim[1];
301
302             int slice = 0;
303                 std::vector<std::string>::iterator it;
304            for (it=im.begin(); it!=im.end(); ++it) 
305               {
306                 //std::cout << "copying slice "<<slice <<std::endl;
307                           vtkImageData* cur = mReader.GetImage( (*it));
308                 
309                 void* src = cur->GetScalarPointer(0,0,0);
310                 void* dst = out->GetScalarPointer(0,0,slice);
311                 //              std::cout << "src="<<src<<std::endl;
312                 //              std::cout << "dst="<<dst<<std::endl;
313                 //              std::cout << "siz="<<imsize<<std::endl;
314                 memcpy(dst,src,imsize);
315
316                 slice++;
317               }
318             s.push_back(out);
319           }
320         else 
321           {
322             // n3D
323                   std::vector<std::string>::iterator it;
324             for (it=im.begin(); it!=im.end(); ++it) 
325               {
326                 vtkImageData* out = vtkImageData::New();
327                 out->ShallowCopy(mReader.GetImage(*it));
328                 s.push_back(out);
329               }
330           }
331       }
332         
333   }
334   //======================================================================
335
336   //======================================================================
337   ///Requests the reading of an image
338   void GimmickView::RequestReading(tree::Node* n, 
339                                    int prio, int selection_index, ImagePointerHolder *p)
340   {
341           if(!mReaderStarted)
342           {
343                 mReader.Start();
344                 mReaderStarted=true;
345           }
346     ImageEventType t(n,selection_index, p);
347     mImageEventMap[n->GetAttribute("FullFileName")] = t;    
348     mReader.Request(this,n->GetAttribute("FullFileName"),prio);
349   }
350   //======================================================================
351
352   //======================================================================
353   void GimmickView::
354   OnMultiThreadImageReaderEvent(const std::string& filename,
355                                 MultiThreadImageReaderUser::EventType e,
356                                 vtkImageData* image)
357   {
358     GimmickDebugMessage(7,
359                         "MultiThreadImageReader event : "<<e<<std::endl);
360         if (e==ImageLoaded)
361         {
362     if (filename.size()==0)
363       {
364                   //What to do in this case?
365                   /*
366                 GimmickDebugMessage(5,
367                                         "Pushing unknown image in queue"
368                                         <<std::endl);
369                 mImageEventQueue.push_back(ImageEventType(image));*/
370                 return;
371       }
372     ImageEventTypeMap::iterator i;
373     i = mImageEventMap.find(filename);
374     if (i!=mImageEventMap.end())
375       {
376                 GimmickDebugMessage(5,
377                                         "Putting image of file '"<<filename<<"' on pointer"
378                                         <<std::endl);
379                 ImageEventType ie(i->second);
380                 ie.image = image;
381                 ie.pointerHolder->Set(ie.image);
382                 //mImageEventMap.erase(i);
383       }
384         }
385         else if (e==Error)
386         {
387                 std::string mess="ERROR: MultiThreadImageReader: Cannot read image in file ";
388                 mess+=filename;
389                 mess+="\n";
390                 GimmickMessage(1,mess);
391                 ImageEventTypeMap::iterator i;
392                 i = mImageEventMap.find(filename);
393                 if (i!=mImageEventMap.end())
394                 {
395                 ImageEventType ie(i->second);
396                 ie.image = image;
397                 ie.pointerHolder->Set(GetDefaultImage());
398                 //mImageEventMap.erase(i);
399                 }
400         }
401
402         else if (e==ImageUnloaded)
403         {
404                 std::string mess="Unloaded image in file ";
405                 mess+=filename;
406                 mess+="\n";
407                 GimmickMessage(1,mess);
408                                 ImageEventTypeMap::iterator i;
409                 i = mImageEventMap.find(filename);
410                 if (i!=mImageEventMap.end())
411                 {
412                 ImageEventType ie(i->second);
413                 ie.image = image;
414                 ie.pointerHolder->Set(GetDefaultImage());
415                 //mImageEventMap.erase(i);
416                 }
417
418         }
419   }
420
421   //====================================================================
422
423   //====================================================================
424   void GimmickView::ConnectValidationObserver(ValidationCallbackType callback)
425   {
426     mValidationSignal.connect(callback);
427   }
428           
429   
430 } // EO namespace creaImageIO
431
432