]> Creatis software - creaImageIO.git/blob - src2/creaImageIOGimmickView.cpp
2c2507f2ed90388baeab450522f415e5992a8c7b
[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, mGimmick->GetTimestampDatabase());
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           if(mExtent[2]>1)
166           {
167           SetDimension(3);
168           }
169   }
170
171   //======================================================================
172   ///Validates the dimension compliance of the images with the maximum and 
173   ///minimum given, and between their sizes
174   bool GimmickView::ValidateSelected (tree::Node* sel, int min_dim, int max_dim)
175   {
176         GimmickDebugMessage(2,"Validating selected"<<std::endl);
177         std::string mMessage;
178         
179         if(sel==0)
180         {
181                 mMessage="Cannot have 0 images selected!";
182                 valid=false;
183         }
184         else
185         {
186         ImageExtent* ie=new ImageExtent((*sel).GetAttribute("D0028_0010"),
187                                                  (*sel).GetAttribute("D0028_0011"),
188                                                                          (*sel).GetAttribute("D0028_0012"), 
189                                                                          "");
190         if(mImageExtent==0)
191         {
192                 mImageExtent=ie;
193                 if((mImageExtent->Get(min_dim-1)<2)||(mImageExtent->Get(max_dim)>1))
194                 {
195                         valid=false;
196                 }
197                 else
198                 {
199                         std::stringstream out;
200                         out << mImageExtent->GetDimension() << "D image " << mImageExtent->Get(0) << "x"<< mImageExtent->Get(1) << "x"<< mImageExtent->Get(2) <<" selected";
201                 mMessage = out.str();
202                         mImageExtent->SetDimension(2);
203                         valid=true;
204                 }
205         }
206         else
207         {
208                 if(mImageExtent->IsCompatible(*ie))
209                 {
210                         if(mImageExtent->GetDimension()==max_dim && mImageExtent->Get(max_dim)>2)
211                         {
212                                 std::stringstream out;
213                                 out<<"Cannot add this image to selection : would result in a "<<mImageExtent->GetDimension()+1<<"D image!";
214                                 mMessage=out.str();
215                                 valid=false;
216                         }
217                         else if(max_dim<3)
218                         {
219                                 std::stringstream out;
220                                 out<<"Selecting "<<mImageExtent->GetDimension()<<"D images is not allowed !";
221                                 mMessage=out.str();
222                                 valid=false;
223                         }
224                         else if(min_dim==3 && (ie->Get(2)+mImageExtent->Get(2))<2)
225                         {
226                                 std::stringstream out;
227                                 out << "Cannot build the selection as it would result in a ";
228                                 out << mImageExtent->GetDimension();
229                                 out << "D image, and the minimum is ";
230                                 out << min_dim;
231                                 out << "D!";
232                                 mMessage=out.str();
233                                 valid=false;
234                         }
235                         else
236                         {
237             mImageExtent->Add(*ie);
238                         std::stringstream out;
239                         out << mImageExtent->GetDimension() << "D image " << mImageExtent->Get(0) << "x"<< mImageExtent->Get(1) << "x"<< mImageExtent->Get(2) <<" selected";
240                 mMessage = out.str();
241                         }
242                         
243                 }
244                 else
245                 {
246                         mMessage="The selected images are not compatible.";
247                         valid=false;
248                 }
249         }
250         }
251
252         
253         modifyValidationSignal(valid);
254         SetMessage(mMessage);
255         return valid;
256   }
257
258   //======================================================================
259   void GimmickView::modifyValidationSignal(bool ivalid)
260   {
261           mValidationSignal(ivalid);
262   }
263
264
265    //======================================================================
266   ///Reads Images (Non Threaded)
267   void GimmickView::ReadImagesNotThreaded(std::vector<vtkImageData*>& s,std::vector<std::string> im, int dimension)
268   {
269           
270         // Create the output data
271         if (im.size()==1) 
272       {
273                   
274                 // Only one image : give it
275                 vtkImageData* out = vtkImageData::New();
276                 GimmickDebugMessage(3, "State Check: Full Filename: "
277                                                 <<im.front()
278                                                 <<std::endl);
279                 out->ShallowCopy(mReader.GetImage(im.front()));
280                 s.push_back( out );
281       }
282           
283     else if (im.size()>1)
284       {
285         vtkImageData* first = mReader.GetImage( im.front());
286         if (dimension==2) 
287           {     
288             // n2D to 3D
289             vtkImageData* out = vtkImageData::New();
290             out->CopyStructure(first);  
291             out->SetScalarType(first->GetScalarType());
292             int ext[6];
293             first->GetExtent(ext);
294             ext[5] = im.size();
295             out->SetExtent(ext);
296             // LG : TODO : Z Spacing  ?
297             
298             out->AllocateScalars();
299             
300             //first->Print(std::cout);
301             //      out->Print(std::cout);
302             
303             int dim[3];
304             first->GetDimensions(dim);
305             unsigned long imsize = 
306               ( (unsigned long)first->GetScalarPointer(0,1,0)
307                 - (unsigned long)first->GetScalarPointer(0,0,0))
308               *dim[1];
309
310             int slice = 0;
311                 std::vector<std::string>::iterator it;
312            for (it=im.begin(); it!=im.end(); ++it) 
313               {
314                 //std::cout << "copying slice "<<slice <<std::endl;
315                           vtkImageData* cur = mReader.GetImage( (*it));
316                 
317                 void* src = cur->GetScalarPointer(0,0,0);
318                 void* dst = out->GetScalarPointer(0,0,slice);
319                 //              std::cout << "src="<<src<<std::endl;
320                 //              std::cout << "dst="<<dst<<std::endl;
321                 //              std::cout << "siz="<<imsize<<std::endl;
322                 memcpy(dst,src,imsize);
323
324                 slice++;
325               }
326             s.push_back(out);
327           }
328         else 
329           {
330             // n3D
331                   std::vector<std::string>::iterator it;
332             for (it=im.begin(); it!=im.end(); ++it) 
333               {
334                 vtkImageData* out = vtkImageData::New();
335                 out->ShallowCopy(mReader.GetImage(*it));
336                 s.push_back(out);
337               }
338           }
339       }
340         
341   }
342   //======================================================================
343
344   //======================================================================
345   ///Requests the reading of an image
346   void GimmickView::RequestReading(tree::Node* n, 
347                                    int prio, int selection_index, ImagePointerHolder *p)
348   {
349           if(!mReaderStarted)
350           {
351                 mReader.Start();
352                 mReaderStarted=true;
353           }
354     ImageEventType t(n,selection_index, p);
355     mImageEventMap[n->GetAttribute("FullFileName")] = t;    
356     mReader.Request(this,n->GetAttribute("FullFileName"),prio);
357   }
358   //======================================================================
359
360   //======================================================================
361   void GimmickView::
362   OnMultiThreadImageReaderEvent(const std::string& filename,
363                                 MultiThreadImageReaderUser::EventType e,
364                                 vtkImageData* image)
365   {
366     GimmickDebugMessage(7,
367                         "MultiThreadImageReader event : "<<e<<std::endl);
368         if (e==ImageLoaded)
369         {
370     if (filename.size()==0)
371       {
372                   //What to do in this case?
373                   /*
374                 GimmickDebugMessage(5,
375                                         "Pushing unknown image in queue"
376                                         <<std::endl);
377                 mImageEventQueue.push_back(ImageEventType(image));*/
378                 return;
379       }
380     ImageEventTypeMap::iterator i;
381     i = mImageEventMap.find(filename);
382     if (i!=mImageEventMap.end())
383       {
384                 GimmickDebugMessage(5,
385                                         "Putting image of file '"<<filename<<"' on pointer"
386                                         <<std::endl);
387                 ImageEventType ie(i->second);
388                 ie.image = image;
389                 ie.pointerHolder->Set(ie.image);
390                 //mImageEventMap.erase(i);
391       }
392         }
393         else if (e==Error)
394         {
395                 std::string mess="ERROR: MultiThreadImageReader: Cannot read image in file ";
396                 mess+=filename;
397                 mess+="\n";
398                 GimmickMessage(1,mess);
399                 ImageEventTypeMap::iterator i;
400                 i = mImageEventMap.find(filename);
401                 if (i!=mImageEventMap.end())
402                 {
403                 ImageEventType ie(i->second);
404                 ie.image = image;
405                 ie.pointerHolder->Set(GetDefaultImage());
406                 //mImageEventMap.erase(i);
407                 }
408         }
409
410         else if (e==ImageUnloaded)
411         {
412                 std::string mess="Unloaded image in file ";
413                 mess+=filename;
414                 mess+="\n";
415                 GimmickMessage(1,mess);
416                                 ImageEventTypeMap::iterator i;
417                 i = mImageEventMap.find(filename);
418                 if (i!=mImageEventMap.end())
419                 {
420                 ImageEventType ie(i->second);
421                 ie.image = image;
422                 ie.pointerHolder->Set(GetDefaultImage());
423                 //mImageEventMap.erase(i);
424                 }
425
426         }
427   }
428
429   //====================================================================
430
431   //====================================================================
432   void GimmickView::ConnectValidationObserver(ValidationCallbackType callback)
433   {
434     mValidationSignal.connect(callback);
435   }
436           
437   
438 } // EO namespace creaImageIO
439
440