From: caballero Date: Fri, 6 Mar 2009 14:18:59 +0000 (+0000) Subject: Viewer with movie done. X-Git-Tag: EED.02Oct2009~157 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=6cac83c30fb8c3cd89c41685078eccff6e952a50;p=creaImageIO.git Viewer with movie done. --- diff --git a/src2/CMakeLists.txt b/src2/CMakeLists.txt index e8e9aae..1ce13d9 100644 --- a/src2/CMakeLists.txt +++ b/src2/CMakeLists.txt @@ -48,6 +48,9 @@ SET( SRCS BlockScopeWxApp creaImageIOGimmickReaderDialog + # Viewer + creaImageIOWxViewer + ) diff --git a/src2/creaImageIOGimmickView.cpp b/src2/creaImageIOGimmickView.cpp index 49297e9..6084c7d 100644 --- a/src2/creaImageIOGimmickView.cpp +++ b/src2/creaImageIOGimmickView.cpp @@ -13,6 +13,7 @@ namespace creaImageIO <::iterator i; + i = mImageFileNameToNode.find(filename); + if (i!=mImageFileNameToNode.end()) + { + mImageEventQueue.push_back(ImageEventType(i->second,image)); + } + } } // EO namespace creaImageIO diff --git a/src2/creaImageIOGimmickView.h b/src2/creaImageIOGimmickView.h index 62dc2d1..9aa5072 100644 --- a/src2/creaImageIOGimmickView.h +++ b/src2/creaImageIOGimmickView.h @@ -35,8 +35,6 @@ namespace creaImageIO GimmickView(Gimmick*, int number_of_threads = 0 ); /// Virtual destructor virtual ~GimmickView(); - - /// Initializes the view : /// Creates the TreeViews for all the TreeHandler of the Controller /// @@ -55,6 +53,9 @@ namespace creaImageIO /// Finalize virtual void Finalize(); + //Returns the maximal priority + int GetMaximalPriority(){return mReader.GetMaximalPriority();} + ///Returns the selected Images and validates to see if they comply with the given parameter(<4D) vtkImageData* GetSelectedImage(int dim); ///Adds the selected Images to the given vector and validates to see if they comply with the given parameter (4D) @@ -69,6 +70,21 @@ namespace creaImageIO ///Reads the vector of nodes, builds images in the dimension required and returns them in the supplied vector. void ReadImagesNotThreaded(std::vector& s,std::vector im, int dim); + ///Requests the reading of an image + void RequestReading(tree::Node* n, int prio){mReader.Request(this,n->GetAttribute("FullFileName"),prio);} + ///Adds an entry to the filename to node map + void AddEntryToMap(tree::Node* node){mImageFileNameToNode[node->GetAttribute("FullFileName")] = node;} + ///Returns true if the ImageEventQueue is empty + bool IsQueueEmpty(){return mImageEventQueue.empty();} + ///Clears the queue + void ClearQueue(){mImageEventQueue.clear();} + ///Returns the next in line EventType's image + vtkImageData* GetNextImageQueued(){return mImageEventQueue.front().image;} + ///Returns the next in line EventType's node + tree::Node* GetNextNodeQueued(){return mImageEventQueue.front().node;} + ///Unqueus the next in line EventType + void UnqueueNext(){mImageEventQueue.pop_front();} + ///Obtains the message of the state std::string GetMessage(){return mMess;} @@ -85,6 +101,10 @@ namespace creaImageIO /// Updates the TreeView of given name from level l to bottom /// (calls the virtual method TreeView::UpdateLevel(l)) virtual void UpdateTreeViewLevel(const std::string&, int l); + // Multi-thread image reader callback + void OnMultiThreadImageReaderEvent(const std::string& filename, + MultiThreadImageReaderUser::EventType t, + vtkImageData* image); private: /// Controller which manages the interaction with the model @@ -95,7 +115,23 @@ namespace creaImageIO std::string mMess; /// Multi-thread image reader MultiThreadImageReader mReader; - + /// Map of images' names to nodes + std::map mImageFileNameToNode; + /// type of image event + /// If the image pointer is non null then the image is available (loaded) + /// else it has been unloaded + struct ImageEventType + { + ImageEventType( tree::Node* no, vtkImageData* im ) + : node(no), image(im) {} + ImageEventType(vtkImageData* im ) + : image(im) {} + tree::Node* node; + vtkImageData* image; + }; + // queue of image event + typedef std::deque ImageEventQueueType; + ImageEventQueueType mImageEventQueue; }; // EO class GimmickView diff --git a/src2/creaImageIOTreeView.h b/src2/creaImageIOTreeView.h index 4434789..a807140 100644 --- a/src2/creaImageIOTreeView.h +++ b/src2/creaImageIOTreeView.h @@ -44,6 +44,9 @@ namespace creaImageIO /// Gets the user selected data from the level passed as a parameter virtual std::vector GetSelected(int level){ GimmickError("INTERNAL ERROR : TreeView::GetSelected not overloaded"); } + /// Gets the next nodes on the list, be it up(true) or down(false). + virtual void GetNodes(std::vector& nodes, bool direction){ GimmickError("INTERNAL ERROR : TreeView::GetNodes not overloaded"); } + protected: TreeHandler* GetTreeHandler() { return mTreeHandler; } diff --git a/src2/creaImageIOWxGimmickView.cpp b/src2/creaImageIOWxGimmickView.cpp index 5e851a3..a21617c 100644 --- a/src2/creaImageIOWxGimmickView.cpp +++ b/src2/creaImageIOWxGimmickView.cpp @@ -98,7 +98,9 @@ namespace creaImageIO //Gimmick mGimmick=gimmick; + mViewer=new WxViewer(this, wxID_ANY, wxT("Gimmick! Viewer"),wxDefaultPosition, wxDefaultSize ); + mSelectionMaxDimension= max_dim; mSelectionMinDimension= min_dim; @@ -359,12 +361,132 @@ namespace creaImageIO std::vector sel=* (std::vector *) s; bool valid=ValidateSelected(sel,mSelectionMinDimension,mSelectionMaxDimension ); mText->SetLabel(_T("Status: ")+GetMessage()); + if(valid) + { + ReadImageThreaded(sel); + } + else + { + mViewer->Hide(); + } return valid; } - //================================================= - //================================================= + //================================================== + + //================================================== + ///Reads Images (Threaded) + void WxGimmickView::ReadImageThreaded(std::vector sel) + { + int maxprio = GetMaximalPriority(); + int prio = maxprio + 2000; + + //First load the selected images + mCurImageItemToShow = sel.front(); + std::vector::iterator selected; + for(selected=sel.begin();selected!=sel.end();++selected) + { + GimmickDebugMessage(5, + "Requesting image from selected " + <<(*selected)->GetAttribute("FullFileName") + < up; + GetTreeViewMap()["Local database"]->GetNodes(up,true); + std::vector::iterator iterUp; + for(iterUp=up.begin();iterUp!=up.end();++iterUp) + { + GimmickDebugMessage(5, + "Requesting image from neighbors up " + <<(*iterUp)->GetAttribute("FullFileName") + < down; + GetTreeViewMap()["Local database"]->GetNodes(down,false); + std::vector::iterator iterDown; + for(iterDown=down.begin();iterDown!=down.end();++iterDown) + { + GimmickDebugMessage(5, + "Requesting image from neighbors down " + <<(*iterDown)->GetAttribute("FullFileName") + <GetNumberOfLevels(); + std::vector sel=GetTreeViewMap()["Local database"]->GetSelected(level+1); + GimmickDebugMessage(5, + "Processing Images. Lock Started" + <ClearImages(); + while (!IsQueueEmpty()) + { + vtkImageData* image=GetNextImageQueued(); + tree::Node* node=GetNextNodeQueued(); + if( image!=0 ) + { + bool found=false; + std::vector::iterator i; + for(i=sel.begin();i!=sel.end()&&!found;++i) + { + if((*i)==node) + { + mViewer->AddImage(image); + found=true; + } + } + UnqueueNext(); + } + } + if(!(mViewer->ImagesEmpty())) + { + mViewer->ShowImages(); + mViewer->Show(); + } + ClearQueue(); + + + MultiThreadImageReaderEventUnlock(); + GimmickDebugMessage(5, + "Processing Images. Lock Ended" + < +#include #include #include @@ -47,6 +48,9 @@ namespace creaImageIO void GetSelectedImages(std::vector& s, int dim); /// Validates the selected images bool ValidateSelection(void *); + ///Sends a request to read the currently selected node and the ones that surround it. + void ReadImageThreaded(std::vector sel); + protected: /// Creates the tool bar @@ -89,6 +93,12 @@ namespace creaImageIO /// AddProgress Gimmick callback void OnAddProgress( Gimmick::AddProgress& ); + /// Processes the queue of image events + /// Called in OnInternalIdle(); + /// (locks the MultiThreadImageReaderEvent mutex) + void ProcessImageEvents(); + /// Called upon to refresh the viewer once there are no actions to be done + void OnInternalIdle(); /// Progress dialog wxProgressDialog* mProgressDialog; @@ -96,6 +106,10 @@ namespace creaImageIO int mSelectionMaxDimension; ///The selection's minimum dimension int mSelectionMinDimension; + ///Image previewer + WxViewer* mViewer; + ///Currently Displayed Node + tree::Node* mCurImageItemToShow; wxString mCurrentDirectory; diff --git a/src2/creaImageIOWxTreeView.cpp b/src2/creaImageIOWxTreeView.cpp index 1f3ccfe..72b58fc 100644 --- a/src2/creaImageIOWxTreeView.cpp +++ b/src2/creaImageIOWxTreeView.cpp @@ -1,16 +1,11 @@ #include #include #include +///Comparing function for ordering algorithm. Takes parameters as strings. int wxCALLBACK CompareFunctionStrings(long item1, long item2, long sortData) { std::string s1((char*)((long*)item1)[1]); std::string s2((char*)((long*)item2)[1]); - GimmickMessage(1, - " Check: STRING 1: " - <Add( mLevelList[0].wxSplitter ,1, wxGROW ,0); mColumnSelected=1; + mLastSelected=0; mDirection=true; UpdateLevel(1); @@ -204,7 +195,16 @@ namespace creaImageIO { long adr = GetCtrl(l-1)->GetItemData(i); tree::Node* n = ((ItemData*)adr)->node; - sel.push_back(n); + if(mLastSelected==i) + { + std::vector::iterator it; + it = sel.begin(); + it = sel.insert ( it , n ); + } + else + { + sel.push_back(n); + } } } } @@ -248,7 +248,7 @@ namespace creaImageIO //===================================================================== - /// + /// Updates a level of the view (adds or removes children, proganizes, etc.) void WxTreeView::UpdateLevel( int level ) { GimmickDebugMessage(1, @@ -270,7 +270,7 @@ namespace creaImageIO } //===================================================================== - /// + /// Recursive method called upon by UpdateLevel to refresh all windows void WxTreeView::RecursiveUpdateLevel( int level ) { GimmickDebugMessage(2, @@ -387,7 +387,7 @@ namespace creaImageIO wxListItem info; info.m_itemId = event.m_itemIndex; - + mLastSelected=event.m_itemIndex; // retrieve the level wxObject* obj = event.GetEventObject(); @@ -410,93 +410,94 @@ namespace creaImageIO { //Obtain the column name and the level that needs to be organized mColumnSelected=event.m_col; - GimmickMessage(1, - " Column " <GetItemCount(); - for (int i = 0; i < n; i++) - { + if(mColumnSelected!=0) + { + wxObject* ctrl = event.GetEventObject(); + unsigned int level = 0; + for (level = 0; levelGetItemCount(); + for (int i = 0; i < n; i++) + { + + //Gets current item data + long adr = GetCtrl(level)->GetItemData(i); + //Extracts the node and the type of attribute + tree::Node* nod = ((ItemData*)adr)->node; + if(i==0) + { + (*nod).GetAttributeDescriptor(mLevelList[level].key[mColumnSelected-1]).DecodeType(ty); + } + //Obtains the organizing attribute + att=(*nod).GetAttribute(mLevelList[level].key[mColumnSelected-1]); + + char* d= new char [att.size()+1]; + strcpy (d, att.c_str()); + + //Creates array + long* lp= new long[2]; + lp[0]=adr; + lp[1]=(long)d; + + //Sets it as the data + GetCtrl(level)->SetItemData(i,(long)lp); + } - //Gets current item data - long adr = GetCtrl(level)->GetItemData(i); - //Extracts the node and the type of attribute - tree::Node* nod = ((ItemData*)adr)->node; - if(i==0) - { - (*nod).GetAttributeDescriptor(mLevelList[level].key[mColumnSelected-1]).DecodeType(ty); - } - //Obtains the organizing attribute - att=(*nod).GetAttribute(mLevelList[level].key[mColumnSelected-1]); - - char* d= new char [att.size()+1]; - strcpy (d, att.c_str()); - - //Creates array - long* lp= new long[2]; - lp[0]=adr; - lp[1]=(long)d; - - //Sets it as the data - GetCtrl(level)->SetItemData(i,(long)lp); - } - - //int ty=GetAttributeDescriptor(mLevelList[level].key[mColumnSelected-1]).GetType(); - if(mDirection) - { - if(ty==1) - { - GetCtrl(level)->SortItems(CompareFunctionInts, 0); - } - else - { - GetCtrl(level)->SortItems(CompareFunctionStrings, 0); - } - - mDirection=false; - } - else - { - if(ty==1) - { - GetCtrl(level)->SortItems(CompareFunctionInts, 1); - } - else - { - GetCtrl(level)->SortItems(CompareFunctionStrings, 1); - } - mDirection=true; - } + if(mDirection) + { + if(ty==1) + { + GetCtrl(level)->SortItems(CompareFunctionInts, 0); + } + else + { + GetCtrl(level)->SortItems(CompareFunctionStrings, 0); + } + + mDirection=false; + } + else + { + if(ty==1) + { + GetCtrl(level)->SortItems(CompareFunctionInts, 1); + } + else + { + GetCtrl(level)->SortItems(CompareFunctionStrings, 1); + } + mDirection=true; + } - //Resets original data - - long it = -1; - for ( ;; ) - { - it = GetCtrl(level)->GetNextItem(it, - wxLIST_NEXT_ALL); - if ( it == -1 ) - break; - //Gets current item data, extracts the node and resets it - long item = GetCtrl(level)->GetItemData(it); - GetCtrl(level)->SetItemData(it,((long*)item)[0]); - - } + //Resets original data + + long it = -1; + for ( ;; ) + { + it = GetCtrl(level)->GetNextItem(it, + wxLIST_NEXT_ALL); + if ( it == -1 ) + break; + //Gets current item data, extracts the node and resets it + long item = GetCtrl(level)->GetItemData(it); + GetCtrl(level)->SetItemData(it,((long*)item)[0]); + + } + } } //================================================================ @@ -510,6 +511,42 @@ namespace creaImageIO event.SetClientData(&sel); GetEventHandler()->ProcessEvent( event ); } + + //================================================================ + void WxTreeView::GetNodes(std::vector& nodes, bool direction) + { + long item = mLastSelected; + int level=mLevelList.size()-1; + //Gets current item data + long adr = GetCtrl(level)->GetItemData(item); + //Extracts the node + tree::Node* nod = ((ItemData*)adr)->node; + for ( ;; ) + { + if(direction) + { + item = GetCtrl(level)->GetNextItem(item, + wxLIST_NEXT_ABOVE); + } + else + { + item = GetCtrl(level)->GetNextItem(item, + wxLIST_NEXT_BELOW); + } + if ( item == -1 ) + { + break; + } + if(GetCtrl(level)->GetItemState(item, wxLIST_STATE_SELECTED)==0) + { + adr = GetCtrl(level)->GetItemData(item); + nod = ((ItemData*)adr)->node; + nodes.push_back(nod); + } + } + + } + //================================================================ void WxTreeView::GetSelectedAsString(std::vector&s) { diff --git a/src2/creaImageIOWxTreeView.h b/src2/creaImageIOWxTreeView.h index 6b93641..7401e90 100644 --- a/src2/creaImageIOWxTreeView.h +++ b/src2/creaImageIOWxTreeView.h @@ -66,6 +66,8 @@ namespace creaImageIO void ValidateSelectedImages(); ///Gets selected filenames void GetSelectedAsString(std::vector&s); + /// Gets the next nodes on the list, be it up(true) or down(false). + void GetNodes(std::vector& nodes, bool direction); /// Updates the view of a level given the selected items of upper level /// Recursive method virtual void RecursiveUpdateLevel( int ); @@ -76,6 +78,8 @@ namespace creaImageIO ///Boolean that defines the direction of the organization ///True is ascending order and false is descending bool mDirection; + ///The last selected item on the list + long mLastSelected; diff --git a/src2/creaImageIOWxViewer.cpp b/src2/creaImageIOWxViewer.cpp new file mode 100644 index 0000000..f8ae7b9 --- /dev/null +++ b/src2/creaImageIOWxViewer.cpp @@ -0,0 +1,370 @@ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +using namespace crea; + +namespace creaImageIO +{ + + //===================================================================== + + //===================================================================== + class ThreadedMovie: public wxThread + { + public: + ThreadedMovie(std::vector m, vtkImageViewer2* v, crea::creawxVTKRenderWindowInteractor* i, WxViewer* parent) : + mImagesToPlay(m), mViewer(v), mInteractor(i), mParent(parent) + {} + + void* Entry(); + void SetImagesToPlay(std::vector im); + void ShowImage(vtkImageData* v); + void StartIterator(); + void OnExit(); + + private: + std::vector mImagesToPlay; + vtkImageViewer2* mViewer; + /// Associated wxvtk interactor + crea::creawxVTKRenderWindowInteractor *mInteractor; + std::vector::iterator i; + WxViewer* mParent; + + int mx1,mx2,my1,my2,mz1,mz2; + double mspx,mspy,mspz; + }; + + + // CTor + WxViewer::WxViewer(wxWindow *parent, + wxWindowID id, + wxString title, + const wxPoint& pos, + const wxSize& size) + : wxFrame( parent, + id, + title, + pos, + size, + wxCAPTION) + { + GimmickDebugMessage(1,"WxViewer::WxViewer" + <UseCaptureMouseOn(); + + mViewer = vtkImageViewer2::New(); + mViewer->SetupInteractor ( mInteractor ); + + mMovie=new ThreadedMovie(images, mViewer, mInteractor, this); + + topsizer-> Add( mInteractor ,1,wxGROW ,0); + SetSizer( topsizer ); + Layout(); + } + + /// Destructor + WxViewer::~WxViewer() + { + GimmickDebugMessage(1,"WxViewer::~WxViewer" + <SetInput(im); + mViewer->SetSlice( 0 ); + + int x1,x2,y1,y2,z1,z2; + double spx,spy,spz; + im->Update(); + + im->GetSpacing(spx,spy,spz); + im->GetExtent (x1,x2,y1,y2,z1,z2); + /* + std::cout << "-----------------------------"<GetScalarRange(); + mViewer->SetColorWindow(range[1] - range[0]); + mViewer->SetColorLevel(0.5 * (range[1] + range[0])); + + mViewer->GetRenderer()->ResetCamera(); + double bounds[6]; + + + mViewer->GetRenderer()->ComputeVisiblePropBounds(bounds); + + /* + std::cout <<"bounds : "<GetRenderer()->ResetCameraClippingRange(bounds); + /* + vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera(); + + camera->SetViewUp ( spx*0, -spy*1, spz*0); + camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, spz*10000000); + camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0); + + camera->ComputeViewPlaneNormal(); + camera->SetParallelScale( spx*(x2-x1)/2.0 ); + + camera->Roll ( 180 ); + */ + + } + + + + } + + //================================================================ + + //================================================================ + + void WxViewer::AddImage(vtkImageData* im) + { + images.push_back(im); + } + + //================================================================ + + //================================================================ + + void WxViewer::ShowImages() + { + if(!(mMovie->IsAlive())) + { + mMovie->SetImagesToPlay(images); + mMovie->StartIterator(); + mMovie->Create(); + mMovie->Run(); + } + else + { + if(!images.empty()) + { + mMovie->Pause(); + mMovie->SetImagesToPlay(images); + mMovie->StartIterator(); + mMovie->Resume(); + } + else + { + GimmickMessage(1,"I'm empty!!!!! "<Refresh(); + endwait = clock () + 0.2 * CLOCKS_PER_SEC ; + while (clock() < endwait) {} + } + + } + + } + return 0; + } + + //===================================================================== + + //===================================================================== + void ThreadedMovie::OnExit() + { + GimmickMessage(1,"Hello WORLD IM OUT!!!!!!!! "< im) + { + mImagesToPlay=im; + } + + //===================================================================== + + //===================================================================== + void ThreadedMovie::StartIterator() + { + i=mImagesToPlay.begin(); + } + + //===================================================================== + + //===================================================================== + + void ThreadedMovie::ShowImage(vtkImageData* im) + { + mViewer->SetInput(im); + mViewer->SetSlice( 0 ); + + int x1,x2,y1,y2,z1,z2; + double spx,spy,spz; + + im->Update(); + + im->GetSpacing(spx,spy,spz); + im->GetExtent (x1,x2,y1,y2,z1,z2); + /* + std::cout << "-----------------------------"<GetScalarRange(); + mViewer->SetColorWindow(range[1] - range[0]); + mViewer->SetColorLevel(0.5 * (range[1] + range[0])); + + mViewer->GetRenderer()->ResetCamera(); + double bounds[6]; + + + mViewer->GetRenderer()->ComputeVisiblePropBounds(bounds); + + /* + std::cout <<"bounds : "<GetRenderer()->ResetCameraClippingRange(bounds); + /* + vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera(); + + camera->SetViewUp ( spx*0, -spy*1, spz*0); + camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, spz*10000000); + camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0); + + camera->ComputeViewPlaneNormal(); + camera->SetParallelScale( spx*(x2-x1)/2.0 ); + + camera->Roll ( 180 ); + */ + + } + + //mInteractor->Render(); + } + +} // EO namespace creaImageIO + diff --git a/src2/creaImageIOWxViewer.h b/src2/creaImageIOWxViewer.h new file mode 100644 index 0000000..9323e3d --- /dev/null +++ b/src2/creaImageIOWxViewer.h @@ -0,0 +1,67 @@ +#ifndef __creaImageIOWxViewer_h_INCLUDED__ +#define __creaImageIOWxViewer_h_INCLUDED__ + +#ifdef USE_WXWIDGETS + +// wx +#include +#include +#include +#include + +#include + +// For image preview +// vtk and wxvtk classes +#include "creawxVTKRenderWindowInteractor.h" +#include "vtkImageViewer2.h" + +namespace creaImageIO +{ + + class WxViewer : public wxFrame + { + + public: + friend class ThreadedMovie; + /// Ctor + WxViewer(); + WxViewer(wxWindow *parent, + const wxWindowID id, + wxString title, + const wxPoint& pos, + const wxSize& size); + /// Dtor + virtual ~WxViewer(); + ///Shows the image in the vector as a movie + void ShowImages(); + ///Shows the image passed as parameter + void ShowImage(vtkImageData* im); + ///Adds an image to the selection + void AddImage(vtkImageData* im); + ///Clears the selection of images + void ClearImages(); + ///Returns true if the image vector is empty + bool ImagesEmpty(); + + private: + /// Previewer + vtkImageViewer2* mViewer; + /// Associated wxvtk interactor + crea::creawxVTKRenderWindowInteractor *mInteractor; + + int mx1,mx2,my1,my2,mz1,mz2; + double mspx,mspy,mspz; + + /// The vector of images to show + std::vector images; + ///The threaded movie + ThreadedMovie* mMovie; + + }; + +} + +#endif // USE_WIDGETS +// EOF +#endif \ No newline at end of file