]> Creatis software - creaImageIO.git/blob - src2/creaImageIOGimmickView.cpp
16ad8ff9ae8926e23b522ab9ad520810ce983808
[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   }
91   //======================================================================
92   
93   //======================================================================
94   /// Finalize 
95   void GimmickView::Finalize()
96   {
97   }
98
99   //======================================================================
100
101   //======================================================================
102   /// Create the tree views 
103   void GimmickView::CreateTreeViews()
104   {
105     GimmickMessage(2,"Creating the tree views"<<std::endl);
106     Gimmick::TreeHandlerMapType::const_iterator i;
107     for (i = mGimmick->GetTreeHandlerMap().begin();
108          i!= mGimmick->GetTreeHandlerMap().end();
109          ++i)
110       {
111         this->CreateTreeView(i->second);
112       }
113   }
114   //======================================================================
115
116   //======================================================================
117   /// Updates the TreeView of given name from level l to bottom
118   /// (calls the virtual method TreeView::Update())
119   void GimmickView::UpdateTreeViewLevel(const std::string& t, int l)
120   {
121     TreeViewMapType::iterator i;
122     i = GetTreeViewMap().find(t);
123     if ( i == GetTreeViewMap().end() )
124       {
125         GimmickError("INTERNAL ERROR : GimmickView::UpdateTreeView : '"
126                      <<t<<"' is not in TreeViewMap");
127       }
128     i->second->UpdateLevel(l);    
129   }
130   //======================================================================
131   /// Clears the status and begins a new selection process
132   void GimmickView::ResetExtent()
133   {
134           if(mImageExtent!=0)
135           {
136           mImageExtent=0;
137           }
138           valid=true;
139   }
140
141
142   //======================================================================
143   
144   //======================================================================
145   bool ImageExtent::IsCompatible(const ImageExtent& ie)
146   {
147           bool compatible=true;
148           ImageExtent * extent= (ImageExtent*)&ie;
149           if((*extent).Get(0)!=Get(0)
150                  || (*extent).Get(1)!=Get(1))
151           {
152                   compatible=false;
153           }
154           return compatible;
155   }
156
157   //======================================================================
158   
159   //======================================================================
160   void ImageExtent::Add(const ImageExtent& ie)
161   {
162           ImageExtent * extent= (ImageExtent*)&ie;
163           mExtent[2]+=(*extent).Get(2);
164           SetDimension(3);
165   }
166
167   //======================================================================
168   ///Validates the dimension compliance of the images with the maximum and 
169   ///minimum given, and between their sizes
170   bool GimmickView::ValidateSelected (tree::Node* sel, int min_dim, int max_dim)
171   {
172         GimmickDebugMessage(2,"Validating selected"<<std::endl);
173         std::string mMessage;
174         
175         if(sel==0)
176         {
177                 mMessage="Cannot have 0 images selected!";
178                 valid=false;
179         }
180         else
181         {
182         ImageExtent* ie=new ImageExtent((*sel).GetAttribute("D0028_0010"),
183                                                  (*sel).GetAttribute("D0028_0011"),
184                                                                          (*sel).GetAttribute("D0028_0012"), 
185                                                                          "");
186         if(mImageExtent==0)
187         {
188                 mImageExtent=ie;
189                 if((mImageExtent->Get(min_dim-1)<2)||(mImageExtent->Get(max_dim)>1))
190                 {
191                         valid=false;
192                 }
193                 else
194                 {
195                         std::stringstream out;
196                         out << mImageExtent->GetDimension() << "D image " << mImageExtent->Get(0) << "x"<< mImageExtent->Get(1) << "x"<< mImageExtent->Get(2) <<" selected";
197                 mMessage = out.str();
198                         mImageExtent->SetDimension(2);
199                         valid=true;
200                 }
201         }
202         else
203         {
204                 if(mImageExtent->IsCompatible(*ie))
205                 {
206                         if(mImageExtent->GetDimension()==max_dim && mImageExtent->Get(max_dim)>2)
207                         {
208                                 std::stringstream out;
209                                 out<<"Cannot add this image to selection : would result in a "<<mImageExtent->GetDimension()+1<<"D image!";
210                                 mMessage=out.str();
211                                 valid=false;
212                         }
213                         else if(max_dim<3)
214                         {
215                                 std::stringstream out;
216                                 out<<"Selecting "<<mImageExtent->GetDimension()<<"D images is not allowed !";
217                                 mMessage=out.str();
218                                 valid=false;
219                         }
220                         else if(min_dim==3 && (ie->Get(2)+mImageExtent->Get(2))<2)
221                         {
222                                 std::stringstream out;
223                                 out << "Cannot build the selection as it would result in a ";
224                                 out << mImageExtent->GetDimension();
225                                 out << "D image, and the minimum is ";
226                                 out << min_dim;
227                                 out << "D!";
228                                 mMessage=out.str();
229                                 valid=false;
230                         }
231                         else
232                         {
233             mImageExtent->Add(*ie);
234                         std::stringstream out;
235                         out << mImageExtent->GetDimension() << "D image " << mImageExtent->Get(0) << "x"<< mImageExtent->Get(1) << "x"<< mImageExtent->Get(2) <<" selected";
236                 mMessage = out.str();
237                         }
238                         
239                 }
240                 else
241                 {
242                         mMessage="The selected images are not compatible.";
243                         valid=false;
244                 }
245         }
246         }
247
248         
249         mValidationSignal(valid);
250         SetMessage(mMessage);
251         return valid;
252   }
253
254 //======================================================================
255
256    //======================================================================
257   ///Reads Images (Non Threaded)
258   void GimmickView::ReadImagesNotThreaded(std::vector<vtkImageData*>& s,std::vector<tree::Node*> im, int dimension)
259   {
260           
261         // Create the output data
262         if (im.size()==1) 
263       {
264                   
265                 // Only one image : give it
266                 vtkImageData* out = vtkImageData::New();
267                 GimmickMessage(1, "State Check: Full Filename: "
268                                                 <<im.front()->GetAttribute("FullFileName")
269                                                 <<std::endl);
270                 out->ShallowCopy(mReader.GetImage(im.front()->GetAttribute("FullFileName")));
271                 s.push_back( out );
272       }
273           
274     else if (im.size()>1)
275       {
276         vtkImageData* first = mReader.GetImage( im.front()->GetAttribute("FullFileName"));
277         if (dimension==2) 
278           {     
279             // n2D to 3D
280             vtkImageData* out = vtkImageData::New();
281             out->CopyStructure(first);  
282             out->SetScalarType(first->GetScalarType());
283             int ext[6];
284             first->GetExtent(ext);
285             ext[5] = im.size();
286             out->SetExtent(ext);
287             // LG : TODO : Z Spacing  ?
288             
289             out->AllocateScalars();
290             
291             //first->Print(std::cout);
292             //      out->Print(std::cout);
293             
294             int dim[3];
295             first->GetDimensions(dim);
296             unsigned long imsize = 
297               ( (unsigned long)first->GetScalarPointer(0,1,0)
298                 - (unsigned long)first->GetScalarPointer(0,0,0))
299               *dim[1];
300
301             int slice = 0;
302                 std::vector<tree::Node*>::iterator it;
303             for (it=im.begin(); it!=im.end(); ++it) 
304               {
305                 //std::cout << "copying slice "<<slice <<std::endl;
306                           vtkImageData* cur = mReader.GetImage( (*it)->GetAttribute("FullFileName"));
307                 
308                 void* src = cur->GetScalarPointer(0,0,0);
309                 void* dst = out->GetScalarPointer(0,0,slice);
310                 //              std::cout << "src="<<src<<std::endl;
311                 //              std::cout << "dst="<<dst<<std::endl;
312                 //              std::cout << "siz="<<imsize<<std::endl;
313                 memcpy(dst,src,imsize);
314
315                 slice++;
316               }
317             s.push_back(out);
318           }
319         else 
320           {
321             // n3D
322                   std::vector<tree::Node*>::iterator it;
323             for (it=im.begin(); it!=im.end(); ++it) 
324               {
325                 vtkImageData* out = vtkImageData::New();
326                 out->ShallowCopy(mReader.GetImage((*it)->GetAttribute("FullFileName")));
327                 s.push_back(out);
328               }
329           }
330       }
331         
332   }
333   //======================================================================
334
335   //======================================================================
336   ///Requests the reading of an image
337   void GimmickView::RequestReading(tree::Node* n, 
338                                    int prio, int selection_index, ImagePointerHolder *p)
339   {
340         mReader.Start();
341     ImageEventType t(n,selection_index, p);
342     mImageEventMap[n->GetAttribute("FullFileName")] = t;    
343     mReader.Request(this,n->GetAttribute("FullFileName"),prio);
344   }
345   //======================================================================
346
347   //======================================================================
348   void GimmickView::
349   OnMultiThreadImageReaderEvent(const std::string& filename,
350                                 MultiThreadImageReaderUser::EventType e,
351                                 vtkImageData* image)
352   {
353     GimmickDebugMessage(7,
354                         "MultiThreadImageReader event : "<<e<<std::endl);
355         if (e==ImageLoaded)
356         {
357     if (filename.size()==0)
358       {
359                   //What to do in this case?
360                   /*
361                 GimmickDebugMessage(5,
362                                         "Pushing unknown image in queue"
363                                         <<std::endl);
364                 mImageEventQueue.push_back(ImageEventType(image));*/
365                 return;
366       }
367     ImageEventTypeMap::iterator i;
368     i = mImageEventMap.find(filename);
369     if (i!=mImageEventMap.end())
370       {
371                 GimmickDebugMessage(5,
372                                         "Putting image of file '"<<filename<<"' on pointer"
373                                         <<std::endl);
374                 ImageEventType ie(i->second);
375                 ie.image = image;
376                 ie.pointerHolder->Set(ie.image);
377                 //mImageEventMap.erase(i);
378       }
379         }
380         else if (e==Error)
381         {
382                 std::string mess="ERROR: MultiThreadImageReader: Cannot read image in file ";
383                 mess+=filename;
384                 mess+="\n";
385                 GimmickMessage(1,mess);
386                 ImageEventTypeMap::iterator i;
387                 i = mImageEventMap.find(filename);
388                 if (i!=mImageEventMap.end())
389                 {
390                 ImageEventType ie(i->second);
391                 ie.image = image;
392                 ie.pointerHolder->Set(GetDefaultImage());
393                 //mImageEventMap.erase(i);
394                 }
395         }
396
397         else if (e==ImageUnloaded)
398         {
399                 std::string mess="Unloaded image in file ";
400                 mess+=filename;
401                 mess+="\n";
402                 GimmickMessage(1,mess);
403                                 ImageEventTypeMap::iterator i;
404                 i = mImageEventMap.find(filename);
405                 if (i!=mImageEventMap.end())
406                 {
407                 ImageEventType ie(i->second);
408                 ie.image = image;
409                 ie.pointerHolder->Set(GetDefaultImage());
410                 //mImageEventMap.erase(i);
411                 }
412
413         }
414   }
415
416   //====================================================================
417
418   //====================================================================
419   void GimmickView::ConnectValidationObserver(ValidationCallbackType callback)
420   {
421     mValidationSignal.connect(callback);
422   }
423           
424   
425 } // EO namespace creaImageIO
426
427