]> Creatis software - creaImageIO.git/blob - src2/creaImageIOGimmickView.cpp
Added synchronization classes and methods.
[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           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         mValidationSignal(valid);
254         SetMessage(mMessage);
255         return valid;
256   }
257
258 //======================================================================
259
260    //======================================================================
261   ///Reads Images (Non Threaded)
262   void GimmickView::ReadImagesNotThreaded(std::vector<vtkImageData*>& s,std::vector<std::string> im, int dimension)
263   {
264           
265         // Create the output data
266         if (im.size()==1) 
267       {
268                   
269                 // Only one image : give it
270                 vtkImageData* out = vtkImageData::New();
271                 GimmickDebugMessage(3, "State Check: Full Filename: "
272                                                 <<im.front()
273                                                 <<std::endl);
274                 out->ShallowCopy(mReader.GetImage(im.front()));
275                 s.push_back( out );
276       }
277           
278     else if (im.size()>1)
279       {
280         vtkImageData* first = mReader.GetImage( im.front());
281         if (dimension==2) 
282           {     
283             // n2D to 3D
284             vtkImageData* out = vtkImageData::New();
285             out->CopyStructure(first);  
286             out->SetScalarType(first->GetScalarType());
287             int ext[6];
288             first->GetExtent(ext);
289             ext[5] = im.size();
290             out->SetExtent(ext);
291             // LG : TODO : Z Spacing  ?
292             
293             out->AllocateScalars();
294             
295             //first->Print(std::cout);
296             //      out->Print(std::cout);
297             
298             int dim[3];
299             first->GetDimensions(dim);
300             unsigned long imsize = 
301               ( (unsigned long)first->GetScalarPointer(0,1,0)
302                 - (unsigned long)first->GetScalarPointer(0,0,0))
303               *dim[1];
304
305             int slice = 0;
306                 std::vector<std::string>::iterator it;
307            for (it=im.begin(); it!=im.end(); ++it) 
308               {
309                 //std::cout << "copying slice "<<slice <<std::endl;
310                           vtkImageData* cur = mReader.GetImage( (*it));
311                 
312                 void* src = cur->GetScalarPointer(0,0,0);
313                 void* dst = out->GetScalarPointer(0,0,slice);
314                 //              std::cout << "src="<<src<<std::endl;
315                 //              std::cout << "dst="<<dst<<std::endl;
316                 //              std::cout << "siz="<<imsize<<std::endl;
317                 memcpy(dst,src,imsize);
318
319                 slice++;
320               }
321             s.push_back(out);
322           }
323         else 
324           {
325             // n3D
326                   std::vector<std::string>::iterator it;
327             for (it=im.begin(); it!=im.end(); ++it) 
328               {
329                 vtkImageData* out = vtkImageData::New();
330                 out->ShallowCopy(mReader.GetImage(*it));
331                 s.push_back(out);
332               }
333           }
334       }
335         
336   }
337   //======================================================================
338
339   //======================================================================
340   ///Requests the reading of an image
341   void GimmickView::RequestReading(tree::Node* n, 
342                                    int prio, int selection_index, ImagePointerHolder *p)
343   {
344           if(!mReaderStarted)
345           {
346                 mReader.Start();
347                 mReaderStarted=true;
348           }
349     ImageEventType t(n,selection_index, p);
350     mImageEventMap[n->GetAttribute("FullFileName")] = t;    
351     mReader.Request(this,n->GetAttribute("FullFileName"),prio);
352   }
353   //======================================================================
354
355   //======================================================================
356   void GimmickView::
357   OnMultiThreadImageReaderEvent(const std::string& filename,
358                                 MultiThreadImageReaderUser::EventType e,
359                                 vtkImageData* image)
360   {
361     GimmickDebugMessage(7,
362                         "MultiThreadImageReader event : "<<e<<std::endl);
363         if (e==ImageLoaded)
364         {
365     if (filename.size()==0)
366       {
367                   //What to do in this case?
368                   /*
369                 GimmickDebugMessage(5,
370                                         "Pushing unknown image in queue"
371                                         <<std::endl);
372                 mImageEventQueue.push_back(ImageEventType(image));*/
373                 return;
374       }
375     ImageEventTypeMap::iterator i;
376     i = mImageEventMap.find(filename);
377     if (i!=mImageEventMap.end())
378       {
379                 GimmickDebugMessage(5,
380                                         "Putting image of file '"<<filename<<"' on pointer"
381                                         <<std::endl);
382                 ImageEventType ie(i->second);
383                 ie.image = image;
384                 ie.pointerHolder->Set(ie.image);
385                 //mImageEventMap.erase(i);
386       }
387         }
388         else if (e==Error)
389         {
390                 std::string mess="ERROR: MultiThreadImageReader: Cannot read image in file ";
391                 mess+=filename;
392                 mess+="\n";
393                 GimmickMessage(1,mess);
394                 ImageEventTypeMap::iterator i;
395                 i = mImageEventMap.find(filename);
396                 if (i!=mImageEventMap.end())
397                 {
398                 ImageEventType ie(i->second);
399                 ie.image = image;
400                 ie.pointerHolder->Set(GetDefaultImage());
401                 //mImageEventMap.erase(i);
402                 }
403         }
404
405         else if (e==ImageUnloaded)
406         {
407                 std::string mess="Unloaded image in file ";
408                 mess+=filename;
409                 mess+="\n";
410                 GimmickMessage(1,mess);
411                                 ImageEventTypeMap::iterator i;
412                 i = mImageEventMap.find(filename);
413                 if (i!=mImageEventMap.end())
414                 {
415                 ImageEventType ie(i->second);
416                 ie.image = image;
417                 ie.pointerHolder->Set(GetDefaultImage());
418                 //mImageEventMap.erase(i);
419                 }
420
421         }
422   }
423
424   //====================================================================
425
426   //====================================================================
427   void GimmickView::ConnectValidationObserver(ValidationCallbackType callback)
428   {
429     mValidationSignal.connect(callback);
430   }
431           
432   
433 } // EO namespace creaImageIO
434
435