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