#include "ImageMPR.h" #include "ui_ImageMPR.h" #include // ------------------------------------------------------------------------- #define ImageMPR_ConnectAction( ACTION ) \ QObject::connect( \ this->m_UI->a##ACTION, SIGNAL( triggered( ) ), \ this, SLOT( _a##ACTION( ) ) \ ) // ------------------------------------------------------------------------- ImageMPR:: ImageMPR( QWidget* parent ) : QMainWindow( parent ), m_UI( new Ui::ImageMPR ), m_Plugins( new TPlugins ) { this->m_UI->setupUi( this ); this->m_Plugins->SetWidget( this ); // Connect actions ImageMPR_ConnectAction( OpenImage ); ImageMPR_ConnectAction( OpenDICOMSeries ); ImageMPR_ConnectAction( OpenSegmentation ); ImageMPR_ConnectAction( OpenPolyData ); ImageMPR_ConnectAction( SaveImage ); ImageMPR_ConnectAction( SaveSegmentation ); ImageMPR_ConnectAction( SavePolyData ); ImageMPR_ConnectAction( Undo ); ImageMPR_ConnectAction( Redo ); ImageMPR_ConnectAction( LoadPlugins ); ImageMPR_ConnectAction( ShowPlugins ); // Try to load default plugins #ifdef WIN32 this->m_Plugins->LoadPlugins("cpPluginsIO.dll"); this->m_Plugins->LoadPlugins("cpPluginsBasicFilters.dll"); #else this->m_Plugins->LoadPluginsConfigurationFile("Plugins.cfg"); #endif this->m_Plugins->AssociatePluginsToMenu( this->m_UI->MenuFilters, this, SLOT( _execPlugin( ) ) ); } // ------------------------------------------------------------------------- ImageMPR:: ~ImageMPR( ) { delete this->m_UI; delete this->m_Plugins; } // ------------------------------------------------------------------------- void ImageMPR:: _aOpenImage( ) { // Clear all, since we are loading the main image if( this->m_Objects.size( ) > 0 ) { this->m_UI->MPR->ClearAll( ); this->m_Objects.clear( ); } // fi // Read and show image, if possible TPlugins::TImage::Pointer image; if( this->m_Plugins->ReadImage( image, true ) ) { vtkImageData* vimage = image->GetVTK< vtkImageData >( ); if( vimage == NULL ) QMessageBox::critical( this, QMessageBox::tr( "Error showing image." ), QMessageBox::tr( "Image was read, but no valid VTK conversion was found." ) ); else this->m_UI->MPR->ShowImage( vimage, image->GetName( ) ); // Keep a track on a local data tree this->m_Objects[ image->GetName( ) ] = TTreeNode( "", image.GetPointer( ) ); } // fi } // ------------------------------------------------------------------------- void ImageMPR:: _aOpenDICOMSeries( ) { // Clear all, since we are loading the main image if( this->m_Objects.size( ) > 0 ) { this->m_UI->MPR->ClearAll( ); this->m_Objects.clear( ); } // fi // Read and show image, if possible TPlugins::TImage::Pointer image; if( this->m_Plugins->ReadDicomSeries( image ) ) { vtkImageData* vimage = image->GetVTK< vtkImageData >( ); if( vimage == NULL ) QMessageBox::critical( this, QMessageBox::tr( "Error showing image." ), QMessageBox::tr( "Image was read, but no valid VTK conversion was found." ) ); else this->m_UI->MPR->ShowImage( vimage, image->GetName( ) ); // Keep a track on a local data tree this->m_Objects[ image->GetName( ) ] = TTreeNode( "", image.GetPointer( ) ); } // fi } // ------------------------------------------------------------------------- void ImageMPR:: _aOpenSegmentation( ) { /* if( this->m_ImageLoaded != "" ) this->m_ImageLoaded = this->m_UI->MPR->LoadImage( ); */ } // ------------------------------------------------------------------------- void ImageMPR:: _aOpenPolyData( ) { } // ------------------------------------------------------------------------- void ImageMPR:: _aSaveImage( ) { std::string data_name = this->m_UI->MPR->GetSelectedData( ); TPlugins::TImage* image = dynamic_cast< TPlugins::TImage* >( this->m_Objects[ data_name ].second.GetPointer( ) ); if( image == NULL ) return; this->m_Plugins->WriteImage( image, true ); } // ------------------------------------------------------------------------- void ImageMPR:: _aSaveSegmentation( ) { } // ------------------------------------------------------------------------- void ImageMPR:: _aSavePolyData( ) { std::string data_name = this->m_UI->MPR->GetSelectedData( ); TPlugins::TMesh* mesh = dynamic_cast< TPlugins::TMesh* >( this->m_Objects[ data_name ].second.GetPointer( ) ); if( mesh == NULL ) return; this->m_Plugins->WriteMesh( mesh, true ); } // ------------------------------------------------------------------------- void ImageMPR:: _aUndo( ) { } // ------------------------------------------------------------------------- void ImageMPR:: _aRedo( ) { } // ------------------------------------------------------------------------- void ImageMPR:: _aLoadPlugins( ) { this->m_Plugins->DialogLoadPlugins( ); this->m_Plugins->AssociatePluginsToMenu( this->m_UI->MenuFilters, this, SLOT( _execPlugin( ) ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _aShowPlugins( ) { } // ------------------------------------------------------------------------- void ImageMPR:: _execPlugin( ) { // Get filter name QAction* action = dynamic_cast< QAction* >( this->sender( ) ); if( action == NULL ) return; QMenu* menu = dynamic_cast< QMenu* >( action->parentWidget( ) ); if( menu == NULL ) return; std::string filter_cate = menu->title( ).toStdString( ); std::string filter_name = action->text( ).toStdString( ); // Create filter TPlugins::TProcessObject::Pointer filter; if( !( this->m_Plugins->CreateFilter( filter, filter_name ) ) ) { QMessageBox::critical( this, tr( "Error creating filter" ), tr( ( std::string( "No valid filter \"" ) + filter_name + std::string( "\"defined." ) ).c_str( ) ) ); return; } // fi // Configure filter if( !( filter->ExecConfigurationDialog( this ) ) ) return; // Assign inputs std::string data_name = this->m_UI->MPR->GetSelectedData( ); std::vector< std::string > inputs_names = filter->GetInputsNames( ); if( inputs_names.size( ) == 1 ) { TTree::iterator iIt = this->m_Objects.find( data_name ); if( iIt == this->m_Objects.end( ) ) { QMessageBox::critical( this, tr( "Error configuring filter" ), tr( "No valid input found. Please select a valid input." ) ); return; } //fi filter->SetInput( inputs_names[ 0 ], iIt->second.second ); } else if( inputs_names.size( ) > 1 ) { QMessageBox::critical( this, tr( "Error executing" ), tr( "Filter has multiple inputs: NOT YET IMPLEMENTED!!!" ) ); return; } // fi // Execute filter this->_Block( ); std::string filter_err = filter->Update( ); this->_Unblock( ); if( filter_err != "" ) { QMessageBox::critical( this, tr( "Error executing" ), tr( filter_err.c_str( ) ) ); return; } // fi // Get outputs std::vector< std::string > outputs_names = filter->GetOutputsNames( ); for( auto oIt = outputs_names.begin( ); oIt != outputs_names.end( ); ++oIt ) { std::string out_name = filter_name + "_" + *oIt; TPlugins::TImage* image = filter->GetOutput< TPlugins::TImage >( *oIt ); if( image != NULL ) { if( filter_cate == "ImageToBinaryImageFilter" ) { this->m_UI->MPR->ShowImage( image->GetVTK< vtkImageData >( ), out_name, data_name, 1, 0, 0 ); } else if( filter_cate == "ImageToImageFilter" ) { } // fi // Keep a track on a local data tree and go to next output this->m_Objects[ out_name ] = TTreeNode( data_name, image ); continue; } // fi TPlugins::TMesh* mesh = filter->GetOutput< TPlugins::TMesh >( *oIt ); if( mesh != NULL ) { // Show mesh this->_Block( ); this->m_UI->MPR->ShowMesh( mesh->GetVTK< vtkPolyData >( ), out_name, data_name ); this->_Unblock( ); // Keep a track on a local data tree and go to next output this->m_Objects[ out_name ] = TTreeNode( data_name, mesh ); continue; } // fi } // rof } // ------------------------------------------------------------------------- /* TODO void ImageMPR:: _CursorCommand( double* pos, int axis, void* data ) { Self* app = reinterpret_cast< Self* >( data ); if( app == NULL ) return; if( !( app->m_Flooding ) ) return; cpPlugins::Interface::ProcessObject::Pointer filter = app->m_UI->MPR->CreateFilter( "cpPlugins::BasicFilters::FloodFillImageFilter" ); if( filter.IsNull( ) ) return; cpPlugins::Interface::Parameters* params = filter->GetParameters( ); params->SetPoint( "Seed", 3, pos ); params->SetReal( "Window", app->m_UI->MPR->GetWindow( ) ); params->SetReal( "Level", app->m_UI->MPR->GetLevel( ) ); params->SetUint( "InsideValue", 1 ); params->SetUint( "OutsideValue", 0 ); filter->SetInput( "Input", app->m_UI->MPR->GetImage( app->m_ImageLoaded ) ); app->m_UI->MPR->Block( ); std::string err = filter->Update( ); cpPlugins::Interface::BaseMPRWindow::TImage::Pointer image = filter->GetOutput< cpPlugins::Interface::BaseMPRWindow::TImage >( "Output" ); filter->DisconnectOutputs( ); app->m_UI->MPR->AddImage( "Segmentation", image ); app->m_UI->MPR->Unblock( ); std::cout << "CursorCommand ==> " << pos[ 0 ] << " " << pos[ 1 ] << " " << pos[ 2 ] << " : " << axis << " " << data << std::endl; } */ /* #include "MementoState.h" #include #include #include #include #include #ifdef _WIN32 # define PLUGIN_PREFIX "" # define PLUGIN_EXT "dll" # define PLUGIN_REGEX "Plugins file (*.dll);;All files (*)" #else # define PLUGIN_PREFIX "lib" # define PLUGIN_EXT "so" # define PLUGIN_REGEX "Plugins file (*.so);;All files (*)" #endif // _WIN32 // ------------------------------------------------------------------------- ImageMPR::ImageMPR( QWidget* parent ) : QMainWindow( parent ), m_UI( new Ui::ImageMPR ), m_ImageReaderClass( "" ), m_ImageWriterClass( "" ), m_MeshReaderClass( "" ), m_MeshWriterClass( "" ), m_MeshCutterClass( "" ), m_Image( NULL ), m_state(0), m_max_state(0) { this->m_UI->setupUi( this ); // Create and associate renderers this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( ); this->m_MPRObjects->SetRenderWindows( this->m_UI->m_XPlaneVTK->GetRenderWindow( ), this->m_UI->m_YPlaneVTK->GetRenderWindow( ), this->m_UI->m_ZPlaneVTK->GetRenderWindow( ), this->m_UI->m_3DVTK->GetRenderWindow( ) ); // signals <-> slots QObject::connect( this->m_UI->actionOpenPlugins, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionOpenPlugins( ) ) ); QObject::connect( this->m_UI->actionOpenInputImage, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionOpenInputImage( ) ) ); QObject::connect( this->m_UI->actionOpenSegmentation, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionOpenSegmentation( ) ) ); QObject::connect( this->m_UI->actionOpenInputPolyData, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionOpenInputPolyData( ) ) ); QObject::connect( this->m_UI->actionUndo, SIGNAL(triggered()), this, SLOT(_triggered_actionUndo()) ); QObject::connect( this->m_UI->actionRedo, SIGNAL(triggered()), this, SLOT(_triggered_actionRedo()) ); // Start: load all disponible plugins this->_LoadPlugins( std::string( PLUGIN_PREFIX ) + std::string( "cpPluginsIO." ) + std::string( PLUGIN_EXT ) ); this->_LoadPlugins( std::string( PLUGIN_PREFIX ) + std::string( "cpPluginsBasicFilters." ) + std::string( PLUGIN_EXT ) ); } // ------------------------------------------------------------------------- ImageMPR:: ~ImageMPR( ) { // Close all connections this->m_Plugins.UnloadAll( ); // Delete objects delete this->m_UI; } // ------------------------------------------------------------------------- bool ImageMPR:: _LoadPlugins( const std::string& filename ) { QApplication::setOverrideCursor( Qt::WaitCursor ); this->setEnabled( false ); this->m_ImageReaderClass = ""; this->m_ImageWriterClass = ""; this->m_MeshReaderClass = ""; this->m_MeshWriterClass = ""; this->m_MeshCutterClass = ""; this->m_UI->MenuImageToImage->clear( ); this->m_UI->MenuImageToMesh->clear( ); if( !( this->m_Plugins.Load( filename ) ) ) return( false ); typedef TPluginsInterface::TClasses _TClasses; _TClasses::const_iterator cIt = this->m_Plugins.GetClasses( ).begin( ); for( ; cIt != this->m_Plugins.GetClasses( ).end( ); ++cIt ) { TPluginFilter::Pointer o = this->m_Plugins.CreateProcessObject( cIt->first ); std::string name = o->GetClassName( ); std::string category = o->GetClassCategory( ); if( category == "ImageReader" ) this->m_ImageReaderClass = name; else if( category == "ImageWriter" ) this->m_ImageWriterClass = name; else if( category == "MeshReader" ) this->m_MeshReaderClass = name; else if( category == "MeshWriter" ) this->m_MeshWriterClass = name; else if( category == "MeshToMeshFilter" ) { if( name.find_last_of( "Cutter" ) != std::string::npos ) this->m_MeshCutterClass = name; } else if( category == "ImageToImageFilter" ) { QAction* action = this->m_UI->MenuImageToImage->addAction( QString( name.c_str( ) ) ); QObject::connect( action, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionImageToImage( ) ) ); } else if( category == "ImageToMeshFilter" ) { QAction* action = this->m_UI->MenuImageToMesh->addAction( QString( name.c_str( ) ) ); QObject::connect( action, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionImageToMesh( ) ) ); } // fi } // rof QApplication::restoreOverrideCursor( ); this->setEnabled( true ); return( true ); } // ------------------------------------------------------------------------- std::string ImageMPR:: _LoadImage( TPluginImage::Pointer& image ) { std::string ret = ""; image = NULL; // Get a reader from loaded plugins TPluginFilter::Pointer reader = this->m_Plugins.CreateProcessObject( this->m_ImageReaderClass ); if( reader.IsNotNull( ) ) { if( reader->ExecConfigurationDialog( this ) ) { // Block application QApplication::setOverrideCursor( Qt::WaitCursor ); this->setEnabled( false ); // Execute and get error message, if any ret = reader->Update( ); // Assign fresh image, if any if( ret == "" ) { image = reader->GetOutput< TPluginImage >( 0 ); reader->DisconnectOutputs( ); } // fi // Unblock application QApplication::restoreOverrideCursor( ); this->setEnabled( true ); } // fi } else ret = "No suitable reader object found in loaded plugins."; return( ret ); } // ------------------------------------------------------------------------- std::string ImageMPR:: _ConfigureMeshActors( ) { if( this->m_Mesh.IsNull( ) ) return( "Valid mesh not found." ); this->m_Mesh->CreateVTKActor( ); vtkActor* vtk_actor = this->m_Mesh->GetVTKActor( ); if( vtk_actor != NULL ) { this->m_MPRObjects->Get3DRenderer( )->AddActor( vtk_actor ); this->m_MPRObjects->Render( 4 ); } // fi TMPRObjects::TMPRActors* mprActors = this->m_MPRObjects->GetMPRActors( ); std::string err = ""; for( unsigned int i = 0; i < 3; ++i ) { this->m_Cutters[ i ] = this->m_Plugins.CreateProcessObject( this->m_MeshCutterClass ); this->m_Planes[ i ] = TPluginImplicitFunction::New( ); this->m_Planes[ i ]->SetFunction( mprActors->GetSliceActors( i )->GetPlaneFunction( ) ); this->m_Cutters[ i ]->SetInput( 0, this->m_Mesh ); this->m_Cutters[ i ]->SetInput( 1, this->m_Planes[ i ] ); std::string lerr = this->m_Cutters[ i ]->Update( ); if( lerr == "" ) { this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->CreateVTKActor( ); vtkActor* actor = this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->GetVTKActor( ); mprActors->GetSliceActors( i )->AddActor( this->m_Cutters[ i ]->GetVTK< vtkAlgorithm >( ), actor ); if( i == 0 ) this->m_MPRObjects->GetXRenderer( )->AddActor( actor ); else if( i == 1 ) this->m_MPRObjects->GetYRenderer( )->AddActor( actor ); else if( i == 2 ) this->m_MPRObjects->GetZRenderer( )->AddActor( actor ); } // fi err += lerr; } // rof this->m_MPRObjects->RenderAll( ); return( err ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionOpenPlugins( ) { // Show dialog and check if it was accepted QFileDialog dialog( this ); dialog.setFileMode( QFileDialog::ExistingFile ); dialog.setDirectory( "." ); dialog.setNameFilter( tr( PLUGIN_REGEX ) ); dialog.setDefaultSuffix( tr( PLUGIN_EXT ) ); if( !( dialog.exec( ) ) ) return; std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( ); if( !( _LoadPlugins( fname ) ) ) QMessageBox::critical( this, tr( "Ignoring plugin" ), tr( fname.c_str( ) ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionOpenInputImage( ) { // Read image std::string err = this->_LoadImage( this->m_Image ); if( err == "" ) { vtkImageData* vtk_id = this->m_Image->GetVTK< vtkImageData >( ); if( vtk_id != NULL ) { this->m_MPRObjects->SetImage( vtk_id ); this->m_MPRObjects->ActivateInteractors( ); this->m_MPRObjects->ResetCameras( ); this->m_MPRObjects->RenderAll( ); MementoState(m_state, this->m_Image); this->m_state++; } else QMessageBox::critical( this, tr( "Error message" ), tr( "Read image does not have a valid VTK converter." ) ); } else QMessageBox::critical( this, tr( "Error reading single image" ), tr( err.c_str( ) ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionOpenSegmentation( ) { if( this->m_Image.IsNull( ) ) { QMessageBox::critical( this, tr( "Error message" ), tr( "Before reading a segmentation, first load a raw image." ) ); return; } // fi // Read image std::string err = this->_LoadImage( this->m_Segmentation ); if( err == "" ) { vtkImageData* vtk_id = this->m_Segmentation->GetVTK< vtkImageData >( ); if( vtk_id != NULL ) { this->m_MPRObjects->AddAuxiliaryImage( vtk_id ); this->m_MPRObjects->RenderAll( ); } else QMessageBox::critical( this, tr( "Error message" ), tr( "Read image does not have a valid VTK converter." ) ); } else QMessageBox::critical( this, tr( "Error reading single image" ), tr( err.c_str( ) ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionOpenInputPolyData( ) { this->m_Mesh = NULL; // Get a reader from plugins TPluginFilter::Pointer reader = this->m_Plugins.CreateProcessObject( this->m_MeshReaderClass ); if( reader.IsNotNull( ) ) { // Configure reader if( reader->ExecConfigurationDialog( this ) ) { // Execute and get error message, if any QApplication::setOverrideCursor( Qt::WaitCursor ); this->setEnabled( false ); std::string err = reader->Update( ); QApplication::restoreOverrideCursor( ); this->setEnabled( true ); // Assign fresh mesh, if any if( err == "" ) { this->m_Mesh = reader->GetOutput< TPluginMesh >( 0 ); reader->DisconnectOutputs( ); err = this->_ConfigureMeshActors( ); if( err != "" ) QMessageBox::critical( this, tr( "Error message" ), tr( err.c_str( ) ) ); } else QMessageBox::critical( this, tr( "Error reading mesh" ), tr( err.c_str( ) ) ); } // fi } else QMessageBox::critical( this, tr( "Error reading single mesh" ), tr( "No suitable mesh reader found in loaded plugins." ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionImageToImage( ) { if( this->m_Image.IsNull( ) ) return; // Get filter name QAction* action = dynamic_cast< QAction* >( this->sender( ) ); if( action == NULL ) return; std::string name = action->text( ).toStdString( ); // Configure filter TPluginFilter::Pointer filter = this->m_Plugins.CreateProcessObject( name ); bool dlg_ok = filter->ExecConfigurationDialog( NULL ); if( !dlg_ok ) return; // Execute filter QApplication::setOverrideCursor( Qt::WaitCursor ); this->setEnabled( false ); filter->SetInput( 0, this->m_Image ); std::string err = filter->Update( ); QApplication::restoreOverrideCursor( ); this->setEnabled( true ); // Update image if( err == "" ) { TPluginImage* result = filter->GetOutput< TPluginImage >( 0 ); result->DisconnectPipeline( ); this->m_Image = result; if( this->m_Image.IsNotNull( ) ) this->m_MPRObjects->SetImage( this->m_Image->GetVTK< vtkImageData >( ) ); MementoState(this->m_state, this->m_Image); this->m_state++; if (this->m_state > this->m_max_state) { this->m_max_state = this->m_state; } } else QMessageBox::critical( this, tr( "Error executing filter" ), tr( err.c_str( ) ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionImageToMesh( ) { if( this->m_Image.IsNull( ) ) return; // Get filter name QAction* action = dynamic_cast< QAction* >( this->sender( ) ); if( action == NULL ) return; std::string name = action->text( ).toStdString( ); // Configure filter TPluginFilter::Pointer filter = this->m_Plugins.CreateProcessObject( name ); bool dlg_ok = filter->ExecConfigurationDialog( NULL ); if( !dlg_ok ) return; // Execute filter QApplication::setOverrideCursor( Qt::WaitCursor ); this->setEnabled( false ); filter->SetInput( 0, this->m_Image ); std::string err = filter->Update( ); QApplication::restoreOverrideCursor( ); this->setEnabled( true ); // Update image if( err == "" ) { TPluginMesh* result = filter->GetOutput< TPluginMesh >( 0 ); result->DisconnectPipeline( ); this->m_Mesh = result; err = this->_ConfigureMeshActors( ); if( err != "" ) QMessageBox::critical( this, tr( "Error message" ), tr( err.c_str( ) ) ); } else QMessageBox::critical( this, tr( "Error executing filter" ), tr( err.c_str( ) ) ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionUndo() { MementoState memento = MementoState(); if (this->m_state>1) { this->m_state--; this->m_MPRObjects->SetImage( memento.getMemento(this->m_state)->GetOutput() ); } else { QMessageBox::warning( this, tr("message"), tr("No history to undo") ); } } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionRedo() { MementoState memento = MementoState(); if (this->m_state + 1 <= m_max_state) { this->m_state++; this->m_MPRObjects->SetImage( memento.getMemento(this->m_state)->GetOutput() ); } else { QMessageBox::warning( this, tr("message"), tr("No history to redo") ); } } */ // eof - $RCSfile$