diff --git a/CMake/mitkBuildConfigurationWorkbenchRelease.cmake b/CMake/mitkBuildConfigurationWorkbenchRelease.cmake index c89ea2a18c..d354b0bb40 100644 --- a/CMake/mitkBuildConfigurationWorkbenchRelease.cmake +++ b/CMake/mitkBuildConfigurationWorkbenchRelease.cmake @@ -1,3 +1,3 @@ include(${CMAKE_CURRENT_LIST_DIR}/mitkBuildConfigurationDefault.cmake) -set(MITK_VTK_DEBUG_LEAKS FALSE) +set(MITK_VTK_DEBUG_LEAKS OFF CACHE BOOL "Enable VTK Debug Leaks" FORCE) diff --git a/CMake/mitkTestPluginGenerator.cmake b/CMake/mitkTestPluginGenerator.cmake index 001229ec94..971860cbcf 100644 --- a/CMake/mitkTestPluginGenerator.cmake +++ b/CMake/mitkTestPluginGenerator.cmake @@ -1,110 +1,113 @@ if(BUILD_TESTING) set(proj GP) # Means GenerateProject (use a short name due to Windows limitations) set(test_project_out_dir "${MITK_BINARY_DIR}") set(test_project_source_dir "${MITK_BINARY_DIR}/${proj}") set(test_project_binary_dir "${MITK_BINARY_DIR}/${proj}-bin") add_test(NAME mitkPluginGeneratorCleanTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${test_project_source_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest PROPERTIES LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCleanTest2 COMMAND ${CMAKE_COMMAND} -E remove_directory "${test_project_binary_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest2 PROPERTIES LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCleanTest3 COMMAND ${CMAKE_COMMAND} -E make_directory "${test_project_binary_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest3 PROPERTIES DEPENDS mitkPluginGeneratorCleanTest2 LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCreateTest COMMAND ${exec_target} --project-name "${proj}" --project-app-name "TestApp" -ps org.test.plugin -pn "Test Plugin" -vn "Test View" -o ${test_project_out_dir} -y -n ) set_tests_properties(mitkPluginGeneratorCreateTest PROPERTIES DEPENDS "${exec_target};mitkPluginGeneratorCleanTest;mitkPluginGeneratorCleanTest3" LABELS "MITK;BlueBerry") set(configure_options -DMITK_DIR:PATH=${MITK_BINARY_DIR} -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} + -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} -G${CMAKE_GENERATOR} ) if(MITK_USE_Qt4) list(APPEND configure_options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}) endif() if(CMAKE_PREFIX_PATH) list(APPEND configure_options -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH}) endif() if(CMAKE_CONFIGURATION_TYPES) foreach(config ${CMAKE_CONFIGURATION_TYPES}) add_test(NAME mitkPluginGeneratorConfigureTest-${config} CONFIGURATIONS ${config} WORKING_DIRECTORY "${test_project_binary_dir}" COMMAND ${CMAKE_COMMAND} ${configure_options} "${test_project_source_dir}") set_tests_properties(mitkPluginGeneratorConfigureTest-${config} PROPERTIES DEPENDS mitkPluginGeneratorCreateTest LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorBuildTest-${config} CONFIGURATIONS ${config} COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir} --config ${config}) set_tests_properties(mitkPluginGeneratorBuildTest-${config} PROPERTIES DEPENDS mitkPluginGeneratorConfigureTest-${config} LABELS "MITK;BlueBerry") endforeach() else() add_test(NAME mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} WORKING_DIRECTORY "${test_project_binary_dir}" COMMAND ${CMAKE_COMMAND} ${configure_options} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} "${test_project_source_dir}") set_tests_properties(mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS mitkPluginGeneratorCreateTest LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir} --config ${CMAKE_BUILD_TYPE}) set_tests_properties(mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} LABELS "MITK;BlueBerry") endif() set(package_test_configurations) if(WIN32) # Only test packaging if build type is "Release" on Windows set(package_test_configurations CONFIGURATIONS Release) endif() if(NOT MITK_FAST_TESTING) if(WIN32) # Only test packaging if build type is "Release" on Windows add_test(NAME mitkPluginGeneratorPackageTest CONFIGURATIONS Release COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir}/${proj}-build --config Release --target package) set_tests_properties(mitkPluginGeneratorPackageTest PROPERTIES DEPENDS mitkPluginGeneratorBuildTest-Release TIMEOUT 6000 LABELS "MITK;BlueBerry;PACKAGE_TESTS") elseif(CMAKE_BUILD_TYPE) add_test(mitkPluginGeneratorPackageTest ${CMAKE_COMMAND} --build ${test_project_binary_dir}/${proj}-build --config ${CMAKE_BUILD_TYPE} --target package) set_tests_properties(mitkPluginGeneratorPackageTest PROPERTIES DEPENDS mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} TIMEOUT 6000 LABELS "MITK;BlueBerry;PACKAGE_TESTS") endif() endif() endif() diff --git a/CMake/mitkTestProjectTemplate.cmake b/CMake/mitkTestProjectTemplate.cmake index 5fda20517f..64019cc556 100644 --- a/CMake/mitkTestProjectTemplate.cmake +++ b/CMake/mitkTestProjectTemplate.cmake @@ -1,110 +1,113 @@ if(BUILD_TESTING) include(ExternalProject) set(proj PT) # Means ProjectTemplate (use a short name due to Windows limitations) set(MITK-ProjectTemplate_SOURCE_DIR "${MITK_BINARY_DIR}/${proj}") set(MITK-ProjectTemplate_BINARY_DIR "${MITK_BINARY_DIR}/${proj}-bin") add_test(NAME mitkProjectTemplateRmSrcTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${MITK-ProjectTemplate_SOURCE_DIR}" ) set_tests_properties(mitkProjectTemplateRmSrcTest PROPERTIES LABELS "MITK;BlueBerry") add_test(NAME mitkProjectTemplateRmBinTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${MITK-ProjectTemplate_BINARY_DIR}" ) set_tests_properties(mitkProjectTemplateRmBinTest PROPERTIES LABELS "MITK;BlueBerry") add_test(NAME mitkProjectTemplateMakeBinTest COMMAND ${CMAKE_COMMAND} -E make_directory "${MITK-ProjectTemplate_BINARY_DIR}" ) set_tests_properties(mitkProjectTemplateMakeBinTest PROPERTIES DEPENDS mitkProjectTemplateRmBinTest LABELS "MITK;BlueBerry") add_test(NAME mitkProjectTemplateCloneTest COMMAND ${GIT_EXECUTABLE} clone http://git.mitk.org/MITK-ProjectTemplate.git ${MITK-ProjectTemplate_SOURCE_DIR} ) set_tests_properties(mitkProjectTemplateCloneTest PROPERTIES DEPENDS mitkProjectTemplateRmSrcTest LABELS "MITK;BlueBerry") set(configure_options -DMITK_DIR:PATH=${MITK_BINARY_DIR} -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} + -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} -DAwesomeProject_BUILD_ALL_PLUGINS:BOOL=ON -DAwesomeProject_BUILD_ALL_APPS:BOOL=ON -G${CMAKE_GENERATOR} ) if(MITK_USE_Qt4) list(APPEND configure_options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}) endif() if(CMAKE_PREFIX_PATH) list(APPEND configure_options -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH}) endif() if(CMAKE_CONFIGURATION_TYPES) foreach(config ${CMAKE_CONFIGURATION_TYPES}) add_test(NAME mitkProjectTemplateConfigureTest-${config} CONFIGURATIONS ${config} WORKING_DIRECTORY "${MITK-ProjectTemplate_BINARY_DIR}" COMMAND ${CMAKE_COMMAND} ${configure_options} "${MITK-ProjectTemplate_SOURCE_DIR}") set_tests_properties(mitkProjectTemplateConfigureTest-${config} PROPERTIES DEPENDS "mitkProjectTemplateCloneTest;mitkProjectTemplateMakeBinTest" LABELS "MITK;BlueBerry") add_test(NAME mitkProjectTemplateBuildTest-${config} CONFIGURATIONS ${config} COMMAND ${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR} --config ${config}) set_tests_properties(mitkProjectTemplateBuildTest-${config} PROPERTIES DEPENDS mitkProjectTemplateConfigureTest-${config} LABELS "MITK;BlueBerry") endforeach() else() add_test(NAME mitkProjectTemplateConfigureTest-${CMAKE_BUILD_TYPE} WORKING_DIRECTORY "${MITK-ProjectTemplate_BINARY_DIR}" COMMAND ${CMAKE_COMMAND} ${configure_options} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} "${MITK-ProjectTemplate_SOURCE_DIR}") set_tests_properties(mitkProjectTemplateConfigureTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS "mitkProjectTemplateCloneTest;mitkProjectTemplateMakeBinTest" LABELS "MITK;BlueBerry") add_test(NAME mitkProjectTemplateBuildTest-${CMAKE_BUILD_TYPE} COMMAND ${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR} --config ${CMAKE_BUILD_TYPE}) set_tests_properties(mitkProjectTemplateBuildTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS mitkProjectTemplateConfigureTest-${CMAKE_BUILD_TYPE} LABELS "MITK;BlueBerry") endif() set(package_test_configurations) if(WIN32) # Only test packaging if build type is "Release" on Windows set(package_test_configurations CONFIGURATIONS Release) endif() if(NOT MITK_FAST_TESTING) if(WIN32) # Only test packaging if build type is "Release" on Windows add_test(NAME mitkProjectTemplatePackageTest CONFIGURATIONS Release COMMAND ${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR}/AwesomeProject-build --config Release --target package) set_tests_properties(mitkProjectTemplatePackageTest PROPERTIES DEPENDS mitkProjectTemplateBuildTest-Release TIMEOUT 6000 LABELS "MITK;BlueBerry;PACKAGE_TESTS") elseif(CMAKE_BUILD_TYPE) add_test(NAME mitkProjectTemplatePackageTest COMMAND ${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR}/AwesomeProject-build --config ${CMAKE_BUILD_TYPE} --target package) set_tests_properties(mitkProjectTemplatePackageTest PROPERTIES DEPENDS mitkProjectTemplateBuildTest-${CMAKE_BUILD_TYPE} TIMEOUT 6000 LABELS "MITK;BlueBerry;PACKAGE_TESTS") endif() endif() endif() diff --git a/Core/Code/DataManagement/mitkImageVtkReadAccessor.cpp b/Core/Code/DataManagement/mitkImageVtkReadAccessor.cpp index c3f8c3af71..61c439bb3c 100644 --- a/Core/Code/DataManagement/mitkImageVtkReadAccessor.cpp +++ b/Core/Code/DataManagement/mitkImageVtkReadAccessor.cpp @@ -1,61 +1,61 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageVtkReadAccessor.h" #include "mitkImage.h" #include const mitk::Image* mitk::ImageVtkReadAccessor::GetImage() const { return m_Image; } mitk::ImageVtkReadAccessor::ImageVtkReadAccessor( ImageConstPointer iP, const mitk::ImageDataItem* iDI, const vtkImageData* imageDataVtk) - : ImageAccessorBase(NULL, iDI) + : ImageAccessorBase(iP, iDI) , m_Image(iP.GetPointer()) , m_ImageDataVtk(imageDataVtk) { m_Image->m_VtkReadersLock.Lock(); m_Image->m_VtkReaders.push_back(this); //printf("m_VtkReaders.size(): %d\n", (int) m_Image->m_VtkReaders.size()); m_Image->m_VtkReadersLock.Unlock(); } mitk::ImageVtkReadAccessor::~ImageVtkReadAccessor() { m_Image->m_VtkReadersLock.Lock(); std::vector::iterator it = std::find(m_Image->m_VtkReaders.begin(), m_Image->m_VtkReaders.end(), this); if (it != m_Image->m_VtkReaders.end()) { m_Image->m_VtkReaders.erase(it); } //printf("m_VtkReaders.size(): %d\n", (int) m_Image->m_VtkReaders.size()); m_Image->m_VtkReadersLock.Unlock(); } const vtkImageData*mitk::ImageVtkReadAccessor::GetVtkImageData() const { return m_ImageDataVtk; } diff --git a/Core/Code/Internal/mitkImageVtkLegacyIO.cpp b/Core/Code/Internal/mitkImageVtkLegacyIO.cpp index 4ceb996638..a24fd7ed91 100644 --- a/Core/Code/Internal/mitkImageVtkLegacyIO.cpp +++ b/Core/Code/Internal/mitkImageVtkLegacyIO.cpp @@ -1,107 +1,107 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageVtkLegacyIO.h" #include "mitkImage.h" #include "mitkIOMimeTypes.h" #include "mitkImageVtkReadAccessor.h" #include #include #include #include #include namespace mitk { ImageVtkLegacyIO::ImageVtkLegacyIO() - : AbstractFileIO(Image::GetStaticNameOfClass(), IOMimeTypes::VTK_IMAGE_MIMETYPE(), "VTK XML Image") + : AbstractFileIO(Image::GetStaticNameOfClass(), IOMimeTypes::VTK_IMAGE_LEGACY_MIMETYPE(), "VTK Legacy Image") { this->RegisterService(); } std::vector ImageVtkLegacyIO::Read() { // The legay vtk reader cannot work with input streams const std::string fileName = this->GetLocalFileName(); vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(fileName.c_str()); reader->Update(); if ( reader->GetOutput() != NULL ) { mitk::Image::Pointer output = mitk::Image::New(); output->Initialize(reader->GetOutput()); output->SetVolume(reader->GetOutput()->GetScalarPointer()); std::vector result; result.push_back(output.GetPointer()); return result; } else { mitkThrow() << "vtkStructuredPointsReader error: " << vtkErrorCode::GetStringFromErrorCode(reader->GetErrorCode()); } } IFileIO::ConfidenceLevel ImageVtkLegacyIO::GetReaderConfidenceLevel() const { if (AbstractFileIO::GetReaderConfidenceLevel() == Unsupported) return Unsupported; vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(this->GetLocalFileName().c_str()); if (reader->IsFileStructuredPoints()) { return Supported; } return Unsupported; } void ImageVtkLegacyIO::Write() { ValidateOutputLocation(); const Image* input = dynamic_cast(this->GetInput()); vtkSmartPointer writer = vtkSmartPointer::New(); // The legacy vtk image writer cannot write to streams LocalFile localFile(this); writer->SetFileName(localFile.GetFileName().c_str()); - ImageVtkReadAccessor vtkReadAccessor(Image::ConstPointer(input), NULL, NULL); + ImageVtkReadAccessor vtkReadAccessor(Image::ConstPointer(input), NULL, input->GetVtkImageData()); writer->SetInputData(const_cast(vtkReadAccessor.GetVtkImageData())); if (writer->Write() == 0 || writer->GetErrorCode() != 0 ) { mitkThrow() << "vtkStructuredPointesWriter error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()); } } IFileIO::ConfidenceLevel ImageVtkLegacyIO::GetWriterConfidenceLevel() const { if (AbstractFileIO::GetWriterConfidenceLevel() == Unsupported) return Unsupported; const Image* input = static_cast(this->GetInput()); if (input->GetDimension() == 3) return Supported; else if (input->GetDimension() < 3) return PartiallySupported; return Unsupported; } ImageVtkLegacyIO* ImageVtkLegacyIO::IOClone() const { return new ImageVtkLegacyIO(*this); } } diff --git a/Core/Code/Internal/mitkImageVtkXmlIO.cpp b/Core/Code/Internal/mitkImageVtkXmlIO.cpp index cb8c35da10..881f70b890 100644 --- a/Core/Code/Internal/mitkImageVtkXmlIO.cpp +++ b/Core/Code/Internal/mitkImageVtkXmlIO.cpp @@ -1,142 +1,142 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageVtkXmlIO.h" #include "mitkImage.h" #include "mitkIOMimeTypes.h" #include "mitkImageVtkReadAccessor.h" #include #include #include #include #include namespace mitk { class VtkXMLImageDataReader : public ::vtkXMLImageDataReader { public: static VtkXMLImageDataReader *New() { return new VtkXMLImageDataReader(); } vtkTypeMacro(VtkXMLImageDataReader,vtkXMLImageDataReader) void SetStream(std::istream* is) { this->Stream = is; } std::istream* GetStream() const { return this->Stream; } }; class VtkXMLImageDataWriter : public ::vtkXMLImageDataWriter { public: static VtkXMLImageDataWriter *New() { return new VtkXMLImageDataWriter(); } vtkTypeMacro(VtkXMLImageDataWriter,vtkXMLImageDataWriter) void SetStream(std::ostream* os) { this->Stream = os; } std::ostream* GetStream() const { return this->Stream; } }; ImageVtkXmlIO::ImageVtkXmlIO() : AbstractFileIO(Image::GetStaticNameOfClass(), IOMimeTypes::VTK_IMAGE_MIMETYPE(), "VTK XML Image") { this->RegisterService(); } std::vector ImageVtkXmlIO::Read() { vtkSmartPointer reader = vtkSmartPointer::New(); if (this->GetInputStream()) { reader->SetStream(this->GetInputStream()); } else { reader->SetFileName(this->GetInputLocation().c_str()); } reader->Update(); if (reader->GetOutput() != NULL) { mitk::Image::Pointer output = mitk::Image::New(); output->Initialize(reader->GetOutput()); output->SetVolume(reader->GetOutput()->GetScalarPointer()); std::vector result; result.push_back(output.GetPointer()); return result; } else { mitkThrow() << "vtkXMLImageDataReader error: " << vtkErrorCode::GetStringFromErrorCode(reader->GetErrorCode()); } } IFileIO::ConfidenceLevel ImageVtkXmlIO::GetReaderConfidenceLevel() const { if (AbstractFileIO::GetReaderConfidenceLevel() == Unsupported) return Unsupported; if (this->GetInputStream() == NULL) { // check if the xml vtk reader can handle the file vtkSmartPointer xmlReader = vtkSmartPointer::New(); if (xmlReader->CanReadFile(this->GetInputLocation().c_str()) != 0) { return Supported; } return Unsupported; } // in case of an input stream, VTK does not seem to have methods for // validating it return Supported; } void ImageVtkXmlIO::Write() { ValidateOutputLocation(); const Image* input = dynamic_cast(this->GetInput()); vtkSmartPointer writer = vtkSmartPointer::New(); if (this->GetOutputStream()) { writer->SetStream(this->GetOutputStream()); } else { writer->SetFileName(this->GetOutputLocation().c_str()); } - ImageVtkReadAccessor vtkReadAccessor(Image::ConstPointer(input), NULL, NULL); + ImageVtkReadAccessor vtkReadAccessor(Image::ConstPointer(input), NULL, input->GetVtkImageData()); writer->SetInputData(const_cast(vtkReadAccessor.GetVtkImageData())); if (writer->Write() == 0 || writer->GetErrorCode() != 0 ) { mitkThrow() << "vtkXMLImageDataWriter error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()); } } IFileIO::ConfidenceLevel ImageVtkXmlIO::GetWriterConfidenceLevel() const { if (AbstractFileIO::GetWriterConfidenceLevel() == Unsupported) return Unsupported; const Image* input = static_cast(this->GetInput()); if (input->GetDimension() == 3) return Supported; else if (input->GetDimension() < 3) return PartiallySupported; return Unsupported; } ImageVtkXmlIO* ImageVtkXmlIO::IOClone() const { return new ImageVtkXmlIO(*this); } } diff --git a/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox b/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox index be03f2ba30..1b70e25a7f 100644 --- a/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox +++ b/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox @@ -1,46 +1,45 @@ /** \page PluginListPage MITK Plugin Manuals \section PluginListPageOverview Overview The plugins and bundles provide much of the extended functionality of MITK. Each encapsulates a solution to a problem and associated features. This way one can easily assemble the necessary capabilites for a workflow without adding a lot of bloat, by combining plugins as needed. The distinction between developer and end user use is for convenience only and mainly distinguishes which group a plugin is primarily aimed at. \section PluginListPageEndUserPluginList List of Plugins for End User Use \li \subpage org_blueberry_ui_qt_log \li \subpage org_mitk_views_basicimageprocessing \li \subpage org_mitk_views_cmdlinemodules \li \subpage org_mitk_views_datamanager \li \subpage org_mitk_gui_qt_dicom \li \subpage org_mitk_gui_qt_diffusionimaging \li \subpage org_mitk_views_imagecropper \li \subpage org_mitk_views_imagenavigator \li \subpage org_mitk_gui_qt_measurementtoolbox - \li \subpage org_mitk_views_meshdecimation \li \subpage org_mitk_views_moviemaker \li \subpage org_mitk_views_screenshotmaker \li \subpage org_mitk_views_pointsetinteraction \li \subpage org_mitk_gui_qt_python \li \subpage org_mitk_gui_qt_registration \li \subpage org_mitk_gui_qt_remeshing \li \subpage org_mitk_views_segmentation \li \subpage org_mitk_gui_qt_ultrasound \li \subpage org_mitk_gui_qt_viewnavigator \li \subpage org_mitk_views_volumevisualization \li \subpage org_mitk_gui_qt_xnat \section PluginListPageDevPluginList List of Plugins for Developer Use and Examples \li \subpage org_surfacematerialeditor \li \subpage org_toftutorial \li \subpage org_mitk_gui_qt_examples \li \subpage org_mitkexamplesopencv \li \subpage org_mitk_gui_qt_igtexample \li \subpage org_mitk_gui_qt_igttracking \li \subpage org_blueberry_ui_qt_objectinspector \li \subpage org_mitk_gui_qt_eventrecorder */ diff --git a/Modules/AlgorithmsExt/Testing/files.cmake b/Modules/AlgorithmsExt/Testing/files.cmake index 9a9b325349..b9ad765e69 100644 --- a/Modules/AlgorithmsExt/Testing/files.cmake +++ b/Modules/AlgorithmsExt/Testing/files.cmake @@ -1,9 +1,10 @@ set(MODULE_TESTS mitkAutoCropImageFilterTest.cpp mitkBoundingObjectCutterTest.cpp mitkSimpleHistogramTest.cpp + mitkUnstructuredGridToUnstructuredGridFilterTest.cpp ) set(MODULE_CUSTOM_TESTS mitkLabeledImageToSurfaceFilterTest.cpp ) diff --git a/Modules/AlgorithmsExt/Testing/mitkUnstructuredGridToUnstructuredGridFilterTest.cpp b/Modules/AlgorithmsExt/Testing/mitkUnstructuredGridToUnstructuredGridFilterTest.cpp new file mode 100644 index 0000000000..d9109def30 --- /dev/null +++ b/Modules/AlgorithmsExt/Testing/mitkUnstructuredGridToUnstructuredGridFilterTest.cpp @@ -0,0 +1,91 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include +#include +#include + +#include + +#include +#include +#include + +class mitkUnstructuredGridToUnstructuredGridFilterTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkUnstructuredGridToUnstructuredGridFilterTestSuite); + MITK_TEST(testImageToUnstructuredGridFilterInitialization); + MITK_TEST(testInput); + MITK_TEST(testUnstructuredGridGeneration); + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::UnstructuredGrid::Pointer m_UnstructuredGrid; + +public: + + void setUp() + { + m_UnstructuredGrid = mitk::UnstructuredGrid::New(); + vtkSmartPointer vtkGrid = vtkSmartPointer::New(); + vtkSmartPointer points = vtkSmartPointer::New(); + + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + { + for(int k=0; k<3; k++) + { + mitk::Point3D point; + point[0]=i; + point[1]=j; + point[2]=k; + + points->InsertNextPoint(point[0],point[1],point[2]); + } + } + } + + vtkGrid->SetPoints(points); + m_UnstructuredGrid->SetVtkUnstructuredGrid(vtkGrid); + } + + void testImageToUnstructuredGridFilterInitialization() + { + mitk::UnstructuredGridToUnstructuredGridFilter::Pointer testFilter = mitk::UnstructuredGridToUnstructuredGridFilter::New(); + CPPUNIT_ASSERT_MESSAGE("Testing instantiation of test object", testFilter.IsNotNull()); + } + + void testInput() + { + mitk::UnstructuredGridToUnstructuredGridFilter::Pointer testFilter = mitk::UnstructuredGridToUnstructuredGridFilter::New(); + testFilter->SetInput(m_UnstructuredGrid); + CPPUNIT_ASSERT_MESSAGE("Testing set / get input!", testFilter->GetInput() == m_UnstructuredGrid); + } + + void testUnstructuredGridGeneration() + { + mitk::UnstructuredGridToUnstructuredGridFilter::Pointer testFilter = mitk::UnstructuredGridToUnstructuredGridFilter::New(); + testFilter->SetInput(m_UnstructuredGrid); + testFilter->Update(); + CPPUNIT_ASSERT_MESSAGE("Testing surface generation!", testFilter->GetOutput() != NULL); + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkUnstructuredGridToUnstructuredGridFilter) diff --git a/Modules/AlgorithmsExt/files.cmake b/Modules/AlgorithmsExt/files.cmake index 62667e34bc..b7bf93d29d 100644 --- a/Modules/AlgorithmsExt/files.cmake +++ b/Modules/AlgorithmsExt/files.cmake @@ -1,23 +1,24 @@ set(CPP_FILES mitkAutoCropImageFilter.cpp mitkBoundingObjectCutter.cpp mitkBoundingObjectToSegmentationFilter.cpp mitkGeometryClipImageFilter.cpp mitkHeightFieldSurfaceClipImageFilter.cpp mitkLabeledImageToSurfaceFilter.cpp mitkMaskAndCutRoiImageFilter.cpp mitkMaskImageFilter.cpp mitkMovieGenerator.cpp mitkNonBlockingAlgorithm.cpp mitkPadImageFilter.cpp mitkPlaneLandmarkProjector.cpp mitkPointLocator.cpp mitkSimpleHistogram.cpp mitkSimpleUnstructuredGridHistogram.cpp + mitkUnstructuredGridToUnstructuredGridFilter.cpp ) if(WIN32 AND NOT MINGW) list(APPEND CPP_FILES mitkMovieGeneratorWin32.cpp ) endif() diff --git a/Modules/AlgorithmsExt/mitkUnstructuredGridToUnstructuredGridFilter.cpp b/Modules/AlgorithmsExt/mitkUnstructuredGridToUnstructuredGridFilter.cpp new file mode 100644 index 0000000000..f42ba6f924 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkUnstructuredGridToUnstructuredGridFilter.cpp @@ -0,0 +1,62 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include +#include +#include + +#include + +#include + + +mitk::UnstructuredGridToUnstructuredGridFilter::UnstructuredGridToUnstructuredGridFilter() +{ + this->m_UnstructGrid = mitk::UnstructuredGrid::New(); +} + +mitk::UnstructuredGridToUnstructuredGridFilter::~UnstructuredGridToUnstructuredGridFilter(){} + +void mitk::UnstructuredGridToUnstructuredGridFilter::SetInput(const mitk::UnstructuredGrid* image) +{ + this->ProcessObject::SetNthInput(0, const_cast< mitk::UnstructuredGrid* >( image ) ); +} + + +const mitk::UnstructuredGrid* mitk::UnstructuredGridToUnstructuredGridFilter::GetInput(void) +{ + if (this->GetNumberOfInputs() < 1) + { + MITK_ERROR << "No input set" << std::endl; + return 0; + } + + return static_cast( this->ProcessObject::GetInput(0) ); +} + + +void mitk::UnstructuredGridToUnstructuredGridFilter::GenerateOutputInformation() +{ + mitk::UnstructuredGrid::ConstPointer inputImage = this->GetInput(); + + m_UnstructGrid = this->GetOutput(); + + itkDebugMacro(<<"GenerateOutputInformation()"); + + if(inputImage.IsNull()) return; +} diff --git a/Modules/AlgorithmsExt/mitkUnstructuredGridToUnstructuredGridFilter.h b/Modules/AlgorithmsExt/mitkUnstructuredGridToUnstructuredGridFilter.h new file mode 100644 index 0000000000..f50ac1efa1 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkUnstructuredGridToUnstructuredGridFilter.h @@ -0,0 +1,71 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _MITKUNSTRUCTUREDGRIDTOUNSTRUCTUREDGRID_h__ +#define _MITKUNSTRUCTUREDGRIDTOUNSTRUCTUREDGRID_h__ + +#include + +#include + +#include +#include +#include + + +namespace mitk { + + class MitkAlgorithmsExt_EXPORT UnstructuredGridToUnstructuredGridFilter + : public UnstructuredGridSource + { + public: + + mitkClassMacro(UnstructuredGridToUnstructuredGridFilter, UnstructuredGridSource) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Initializes the output information */ + virtual void GenerateOutputInformation(); + + /** Returns a const reference to the input image */ + const mitk::UnstructuredGrid* GetInput(void); + + /** Set the source grid. As input every mitk unstructured grid can be used. */ + using itk::ProcessObject::SetInput; + virtual void SetInput(const UnstructuredGrid *image); + + + protected: + + /** Constructor */ + UnstructuredGridToUnstructuredGridFilter(); + + /** Destructor */ + virtual ~UnstructuredGridToUnstructuredGridFilter(); + + + private: + + /** The output of the filter */ + mitk::UnstructuredGrid::Pointer m_UnstructGrid; + + }; + +} // namespace mitk + +#endif //_MITKUNSTRUCTUREDGRIDTOUNSTRUCTUREDGRID_h__ + + diff --git a/Modules/DiffusionImaging/DiffusionCore/CMakeLists.txt b/Modules/DiffusionImaging/DiffusionCore/CMakeLists.txt index 53c8d0b53e..b0ee596bbe 100644 --- a/Modules/DiffusionImaging/DiffusionCore/CMakeLists.txt +++ b/Modules/DiffusionImaging/DiffusionCore/CMakeLists.txt @@ -1,20 +1,19 @@ # With apple gcc 4.2.1 the following waring leads to an build error if boost is enabled if(APPLE) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=empty-body" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() MITK_CREATE_MODULE( SUBPROJECTS MITK-DTI INCLUDE_DIRS Algorithms Algorithms/Reconstruction Algorithms/Registration Algorithms/Reconstruction/MultishellProcessing DicomImport IODataStructures/DiffusionWeightedImages IODataStructures/QBallImages IODataStructures/TensorImages IODataStructures Rendering ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MitkMapperExt MitkPlanarFigure MitkImageExtraction MitkSceneSerializationBase MitkDICOMReader PACKAGE_DEPENDS VTK|vtkFiltersProgrammable ITK|ITKDistanceMap+ITKRegistrationCommon+ITKLabelVoting+ITKVTK Boost ITK|ITKMetricsv4+ITKRegistrationMethodsv4 WARNINGS_AS_ERRORS ) if(MSVC) - list(APPEND module_compile_flags /wd4005) - set_target_properties(${MODULE_TARGET} PROPERTIES COMPILE_FLAGS "${module_compile_flags}") - endif() + mitkFunctionCheckCAndCXXCompilerFlags("/wd4005" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) +endif() add_subdirectory(Testing) diff --git a/Modules/GPGPU/mitkGPGPU.cpp b/Modules/GPGPU/mitkGPGPU.cpp index 56de055027..abb8c2320c 100644 --- a/Modules/GPGPU/mitkGPGPU.cpp +++ b/Modules/GPGPU/mitkGPGPU.cpp @@ -1,627 +1,627 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkGPGPU.h" #include #define GPGPU_INFO MITK_INFO("mitk.gpgpu") #define GPGPU_ERROR MITK_ERROR("mitk.gpgpu") #define GPGPU_CHECKGLERR MITK_ERROR(glGetError()!=GL_NO_ERROR)("mitk.gpgpu") << "GL ERROR @ " #define OPERATING_TEXTURE GL_TEXTURE15 static GLint convertTextureFormatToInternalFormatGL(mitk::GPGPU::TextureFormat format) { switch(format) { case mitk::GPGPU::FLOAT32_LUMINANCE: return GL_LUMINANCE_FLOAT32_ATI; case mitk::GPGPU::FLOAT32_LUMINANCE_ALPHA: return GL_LUMINANCE_ALPHA_FLOAT32_ATI; case mitk::GPGPU::FLOAT32_RGBA: return GL_RGBA32F_ARB; case mitk::GPGPU::UINT8_RGBA: return GL_RGBA8; } return 0; } static GLint convertTextureFormatToFormatGL(mitk::GPGPU::TextureFormat format) { switch(format) { case mitk::GPGPU::FLOAT32_LUMINANCE: return GL_LUMINANCE; case mitk::GPGPU::FLOAT32_LUMINANCE_ALPHA: return GL_LUMINANCE_ALPHA; case mitk::GPGPU::FLOAT32_RGBA: return GL_RGBA; case mitk::GPGPU::UINT8_RGBA: return GL_RGBA; } return 0; } static GLint convertTextureFormatToTypeGL(mitk::GPGPU::TextureFormat format) { switch(format) { case mitk::GPGPU::FLOAT32_LUMINANCE: return GL_FLOAT; case mitk::GPGPU::FLOAT32_LUMINANCE_ALPHA: return GL_FLOAT; case mitk::GPGPU::FLOAT32_RGBA: return GL_FLOAT; case mitk::GPGPU::UINT8_RGBA: return GL_UNSIGNED_BYTE; } return 0; } int mitk::GPGPU::Texture::GetWidth(){return myWidth;} int mitk::GPGPU::Texture::GetHeigth(){return myHeight;} int mitk::GPGPU::Texture::GetDepth(){return myDepth;} mitk::GPGPU::Texture::Texture(mitk::GPGPU::TextureFormat format,int width,int height,int depth) { if(depth==0) glTarget=GL_TEXTURE_2D; else glTarget=GL_TEXTURE_3D; myFormat=format; myWidth=width; myHeight=height; myDepth=depth; GLuint handle; glGenTextures(1,&handle); glTextureHandle = handle; glActiveTexture(OPERATING_TEXTURE); glBindTexture(glTarget,glTextureHandle); GPGPU_CHECKGLERR << "allocating texture handle"; if(glTarget==GL_TEXTURE_2D) { glTexImage2D(GL_TEXTURE_2D,0,convertTextureFormatToInternalFormatGL(myFormat),width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,0); // glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); } else { glTexImage3D(GL_TEXTURE_3D,0,convertTextureFormatToInternalFormatGL(myFormat),width,height,depth,0,GL_RGBA,GL_UNSIGNED_BYTE,0); // glGenerateMipmap(GL_TEXTURE_3D); glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); } GPGPU_CHECKGLERR << "declaring texture format&dimensions"; glGenFramebuffers(1,&handle); glFBOHandle = handle; GPGPU_CHECKGLERR << "allocating framebuffer object"; } mitk::GPGPU::Texture::~Texture() { GLuint handle; handle=glFBOHandle; glDeleteFramebuffers(1,&handle); GPGPU_CHECKGLERR << "deleting framebufferobject"; handle=glTextureHandle; glDeleteTextures(1,&handle); GPGPU_CHECKGLERR << "deleting texture handle"; } void mitk::GPGPU::Texture::ActivateAsSource(int unit) { glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(glTarget,glTextureHandle); GPGPU_CHECKGLERR << "binding texture to unit"; } void mitk::GPGPU::Texture::ActivateAsDestination() { static GLenum buffers[5][4] = { { GL_NONE, GL_NONE, GL_NONE, GL_NONE }, { GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE, GL_NONE }, { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_NONE, GL_NONE }, { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_NONE }, { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }, }; glBindFramebuffer( GL_FRAMEBUFFER, glFBOHandle ); glDrawBuffers(4, buffers[1]); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glTarget,glTextureHandle,0); GPGPU_CHECKGLERR << "associating texture to framebufferobject"; int error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch(error) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: GPGPU_ERROR << "Incomplete attachment\n";break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: GPGPU_ERROR << "Missing attachment\n";break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: GPGPU_ERROR << "Incomplete dimensions\n";break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: GPGPU_ERROR << "Incomplete formats\n";break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: GPGPU_ERROR << "Incomplete draw buffer\n";break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: GPGPU_ERROR << "Incomplete read buffer\n";break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: GPGPU_ERROR << "Framebufferobjects unsupported\n";break; default: GPGPU_ERROR << "unknown framebuffer status\n";break; } glViewport(0,0,myWidth,myHeight); GPGPU_CHECKGLERR << "setting viewport"; } void mitk::GPGPU::Texture::Upload(TextureFormat inputformat,const void *src) { glActiveTexture(OPERATING_TEXTURE); glBindTexture(glTarget,glTextureHandle); if(glTarget==GL_TEXTURE_2D) { glTexSubImage2D(GL_TEXTURE_2D,0,0,0,myWidth,myHeight,convertTextureFormatToFormatGL(inputformat),convertTextureFormatToTypeGL(inputformat),src); } else { glTexSubImage3D(GL_TEXTURE_3D,0,0,0,0,myWidth,myHeight,myDepth,convertTextureFormatToFormatGL(inputformat),convertTextureFormatToTypeGL(inputformat),src); } GPGPU_CHECKGLERR << "texture upload to gpu"; } void mitk::GPGPU::Texture::Download(TextureFormat inputformat,void *dst) { glActiveTexture(OPERATING_TEXTURE); glBindTexture(glTarget,glTextureHandle); if(glTarget==GL_TEXTURE_2D) { glGetTexImage( GL_TEXTURE_2D,0,convertTextureFormatToFormatGL(inputformat),convertTextureFormatToTypeGL(inputformat),dst); GPGPU_CHECKGLERR << "texture download to cpu"; } else { } } static char stubVertexShader[] = "void main() { gl_Position = vec4( 2*gl_Vertex.xy-1,0,1 ); }\n"; mitk::GPGPU::Shader::Shader(char *source) { //std::cout << "compiling shader:\n" << source << std::endl; glHandleVertex = glCreateShader(GL_VERTEX_SHADER); glHandleFragment = glCreateShader(GL_FRAGMENT_SHADER); glHandleProgram = glCreateProgram(); GLchar *src[2]; src[0] = stubVertexShader; src[1] = 0; glShaderSource(glHandleVertex,1,(const GLchar **)src,0); src[0] = source; src[1] = 0; glShaderSource(glHandleFragment,1,(const GLchar **)src,0); bool failed=false; GLint _sv,_sf,_sl; glCompileShader( glHandleVertex ); GPGPU_CHECKGLERR << "compiling vertex shader"; glGetShaderiv( glHandleVertex, GL_COMPILE_STATUS, &_sv); if( !_sv) { GPGPU_ERROR << "vertex shader compilation failed\n"; failed=true; } glCompileShader( glHandleFragment ); GPGPU_CHECKGLERR << "compiling fragment shader"; glGetShaderiv( glHandleFragment, GL_COMPILE_STATUS, &_sf); if( !_sf) { GPGPU_ERROR << "fragment shader compilation failed\n"; failed=true; } glAttachShader( glHandleProgram,glHandleVertex ); glAttachShader( glHandleProgram,glHandleFragment ); glLinkProgram( glHandleProgram ); GPGPU_CHECKGLERR << "linking shader program"; glGetProgramiv( glHandleProgram, GL_LINK_STATUS, &_sl); if( !_sl) { GPGPU_ERROR << "shader linkage failed\n"; failed=true; } if(failed) { int infologLength = 0; int charsWritten = 0; char *infoLog; glGetProgramiv(glHandleProgram, GL_INFO_LOG_LENGTH,&infologLength); if (infologLength > 0) { infoLog = (char *)malloc(infologLength); glGetProgramInfoLog(glHandleProgram, infologLength, &charsWritten, infoLog); GPGPU_ERROR << "SHADER CREATION FAILED INFOLOG:\n" << infoLog; free(infoLog); } } } mitk::GPGPU::Shader::~Shader() { glDeleteProgram( glHandleProgram); glDeleteShader( glHandleVertex ); glDeleteShader( glHandleFragment ); } void mitk::GPGPU::Shader::Activate() { glUseProgram( glHandleProgram ); GPGPU_CHECKGLERR << "activating shader"; } int mitk::GPGPU::Shader::GetUniformLocation(char *name) { return glGetUniformLocation(glHandleProgram,name); } void mitk::GPGPU::Shader::SetUniform(char *name,int i0) { glUniform1i( GetUniformLocation(name) , i0); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,int i0,int i1) { GLint i[2]; i[0]=i0; i[1]=i1; glUniform2iv( GetUniformLocation(name) , 1 , i ); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,int i0,int i1,int i2) { GLint i[3]; i[0]=i0; i[1]=i1; i[2]=i2; glUniform3iv( GetUniformLocation(name) , 1 , i ); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,int i0,int i1,int i2,int i3) { GLint i[4]; i[0]=i0; i[1]=i1; i[2]=i2; i[3]=i3; glUniform4iv( GetUniformLocation(name) , 1 , i ); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,float i0) { GLint location = GetUniformLocation(name); glUniform1f(location,i0); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,float i0,float i1) { GLfloat i[2]; i[0]=i0; i[1]=i1; glUniform2fv(GetUniformLocation(name),1,i); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,float i0,float i1,float i2) { GLfloat i[3]; i[0]=i0; i[1]=i1; i[2]=i2; glUniform3fv(GetUniformLocation(name),1,i); GPGPU_CHECKGLERR << "setting uniform"; } void mitk::GPGPU::Shader::SetUniform(char *name,float i0,float i1,float i2,float i3) { GLfloat i[4]; i[0]=i0; i[1]=i1; i[2]=i2; i[3]=i3; glUniform4fv(GetUniformLocation(name),1,i); GPGPU_CHECKGLERR << "setting uniform"; } #ifdef _WIN32 LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } #endif mitk::GPGPU::GPGPU() { #ifdef _WIN32 /* WNDCLASSEX wcx; // Fill in the window class structure with parameters // that describe the main window. wcx.cbSize = sizeof(wcx); // size of structure wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes wcx.lpfnWndProc = MainWndProc; // points to window procedure wcx.cbClsExtra = 0; // no extra class memory wcx.cbWndExtra = 0; // no extra window memory wcx.hInstance = GetModuleHandle(NULL); // handle to inst ance wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); // predefined app. icon wcx.hCursor = LoadCursor(NULL, IDC_ARROW); // predefined arrow wcx.hbrBackground = NULL; // white background brush wcx.lpszMenuName = (LPCSTR) "MainMenu"; // name of menu resource wcx.lpszClassName = (LPCSTR) "MainWClass"; // name of window class wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Register the window class. if(!RegisterClassEx(&wcx)) std::cout << "failed registering window class\n"; HWND desktopWindow=CreateWindowEx( WS_EX_CLIENTEDGE, (LPCSTR)"MainWClass", (LPCSTR)"Anatomy of a Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, GetModuleHandle(NULL), NULL); windowHandle = desktopWindow; ShowWindow(desktopWindow, SW_RESTORE); if(desktopWindow==0) std::cout << "failed creating window\n"; */ - HWND desktopWindow=QApplication::topLevelWidgets().at(0)->winId(); + HWND desktopWindow= (HWND)QApplication::topLevelWidgets().at(0)->winId(); windowsContext = GetDC(desktopWindow); if(windowsContext==0) std::cout << "failed getting window device context\n"; static PIXELFORMATDESCRIPTOR pfd =// pfd Tells Windows How We Want Things To Be { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE , // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format 24, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored if(openGLContext==0) 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 0, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; // Sonstiges einstellen int iFormat = ChoosePixelFormat(windowsContext,&pfd); SetPixelFormat(windowsContext,iFormat,&pfd); openGLContext = wglCreateContext(windowsContext); int errw=GetLastError(); if(openGLContext==0) std::cout << "failed creating openGL context "<winId(); GPGPU_ERROR( !GLX_drawable ) << "cant get toplevel widget from QT"; static int visAttributes[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; XVisualInfo *visinfo = glXChooseVisual(X_display, 0, visAttributes); GPGPU_ERROR(!visinfo) << "Unable to choose specified visual!"; openGLContext = glXCreateContext(X_display, visinfo, 0, true); if(visinfo) XFree(visinfo); GPGPU_ERROR(!openGLContext) << "cant create GLX context"; #endif Activate(); GPGPU_INFO << "initializing glew"; int err=glewInit(); GPGPU_CHECKGLERR << "initializing glew"; GPGPU_ERROR(GLEW_OK != err) << "glewInit() fails with " << err << " as text: " << glewGetErrorString(err); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1,0,1,-1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GPGPU_CHECKGLERR << "intializing projection&modelview matrix"; glDisable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); // Enable Smooth Shading glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background glClearDepth(1.0f); // Depth Buffer Setup glDisable(GL_DEPTH_TEST); // Enables Depth Testing glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); glDepthMask(false); GPGPU_CHECKGLERR << "setting up openGL context"; } mitk::GPGPU::~GPGPU() { #ifdef _WIN32 wglDeleteContext( openGLContext ); #else if(openGLContext) glXDestroyContext(X_display,openGLContext); if(X_display) XCloseDisplay(X_display); #endif } void mitk::GPGPU::Activate() { #ifdef _WIN32 wglMakeCurrent(windowsContext,openGLContext); #else glXMakeCurrent(X_display, GLX_drawable, openGLContext); #endif GPGPU_CHECKGLERR << "activating openGL context"; } void mitk::GPGPU::Deactivate() { } void mitk::GPGPU::Run() { glBegin( GL_TRIANGLE_STRIP ); glVertex2f( 0,0 ); glVertex2f( 0,1 ); glVertex2f( 1,0 ); glVertex2f( 1,1 ); glEnd(); GPGPU_CHECKGLERR << "running a shader"; } void mitk::GPGPU::Run(float start,float end) { glBegin( GL_TRIANGLE_STRIP ); glVertex2f( 0,start ); glVertex2f( 0,end ); glVertex2f( 1,start ); glVertex2f( 1,end ); glEnd(); GPGPU_CHECKGLERR << "running a shader"; } diff --git a/Modules/QtWidgets/QmitkFileReaderOptionsDialog.ui b/Modules/QtWidgets/QmitkFileReaderOptionsDialog.ui index 3ee173c788..5e5e9d6748 100644 --- a/Modules/QtWidgets/QmitkFileReaderOptionsDialog.ui +++ b/Modules/QtWidgets/QmitkFileReaderOptionsDialog.ui @@ -1,147 +1,131 @@ QmitkFileReaderOptionsDialog 0 0 - 458 - 343 + 272 + 186 Dialog - true + false true + + QLayout::SetFixedSize + Choose file reader true - - - 0 - 0 - - Options false - - - - Qt::Vertical - - - - 20 - 10 - - - - - Remember settings for all remaining files of the same type + Apply to the next files with same type Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() QmitkFileReaderOptionsDialog accept() 248 254 157 274 buttonBox rejected() QmitkFileReaderOptionsDialog reject() 316 260 286 274 m_ReaderComboBox currentIndexChanged(int) m_StackedOptionsWidget setCurrentIndex(int) 199 44 203 167 diff --git a/Modules/QtWidgets/QmitkFileWriterOptionsDialog.ui b/Modules/QtWidgets/QmitkFileWriterOptionsDialog.ui index a86d37ed1a..dd38619b01 100644 --- a/Modules/QtWidgets/QmitkFileWriterOptionsDialog.ui +++ b/Modules/QtWidgets/QmitkFileWriterOptionsDialog.ui @@ -1,147 +1,131 @@ QmitkFileWriterOptionsDialog 0 0 - 458 - 343 + 272 + 186 Dialog - true + false true + + QLayout::SetFixedSize + Choose file writer true - - - 0 - 0 - - Options false - - - - Qt::Vertical - - - - 20 - 10 - - - - - Remember settings for all remaining files of the same type + Apply to the next files with same type Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() QmitkFileWriterOptionsDialog accept() 248 254 157 274 buttonBox rejected() QmitkFileWriterOptionsDialog reject() 316 260 286 274 m_WriterComboBox currentIndexChanged(int) m_StackedOptionsWidget setCurrentIndex(int) 199 44 203 167 diff --git a/Modules/QtWidgets/QmitkIOUtil.cpp b/Modules/QtWidgets/QmitkIOUtil.cpp index 8f2576dd14..8d170d27cb 100644 --- a/Modules/QtWidgets/QmitkIOUtil.cpp +++ b/Modules/QtWidgets/QmitkIOUtil.cpp @@ -1,528 +1,548 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIOUtil.h" #include #include #include #include "mitkCoreServices.h" #include "mitkIMimeTypeProvider.h" #include "mitkMimeType.h" #include "mitkCustomMimeType.h" #include "mitkFileReaderRegistry.h" #include "mitkFileWriterRegistry.h" #include "QmitkFileReaderOptionsDialog.h" #include "QmitkFileWriterOptionsDialog.h" // QT #include #include #include #include //ITK #include #include struct QmitkIOUtil::Impl { struct ReaderOptionsDialogFunctor : public ReaderOptionsFunctorBase { virtual bool operator()(LoadInfo& loadInfo) { QmitkFileReaderOptionsDialog dialog(loadInfo); if (dialog.exec() == QDialog::Accepted) { return !dialog.ReuseOptions(); } else { loadInfo.m_Cancel = true; return true; } } }; struct WriterOptionsDialogFunctor : public WriterOptionsFunctorBase { virtual bool operator()(SaveInfo& saveInfo) { QmitkFileWriterOptionsDialog dialog(saveInfo); if (dialog.exec() == QDialog::Accepted) { return !dialog.ReuseOptions(); } else { saveInfo.m_Cancel = true; return true; } } }; }; struct MimeTypeComparison : public std::unary_function { MimeTypeComparison(const std::string& mimeTypeName) : m_Name(mimeTypeName) {} bool operator()(const mitk::MimeType& mimeType) const { return mimeType.GetName() == m_Name; } const std::string m_Name; }; QString QmitkIOUtil::GetFileOpenFilterString() { QString filters; mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); std::vector categories = mimeTypeProvider->GetCategories(); for (std::vector::iterator cat = categories.begin(); cat != categories.end(); ++cat) { QSet filterExtensions; std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForCategory(*cat); for (std::vector::iterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt) { std::vector extensions = mt->GetExtensions(); for (std::vector::iterator ext = extensions.begin(); ext != extensions.end(); ++ext) { filterExtensions << QString::fromStdString(*ext); } } QString filter = QString::fromStdString(*cat) + " ("; foreach(const QString& extension, filterExtensions) { filter += "*." + extension + " "; } filter = filter.replace(filter.size()-1, 1, ')'); filters += ";;" + filter; } - filters.prepend("All (*.*)"); + filters.prepend("All (*)"); return filters; } QList QmitkIOUtil::Load(const QStringList& paths, QWidget* parent) { std::vector loadInfos; foreach(const QString& file, paths) { loadInfos.push_back(LoadInfo(file.toStdString())); } Impl::ReaderOptionsDialogFunctor optionsCallback; std::string errMsg = Load(loadInfos, NULL, NULL, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error reading files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } QList qResult; for(std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { for (std::vector::const_iterator dataIter = iter->m_Output.begin(), dataIterEnd = iter->m_Output.end(); dataIter != dataIterEnd; ++dataIter) { qResult << *dataIter; } } return qResult; } mitk::DataStorage::SetOfObjects::Pointer QmitkIOUtil::Load(const QStringList& paths, mitk::DataStorage& storage, QWidget* parent) { std::vector loadInfos; foreach(const QString& file, paths) { loadInfos.push_back(LoadInfo(QFile::encodeName(file).constData())); } mitk::DataStorage::SetOfObjects::Pointer nodeResult = mitk::DataStorage::SetOfObjects::New(); Impl::ReaderOptionsDialogFunctor optionsCallback; std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error reading files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } return nodeResult; } QList QmitkIOUtil::Load(const QString& path, QWidget* parent) { QStringList paths; paths << path; return Load(paths, parent); } mitk::DataStorage::SetOfObjects::Pointer QmitkIOUtil::Load(const QString& path, mitk::DataStorage& storage, QWidget* parent) { QStringList paths; paths << path; return Load(paths, storage, parent); } QString QmitkIOUtil::Save(const mitk::BaseData* data, const QString& defaultBaseName, const QString& defaultPath, QWidget* parent) { std::vector dataVector; dataVector.push_back(data); QStringList defaultBaseNames; defaultBaseNames.push_back(defaultBaseName); return Save(dataVector, defaultBaseNames, defaultPath, parent).back(); } QStringList QmitkIOUtil::Save(const std::vector& data, const QStringList& defaultBaseNames, const QString& defaultPath, QWidget* parent) { QStringList fileNames; QString currentPath = defaultPath; std::vector saveInfos; int counter = 0; for(std::vector::const_iterator dataIter = data.begin(), dataIterEnd = data.end(); dataIter != dataIterEnd; ++dataIter, ++counter) { SaveInfo saveInfo(*dataIter, mitk::MimeType(), std::string()); SaveFilter filters(saveInfo); // If there is only the "__all__" filter string, it means there is no writer for this base data if (filters.Size() < 2) { QMessageBox::warning(parent, "Saving not possible", QString("No writer available for type \"%1\"").arg( QString::fromStdString((*dataIter)->GetNameOfClass()))); continue; } // Construct a default path and file name QString filterString = filters.ToString(); QString selectedFilter = filters.GetDefaultFilter(); QString fileName = currentPath; QString dialogTitle = "Save " + QString::fromStdString((*dataIter)->GetNameOfClass()); if (counter < defaultBaseNames.size()) { dialogTitle += " \"" + defaultBaseNames[counter] + "\""; fileName += QDir::separator() + defaultBaseNames[counter]; // We do not append an extension to the file name by default. The extension // is chosen by the user by either selecting a filter or writing the // extension in the file name himself (in the file save dialog). /* QString defaultExt = filters.GetDefaultExtension(); if (!defaultExt.isEmpty()) { fileName += "." + defaultExt; } */ } // Ask the user for a file name QString nextName = QFileDialog::getSaveFileName(parent, dialogTitle, fileName, filterString, &selectedFilter); if (nextName.isEmpty()) { // We stop asking for further file names, but we still save the // data where the user already confirmed the save dialog. break; } fileName = nextName; std::string stdFileName = QFile::encodeName(fileName).constData(); QFileInfo fileInfo(fileName); currentPath = fileInfo.absolutePath(); QString suffix = fileInfo.completeSuffix(); - mitk::MimeType mimeType = filters.GetMimeTypeForFilter(selectedFilter); + mitk::MimeType filterMimeType = filters.GetMimeTypeForFilter(selectedFilter); + mitk::MimeType selectedMimeType; - mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); - // If the filename contains a suffix, use it but check if it is valid - if (!suffix.isEmpty()) + if (fileInfo.exists() && !fileInfo.isFile()) { - std::vector availableTypes = mimeTypeProvider->GetMimeTypesForFile(stdFileName); - - // Check if the selected mime-type is related to the specified suffix (file extension). - // If not, get the best matching mime-type for the suffix. - if (std::find(availableTypes.begin(), availableTypes.end(), mimeType) == availableTypes.end()) - { - mimeType = mitk::MimeType(); - for (std::vector::const_iterator availIter = availableTypes.begin(), - availIterEnd = availableTypes.end(); availIter != availIterEnd; ++availIter) - { - if (filters.ContainsMimeType(availIter->GetName())) - { - mimeType = *availIter; - break; - } - } - } + QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not a file").arg(fileName)); + continue; + } - if (!mimeType.IsValid()) + // Check if one of the available mime-types match the filename + std::vector filterMimeTypes = filters.GetMimeTypes(); + for (std::vector::const_iterator mimeTypeIter = filterMimeTypes.begin(), + mimeTypeIterEnd = filterMimeTypes.end(); mimeTypeIter != mimeTypeIterEnd; ++mimeTypeIter) + { + if (mimeTypeIter->AppliesTo(stdFileName)) { - // The extension is not valid (no mime-type found), bail out - QMessageBox::warning(parent, - "Saving not possible", - QString("Extension \"%1\" unknown for type \"%2\"") - .arg(suffix) - .arg(QString::fromStdString((*dataIter)->GetNameOfClass()))); - continue; + selectedMimeType = *mimeTypeIter; + break; } } - else + + if (!selectedMimeType.IsValid()) { - // Create a default suffix, unless the file already exists and the user - // already confirmed to overwrite it (without using a suffix) - if (mimeType == SaveFilter::ALL_MIMETYPE()) - { - // Use the highest ranked mime-type from the list - mimeType = filters.GetDefaultMimeType(); - } + // The file name either does not contain an extension or the + // extension is unknown. + + // If the file already exists, we stop here because we are not able + // to (over)write the file without adding a custom suffix. If the file + // does not exist, we add the default extension from the currently + // selected filter. If the "All" filter was selected, we only add the + // default extensions if the file name itself does not already contain + // an extension. if (!fileInfo.exists()) { - suffix = QString::fromStdString(mimeType.GetExtensions().front()); - fileName += "." + suffix; - // We changed the file name (added a suffix) so ask in case - // the file aready exists. - fileInfo = QFileInfo(fileName); - if (fileInfo.exists()) + if (filterMimeType == SaveFilter::ALL_MIMETYPE()) { - if (!fileInfo.isFile()) + if (suffix.isEmpty()) { - QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not a file").arg(fileName)); - continue; + // Use the highest ranked mime-type from the list + selectedMimeType = filters.GetDefaultMimeType(); } - if (QMessageBox::question(parent, "Replace File", - QString("A file named \"%1\" already exists. Do you want to replace it?").arg(fileName)) == - QMessageBox::No) + } + else + { + selectedMimeType = filterMimeType; + } + + if (selectedMimeType.IsValid()) + { + suffix = QString::fromStdString(selectedMimeType.GetExtensions().front()); + fileName += "." + suffix; + stdFileName = QFile::encodeName(fileName).constData(); + // We changed the file name (added a suffix) so ask in case + // the file aready exists. + fileInfo = QFileInfo(fileName); + if (fileInfo.exists()) { - continue; + if (!fileInfo.isFile()) + { + QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not a file").arg(fileName)); + continue; + } + if (QMessageBox::question(parent, "Replace File", + QString("A file named \"%1\" already exists. Do you want to replace it?").arg(fileName)) == + QMessageBox::No) + { + continue; + } } } } } + if (!selectedMimeType.IsValid()) + { + // The extension/filename is not valid (no mime-type found), bail out + QMessageBox::warning(parent, + "Saving not possible", + QString("No mime-type available which can handle \"%1\".") + .arg(fileName)); + continue; + } + if (!QFileInfo(fileInfo.absolutePath()).isWritable()) { QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not writable").arg(fileName)); continue; } fileNames.push_back(fileName); saveInfo.m_Path = stdFileName; - saveInfo.m_MimeType = mimeType; + saveInfo.m_MimeType = selectedMimeType; // pre-select the best writer for the chosen mime-type - saveInfo.m_WriterSelector.Select(mimeType.GetName()); + saveInfo.m_WriterSelector.Select(selectedMimeType.GetName()); saveInfos.push_back(saveInfo); } if (!saveInfos.empty()) { Impl::WriterOptionsDialogFunctor optionsCallback; std::string errMsg = Save(saveInfos, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error writing files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } } return fileNames; } void QmitkIOUtil::SaveBaseDataWithDialog(mitk::BaseData* data, std::string fileName, QWidget* /*parent*/) { Save(data, fileName); } void QmitkIOUtil::SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName, QWidget* /*parent*/) { Save(surface, fileName); } void QmitkIOUtil::SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName, QWidget* /*parent*/) { Save(image, fileName); } void QmitkIOUtil::SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName, QWidget* /*parent*/) { Save(pointset, fileName); } struct QmitkIOUtil::SaveFilter::Impl { Impl(const mitk::IOUtil::SaveInfo& saveInfo) : m_SaveInfo(saveInfo) { // Add an artifical filter for "All" m_MimeTypes.push_back(ALL_MIMETYPE()); m_FilterStrings.push_back("All (*.*)"); // Get all writers and their mime types for the given base data type // (this is sorted already) std::vector mimeTypes = saveInfo.m_WriterSelector.GetMimeTypes(); for (std::vector::const_reverse_iterator iter = mimeTypes.rbegin(), iterEnd = mimeTypes.rend(); iter != iterEnd; ++iter) { QList filterExtensions; mitk::MimeType mimeType = *iter; std::vector extensions = mimeType.GetExtensions(); for (std::vector::iterator extIter = extensions.begin(), extIterEnd = extensions.end(); extIter != extIterEnd; ++extIter) { filterExtensions << QString::fromStdString(*extIter); } if (m_DefaultExtension.isEmpty()) { m_DefaultExtension = QString::fromStdString(extensions.front()); } QString filter = QString::fromStdString(mimeType.GetComment()) + " ("; foreach(const QString& extension, filterExtensions) { filter += "*." + extension + " "; } filter = filter.replace(filter.size()-1, 1, ')'); m_MimeTypes.push_back(mimeType); m_FilterStrings.push_back(filter); } } const mitk::IOUtil::SaveInfo m_SaveInfo; std::vector m_MimeTypes; QStringList m_FilterStrings; QString m_DefaultExtension; }; mitk::MimeType QmitkIOUtil::SaveFilter::ALL_MIMETYPE() { static mitk::CustomMimeType allMimeType(std::string("__all__")); return mitk::MimeType(allMimeType, -1, -1); } QmitkIOUtil::SaveFilter::SaveFilter(const QmitkIOUtil::SaveFilter& other) : d(new Impl(*other.d)) { } QmitkIOUtil::SaveFilter::SaveFilter(const SaveInfo& saveInfo) : d(new Impl(saveInfo)) { } QmitkIOUtil::SaveFilter& QmitkIOUtil::SaveFilter::operator=(const QmitkIOUtil::SaveFilter& other) { d.reset(new Impl(*other.d)); return *this; } +std::vector QmitkIOUtil::SaveFilter::GetMimeTypes() const +{ + return d->m_MimeTypes; +} + QString QmitkIOUtil::SaveFilter::GetFilterForMimeType(const std::string& mimeType) const { std::vector::const_iterator iter = std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)); if (iter == d->m_MimeTypes.end()) { return QString(); } int index = static_cast(iter - d->m_MimeTypes.begin()); if (index < 0 || index >= d->m_FilterStrings.size()) { return QString(); } return d->m_FilterStrings[index]; } mitk::MimeType QmitkIOUtil::SaveFilter::GetMimeTypeForFilter(const QString& filter) const { int index = d->m_FilterStrings.indexOf(filter); if (index < 0) { return mitk::MimeType(); } return d->m_MimeTypes[index]; } QString QmitkIOUtil::SaveFilter::GetDefaultFilter() const { if (d->m_FilterStrings.size() > 1) { return d->m_FilterStrings.at(1); } else if (d->m_FilterStrings.size() > 0) { return d->m_FilterStrings.front(); } return QString(); } QString QmitkIOUtil::SaveFilter::GetDefaultExtension() const { return d->m_DefaultExtension; } mitk::MimeType QmitkIOUtil::SaveFilter::GetDefaultMimeType() const { if (d->m_MimeTypes.size() > 1) { return d->m_MimeTypes.at(1); } else if (d->m_MimeTypes.size() > 0) { return d->m_MimeTypes.front(); } return mitk::MimeType(); } QString QmitkIOUtil::SaveFilter::ToString() const { return d->m_FilterStrings.join(";;"); } int QmitkIOUtil::SaveFilter::Size() const { return d->m_FilterStrings.size(); } bool QmitkIOUtil::SaveFilter::IsEmpty() const { return d->m_FilterStrings.isEmpty(); } bool QmitkIOUtil::SaveFilter::ContainsMimeType(const std::string& mimeType) { return std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)) != d->m_MimeTypes.end(); } diff --git a/Modules/QtWidgets/QmitkIOUtil.h b/Modules/QtWidgets/QmitkIOUtil.h index ac3d1bd5a3..3cca02851d 100644 --- a/Modules/QtWidgets/QmitkIOUtil.h +++ b/Modules/QtWidgets/QmitkIOUtil.h @@ -1,234 +1,229 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QmitkIOUtil__h_ #define _QmitkIOUtil__h_ #include "MitkQtWidgetsExports.h" // std #include // mitk includes #include #include #include #include #include #include #include #include //Qt #include #include #include #include class QWidget; class QString; class QStringList; namespace mitk { class DataStorage; class MimeType; struct IFileReader; } /** * @brief QmitkIOUtil Provides static helper methods to open and save files with Qt dialogs. */ class QMITK_EXPORT QmitkIOUtil : public mitk::IOUtil { public: class QMITK_EXPORT SaveFilter { public: static mitk::MimeType ALL_MIMETYPE(); SaveFilter(const SaveFilter& other); SaveFilter(const SaveInfo& saveInfo); SaveFilter& operator=(const SaveFilter& other); + std::vector GetMimeTypes() const; QString GetFilterForMimeType(const std::string& mimeType) const; mitk::MimeType GetMimeTypeForFilter(const QString& filter) const; QString GetDefaultFilter() const; QString GetDefaultExtension() const; mitk::MimeType GetDefaultMimeType() const; QString ToString() const; int Size() const; bool IsEmpty() const; bool ContainsMimeType(const std::string& mimeType); private: struct Impl; QScopedPointer d; }; /** * @brief GetFilterString * @return */ static QString GetFileOpenFilterString(); /** * @brief Loads the specified files * * This methods tries to load all specified files and pop-ups dialog boxes if further * user input is required (e.g. ambiguous mime-types or reader options). * * If the provided DataStorage is not NULL, some files will be added to it automatically, * dependeing on the IFileReader used. * * @param files A list of files to load. * @param ds An optional data storage passed to IFileReader instances * @return A list of BaseData instances which have not already been added to the data storage. */ static QList Load(const QStringList& paths, QWidget* parent = NULL); static mitk::DataStorage::SetOfObjects::Pointer Load(const QStringList& paths, mitk::DataStorage& storage, QWidget* parent = NULL); static QList Load(const QString& path, QWidget* parent = NULL); static mitk::DataStorage::SetOfObjects::Pointer Load(const QString& path, mitk::DataStorage& storage, QWidget* parent = NULL); using mitk::IOUtil::Load; static QString Save(const mitk::BaseData* data, const QString& defaultBaseName, const QString& defaultPath = QString(), QWidget* parent = NULL); /** * @brief Save a list of BaseData objects using a "File Save Dialog". * * For each element in the \c data vector, the following algorithm is * used to find a IFileWriter instance for writing the BaseData object. * * First, the user is prompted to select file names for each BaseData object. This * is equivalent to choosing a specific mime-type, either by selecting a filter * in the save dialog or by explicitly providing a file name extension: *
    *
  1. Get a list of registered IFileWriter objects for the current BaseData object. * If no writers are found, a message box displays a warning and * the process starts from the beginning for the next BaseData object.
  2. *
  3. A QFileDialog for prompting the user to select a file name is opened. * The mime-type associated with each IFileWriter object is used to create * a filter for file name extensions. * The best IFileWriter (see FileWriterSelector) for the current BaseData object * defines the default file name suffix via its associated mime-type. If the * file name is empty (the user cancelled the dialog), the remaining * BaseData objects are skipped. - *
  4. The file name suffix is extracted from the user-supplied file name and validated. - * If the suffix is not empty and it is either not contained in the - * extension list of the selected filter (from the QFileDialog) or the mime-type - * containing the suffix as an extension is not contained in the original - * list of compatible mime-types, a message box displays a warning and - * the process starts from the beginning with the next BaseData object. - * If the suffix is empty, a default suffix is created if the file name does - * not point to an already existing file (in that case, the user already - * confirmed to overwrite that file). The default suffix is the first entry - * in the extension list of the selected filter. If the special "all" - * filter is selected, the first entry from the extensions list of the - * highest-ranked compatible mime-type for the current base data object is used. - * The base data object is associated with the mime-type containing the suffix - * in its extension list. If the suffix is empty (the user is overwriting an - * existing file without an extension, the associated mime-type is the one - * of the selected filter or the mime-type of the best matching IFileWriter - * if the special "all" filter was selected.
  5. + *
  6. The file name is matched against valid mime-types. The first mime-type + * which accepts the file name is associated with the current BaseData object. + * If no mime-type accepts the supplied file name and the file already + * exists, the process starts from the beginning with the next BaseData object. + * Otherwise, if the selected filter is the special "all" filter and the + * file name does not contain periods (which may or may not mark the start of + * a file extension), the current BaseData object is associated with the + * default mime-type. If the selected filter is not the special "all" filter, + * the mime-type for this filter is associated with the current BaseData object. + * The default extension of the associated mime-type is then appended to the + * supplied file name. *
  7. The selected/derived file name and associated mime-type is stored in a list * and the process starts from the beginning for the next BaseData object.
  8. *
* * In the second phase, each BaseData object is saved to disk using the specified * file name and mime-type, according to the following procedure: *
    *
  1. If multiple IFileWriter objects are compatible with the current base data * object or if the single compatible IFileWriter provides configuration * options, a dialog window containing a list of IFileWriter objects and * configurable options is displayed. If the dialog is cancelled by the user, * neither the current nor the remaining base data objects are saved to disk. * If the user previously in this phase enabled the "remember options" checkbox * of the dialog, then the dialog is not shown for base data objects with the * same data type and associated mime-type if the file writer instance reports * a higher or equal confidence level for the current base data object.
  2. *
  3. The selected writer (either the only available one or the user selected one) * is used to write the base data object to disk. On failure, an error is * reported and the second phase continues with the next base data object.
  4. *
* * @param data * @param defaultBaseNames * @param defaultPath * @param parent * @return */ static QStringList Save(const std::vector& data, const QStringList& defaultBaseNames, const QString& defaultPath = QString(), QWidget* parent = NULL); using mitk::IOUtil::Save; /** * @brief SaveBaseDataWithDialog Convenience method to save any data with a Qt dialog. * @param data BaseData holding the data you wish to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static void SaveBaseDataWithDialog(mitk::BaseData *data, std::string fileName, QWidget* parent = NULL)); /** * @brief SaveSurfaceWithDialog Convenience method to save a surface with a Qt dialog. * @param surface The surface to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static void SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName = "", QWidget* parent = NULL)); /** * @brief SaveImageWithDialog Convenience method to save an image with a Qt dialog. * @param image The image to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static void SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName = "", QWidget* parent = NULL)); /** * @brief SavePointSetWithDialog Convenience method to save a pointset with a Qt dialog. * @param pointset The pointset to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static void SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName = "", QWidget* parent = NULL)); private: struct Impl; }; #endif // _QmitkIOUtil__h_ diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp index cd351b7163..d382cf0d7a 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp @@ -1,1137 +1,1159 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkSlicesInterpolator.h" #include "QmitkStdMultiWidget.h" #include "QmitkSelectableGLWidget.h" #include "mitkToolManager.h" #include "mitkDataNodeFactory.h" #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkProgressBar.h" #include "mitkGlobalInteraction.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkInteractionConst.h" #include "mitkApplyDiffImageOperation.h" #include "mitkDiffImageApplier.h" #include "mitkSegTool2D.h" #include "mitkCoreObjectFactory.h" #include "mitkSurfaceToImageFilter.h" #include "mitkSliceNavigationController.h" #include #include #include #include #include #include #include #include #include #include #include //#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) float SURFACE_COLOR_RGB [3] = {0.49f, 1.0f, 0.16f}; const std::map QmitkSlicesInterpolator::createActionToSliceDimension() { std::map actionToSliceDimension; foreach(mitk::SliceNavigationController* slicer, m_ControllerToDeleteObserverTag.keys()) { actionToSliceDimension[new QAction(QString::fromStdString(slicer->GetViewDirectionAsString()),0)] = slicer; } return actionToSliceDimension; } QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget* parent, const char* /*name*/) :QWidget(parent), // ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ), m_Interpolator( mitk::SegmentationInterpolationController::New() ), m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()), m_ToolManager(NULL), m_Initialized(false), m_LastSNC(0), m_LastSliceIndex(0), m_2DInterpolationEnabled(false), m_3DInterpolationEnabled(false) { m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this); QVBoxLayout* vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation->addItem("Disabled"); m_CmbInterpolation->addItem("2-Dimensional"); m_CmbInterpolation->addItem("3-Dimensional"); vboxLayout->addWidget(m_CmbInterpolation); m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply2D); m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApplyForAllSlices2D); m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply3D); m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnReinit3DInterpolation); m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_ChkShowPositionNodes); this->HideAllInterpolationControls(); connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int))); connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked())); connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked())); connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked())); connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation())); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool))); QHBoxLayout* layout = new QHBoxLayout(this); layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode); this->setLayout(layout); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged ); InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver( itk::ModifiedEvent(), command ); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged ); SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver( itk::ModifiedEvent(), command2 ); // feedback node and its visualization properties m_FeedbackNode = mitk::DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_FeedbackNode ); m_FeedbackNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "color", mitk::ColorProperty::New(255.0, 255.0, 0.0) ); m_FeedbackNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(false) ); m_FeedbackNode->SetProperty( "layer", mitk::IntProperty::New( 20 ) ); m_FeedbackNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_FeedbackNode->SetProperty( "name", mitk::StringProperty::New("Interpolation feedback") ); m_FeedbackNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) ); m_FeedbackNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode = mitk::DataNode::New(); m_InterpolatedSurfaceNode->SetProperty( "color", mitk::ColorProperty::New(SURFACE_COLOR_RGB) ); m_InterpolatedSurfaceNode->SetProperty( "name", mitk::StringProperty::New("Surface Interpolation feedback") ); m_InterpolatedSurfaceNode->SetProperty( "opacity", mitk::FloatProperty::New(0.5) ); m_InterpolatedSurfaceNode->SetProperty( "line width", mitk::IntProperty::New(4) ); m_InterpolatedSurfaceNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_InterpolatedSurfaceNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode = mitk::DataNode::New(); m_3DContourNode->SetProperty( "color", mitk::ColorProperty::New(0.0, 0.0, 0.0) ); m_3DContourNode->SetProperty("hidden object", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "name", mitk::StringProperty::New("Drawn Contours") ); m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f)); m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); QWidget::setContentsMargins(0, 0, 0, 0); if ( QWidget::layout() != NULL ) { QWidget::layout()->setContentsMargins(0, 0, 0, 0); } //For running 3D Interpolation in background // create a QFuture and a QFutureWatcher connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer())); m_Timer = new QTimer(this); connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor())); } void QmitkSlicesInterpolator::SetDataStorage( mitk::DataStorage::Pointer storage ) { m_DataStorage = storage; m_SurfaceInterpolator->SetDataStorage(storage); } mitk::DataStorage* QmitkSlicesInterpolator::GetDataStorage() { if ( m_DataStorage.IsNotNull() ) { return m_DataStorage; } else { return NULL; } } void QmitkSlicesInterpolator::Initialize(mitk::ToolManager* toolManager, const QList &controllers) { Q_ASSERT(!controllers.empty()); if (m_Initialized) { // remove old observers Uninitialize(); } m_ToolManager = toolManager; if (m_ToolManager) { // set enabled only if a segmentation is selected mitk::DataNode* node = m_ToolManager->GetWorkingData(0); QWidget::setEnabled( node != NULL ); // react whenever the set of selected segmentation changes m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified ); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified ); // connect to the slice navigation controller. after each change, call the interpolator foreach(mitk::SliceNavigationController* slicer, controllers) { //Has to be initialized m_LastSNC = slicer; m_TimeStep.insert(slicer, slicer->GetTime()->GetPos()); itk::MemberCommand::Pointer deleteCommand = itk::MemberCommand::New(); deleteCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted); m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand)); itk::MemberCommand::Pointer timeChangedCommand = itk::MemberCommand::New(); timeChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnTimeChanged); m_ControllerToTimeObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(NULL,0), timeChangedCommand)); itk::MemberCommand::Pointer sliceChangedCommand = itk::MemberCommand::New(); sliceChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceChanged); m_ControllerToSliceObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(NULL,0), sliceChangedCommand)); } ACTION_TO_SLICEDIMENSION = createActionToSliceDimension(); } m_Initialized = true; } void QmitkSlicesInterpolator::Uninitialize() { if (m_ToolManager.IsNotNull()) { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified); } foreach(mitk::SliceNavigationController* slicer, m_ControllerToSliceObserverTag.keys()) { slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer)); } ACTION_TO_SLICEDIMENSION.clear(); m_ToolManager = NULL; m_Initialized = false; } QmitkSlicesInterpolator::~QmitkSlicesInterpolator() { if (m_Initialized) { // remove old observers Uninitialize(); } if(m_DataStorage->Exists(m_3DContourNode)) m_DataStorage->Remove(m_3DContourNode); if(m_DataStorage->Exists(m_InterpolatedSurfaceNode)) m_DataStorage->Remove(m_InterpolatedSurfaceNode); // remove observer m_Interpolator->RemoveObserver( InterpolationInfoChangedObserverTag ); m_SurfaceInterpolator->RemoveObserver( SurfaceInterpolationInfoChangedObserverTag ); delete m_Timer; } /** External enableization... */ void QmitkSlicesInterpolator::setEnabled( bool enable ) { QWidget::setEnabled(enable); //Set the gui elements of the different interpolation modi enabled if (enable) { if (m_2DInterpolationEnabled) { this->Show2DInterpolationControls(true); m_Interpolator->Activate2DInterpolation(true); } else if (m_3DInterpolationEnabled) { this->Show3DInterpolationControls(true); this->Show3DInterpolationResult(true); } } //Set all gui elements of the interpolation disabled else { this->HideAllInterpolationControls(); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status) { OnInterpolationActivated(status); m_Interpolator->Activate2DInterpolation(status); } void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status) { On3DInterpolationActivated(status); } void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status) { if (status) { OnInterpolationActivated(!status); On3DInterpolationActivated(!status); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::HideAllInterpolationControls() { this->Show2DInterpolationControls(false); this->Show3DInterpolationControls(false); } void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show) { m_BtnApply2D->setVisible(show); m_BtnApplyForAllSlices2D->setVisible(show); } void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show) { m_BtnApply3D->setVisible(show); m_ChkShowPositionNodes->setVisible(show); m_BtnReinit3DInterpolation->setVisible(show); } void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index) { switch(index) { case 0: // Disabled m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation"); this->HideAllInterpolationControls(); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(false); this->Show3DInterpolationResult(false); m_Interpolator->Activate2DInterpolation(false); break; case 1: // 2D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show2DInterpolationControls(true); this->OnInterpolationActivated(true); this->On3DInterpolationActivated(false); m_Interpolator->Activate2DInterpolation(true); break; case 2: // 3D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show3DInterpolationControls(true); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(true); m_Interpolator->Activate2DInterpolation(false); break; default: MITK_ERROR << "Unknown interpolation method!"; m_CmbInterpolation->setCurrentIndex(0); break; } } void QmitkSlicesInterpolator::OnShowMarkers(bool state) { mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker" , mitk::BoolProperty::New(true))); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state)); } } void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified() { if (m_ToolManager->GetWorkingData(0) != 0) { m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); m_BtnReinit3DInterpolation->setEnabled(true); } else { //If no workingdata is set, remove the interpolation feedback this->GetDataStorage()->Remove(m_FeedbackNode); m_FeedbackNode->SetData(NULL); this->GetDataStorage()->Remove(m_3DContourNode); m_3DContourNode->SetData(NULL); this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode); m_InterpolatedSurfaceNode->SetData(NULL); m_BtnReinit3DInterpolation->setEnabled(false); return; } //Updating the current selected segmentation for the 3D interpolation SetCurrentContourListID(); if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } this->CheckSupportedImageDimension(); } void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified() { } void QmitkSlicesInterpolator::OnTimeChanged(itk::Object* sender, const itk::EventObject& e) { //Check if we really have a GeometryTimeEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController* slicer = dynamic_cast(sender); Q_ASSERT(slicer); m_TimeStep[slicer]; if (m_LastSNC == slicer) { slicer->SendSlice();//will trigger a new interpolation } } void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e) { //Check whether we really have a GeometrySliceEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController* slicer = dynamic_cast(sender); if (TranslateAndInterpolateChangedSlice(e, slicer)) { slicer->GetRenderer()->RequestUpdate(); } } bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e, mitk::SliceNavigationController* slicer) { if (!m_2DInterpolationEnabled) return false; try { const mitk::SliceNavigationController::GeometrySliceEvent& event = dynamic_cast(e); mitk::TimeGeometry* tsg = event.GetTimeGeometry(); if (tsg && m_TimeStep.contains(slicer)) { mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(tsg->GetGeometryForTimeStep(m_TimeStep[slicer]).GetPointer()); if (slicedGeometry) { m_LastSNC = slicer; mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetPlaneGeometry( event.GetPos() )); if (plane) Interpolate( plane, m_TimeStep[slicer], slicer ); return true; } } } catch(std::bad_cast) { return false; // so what } return false; } void QmitkSlicesInterpolator::Interpolate( mitk::PlaneGeometry* plane, unsigned int timeStep, mitk::SliceNavigationController* slicer ) { if (m_ToolManager) { mitk::DataNode* node = m_ToolManager->GetWorkingData(0); if (node) { m_Segmentation = dynamic_cast(node->GetData()); if (m_Segmentation) { int clickedSliceDimension(-1); int clickedSliceIndex(-1); // calculate real slice position, i.e. slice of the image and not slice of the TimeSlicedGeometry mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex ); mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( clickedSliceDimension, clickedSliceIndex, plane, timeStep ); m_FeedbackNode->SetData( interpolation ); m_LastSNC = slicer; m_LastSliceIndex = clickedSliceIndex; } } } } void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(); mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if(interpolatedSurface.IsNotNull() && workingNode && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) { m_BtnApply3D->setEnabled(true); m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface()); this->Show3DInterpolationResult(true); if( !m_DataStorage->Exists(m_InterpolatedSurfaceNode) ) { m_DataStorage->Add(m_InterpolatedSurfaceNode); } if (!m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode, workingNode); } } else if (interpolatedSurface.IsNull()) { m_BtnApply3D->setEnabled(false); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { this->Show3DInterpolationResult(false); } } m_BtnReinit3DInterpolation->setEnabled(true); foreach (mitk::SliceNavigationController* slicer, m_ControllerToTimeObserverTag.keys()) { slicer->GetRenderer()->RequestUpdate(); } } void QmitkSlicesInterpolator::OnAcceptInterpolationClicked() { if (m_Segmentation && m_FeedbackNode->GetData()) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); //Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer vtkSmartPointer reslice = vtkSmartPointer::New(); // Set slice as input mitk::Image::Pointer slice = dynamic_cast(m_FeedbackNode->GetData()); reslice->SetInputSlice(slice->GetSliceData()->GetVtkImageAccessor(slice)->GetVtkImageData()); //set overwrite mode to true to write back to the image volume reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); extractor->SetInput( m_Segmentation ); unsigned int timestep = m_LastSNC->GetTime()->GetPos(); extractor->SetTimeStep( timestep ); extractor->SetWorldGeometry( m_LastSNC->GetCurrentPlaneGeometry() ); extractor->SetVtkOutputRequest(true); extractor->SetResliceTransformByGeometry( m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep( timestep ) ); extractor->Modified(); extractor->Update(); //the image was modified within the pipeline, but not marked so m_Segmentation->Modified(); m_Segmentation->GetVtkImageData()->Modified(); m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController* slicer) { /* * What exactly is done here: * 1. We create an empty diff image for the current segmentation * 2. All interpolated slices are written into the diff image * 3. Then the diffimage is applied to the original segmentation */ if (m_Segmentation) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); mitk::Image::Pointer image3D = m_Segmentation; unsigned int timeStep( slicer->GetTime()->GetPos() ); if (m_Segmentation->GetDimension() == 4) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput( m_Segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->Update(); image3D = timeSelector->GetOutput(); } // create a empty diff image for the undo operation mitk::Image::Pointer diffImage = mitk::Image::New(); diffImage->Initialize( image3D ); // Create scope for ImageWriteAccessor so that the accessor is destroyed // after the image is initialized. Otherwise later image access will lead to an error { mitk::ImageWriteAccessor imAccess(diffImage); // Set all pixels to zero mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); memset( imAccess.GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2) ); } // Since we need to shift the plane it must be clone so that the original plane isn't altered mitk::PlaneGeometry::Pointer reslicePlane = slicer->GetCurrentPlaneGeometry()->Clone(); int sliceDimension(-1); int sliceIndex(-1); mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, reslicePlane, sliceDimension, sliceIndex ); unsigned int zslices = m_Segmentation->GetDimension( sliceDimension ); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); mitk::Point3D origin = reslicePlane->GetOrigin(); unsigned int totalChangedSlices(0); for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex) { // Transforming the current origin of the reslice plane // so that it matches the one of the next slice m_Segmentation->GetSlicedGeometry()->WorldToIndex(origin, origin); origin[sliceDimension] = sliceIndex; m_Segmentation->GetSlicedGeometry()->IndexToWorld(origin, origin); reslicePlane->SetOrigin(origin); //Set the slice as 'input' mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( sliceDimension, sliceIndex, reslicePlane, timeStep ); if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does { //Setting up the reslicing pipeline which allows us to write the interpolation results back into //the image volume vtkSmartPointer reslice = vtkSmartPointer::New(); //set overwrite mode to true to write back to the image volume reslice->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData()); reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer diffslicewriter = mitk::ExtractSliceFilter::New(reslice); diffslicewriter->SetInput( diffImage ); diffslicewriter->SetTimeStep( timeStep ); diffslicewriter->SetWorldGeometry(reslicePlane); diffslicewriter->SetVtkOutputRequest(true); diffslicewriter->SetResliceTransformByGeometry( diffImage->GetTimeGeometry()->GetGeometryForTimeStep( timeStep ) ); diffslicewriter->Modified(); diffslicewriter->Update(); ++totalChangedSlices; } mitk::ProgressBar::GetInstance()->Progress(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (totalChangedSlices > 0) { // store undo stack items if ( true ) { // create do/undo operations mitk::ApplyDiffImageOperation* doOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); mitk::ApplyDiffImageOperation* undoOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); undoOp->SetFactor( -1.0 ); std::stringstream comment; comment << "Confirm all interpolations (" << totalChangedSlices << ")"; mitk::OperationEvent* undoStackItem = new mitk::OperationEvent( mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str() ); mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); // acutally apply the changes here to the original image mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation( doOp ); } } m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController* slicer) { //this redirect is for calling from outside if (slicer == NULL) OnAcceptAllInterpolationsClicked(); else AcceptAllInterpolations( slicer ); } void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked() { QMenu orientationPopup(this); std::map::const_iterator it; for(it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++) orientationPopup.addAction(it->first); connect( &orientationPopup, SIGNAL(triggered(QAction*)), this, SLOT(OnAcceptAllPopupActivated(QAction*)) ); orientationPopup.exec( QCursor::pos() ); } void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked() { if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData()) { mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); s2iFilter->SetInput(dynamic_cast(m_InterpolatedSurfaceNode->GetData())); // check if ToolManager holds valid ReferenceData if (m_ToolManager->GetReferenceData(0) == NULL || m_ToolManager->GetWorkingData(0) == NULL) { return; } s2iFilter->SetImage(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); s2iFilter->Update(); mitk::DataNode* segmentationNode = m_ToolManager->GetWorkingData(0); - segmentationNode->SetData(s2iFilter->GetOutput()); + mitk::Image* oldSeg = dynamic_cast(segmentationNode->GetData()); + mitk::Image::Pointer newSeg = s2iFilter->GetOutput(); + if (oldSeg) + m_SurfaceInterpolator->ReplaceInterpolationSession(oldSeg, newSeg); + else + return; + + segmentationNode->SetData(newSeg); m_CmbInterpolation->setCurrentIndex(0); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); mitk::DataNode::Pointer segSurface = mitk::DataNode::New(); float rgb[3]; segmentationNode->GetColor(rgb); segSurface->SetColor(rgb); segSurface->SetData(m_InterpolatedSurfaceNode->GetData()); std::stringstream stream; stream << segmentationNode->GetName(); stream << "_"; stream << "3D-interpolation"; segSurface->SetName(stream.str()); segSurface->SetProperty( "opacity", mitk::FloatProperty::New(0.7) ); - segSurface->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); + segSurface->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(true)); + segSurface->SetProperty( "3DInterpolationResult", mitk::BoolProperty::New(true)); m_DataStorage->Add(segSurface, segmentationNode); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::OnReinit3DInterpolation() { mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("3DContourContainer", mitk::BoolProperty::New(true)); mitk::DataStorage::SetOfObjects::ConstPointer contourNodes = m_DataStorage->GetDerivations( m_ToolManager->GetWorkingData(0), pred); if (contourNodes->Size() != 0) { m_3DContourNode = contourNodes->at(0); } else { QMessageBox errorInfo; errorInfo.setWindowTitle("Reinitialize surface interpolation"); errorInfo.setIcon(QMessageBox::Information); errorInfo.setText("No contours available for the selected segmentation!"); errorInfo.exec(); } mitk::Surface::Pointer contours = dynamic_cast(m_3DContourNode->GetData()); if (contours) mitk::SurfaceInterpolationController::GetInstance()->ReinitializeInterpolation(contours); m_BtnReinit3DInterpolation->setEnabled(false); } void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction* action) { try { std::map::const_iterator iter = ACTION_TO_SLICEDIMENSION.find( action ); if (iter != ACTION_TO_SLICEDIMENSION.end()) { mitk::SliceNavigationController* slicer = iter->second; AcceptAllInterpolations( slicer ); } } catch(...) { /* Showing message box with possible memory error */ QMessageBox errorInfo; errorInfo.setWindowTitle("Interpolation Process"); errorInfo.setIcon(QMessageBox::Critical); errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!"); errorInfo.exec(); //additional error message on std::cerr std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl; } } void QmitkSlicesInterpolator::OnInterpolationActivated(bool on) { m_2DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() ) { if (on && !m_DataStorage->Exists(m_FeedbackNode)) { m_DataStorage->Add( m_FeedbackNode ); } } } catch(...) { // don't care (double add/remove) } if (m_ToolManager) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); QWidget::setEnabled( workingNode != NULL ); m_BtnApply2D->setEnabled( on ); m_FeedbackNode->SetVisibility( on ); if (!on) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } if (workingNode) { mitk::Image* segmentation = dynamic_cast(workingNode->GetData()); if (segmentation) { m_Interpolator->SetSegmentationVolume( segmentation ); if (referenceNode) { mitk::Image* referenceImage = dynamic_cast(referenceNode->GetData()); m_Interpolator->SetReferenceVolume( referenceImage ); // may be NULL } } } } UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::Run3DInterpolation() { m_SurfaceInterpolator->Interpolate(); } void QmitkSlicesInterpolator::StartUpdateInterpolationTimer() { m_Timer->start(500); } void QmitkSlicesInterpolator::StopUpdateInterpolationTimer() { m_Timer->stop(); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB)); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::ChangeSurfaceColor() { float currentColor[3]; m_InterpolatedSurfaceNode->GetColor(currentColor); if( currentColor[2] == SURFACE_COLOR_RGB[2]) { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(1.0f,1.0f,1.0f)); } else { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB)); } m_InterpolatedSurfaceNode->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on) { m_3DInterpolationEnabled = on; this->CheckSupportedImageDimension(); try { if ( m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); + mitk::NodePredicateAnd::Pointer pred = mitk::NodePredicateAnd::New(mitk::NodePredicateProperty::New("3DInterpolationResult", mitk::BoolProperty::New(true)), + mitk::NodePredicateDataType::New("Surface")); + mitk::DataStorage::SetOfObjects::ConstPointer interpolationResults = + m_DataStorage->GetDerivations(workingNode, pred); + + for (unsigned int i = 0; i < interpolationResults->Size(); ++i) + { + mitk::DataNode::Pointer currNode = interpolationResults->at(i); + if (currNode.IsNotNull()) + m_DataStorage->Remove(currNode); + } if ((workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult && m_3DInterpolationEnabled) { int ret = QMessageBox::Yes; if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5) { QMessageBox msgBox; msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!"); msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?"); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); ret = msgBox.exec(); } if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); if (ret == QMessageBox::Yes) { m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } else { m_CmbInterpolation->setCurrentIndex(0); } } else if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); } } else { QWidget::setEnabled( false ); m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled); } } if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); } } catch(...) { MITK_ERROR<<"Error with 3D surface interpolation!"; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::EnableInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated OnInterpolationActivated(on); } void QmitkSlicesInterpolator::Enable3DInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated On3DInterpolationActivated(on); } void QmitkSlicesInterpolator::UpdateVisibleSuggestion() { if (m_2DInterpolationEnabled && m_LastSNC) { // determine which one is the current view, try to do an initial interpolation mitk::BaseRenderer* renderer = m_LastSNC->GetRenderer(); if (renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeGeometry* timeGeometry = dynamic_cast( renderer->GetWorldGeometry() ); if (timeGeometry) { mitk::SliceNavigationController::GeometrySliceEvent event( const_cast(timeGeometry), renderer->GetSlice() ); TranslateAndInterpolateChangedSlice(event, m_LastSNC); } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject& /*e*/) { // something (e.g. undo) changed the interpolation info, we should refresh our display UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject& /*e*/) { if(m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } void QmitkSlicesInterpolator:: SetCurrentContourListID() { // New ContourList = hide current interpolation Show3DInterpolationResult(false); if ( m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC ) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); if (!isInterpolationResult) { QWidget::setEnabled( true ); //TODO Aufruf hier pruefen! mitk::Vector3D spacing = workingNode->GetData()->GetGeometry( m_LastSNC->GetTime()->GetPos() )->GetSpacing(); double minSpacing (100); double maxSpacing (0); for (int i =0; i < 3; i++) { if (spacing[i] < minSpacing) { minSpacing = spacing[i]; } else if (spacing[i] > maxSpacing) { maxSpacing = spacing[i]; } } m_SurfaceInterpolator->SetMaxSpacing(maxSpacing); m_SurfaceInterpolator->SetMinSpacing(minSpacing); m_SurfaceInterpolator->SetDistanceImageVolume(50000); mitk::Image* segmentationImage = dynamic_cast(workingNode->GetData()); if (segmentationImage->GetDimension() == 3) m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage); else MITK_INFO<<"3D Interpolation is only supported for 3D images at the moment!"; if (m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } } else { QWidget::setEnabled(false); } } } void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status) { if (m_InterpolatedSurfaceNode.IsNotNull()) m_InterpolatedSurfaceNode->SetVisibility(status); if (m_3DContourNode.IsNotNull()) m_3DContourNode->SetVisibility(status, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::CheckSupportedImageDimension() { - if (m_3DInterpolationEnabled && m_Segmentation->GetDimension() != 3) + if (m_ToolManager->GetWorkingData(0)) + m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); + + if (m_3DInterpolationEnabled && m_Segmentation && m_Segmentation->GetDimension() != 3) { QMessageBox info; info.setWindowTitle("3D Interpolation Process"); info.setIcon(QMessageBox::Information); info.setText("3D Interpolation is only supported for 3D images at the moment!"); info.exec(); m_CmbInterpolation->setCurrentIndex(0); } } void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject& /*e*/) { //Don't know how to avoid const_cast here?! mitk::SliceNavigationController* slicer = dynamic_cast(const_cast(sender)); if (slicer) { m_ControllerToTimeObserverTag.remove(slicer); m_ControllerToSliceObserverTag.remove(slicer); m_ControllerToDeleteObserverTag.remove(slicer); } } diff --git a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp index 3c8977830f..b22d421a5a 100644 --- a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp +++ b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp @@ -1,398 +1,465 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include class mitkSurfaceInterpolationControllerTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkSurfaceInterpolationControllerTestSuite); MITK_TEST(TestSingleton); MITK_TEST(TestSetCurrentInterpolationSession); + MITK_TEST(TestReplaceInterpolationSession); MITK_TEST(TestRemoveAllInterpolationSessions); MITK_TEST(TestRemoveInterpolationSession); MITK_TEST(TestOnSegmentationDeleted); /// \todo Workaround for memory leak in TestAddNewContour. Bug 18096. vtkDebugLeaks::SetExitError(0); MITK_TEST(TestAddNewContour); MITK_TEST(TestRemoveContour); CPPUNIT_TEST_SUITE_END(); private: mitk::SurfaceInterpolationController::Pointer m_Controller; public: mitk::Image::Pointer createImage(unsigned int *dimensions) { mitk::Image::Pointer newImage = mitk::Image::New(); mitk::PixelType p_type = mitk::MakeScalarPixelType(); newImage->Initialize(p_type, 3, dimensions); return newImage; } void setUp() { m_Controller = mitk::SurfaceInterpolationController::GetInstance(); vtkSmartPointer polygonSource = vtkSmartPointer::New(); polygonSource->SetRadius(100); polygonSource->SetNumberOfSides(7); polygonSource->Update(); mitk::Surface::Pointer surface = mitk::Surface::New(); surface->SetVtkPolyData(polygonSource->GetOutput()); } void TestSingleton() { mitk::SurfaceInterpolationController::Pointer controller2 = mitk::SurfaceInterpolationController::GetInstance(); CPPUNIT_ASSERT_MESSAGE("SurfaceInterpolationController pointers are not equal!", m_Controller.GetPointer() == controller2.GetPointer()); } void TestSetCurrentInterpolationSession() { // Create image for testing unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::Pointer segmentation_1 = createImage(dimensions1); unsigned int dimensions2[] = {20, 10, 30}; mitk::Image::Pointer segmentation_2 = createImage(dimensions2); // Test 1 m_Controller->SetCurrentInterpolationSession(segmentation_1); MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal"); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1", m_Controller->GetNumberOfInterpolationSessions() == 1); // Test 2 m_Controller->SetCurrentInterpolationSession(segmentation_2); MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_2->Clone(), "Segmentation images are not equal"); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); // Test 3 m_Controller->SetCurrentInterpolationSession(segmentation_1); MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal"); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); // Test 4 m_Controller->SetCurrentInterpolationSession(segmentation_1); MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal"); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); // Test 5 m_Controller->SetCurrentInterpolationSession(0); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().IsNull()); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); } + void TestReplaceInterpolationSession() + { + // Create segmentation image + unsigned int dimensions1[] = {10, 10, 10}; + mitk::Image::Pointer segmentation_1 = createImage(dimensions1); + m_Controller->SetCurrentInterpolationSession(segmentation_1); + + // Create some contours + double center_1[3] = {1.25f ,3.43f ,4.44f}; + double normal_1[3] = {0.25f ,1.76f, 0.93f}; + vtkSmartPointer p_source = vtkSmartPointer::New(); + p_source->SetNumberOfSides(20); + p_source->SetCenter(center_1); + p_source->SetRadius(4); + p_source->SetNormal(normal_1); + p_source->Update(); + vtkPolyData* poly_1 = p_source->GetOutput(); + mitk::Surface::Pointer surf_1 = mitk::Surface::New(); + surf_1->SetVtkPolyData(poly_1); + + double center_2[3] = {4.0f ,4.0f ,4.0f}; + double normal_2[3] = {1.0f ,0.0f, 0.0f}; + vtkSmartPointer p_source_2 = vtkSmartPointer::New(); + p_source_2->SetNumberOfSides(80); + p_source_2->SetCenter(center_2); + p_source_2->SetRadius(4); + p_source_2->SetNormal(normal_2); + p_source_2->Update(); + vtkPolyData* poly_2 = p_source_2->GetOutput(); + mitk::Surface::Pointer surf_2 = mitk::Surface::New(); + surf_2->SetVtkPolyData(poly_2); + + // Add contours + m_Controller->AddNewContour(surf_1); + m_Controller->AddNewContour(surf_2); + + // Check if all contours are there + mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1; + contourInfo1.contourNormal = normal_1; + contourInfo1.contourPoint = center_1; + + mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2; + contourInfo2.contourNormal = normal_2; + contourInfo2.contourPoint = center_2; + + mitk::Image::Pointer segmentation_2 = createImage(dimensions1); + bool success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_2); + const mitk::Surface* contour_1 = m_Controller->GetContour(contourInfo1); + const mitk::Surface* contour_2 = m_Controller->GetContour(contourInfo2); + + CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == true); + CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2); + CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true)); + CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true)); + CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1", m_Controller->GetNumberOfInterpolationSessions() == 1); + CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer()); + + unsigned int dimensions2[] = {10, 20, 10}; + mitk::Image::Pointer segmentation_3 = createImage(dimensions2); + success = m_Controller->ReplaceInterpolationSession(segmentation_2, segmentation_3); + CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == false); + CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2); + CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1", m_Controller->GetNumberOfInterpolationSessions() == 1); + CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer()); + } + void TestRemoveAllInterpolationSessions() { // Create image for testing unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::Pointer segmentation_1 = createImage(dimensions1); unsigned int dimensions2[] = {20, 10, 30}; mitk::Image::Pointer segmentation_2 = createImage(dimensions2); // Test 1 m_Controller->SetCurrentInterpolationSession(segmentation_1); m_Controller->SetCurrentInterpolationSession(segmentation_2); m_Controller->RemoveAllInterpolationSessions(); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0", m_Controller->GetNumberOfInterpolationSessions() == 0); } void TestRemoveInterpolationSession() { // Create image for testing unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::Pointer segmentation_1 = createImage(dimensions1); unsigned int dimensions2[] = {20, 10, 30}; mitk::Image::Pointer segmentation_2 = createImage(dimensions2); // Test 1 m_Controller->SetCurrentInterpolationSession(segmentation_1); m_Controller->SetCurrentInterpolationSession(segmentation_2); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); // Test current segmentation should not be null if another one was removed m_Controller->RemoveInterpolationSession(segmentation_1); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1", m_Controller->GetNumberOfInterpolationSessions() == 1); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed", m_Controller->GetCurrentSegmentation().IsNotNull()); m_Controller->SetCurrentInterpolationSession(segmentation_1); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); // Test current segmentation should not be null if another one was removed m_Controller->RemoveInterpolationSession(segmentation_1); CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1", m_Controller->GetNumberOfInterpolationSessions() == 1); CPPUNIT_ASSERT_MESSAGE("Current segmentation is not null after session was removed", m_Controller->GetCurrentSegmentation().IsNull()); } void TestOnSegmentationDeleted() { { // Create image for testing unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::Pointer segmentation_1 = createImage(dimensions1); m_Controller->SetCurrentInterpolationSession(segmentation_1); } CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0", m_Controller->GetNumberOfInterpolationSessions() == 0); } void TestAddNewContour() { // Create segmentation image unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::Pointer segmentation_1 = createImage(dimensions1); m_Controller->SetCurrentInterpolationSession(segmentation_1); // Create some contours double center_1[3] = {1.25f ,3.43f ,4.44f}; double normal_1[3] = {0.25f ,1.76f, 0.93f}; vtkSmartPointer p_source = vtkSmartPointer::New(); p_source->SetNumberOfSides(20); p_source->SetCenter(center_1); p_source->SetRadius(4); p_source->SetNormal(normal_1); p_source->Update(); vtkPolyData* poly_1 = p_source->GetOutput(); mitk::Surface::Pointer surf_1 = mitk::Surface::New(); surf_1->SetVtkPolyData(poly_1); double center_2[3] = {4.0f ,4.0f ,4.0f}; double normal_2[3] = {1.0f ,0.0f, 0.0f}; vtkSmartPointer p_source_2 = vtkSmartPointer::New(); p_source_2->SetNumberOfSides(80); p_source_2->SetCenter(center_2); p_source_2->SetRadius(4); p_source_2->SetNormal(normal_2); p_source_2->Update(); vtkPolyData* poly_2 = p_source_2->GetOutput(); mitk::Surface::Pointer surf_2 = mitk::Surface::New(); surf_2->SetVtkPolyData(poly_2); double center_3[3] = {4.0f ,4.0f ,3.0f}; double normal_3[3] = {0.0f ,0.0f, 1.0f}; vtkSmartPointer p_source_3 = vtkSmartPointer::New(); p_source_3->SetNumberOfSides(10); p_source_3->SetCenter(center_3); p_source_3->SetRadius(4); p_source_3->SetNormal(normal_3); p_source_3->Update(); vtkPolyData* poly_3 = p_source_3->GetOutput(); mitk::Surface::Pointer surf_3 = mitk::Surface::New(); surf_3->SetVtkPolyData(poly_3); // Add contours m_Controller->AddNewContour(surf_1); m_Controller->AddNewContour(surf_2); m_Controller->AddNewContour(surf_3); // Check if all contours are there mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1; contourInfo1.contourNormal = normal_1; contourInfo1.contourPoint = center_1; mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2; contourInfo2.contourNormal = normal_2; contourInfo2.contourPoint = center_2; mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3; contourInfo3.contourNormal = normal_3; contourInfo3.contourPoint = center_3; const mitk::Surface* contour_1 = m_Controller->GetContour(contourInfo1); const mitk::Surface* contour_2 = m_Controller->GetContour(contourInfo2); const mitk::Surface* contour_3 = m_Controller->GetContour(contourInfo3); CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_3->GetVtkPolyData()), 0.000001, true)); // Create another segmentation image unsigned int dimensions2[] = {20, 20, 20}; mitk::Image::Pointer segmentation_2 = createImage(dimensions2); m_Controller->SetCurrentInterpolationSession(segmentation_2); // Create some contours double center_4[3] = {10.0f ,10.0f ,10.0f}; double normal_4[3] = {0.0f ,1.0f, 0.0f}; vtkSmartPointer p_source_4 = vtkSmartPointer::New(); p_source_4->SetNumberOfSides(8); p_source_4->SetCenter(center_4); p_source_4->SetRadius(5); p_source_4->SetNormal(normal_4); p_source_4->Update(); vtkPolyData* poly_4 = p_source_4->GetOutput(); mitk::Surface::Pointer surf_4 = mitk::Surface::New(); surf_4->SetVtkPolyData(poly_4); double center_5[3] = {3.0f ,10.0f ,10.0f}; double normal_5[3] = {1.0f ,0.0f, 0.0f}; vtkSmartPointer p_source_5 = vtkSmartPointer::New(); p_source_5->SetNumberOfSides(16); p_source_5->SetCenter(center_5); p_source_5->SetRadius(8); p_source_5->SetNormal(normal_5); p_source_5->Update(); vtkPolyData* poly_5 = p_source_5->GetOutput(); mitk::Surface::Pointer surf_5 = mitk::Surface::New(); surf_5->SetVtkPolyData(poly_5); double center_6[3] = {10.0f ,10.0f ,3.0f}; double normal_6[3] = {0.0f ,0.0f, 1.0f}; vtkSmartPointer p_source_6 = vtkSmartPointer::New(); p_source_6->SetNumberOfSides(100); p_source_6->SetCenter(center_6); p_source_6->SetRadius(5); p_source_6->SetNormal(normal_6); p_source_6->Update(); vtkPolyData* poly_6 = p_source_6->GetOutput(); mitk::Surface::Pointer surf_6 = mitk::Surface::New(); surf_6->SetVtkPolyData(poly_6); mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo4; contourInfo4.contourNormal = normal_4; contourInfo4.contourPoint = center_4; mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo5; contourInfo5.contourNormal = normal_5; contourInfo5.contourPoint = center_5; mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo6; contourInfo6.contourNormal = normal_6; contourInfo6.contourPoint = center_6; // Add contours m_Controller->AddNewContour(surf_4); m_Controller->AddNewContour(surf_5); m_Controller->AddNewContour(surf_6); // Check if all contours are there mitk::Surface* contour_4 = const_cast(m_Controller->GetContour(contourInfo4)); mitk::Surface* contour_5 = const_cast(m_Controller->GetContour(contourInfo5)); mitk::Surface* contour_6 = const_cast(m_Controller->GetContour(contourInfo6)); CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_4->GetVtkPolyData()), *(contour_4->GetVtkPolyData()), 0.000001, true)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_5->GetVtkPolyData()), *(contour_5->GetVtkPolyData()), 0.000001, true)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_6->GetVtkPolyData()), *(contour_6->GetVtkPolyData()), 0.000001, true)); // Modify some contours vtkSmartPointer p_source_7 = vtkSmartPointer::New(); p_source_7->SetNumberOfSides(200); p_source_7->SetCenter(3.0,10.0,10.0); p_source_7->SetRadius(5); p_source_7->SetNormal(1, 0, 0); p_source_7->Update(); vtkPolyData* poly_7 = p_source_7->GetOutput(); mitk::Surface::Pointer surf_7 = mitk::Surface::New(); surf_7->SetVtkPolyData(poly_7); m_Controller->AddNewContour(surf_7); mitk::Surface* contour_7 = const_cast(m_Controller->GetContour(contourInfo5)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_7->GetVtkPolyData()), *(contour_7->GetVtkPolyData()), 0.000001, true)); // Change session and test if all contours are available m_Controller->SetCurrentInterpolationSession(segmentation_1); mitk::Surface* contour_8 = const_cast(m_Controller->GetContour(contourInfo1)); mitk::Surface* contour_9 = const_cast(m_Controller->GetContour(contourInfo2)); mitk::Surface* contour_10 = const_cast(m_Controller->GetContour(contourInfo3)); CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_8->GetVtkPolyData()), 0.000001, true)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_9->GetVtkPolyData()), 0.000001, true)); CPPUNIT_ASSERT_MESSAGE("Contours not equal!", mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_10->GetVtkPolyData()), 0.000001, true)); } void TestRemoveContour() { // Create segmentation image unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::Pointer segmentation_1 = createImage(dimensions1); m_Controller->SetCurrentInterpolationSession(segmentation_1); // Create some contours double center_1[3] = {4.0f ,4.0f ,4.0f}; double normal_1[3] = {0.0f ,1.0f, 0.0f}; vtkSmartPointer p_source = vtkSmartPointer::New(); p_source->SetNumberOfSides(20); p_source->SetCenter(center_1); p_source->SetRadius(4); p_source->SetNormal(normal_1); p_source->Update(); vtkPolyData* poly_1 = p_source->GetOutput(); mitk::Surface::Pointer surf_1 = mitk::Surface::New(); surf_1->SetVtkPolyData(poly_1); double center_2[3] = {4.0f ,4.0f ,4.0f}; double normal_2[3] = {1.0f ,0.0f, 0.0f}; vtkSmartPointer p_source_2 = vtkSmartPointer::New(); p_source_2->SetNumberOfSides(80); p_source_2->SetCenter(center_2); p_source_2->SetRadius(4); p_source_2->SetNormal(normal_2); p_source_2->Update(); vtkPolyData* poly_2 = p_source_2->GetOutput(); mitk::Surface::Pointer surf_2 = mitk::Surface::New(); surf_2->SetVtkPolyData(poly_2); // Add contours m_Controller->AddNewContour(surf_1); m_Controller->AddNewContour(surf_2); CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2); mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3; contourInfo3.contour = surf_1->Clone(); contourInfo3.contourNormal = normal_1; contourInfo3.contourPoint = center_1; // Shift the new contour so that it is different contourInfo3.contourPoint += 0.5; bool success = m_Controller->RemoveContour(contourInfo3); CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was unintentionally removed!", (m_Controller->GetNumberOfContours() == 2) && !success); mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2; contourInfo2.contourNormal = normal_2; contourInfo2.contourPoint = center_2; contourInfo2.contour = surf_2; success = m_Controller->RemoveContour(contourInfo2); CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was not removed!", (m_Controller->GetNumberOfContours() == 1) && success); // Let's see if the other contour No. 1 is still there contourInfo3.contourPoint -= 0.5; const mitk::Surface* remainingContour = m_Controller->GetContour(contourInfo3); CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was accidentally removed!", (m_Controller->GetNumberOfContours() == 1) && mitk::Equal(*(surf_1->GetVtkPolyData()), *(remainingContour->GetVtkPolyData()), 0.000001, true) &&success); } }; MITK_TEST_SUITE_REGISTRATION(mitkSurfaceInterpolationController) diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp index 036348812c..dc6a5fc40d 100644 --- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp +++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp @@ -1,547 +1,577 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceInterpolationController.h" #include "mitkMemoryUtilities.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkImageToSurfaceFilter.h" // Check whether the given contours are coplanar bool ContoursCoplanar(mitk::SurfaceInterpolationController::ContourPositionInformation leftHandSide, mitk::SurfaceInterpolationController::ContourPositionInformation rightHandSide) { // Here we check two things: // 1. Whether the normals of both contours are at least parallel // 2. Whether both contours lie in the same plane // Check for coplanarity: // a. Span a vector between two points one from each contour // b. Calculate dot product for the vector and one of the normals // c. If the dot is zero the two vectors are orthogonal and the contours are coplanar double vec[3]; vec[0] = leftHandSide.contourPoint[0] - rightHandSide.contourPoint[0]; vec[1] = leftHandSide.contourPoint[1] - rightHandSide.contourPoint[1]; vec[2] = leftHandSide.contourPoint[2] - rightHandSide.contourPoint[2]; double n[3]; n[0] = rightHandSide.contourNormal[0]; n[1] = rightHandSide.contourNormal[1]; n[2] = rightHandSide.contourNormal[2]; double dot = vtkMath::Dot(n, vec); double n2[3]; n2[0] = leftHandSide.contourNormal[0]; n2[1] = leftHandSide.contourNormal[1]; n2[2] = leftHandSide.contourNormal[2]; // The normals of both contours have to be parallel but not of the same orientation double lengthLHS = leftHandSide.contourNormal.GetNorm(); double lengthRHS = rightHandSide.contourNormal.GetNorm(); double dot2 = vtkMath::Dot(n, n2); bool contoursParallel = mitk::Equal(fabs(lengthLHS*lengthRHS), fabs(dot2), 0.001); if (mitk::Equal(dot, 0.0, 0.001) && contoursParallel) return true; else return false; } mitk::SurfaceInterpolationController::ContourPositionInformation CreateContourPositionInformation(mitk::Surface::Pointer contour) { mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo; contourInfo.contour = contour; double n[3]; double p[3]; contour->GetVtkPolyData()->GetPoints()->GetPoint(0, p); vtkPolygon::ComputeNormal(contour->GetVtkPolyData()->GetPoints(), n); contourInfo.contourNormal = n; contourInfo.contourPoint = p; return contourInfo; } mitk::SurfaceInterpolationController::SurfaceInterpolationController() :m_SelectedSegmentation(0) { m_ReduceFilter = ReduceContourSetFilter::New(); m_NormalsFilter = ComputeContourSetNormalsFilter::New(); m_InterpolateSurfaceFilter = CreateDistanceImageFromSurfaceFilter::New(); m_ReduceFilter->SetUseProgressBar(false); // m_ReduceFilter->SetProgressStepSize(1); m_NormalsFilter->SetUseProgressBar(true); m_NormalsFilter->SetProgressStepSize(1); m_InterpolateSurfaceFilter->SetUseProgressBar(true); m_InterpolateSurfaceFilter->SetProgressStepSize(7); m_Contours = Surface::New(); m_PolyData = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); m_PolyData->SetPoints(points); m_InterpolationResult = 0; m_CurrentNumberOfReducedContours = 0; } mitk::SurfaceInterpolationController::~SurfaceInterpolationController() { //Removing all observers std::map::iterator dataIter = m_SegmentationObserverTags.begin(); for (; dataIter != m_SegmentationObserverTags.end(); ++dataIter ) { (*dataIter).first->RemoveObserver( (*dataIter).second ); } m_SegmentationObserverTags.clear(); } mitk::SurfaceInterpolationController* mitk::SurfaceInterpolationController::GetInstance() { static mitk::SurfaceInterpolationController::Pointer m_Instance; if ( m_Instance.IsNull() ) { m_Instance = SurfaceInterpolationController::New(); } return m_Instance; } void mitk::SurfaceInterpolationController::AddNewContour (mitk::Surface::Pointer newContour) { if( newContour->GetVtkPolyData()->GetNumberOfPoints() > 0) { ContourPositionInformation contourInfo = CreateContourPositionInformation(newContour); this->AddToInterpolationPipeline(contourInfo); this->Modified(); } } void mitk::SurfaceInterpolationController::AddNewContours(std::vector newContours) { for (unsigned int i = 0; i < newContours.size(); ++i) { if( newContours.at(i)->GetVtkPolyData()->GetNumberOfPoints() > 0) { ContourPositionInformation contourInfo = CreateContourPositionInformation(newContours.at(i)); this->AddToInterpolationPipeline(contourInfo); } } this->Modified(); } void mitk::SurfaceInterpolationController::AddToInterpolationPipeline(ContourPositionInformation contourInfo) { int pos (-1); ContourPositionInformationList currentContourList = m_ListOfInterpolationSessions[m_SelectedSegmentation]; mitk::Surface* newContour = contourInfo.contour; for (unsigned int i = 0; i < currentContourList.size(); i++) { ContourPositionInformation contourFromList = currentContourList.at(i); if (ContoursCoplanar(contourInfo, contourFromList)) { pos = i; break; } } //Don't save a new empty contour if (pos == -1 && newContour->GetVtkPolyData()->GetNumberOfPoints() > 0) { m_ReduceFilter->SetInput(m_ListOfInterpolationSessions[m_SelectedSegmentation].size(), newContour); m_ListOfInterpolationSessions[m_SelectedSegmentation].push_back(contourInfo); } else if (pos != -1 && newContour->GetVtkPolyData()->GetNumberOfPoints() > 0) { m_ListOfInterpolationSessions[m_SelectedSegmentation].at(pos) = contourInfo; m_ReduceFilter->SetInput(pos, newContour); } else if (newContour->GetVtkPolyData()->GetNumberOfPoints() == 0) { this->RemoveContour(contourInfo); } m_ReduceFilter->Update(); m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs(); for (unsigned int i = 0; i < m_CurrentNumberOfReducedContours; i++) { m_NormalsFilter->SetInput(i, m_ReduceFilter->GetOutput(i)); m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i)); } } bool mitk::SurfaceInterpolationController::RemoveContour(ContourPositionInformation contourInfo) { if(!m_SelectedSegmentation) return false; ContourPositionInformationList::iterator it = m_ListOfInterpolationSessions[m_SelectedSegmentation].begin(); while (it != m_ListOfInterpolationSessions[m_SelectedSegmentation].end()) { ContourPositionInformation currentContour = (*it); if (ContoursCoplanar(currentContour, contourInfo)) { m_ListOfInterpolationSessions[m_SelectedSegmentation].erase(it); this->ReinitializeInterpolation(); return true; } ++it; } return false; } const mitk::Surface* mitk::SurfaceInterpolationController::GetContour(ContourPositionInformation contourInfo) { ContourPositionInformationList contourList = m_ListOfInterpolationSessions[m_SelectedSegmentation]; for (unsigned int i = 0; i < contourList.size(); ++i) { ContourPositionInformation currentContour = contourList.at(i); if (ContoursCoplanar(contourInfo, currentContour)) return currentContour.contour; } return 0; } unsigned int mitk::SurfaceInterpolationController::GetNumberOfContours() { return m_ListOfInterpolationSessions[m_SelectedSegmentation].size(); } void mitk::SurfaceInterpolationController::Interpolate() { if (m_CurrentNumberOfReducedContours< 2) { //If no interpolation is possible reset the interpolation result m_InterpolationResult = 0; return; } //Setting up progress bar mitk::ProgressBar::GetInstance()->AddStepsToDo(10); // create a surface from the distance-image mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New(); imageToSurfaceFilter->SetInput( m_InterpolateSurfaceFilter->GetOutput() ); imageToSurfaceFilter->SetThreshold( 0 ); imageToSurfaceFilter->SetSmooth(true); imageToSurfaceFilter->SetSmoothIteration(20); imageToSurfaceFilter->Update(); m_InterpolationResult = imageToSurfaceFilter->GetOutput(); vtkSmartPointer polyDataAppender = vtkSmartPointer::New(); for (unsigned int i = 0; i < m_ListOfInterpolationSessions[m_SelectedSegmentation].size(); i++) { polyDataAppender->AddInputData(m_ListOfInterpolationSessions[m_SelectedSegmentation].at(i).contour->GetVtkPolyData()); } polyDataAppender->Update(); m_Contours->SetVtkPolyData(polyDataAppender->GetOutput()); //Last progress step mitk::ProgressBar::GetInstance()->Progress(20); m_InterpolationResult->DisconnectPipeline(); } mitk::Surface::Pointer mitk::SurfaceInterpolationController::GetInterpolationResult() { return m_InterpolationResult; } mitk::Surface* mitk::SurfaceInterpolationController::GetContoursAsSurface() { return m_Contours; } void mitk::SurfaceInterpolationController::SetDataStorage(DataStorage::Pointer ds) { m_DataStorage = ds; } void mitk::SurfaceInterpolationController::SetMinSpacing(double minSpacing) { m_ReduceFilter->SetMinSpacing(minSpacing); } void mitk::SurfaceInterpolationController::SetMaxSpacing(double maxSpacing) { m_ReduceFilter->SetMaxSpacing(maxSpacing); m_NormalsFilter->SetMaxSpacing(maxSpacing); } void mitk::SurfaceInterpolationController::SetDistanceImageVolume(unsigned int distImgVolume) { m_InterpolateSurfaceFilter->SetDistanceImageVolume(distImgVolume); } mitk::Image::Pointer mitk::SurfaceInterpolationController::GetCurrentSegmentation() { return m_SelectedSegmentation; } mitk::Image* mitk::SurfaceInterpolationController::GetImage() { return m_InterpolateSurfaceFilter->GetOutput(); } double mitk::SurfaceInterpolationController::EstimatePortionOfNeededMemory() { double numberOfPointsAfterReduction = m_ReduceFilter->GetNumberOfPointsAfterReduction()*3; double sizeOfPoints = pow(numberOfPointsAfterReduction,2)*sizeof(double); double totalMem = mitk::MemoryUtilities::GetTotalSizeOfPhysicalRam(); double percentage = sizeOfPoints/totalMem; return percentage; } unsigned int mitk::SurfaceInterpolationController::GetNumberOfInterpolationSessions() { return m_ListOfInterpolationSessions.size(); } template void mitk::SurfaceInterpolationController::GetImageBase(itk::Image* input, itk::ImageBase<3>::Pointer& result) { result->Graft(input); } void mitk::SurfaceInterpolationController::SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation) { this->SetCurrentInterpolationSession(segmentation); } void mitk::SurfaceInterpolationController::SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage) { if (currentSegmentationImage.GetPointer() == m_SelectedSegmentation) return; if (currentSegmentationImage.IsNull()) { m_SelectedSegmentation = 0; return; } m_SelectedSegmentation = currentSegmentationImage.GetPointer(); ContourListMap::iterator it = m_ListOfInterpolationSessions.find(currentSegmentationImage.GetPointer()); // If the session does not exist yet create a new ContourPositionPairList otherwise reinitialize the interpolation pipeline if (it == m_ListOfInterpolationSessions.end()) { ContourPositionInformationList newList; m_ListOfInterpolationSessions.insert(std::pair(m_SelectedSegmentation, newList)); m_InterpolationResult = 0; m_CurrentNumberOfReducedContours = 0; itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted); m_SegmentationObserverTags.insert( std::pair( m_SelectedSegmentation, m_SelectedSegmentation->AddObserver( itk::DeleteEvent(), command ) ) ); } this->ReinitializeInterpolation(); } +bool mitk::SurfaceInterpolationController::ReplaceInterpolationSession(mitk::Image::Pointer oldSession, mitk::Image::Pointer newSession) +{ + if (oldSession.IsNull() || newSession.IsNull()) + return false; + + if (oldSession.GetPointer() == newSession.GetPointer()) + return false; + + if (!mitk::Equal(*(oldSession->GetGeometry()), *(newSession->GetGeometry()), mitk::eps, false)) + return false; + + ContourListMap::iterator it = m_ListOfInterpolationSessions.find(oldSession.GetPointer()); + + if (it == m_ListOfInterpolationSessions.end()) + return false; + + ContourPositionInformationList oldList = (*it).second; + m_ListOfInterpolationSessions.insert(std::pair(newSession.GetPointer(), oldList)); + itk::MemberCommand::Pointer command = itk::MemberCommand::New(); + command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted); + m_SegmentationObserverTags.insert( std::pair( newSession, newSession->AddObserver( itk::DeleteEvent(), command ) ) ); + + if (m_SelectedSegmentation == oldSession) + m_SelectedSegmentation = newSession; + m_NormalsFilter->SetSegmentationBinaryImage(m_SelectedSegmentation); + + this->RemoveInterpolationSession(oldSession); + return true; +} + void mitk::SurfaceInterpolationController::RemoveSegmentationFromContourList(mitk::Image *segmentation) { this->RemoveInterpolationSession(segmentation); } void mitk::SurfaceInterpolationController::RemoveInterpolationSession(mitk::Image::Pointer segmentationImage) { if (segmentationImage) { if (m_SelectedSegmentation == segmentationImage) { m_NormalsFilter->SetSegmentationBinaryImage(NULL); m_SelectedSegmentation = 0; } m_ListOfInterpolationSessions.erase(segmentationImage); // Remove observer std::map::iterator pos = m_SegmentationObserverTags.find(segmentationImage); if (pos != m_SegmentationObserverTags.end()) { segmentationImage->RemoveObserver((*pos).second); m_SegmentationObserverTags.erase(pos); } } } void mitk::SurfaceInterpolationController::RemoveAllInterpolationSessions() { //Removing all observers std::map::iterator dataIter = m_SegmentationObserverTags.begin(); while (dataIter != m_SegmentationObserverTags.end()) { mitk::Image* image = (*dataIter).first; image->RemoveObserver((*dataIter).second); ++dataIter; } m_SegmentationObserverTags.clear(); m_SelectedSegmentation = 0; m_ListOfInterpolationSessions.clear(); } void mitk::SurfaceInterpolationController::ReinitializeInterpolation(mitk::Surface::Pointer contours) { // 1. detect coplanar contours // 2. merge coplanar contours into a single surface // 4. add contour to pipeline // Split the surface into separate polygons vtkSmartPointer existingPolys; vtkSmartPointer existingPoints; existingPolys = contours->GetVtkPolyData()->GetPolys(); existingPoints = contours->GetVtkPolyData()->GetPoints(); existingPolys->InitTraversal(); vtkSmartPointer ids = vtkSmartPointer::New(); typedef std::pair PointNormalPair; std::vector list; std::vector > pointsList; int count (0); for( existingPolys->InitTraversal(); existingPolys->GetNextCell(ids);) { // Get the points vtkSmartPointer points = vtkSmartPointer::New(); existingPoints->GetPoints(ids, points); ++count; pointsList.push_back(points); PointNormalPair p_n; double n[3]; vtkPolygon::ComputeNormal(points, n); p_n.first = n; double p[3]; existingPoints->GetPoint(ids->GetId(0), p); p_n.second = p; ContourPositionInformation p_info; p_info.contourNormal = n; p_info.contourPoint = p; list.push_back(p_info); continue; } // Detect and sort coplanar polygons std::vector::iterator outer = list.begin(); std::vector< std::vector< vtkSmartPointer > > relatedPoints; while (outer != list.end()) { std::vector::iterator inner = outer; ++inner; std::vector< vtkSmartPointer > rel; std::vector< vtkSmartPointer >::iterator pointsIter = pointsList.begin(); rel.push_back((*pointsIter)); pointsIter = pointsList.erase(pointsIter); while (inner != list.end()) { if(ContoursCoplanar((*outer),(*inner))) { inner = list.erase(inner); rel.push_back((*pointsIter)); pointsIter = pointsList.erase(pointsIter); } else { ++inner; ++pointsIter; } } relatedPoints.push_back(rel); ++outer; } // Build the separate surfaces again std::vector finalSurfaces; for (unsigned int i = 0; i < relatedPoints.size(); ++i) { vtkSmartPointer contourSurface = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer polygons = vtkSmartPointer::New(); unsigned int pointId (0); for (unsigned int j = 0; j < relatedPoints.at(i).size(); ++j) { unsigned int numPoints = relatedPoints.at(i).at(j)->GetNumberOfPoints(); vtkSmartPointer polygon = vtkSmartPointer::New(); polygon->GetPointIds()->SetNumberOfIds(numPoints); polygon->GetPoints()->SetNumberOfPoints(numPoints); vtkSmartPointer currentPoints = relatedPoints.at(i).at(j); for (unsigned k = 0; k < numPoints; ++k) { points->InsertPoint(pointId, currentPoints->GetPoint(k)); polygon->GetPointIds()->SetId(k, pointId); ++pointId; } polygons->InsertNextCell(polygon); } contourSurface->SetPoints(points); contourSurface->SetPolys(polygons); contourSurface->BuildLinks(); mitk::Surface::Pointer surface = mitk::Surface::New(); surface->SetVtkPolyData(contourSurface); finalSurfaces.push_back(surface); } // Add detected contours to interpolation pipeline this->AddNewContours(finalSurfaces); } void mitk::SurfaceInterpolationController::OnSegmentationDeleted(const itk::Object *caller, const itk::EventObject &/*event*/) { mitk::Image* tempImage = dynamic_cast(const_cast(caller)); if (tempImage) { if (m_SelectedSegmentation == tempImage) { m_NormalsFilter->SetSegmentationBinaryImage(NULL); m_SelectedSegmentation = 0; } m_SegmentationObserverTags.erase(tempImage); m_ListOfInterpolationSessions.erase(tempImage); } } void mitk::SurfaceInterpolationController::ReinitializeInterpolation() { m_NormalsFilter->SetSegmentationBinaryImage(m_SelectedSegmentation); // If session has changed reset the pipeline m_ReduceFilter->Reset(); m_NormalsFilter->Reset(); m_InterpolateSurfaceFilter->Reset(); itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New(); AccessFixedDimensionByItk_1( m_SelectedSegmentation, GetImageBase, 3, itkImage ); m_InterpolateSurfaceFilter->SetReferenceImage(itkImage.GetPointer()); for (unsigned int i = 0; i < m_ListOfInterpolationSessions[m_SelectedSegmentation].size(); i++) { m_ReduceFilter->SetInput(i, m_ListOfInterpolationSessions[m_SelectedSegmentation].at(i).contour); } m_ReduceFilter->Update(); m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs(); for (unsigned int i = 0; i < m_CurrentNumberOfReducedContours; i++) { m_NormalsFilter->SetInput(i, m_ReduceFilter->GetOutput(i)); m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i)); } Modified(); } diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h index 12285d0361..50654d7785 100644 --- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h +++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h @@ -1,226 +1,236 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkSurfaceInterpolationController_h_Included #define mitkSurfaceInterpolationController_h_Included #include "mitkCommon.h" #include #include "mitkRestorePlanePositionOperation.h" #include "mitkSurface.h" #include "mitkInteractionConst.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkCreateDistanceImageFromSurfaceFilter.h" #include "mitkReduceContourSetFilter.h" #include "mitkComputeContourSetNormalsFilter.h" #include "mitkDataNode.h" #include "mitkDataStorage.h" #include "mitkWeakPointer.h" #include "vtkPolygon.h" #include "vtkPoints.h" #include "vtkCellArray.h" #include "vtkPolyData.h" #include "vtkSmartPointer.h" #include "vtkAppendPolyData.h" #include "vtkMarchingCubes.h" #include "vtkImageData.h" #include "mitkVtkRepresentationProperty.h" #include "vtkProperty.h" #include "mitkProgressBar.h" namespace mitk { class MitkSurfaceInterpolation_EXPORT SurfaceInterpolationController : public itk::Object { public: mitkClassMacro(SurfaceInterpolationController, itk::Object) itkFactorylessNewMacro(Self) itkCloneMacro(Self) struct ContourPositionInformation { Surface::Pointer contour; Vector3D contourNormal; Point3D contourPoint; }; typedef std::vector ContourPositionInformationList; typedef std::map ContourListMap; static SurfaceInterpolationController* GetInstance(); /** * @brief Adds a new extracted contour to the list * @param newContour the contour to be added. If a contour at that position * already exists the related contour will be updated */ void AddNewContour (Surface::Pointer newContour); /** * @brief Removes the contour for a given plane for the current selected segmenation * @param contourInfo the contour which should be removed * @return true if a contour was found and removed, false if no contour was found */ bool RemoveContour (ContourPositionInformation contourInfo); /** * @brief Adds new extracted contours to the list. If one or more contours at a given position * already exist they will be updated respectively * @param newContours the list of the contours */ void AddNewContours (std::vector newContours); /** * @brief Returns the contour for a given plane for the current selected segmenation * @param ontourInfo the contour which should be returned * @return the contour as an mitk::Surface. If no contour is available at the give position NULL is returned */ const mitk::Surface* GetContour (ContourPositionInformation contourInfo); /** * @brief Returns the number of available contours for the current selected segmentation * @return the number of contours */ unsigned int GetNumberOfContours(); /** * Interpolates the 3D surface from the given extracted contours */ void Interpolate (); mitk::Surface::Pointer GetInterpolationResult(); /** * Sets the minimum spacing of the current selected segmentation * This is needed since the contour points we reduced before they are used to interpolate the surface */ void SetMinSpacing(double minSpacing); /** * Sets the minimum spacing of the current selected segmentation * This is needed since the contour points we reduced before they are used to interpolate the surface */ void SetMaxSpacing(double maxSpacing); /** * Sets the volume i.e. the number of pixels that the distance image should have * By evaluation we found out that 50.000 pixel delivers a good result */ void SetDistanceImageVolume(unsigned int distImageVolume); /** * @brief Get the current selected segmentation for which the interpolation is performed * @return the current segmentation image */ mitk::Image::Pointer GetCurrentSegmentation(); Surface* GetContoursAsSurface(); void SetDataStorage(DataStorage::Pointer ds); /** * Sets the current list of contourpoints which is used for the surface interpolation * @param segmentation The current selected segmentation * \deprecatedSince{2014_03} */ DEPRECATED (void SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation)); /** * Sets the current list of contourpoints which is used for the surface interpolation * @param segmentation The current selected segmentation */ void SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage); /** * Removes the segmentation and all its contours from the list * @param segmentation The segmentation to be removed * \deprecatedSince{2014_03} */ DEPRECATED (void RemoveSegmentationFromContourList(mitk::Image* segmentation)); /** * @brief Remove interpolation session * @param segmentationImage the session to be removed */ void RemoveInterpolationSession(mitk::Image::Pointer segmentationImage); + /** + * Replaces the current interpolation session with a new one. All contours form the old + * session will be applied to the new session. This only works if the two images have the + * geometry + * @param oldSession the session which should be replaced + * @param newSession the new session which replaces the old one + * @return true it the the replacement was successful, false if not (e.g. the image's geometry differs) + */ + bool ReplaceInterpolationSession(mitk::Image::Pointer oldSession, mitk::Image::Pointer newSession); + /** * @brief Removes all sessions */ void RemoveAllInterpolationSessions(); /** * @brief Reinitializes the interpolation using the provided contour data * @param contours a mitk::Surface which contains the contours as polys in the vtkPolyData */ void ReinitializeInterpolation(mitk::Surface::Pointer contours); mitk::Image* GetImage(); /** * Estimates the memory which is needed to build up the equationsystem for the interpolation. * \returns The percentage of the real memory which will be used by the interpolation */ double EstimatePortionOfNeededMemory(); unsigned int GetNumberOfInterpolationSessions(); protected: SurfaceInterpolationController(); ~SurfaceInterpolationController(); template void GetImageBase(itk::Image* input, itk::ImageBase<3>::Pointer& result); private: void OnSegmentationDeleted(const itk::Object *caller, const itk::EventObject &event); void ReinitializeInterpolation(); void AddToInterpolationPipeline(ContourPositionInformation contourInfo); ReduceContourSetFilter::Pointer m_ReduceFilter; ComputeContourSetNormalsFilter::Pointer m_NormalsFilter; CreateDistanceImageFromSurfaceFilter::Pointer m_InterpolateSurfaceFilter; Surface::Pointer m_Contours; vtkSmartPointer m_PolyData; mitk::DataStorage::Pointer m_DataStorage; ContourListMap m_ListOfInterpolationSessions; mitk::Surface::Pointer m_InterpolationResult; unsigned int m_CurrentNumberOfReducedContours; mitk::Image* m_SelectedSegmentation; std::map m_SegmentationObserverTags; }; } #endif diff --git a/Modules/ToFHardware/Testing/mitkToFImageRecorderTest.cpp b/Modules/ToFHardware/Testing/mitkToFImageRecorderTest.cpp index 2623414640..2755ea5ce2 100644 --- a/Modules/ToFHardware/Testing/mitkToFImageRecorderTest.cpp +++ b/Modules/ToFHardware/Testing/mitkToFImageRecorderTest.cpp @@ -1,151 +1,155 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include class mitkToFImageRecorderTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkToFImageRecorderTestSuite); //Removed due to random fails on linux continuous bug #12977 -// MITK_TEST(StartRecording_ValidDepthImage_WritesImageToFile); -// MITK_TEST(StartRecording_ValidAmplitudeImage_WritesImageToFile); -// MITK_TEST(StartRecording_ValidIntensityImage_WritesImageToFile); + MITK_TEST(StartRecording_ValidDepthImage_WritesImageToFile); + MITK_TEST(StartRecording_ValidAmplitudeImage_WritesImageToFile); + MITK_TEST(StartRecording_ValidIntensityImage_WritesImageToFile); CPPUNIT_TEST_SUITE_END(); private: /** Members used inside the different (sub-)tests. All members are initialized via setUp(). * Every recorder needs a device. Here we use a player device. * The player device needs data to load. The ground truth is loaded via IOUtil. */ mitk::ToFImageRecorder::Pointer m_ToFImageRecorder; mitk::ToFCameraMITKPlayerDevice::Pointer m_PlayerDevice; std::string m_DistanceImageName; std::string m_AmplitudeImageName; std::string m_IntensityImageName; mitk::Image::Pointer m_GroundTruthDepthImage; mitk::Image::Pointer m_GroundTruthIntensityImage; mitk::Image::Pointer m_GroundTruthAmplitudeImage; public: /** * @brief Setup a recorder including a device. Here, we use a player, because in an automatic test * hardware is not useful. */ void setUp() { m_ToFImageRecorder = mitk::ToFImageRecorder::New(); - m_DistanceImageName = "test_DistanceImage.nrrd"; - m_AmplitudeImageName = "test_AmplitudeImage.nrrd"; - m_IntensityImageName = "test_IntensityImage.nrrd"; + m_DistanceImageName = mitk::IOUtil::CreateTemporaryFile();//"test_DistanceImage.nrrd"; + m_AmplitudeImageName = mitk::IOUtil::CreateTemporaryFile();//"test_AmplitudeImage.nrrd"; + m_IntensityImageName = mitk::IOUtil::CreateTemporaryFile();//"test_IntensityImage.nrrd"; + + m_DistanceImageName.append(".nrrd"); + m_AmplitudeImageName.append(".nrrd"); + m_IntensityImageName.append(".nrrd"); m_PlayerDevice = mitk::ToFCameraMITKPlayerDevice::New(); m_ToFImageRecorder->SetCameraDevice(m_PlayerDevice); //the test data set has 20 frames, so we record 20 per default m_ToFImageRecorder->SetNumOfFrames(20); m_ToFImageRecorder->SetRecordMode(mitk::ToFImageRecorder::PerFrames); std::string dirName = MITK_TOF_DATA_DIR; std::string distanceFileName = dirName + "/PMDCamCube2_MF0_IT0_20Images_DistanceImage.pic"; std::string amplitudeFileName = dirName + "/PMDCamCube2_MF0_IT0_20Images_AmplitudeImage.pic"; std::string intensityFileName = dirName + "/PMDCamCube2_MF0_IT0_20Images_IntensityImage.pic"; m_PlayerDevice->SetProperty("DistanceImageFileName",mitk::StringProperty::New(distanceFileName)); m_PlayerDevice->SetProperty("AmplitudeImageFileName",mitk::StringProperty::New(amplitudeFileName)); m_PlayerDevice->SetProperty("IntensityImageFileName",mitk::StringProperty::New(intensityFileName)); //comparing against IOUtil seems fair enough m_GroundTruthDepthImage = mitk::IOUtil::LoadImage(distanceFileName); m_GroundTruthAmplitudeImage = mitk::IOUtil::LoadImage(amplitudeFileName); m_GroundTruthIntensityImage = mitk::IOUtil::LoadImage(intensityFileName); m_PlayerDevice->ConnectCamera(); m_PlayerDevice->StartCamera(); } void tearDown() { m_PlayerDevice->StopCamera(); m_PlayerDevice->DisconnectCamera(); } void StartRecording_ValidDepthImage_WritesImageToFile() { m_ToFImageRecorder->SetDistanceImageFileName(m_DistanceImageName); m_ToFImageRecorder->StartRecording(); m_ToFImageRecorder->WaitForThreadBeingTerminated(); // wait to allow recording m_ToFImageRecorder->StopRecording(); mitk::Image::Pointer recordedImage = mitk::IOUtil::LoadImage(m_DistanceImageName); MITK_ASSERT_EQUAL( m_GroundTruthDepthImage, recordedImage, "Recorded image should be equal to the test data."); if( remove( m_DistanceImageName.c_str() ) != 0 ) { - MITK_ERROR<<"File: test_distance.nrrd not successfully deleted!"; + MITK_ERROR<<"File: "<< m_DistanceImageName << " not successfully deleted!"; } } void StartRecording_ValidAmplitudeImage_WritesImageToFile() { m_ToFImageRecorder->SetAmplitudeImageFileName(m_AmplitudeImageName); m_ToFImageRecorder->SetAmplitudeImageSelected(true); m_ToFImageRecorder->SetDistanceImageSelected(false); m_ToFImageRecorder->StartRecording(); m_ToFImageRecorder->WaitForThreadBeingTerminated(); // wait to allow recording m_ToFImageRecorder->StopRecording(); mitk::Image::Pointer recordedImage = mitk::IOUtil::LoadImage(m_AmplitudeImageName); MITK_ASSERT_EQUAL( m_GroundTruthAmplitudeImage, recordedImage, "Recorded image should be equal to the test data."); if( remove( m_AmplitudeImageName.c_str() ) != 0 ) { - MITK_ERROR<<"File: test_amplitude.nrrd not successfully deleted!"; + MITK_ERROR<<"File: "<< m_AmplitudeImageName << " not successfully deleted!"; } } void StartRecording_ValidIntensityImage_WritesImageToFile() { m_ToFImageRecorder->SetIntensityImageFileName(m_IntensityImageName); m_ToFImageRecorder->SetIntensityImageSelected(true); m_ToFImageRecorder->SetDistanceImageSelected(false); m_ToFImageRecorder->StartRecording(); m_ToFImageRecorder->WaitForThreadBeingTerminated(); // wait to allow recording m_ToFImageRecorder->StopRecording(); mitk::Image::Pointer recordedImage = mitk::IOUtil::LoadImage(m_IntensityImageName); MITK_ASSERT_EQUAL( m_GroundTruthIntensityImage, recordedImage, "Recorded image should be equal to the test data."); if( remove( m_IntensityImageName.c_str() ) != 0 ) { - MITK_ERROR<<"File: test_intensity.nrrd not successfully deleted!"; + MITK_ERROR<<"File: "<< m_IntensityImageName << " not successfully deleted!"; } } }; MITK_TEST_SUITE_REGISTRATION(mitkToFImageRecorder) diff --git a/Modules/ToFHardware/mitkToFImageRecorder.cpp b/Modules/ToFHardware/mitkToFImageRecorder.cpp index 7eb8605e30..3ad365601b 100644 --- a/Modules/ToFHardware/mitkToFImageRecorder.cpp +++ b/Modules/ToFHardware/mitkToFImageRecorder.cpp @@ -1,268 +1,316 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFImageRecorder.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include #pragma GCC visibility push(default) #include #pragma GCC visibility pop namespace mitk { ToFImageRecorder::ToFImageRecorder() { this->m_ToFCameraDevice = NULL; this->m_MultiThreader = itk::MultiThreader::New(); this->m_AbortMutex = itk::FastMutexLock::New(); this->m_ThreadID = 0; this->m_NumOfFrames = 1; //lets record one frame per default this->m_ToFImageWriter = NULL; this->m_DistanceImageSelected = true; //lets assume a device only has depth data by default this->m_AmplitudeImageSelected = false; this->m_IntensityImageSelected = false; this->m_RGBImageSelected = false; this->m_Abort = false; this->m_ToFCaptureWidth = 0; this->m_ToFCaptureHeight = 0; this->m_RGBCaptureWidth = 0; this->m_RGBCaptureHeight = 0; this->m_FileFormat = ".nrrd"; //lets make nrrd the default this->m_ToFPixelNumber = 0; this->m_RGBPixelNumber = 0; this->m_SourceDataSize = 0; this->m_ToFImageType = ToFImageWriter::ToFImageType3D; this->m_RecordMode = ToFImageRecorder::PerFrames; this->m_DistanceImageFileName = ""; this->m_AmplitudeImageFileName = ""; this->m_IntensityImageFileName = ""; this->m_RGBImageFileName = ""; this->m_ImageSequence = 0; this->m_DistanceArray = NULL; this->m_AmplitudeArray = NULL; this->m_IntensityArray = NULL; this->m_RGBArray = NULL; this->m_SourceDataArray = NULL; } ToFImageRecorder::~ToFImageRecorder() { delete[] m_DistanceArray; delete[] m_AmplitudeArray; delete[] m_IntensityArray; delete[] m_RGBArray; delete[] m_SourceDataArray; } void ToFImageRecorder::StopRecording() { this->m_AbortMutex->Lock(); this->m_Abort = true; this->m_AbortMutex->Unlock(); } void ToFImageRecorder::StartRecording() { if (this->m_ToFCameraDevice.IsNull()) { throw std::invalid_argument("ToFCameraDevice is NULL."); return; } if (this->m_FileFormat.compare(".csv") == 0) { this->m_ToFImageWriter = ToFImageCsvWriter::New(); } else if(this->m_FileFormat.compare(".nrrd") == 0) { this->m_ToFImageWriter = ToFNrrdImageWriter::New(); this->m_ToFImageWriter->SetExtension(m_FileFormat); } else { throw std::logic_error("No file format specified!"); } this->m_RGBCaptureWidth = this->m_ToFCameraDevice->GetRGBCaptureWidth(); this->m_RGBCaptureHeight = this->m_ToFCameraDevice->GetRGBCaptureHeight(); this->m_RGBPixelNumber = this->m_RGBCaptureWidth * this->m_RGBCaptureHeight; this->m_ToFCaptureWidth = this->m_ToFCameraDevice->GetCaptureWidth(); this->m_ToFCaptureHeight = this->m_ToFCameraDevice->GetCaptureHeight(); this->m_ToFPixelNumber = this->m_ToFCaptureWidth * this->m_ToFCaptureHeight; this->m_SourceDataSize = this->m_ToFCameraDevice->GetSourceDataSize(); // allocate buffer if(m_IntensityArray == NULL) { this->m_IntensityArray = new float[m_ToFPixelNumber]; } if(this->m_DistanceArray == NULL) { this->m_DistanceArray = new float[m_ToFPixelNumber]; } if(this->m_AmplitudeArray == NULL) { this->m_AmplitudeArray = new float[m_ToFPixelNumber]; } if(this->m_RGBArray == NULL) { this->m_RGBArray = new unsigned char[m_RGBPixelNumber*3]; } if(this->m_SourceDataArray == NULL) { this->m_SourceDataArray = new char[m_SourceDataSize]; } this->m_ToFImageWriter->SetDistanceImageFileName(this->m_DistanceImageFileName); this->m_ToFImageWriter->SetAmplitudeImageFileName(this->m_AmplitudeImageFileName); this->m_ToFImageWriter->SetIntensityImageFileName(this->m_IntensityImageFileName); this->m_ToFImageWriter->SetRGBImageFileName(this->m_RGBImageFileName); this->m_ToFImageWriter->SetRGBCaptureWidth(this->m_RGBCaptureWidth); this->m_ToFImageWriter->SetRGBCaptureHeight(this->m_RGBCaptureHeight); //this->m_ToFImageWriter->SetToFCaptureHeight(this->m_ToFCaptureHeight); this->m_ToFImageWriter->SetToFCaptureWidth(this->m_ToFCaptureWidth); this->m_ToFImageWriter->SetToFCaptureHeight(this->m_ToFCaptureHeight); this->m_ToFImageWriter->SetToFImageType(this->m_ToFImageType); this->m_ToFImageWriter->SetDistanceImageSelected(this->m_DistanceImageSelected); this->m_ToFImageWriter->SetAmplitudeImageSelected(this->m_AmplitudeImageSelected); this->m_ToFImageWriter->SetIntensityImageSelected(this->m_IntensityImageSelected); this->m_ToFImageWriter->SetRGBImageSelected(this->m_RGBImageSelected); this->m_ToFImageWriter->Open(); this->m_AbortMutex->Lock(); this->m_Abort = false; this->m_AbortMutex->Unlock(); - this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->RecordData, this); +// this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->RecordData, this); + + ToFCameraDevice::Pointer toFCameraDevice = this->GetCameraDevice(); + + mitk::RealTimeClock::Pointer realTimeClock; + realTimeClock = mitk::RealTimeClock::New(); + double t1 = 0; + t1 = realTimeClock->GetCurrentStamp(); + int requiredImageSequence = 0; + int numOfFramesRecorded = 0; + + bool abort = false; + this->m_AbortMutex->Lock(); + abort = this->m_Abort; + this->m_AbortMutex->Unlock(); + + while ( !abort ) + { + if ( ((this->m_RecordMode == ToFImageRecorder::PerFrames) && (numOfFramesRecorded < this->m_NumOfFrames)) || + (this->m_RecordMode == ToFImageRecorder::Infinite) ) + { + + toFCameraDevice->GetAllImages(this->m_DistanceArray, this->m_AmplitudeArray, + this->m_IntensityArray, this->m_SourceDataArray, requiredImageSequence, this->m_ImageSequence, this->m_RGBArray ); + + if (this->m_ImageSequence >= requiredImageSequence) + { + if (this->m_ImageSequence > requiredImageSequence) + { + MITK_INFO << "Problem! required: " << requiredImageSequence << " captured: " << this->m_ImageSequence; + } + requiredImageSequence = this->m_ImageSequence + 1; + this->m_ToFImageWriter->Add( this->m_DistanceArray, + this->m_AmplitudeArray, this->m_IntensityArray, this->m_RGBArray ); + numOfFramesRecorded++; + } + this->m_AbortMutex->Lock(); + abort = this->m_Abort; + this->m_AbortMutex->Unlock(); + } + else + { + abort = true; + } + } // end of while loop + + this->InvokeEvent(itk::AbortEvent()); + + this->m_ToFImageWriter->Close(); } void ToFImageRecorder::WaitForThreadBeingTerminated() { this->m_MultiThreader->TerminateThread(this->m_ThreadID); } ITK_THREAD_RETURN_TYPE ToFImageRecorder::RecordData(void* pInfoStruct) { struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFImageRecorder* toFImageRecorder = (ToFImageRecorder*)pInfo->UserData; if (toFImageRecorder!=NULL) { ToFCameraDevice::Pointer toFCameraDevice = toFImageRecorder->GetCameraDevice(); mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); int n = 100; double t1 = 0; double t2 = 0; t1 = realTimeClock->GetCurrentStamp(); bool overflow = false; bool printStatus = false; int requiredImageSequence = 0; int numOfFramesRecorded = 0; bool abort = false; toFImageRecorder->m_AbortMutex->Lock(); abort = toFImageRecorder->m_Abort; toFImageRecorder->m_AbortMutex->Unlock(); while ( !abort ) { if ( ((toFImageRecorder->m_RecordMode == ToFImageRecorder::PerFrames) && (numOfFramesRecorded < toFImageRecorder->m_NumOfFrames)) || (toFImageRecorder->m_RecordMode == ToFImageRecorder::Infinite) ) { toFCameraDevice->GetAllImages(toFImageRecorder->m_DistanceArray, toFImageRecorder->m_AmplitudeArray, toFImageRecorder->m_IntensityArray, toFImageRecorder->m_SourceDataArray, requiredImageSequence, toFImageRecorder->m_ImageSequence, toFImageRecorder->m_RGBArray ); if (toFImageRecorder->m_ImageSequence >= requiredImageSequence) { if (toFImageRecorder->m_ImageSequence > requiredImageSequence) { MITK_INFO << "Problem! required: " << requiredImageSequence << " captured: " << toFImageRecorder->m_ImageSequence; } requiredImageSequence = toFImageRecorder->m_ImageSequence + 1; toFImageRecorder->m_ToFImageWriter->Add( toFImageRecorder->m_DistanceArray, toFImageRecorder->m_AmplitudeArray, toFImageRecorder->m_IntensityArray, toFImageRecorder->m_RGBArray ); numOfFramesRecorded++; if (numOfFramesRecorded % n == 0) { printStatus = true; } if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFImageRecorder->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } toFImageRecorder->m_AbortMutex->Lock(); abort = toFImageRecorder->m_Abort; toFImageRecorder->m_AbortMutex->Unlock(); } else { abort = true; } } // end of while loop toFImageRecorder->InvokeEvent(itk::AbortEvent()); toFImageRecorder->m_ToFImageWriter->Close(); } return ITK_THREAD_RETURN_VALUE; } void ToFImageRecorder::SetCameraDevice(ToFCameraDevice* aToFCameraDevice) { this->m_ToFCameraDevice = aToFCameraDevice; } ToFCameraDevice* ToFImageRecorder::GetCameraDevice() { return this->m_ToFCameraDevice; } ToFImageWriter::ToFImageType ToFImageRecorder::GetToFImageType() { return this->m_ToFImageType; } void ToFImageRecorder::SetToFImageType(ToFImageWriter::ToFImageType toFImageType) { this->m_ToFImageType = toFImageType; } ToFImageRecorder::RecordMode ToFImageRecorder::GetRecordMode() { return this->m_RecordMode; } void ToFImageRecorder::SetRecordMode(ToFImageRecorder::RecordMode recordMode) { this->m_RecordMode = recordMode; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/DataImport/dicom1.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/DataImport/dicom1.png index 0151f56bea..85ca20974f 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/DataImport/dicom1.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/DataImport/dicom1.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs1.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs1.png index 379f21dc7e..1493a30fdf 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs1.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs1.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs2.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs2.png index b208895fc7..981d387842 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs2.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs2.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs3.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs3.png index 8f5155ae2f..9eea5739a5 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs3.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/qballs3.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/residuals.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/residuals.png index 626fbaf6e3..f9d4996e15 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/residuals.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/residuals.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor1.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor1.png index 6aae4ff4d9..23af1def89 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor1.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor1.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor4.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor4.png index c4708fff21..546ab70b2f 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor4.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/tensor4.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/visualization3.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/visualization3.png index acc816f8d7..1f0a0fd15b 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/visualization3.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Preproc_Recons/visualization3.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox index f61238e231..571689e8e1 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox @@ -1,84 +1,84 @@ /** \page org_mitk_gui_qt_diffusionimaging MITK Diffusion Imaging (MITK-DI) \tableofcontents This module provides means to diffusion weighted image reconstruction, visualization and quantification. Diffusion tensors as well as different q-ball reconstruction schemes are supported. Q-ball imaging aims at recovering more detailed information about the orientations of fibers from diffusion MRI measurements and, in particular, to resolve the orientations of crossing fibers. \section org_mitk_gui_qt_diffusionimagingComponents Components MITK Diffusion consists of further components, which have their own documentation, see: \subsection org_mitk_gui_qt_diffusionimagingComponentsDataImport Data Import \li \subpage QmitkDiffusionImagingDataImportPage \subsection org_mitk_gui_qt_diffusionimagingComponentsPreprocessingAndReconstruction Preprocessing and Reconstruction Register or denoise original data and convert it into tensor or q-ball images. \li \subpage org_mitk_views_diffusionregistrationview \li \subpage org_mitk_views_diffusionpreprocessing \li \subpage QmitkDiffusionImagingReconstructionPage \li \subpage org_mitk_views_controlvisualizationpropertiesview \li \subpage org_mitk_views_odfdetails \li \subpage org_mitk_views_odfmaximaextraction \li \subpage org_mitk_views_denoisingview \subsection org_mitk_gui_qt_diffusionimagingComponentsFiberTracking Fiber Tracking Create and work with fiber tractographies. \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_gibbstracking \li \subpage org_mitk_views_stochasticfibertracking \li \subpage org_mitk_views_fiberextraction \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_streamlinetracking \li \subpage org_mitk_views_fiberfoxview \li \subpage org_mitk_views_fieldmapgenerator \subsection org_mitk_gui_qt_diffusionimagingComponentsQuantification Quantification Create parameter maps and quantify different properties. - \li \subpage QmitkDiffusionImagingQuantificationPage + \li \subpage org_mitk_views_diffusionquantification \li \subpage org_mitk_views_ivim \li \subpage org_mitk_views_partialvolumeanalysisview \li \subpage org_mitk_views_tractbasedspatialstatistics \subsection org_mitk_gui_qt_diffusionimagingComponentsConnectomics Connectomics Create and analyse connectome networks. \li \subpage org_mitk_diffusionimagingapp_perspectives_connectomics \section org_mitk_gui_qt_diffusionimagingIssues Known Issues \li Dicom Import: The dicom import has so far only been implemented for Siemens dicom images. MITK-DI is capable of reading the nrrd format, which is documented elsewhere [1, 2]. These files can be created by combining the raw image data with a corresponding textual header file. The file extension should be changed from *.nrrd to *.dwi or from *.nhdr to *.hdwi respectively in order to let MITK-DI recognize the diffusion related header information provided in the files. \section org_mitk_gui_qt_diffusionimagingTechnicalDetails Technical Information for Developers The diffusion imaging module uses additional properties beside the ones in use in other modules, for further information see \ref DiffusionImagingPropertiesPage . \section org_mitk_gui_qt_diffusionimagingReferences References Further reading regarding diffusion: 1. http://teem.sourceforge.net/nrrd/format.html 2. http://www.cmake.org/Wiki/Getting_Started_with_the_NRRD_Format 3. C.F.Westin, S.E.Maier, H.Mamata, A.Nabavi, F.A.Jolesz, R.Kikinis, "Processing and visualization for Diffusion tensor MRI", Medical image Analysis, 2002, pp 93-108 5. Tuch, D.S., 2004. Q-ball imaging. Magn Reson Med 52, 1358-1372. 6. Descoteaux, M., Angelino, E., Fitzgibbons, S., Deriche, R., 2007. Regularized, fast, and robust analytical Q-ball imaging. Magn Reson Med 58, 497-510. 7. Aganj, I., Lenglet, C., Sapiro, G., 2009. ODF reconstruction in q-ball imaging with solid angle consideration. Proceedings of the Sixth IEEE International Symposium on Biomedical Imaging Boston, MA. 8. Goh, A., Lenglet, C., Thompson, P.M., Vidal, R., 2009. Estimating Orientation Distribution Functions with Probability Density Constraints and Spatial Regularity. Med Image Comput Comput Assist Interv Int Conf Med Image Comput Comput Assist Interv LNCS 5761, 877 ff. 9. J.-D. Tournier, S. Mori, A. Leemans., 2011. Diffusion Tensor Imaging and Beyond. Magn Reson Med 65, 1532-1556. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/QmitkDiffusionImagingQuantificationPage.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/QmitkDiffusionImagingQuantificationPage.dox index c3ca35f105..cec142beed 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/QmitkDiffusionImagingQuantificationPage.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/QmitkDiffusionImagingQuantificationPage.dox @@ -1,8 +1,8 @@ /** -\page QmitkDiffusionImagingQuantificationPage Quantification +\page org_mitk_views_diffusionquantification Scalar Indices -The quantification view allows the derivation of different scalar anisotropy measures for the reconstructed tensors (Fractional Anisotropy, Relative Anisotropy, Axial Diffusivity, Radial Diffusivity) or q-balls (Generalized Fractional Anisotropy). +The scalar indices view allows the derivation of different scalar anisotropy measures for the reconstructed tensors (Fractional Anisotropy, Relative Anisotropy, Axial Diffusivity, Radial Diffusivity) or q-balls (Generalized Fractional Anisotropy). -\imageMacro{quantification.png,"Anisotropy quantification",2} -*/ \ No newline at end of file +\imageMacro{ScalarIndicesGUI.png,"Anisotropy quantification",2} +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/ScalarIndicesGUI.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/ScalarIndicesGUI.png new file mode 100644 index 0000000000..e3688f56cc Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/ScalarIndicesGUI.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/quantification.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/quantification.png deleted file mode 100644 index a768b66dca..0000000000 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/Quantification/quantification.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp index e1e77dd053..cd0b53ef56 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,2631 +1,2633 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk #include "QmitkFiberfoxView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view) : m_View(view) { } void QmitkFiberfoxWorker::run() { try{ switch (m_FilterType) { case 0: m_View->m_TractsToDwiFilter->Update(); break; case 1: m_View->m_ArtifactsToDwiFilter->Update(); break; } } catch( ... ) { } m_View->m_Thread.quit(); } const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImage( NULL ) , m_Worker(this) , m_ThreadIsRunning(false) { m_Worker.moveToThread(&m_Thread); connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run())); connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread())); connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_SimulationTimer = new QTimer(this); } void QmitkFiberfoxView::KillThread() { MITK_INFO << "Aborting DWI simulation."; switch (m_Worker.m_FilterType) { case 0: m_TractsToDwiFilter->SetAbortGenerateData(true); break; case 1: m_ArtifactsToDwiFilter->SetAbortGenerateData(true); break; } m_Controls->m_AbortSimulationButton->setEnabled(false); m_Controls->m_AbortSimulationButton->setText("Aborting simulation ..."); } void QmitkFiberfoxView::BeforeThread() { m_SimulationTime = QTime::currentTime(); m_SimulationTimer->start(100); m_Controls->m_AbortSimulationButton->setVisible(true); m_Controls->m_GenerateImageButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(true); m_ThreadIsRunning = true; } void QmitkFiberfoxView::AfterThread() { UpdateSimulationStatus(); m_SimulationTimer->stop(); m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_AbortSimulationButton->setEnabled(true); m_Controls->m_AbortSimulationButton->setText("Abort simulation"); m_Controls->m_GenerateImageButton->setVisible(true); m_ThreadIsRunning = false; QString statusText; FiberfoxParameters parameters; mitk::DiffusionImage::Pointer mitkImage = mitk::DiffusionImage::New(); switch (m_Worker.m_FilterType) { case 0: { statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (m_TractsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_TractsToDwiFilter->GetParameters(); mitkImage->SetVectorImage( m_TractsToDwiFilter->GetOutput() ); mitkImage->SetReferenceBValue(parameters.m_SignalGen.m_Bvalue); mitkImage->SetDirections(parameters.m_SignalGen.GetGradientDirections()); mitkImage->InitializeFromVectorImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() +"_b"+QString::number(parameters.m_SignalGen.m_Bvalue).toStdString() +"_"+parameters.m_Misc.m_SignalModelString +parameters.m_Misc.m_ArtifactModelString); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); parameters.m_Misc.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions(); for (unsigned int k=0; kInitializeByItk(volumeFractions.at(k).GetPointer()); image->SetVolume(volumeFractions.at(k)->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(parameters.m_Misc.m_ParentNode->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString()); GetDataStorage()->Add(node, parameters.m_Misc.m_ParentNode); } } m_TractsToDwiFilter = NULL; break; } case 1: { statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); if (m_ArtifactsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_ArtifactsToDwiFilter->GetParameters().CopyParameters(); mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(parameters.m_Misc.m_ParentNode->GetData()); mitkImage = mitk::DiffusionImage::New(); mitkImage->SetVectorImage( m_ArtifactsToDwiFilter->GetOutput() ); mitkImage->SetReferenceBValue(diffImg->GetReferenceBValue()); mitkImage->SetDirections(diffImg->GetDirections()); mitkImage->InitializeFromVectorImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName()+parameters.m_Misc.m_ArtifactModelString); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); m_ArtifactsToDwiFilter = NULL; break; } } mitk::BaseData::Pointer basedata = parameters.m_Misc.m_ResultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (!parameters.m_Misc.m_OutputPath.empty()) { try{ QString outputFileName(parameters.m_Misc.m_OutputPath.c_str()); outputFileName += parameters.m_Misc.m_ResultNode->GetName().c_str(); outputFileName.replace(QString("."), QString("_")); outputFileName += ".dwi"; QString status("Saving output image to "); status += outputFileName; m_Controls->m_SimulationStatusText->append(status); mitk::IOUtil::SaveBaseData(mitkImage, outputFileName.toStdString()); m_Controls->m_SimulationStatusText->append("File saved successfully."); } catch (itk::ExceptionObject &e) { QString status("Exception during DWI writing: "); status += e.GetDescription(); m_Controls->m_SimulationStatusText->append(status); } catch (...) { m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!"); } } parameters.m_SignalGen.m_FrequencyMap = NULL; } void QmitkFiberfoxView::UpdateSimulationStatus() { QString statusText; switch (m_Worker.m_FilterType) { case 0: statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); break; case 1: statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); break; } if (QString::compare(m_SimulationStatusText,statusText)!=0) { m_Controls->m_SimulationStatusText->clear(); statusText = "
"+statusText+"
"; m_Controls->m_SimulationStatusText->setText(statusText); QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar(); vScrollBar->triggerAction(QScrollBar::SliderToMaximum); } } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { delete m_SimulationTimer; } void QmitkFiberfoxView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberfoxViewControls; m_Controls->setupUi( parent ); // commented out m_Controls->m_DiffusionDirectionBox->setVisible(false); m_Controls->label_3->setVisible(false); m_Controls->m_SeparationAngleBox->setVisible(false); m_Controls->label_4->setVisible(false); // m_Controls->m_StickWidget1->setVisible(true); m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); m_Controls->m_BallWidget1->setVisible(true); m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); m_Controls->m_PrototypeWidget2->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_PrototypeWidget3->SetMinFa(0.0); m_Controls->m_PrototypeWidget3->SetMaxFa(0.15); m_Controls->m_PrototypeWidget4->SetMinFa(0.0); m_Controls->m_PrototypeWidget4->SetMaxFa(0.15); m_Controls->m_PrototypeWidget3->SetMinAdc(0.0); m_Controls->m_PrototypeWidget3->SetMaxAdc(0.001); m_Controls->m_PrototypeWidget4->SetMinAdc(0.003); m_Controls->m_PrototypeWidget4->SetMaxAdc(0.004); m_Controls->m_Comp4FractionFrame->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_NoiseFrame->setVisible(false); m_Controls->m_GhostFrame->setVisible(false); m_Controls->m_DistortionsFrame->setVisible(false); m_Controls->m_EddyFrame->setVisible(false); m_Controls->m_SpikeFrame->setVisible(false); m_Controls->m_AliasingFrame->setVisible(false); m_Controls->m_MotionArtifactFrame->setVisible(false); m_ParameterFile = QDir::currentPath()+"/param.ffp"; m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(false); m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); m_Controls->m_FrequencyMapBox->SetPredicate(finalPredicate); m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp4VolumeFraction->SetPredicate(finalPredicate); connect( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) ); connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread())); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double))); connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int))); connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int))); connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int))); connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(int))); connect((QObject*) m_Controls->m_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int))); connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int))); connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(int))); connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform())); connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters())); connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters())); connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath())); } } template< class ScalarType > FiberfoxParameters< ScalarType > QmitkFiberfoxView::UpdateImageParameters() { FiberfoxParameters< ScalarType > parameters; parameters.m_Misc.m_OutputPath = ""; parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked(); parameters.m_Misc.m_CheckOutputVolumeFractionsBox = m_Controls->m_VolumeFractionsBox->isChecked(); string outputPath = m_Controls->m_SavePathEdit->text().toStdString(); if (outputPath.compare("-")!=0) { parameters.m_Misc.m_OutputPath = outputPath; parameters.m_Misc.m_OutputPath += "/"; } if (m_MaskImageNode.IsNotNull()) { mitk::Image::Pointer mitkMaskImage = dynamic_cast(m_MaskImageNode->GetData()); mitk::CastToItkImage(mitkMaskImage, parameters.m_SignalGen.m_MaskImage); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(parameters.m_SignalGen.m_MaskImage); duplicator->Update(); parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput(); } if (m_SelectedDWI.IsNotNull()) // use parameters of selected DWI { mitk::DiffusionImage::Pointer dwi = dynamic_cast*>(m_SelectedDWI->GetData()); parameters.m_SignalGen.m_ImageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = dwi->GetVectorImage()->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = dwi->GetVectorImage()->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = dwi->GetVectorImage()->GetDirection(); parameters.m_SignalGen.m_Bvalue = dwi->GetReferenceBValue(); parameters.m_SignalGen.SetGradienDirections(dwi->GetDirections()); } else if (m_SelectedImage.IsNotNull()) // use geometry of selected image { mitk::Image::Pointer img = dynamic_cast(m_SelectedImage->GetData()); itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); CastToItkImage< itk::Image< float, 3 > >(img, itkImg); parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); } else // use GUI parameters { parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); parameters.m_SignalGen.m_ImageOrigin[0] = parameters.m_SignalGen.m_ImageSpacing[0]/2; parameters.m_SignalGen.m_ImageOrigin[1] = parameters.m_SignalGen.m_ImageSpacing[1]/2; parameters.m_SignalGen.m_ImageOrigin[2] = parameters.m_SignalGen.m_ImageSpacing[2]/2; parameters.m_SignalGen.m_ImageDirection.SetIdentity(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); parameters.m_SignalGen.GenerateGradientHalfShell(); } // signal relaxation parameters.m_SignalGen.m_DoSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked(); parameters.m_SignalGen.m_SimulateKspaceAcquisition = parameters.m_SignalGen.m_DoSimulateRelaxation; if (parameters.m_SignalGen.m_DoSimulateRelaxation && m_SelectedBundles.size()>0 ) parameters.m_Misc.m_ArtifactModelString += "_RELAX"; // N/2 ghosts parameters.m_Misc.m_CheckAddGhostsBox = m_Controls->m_AddGhosts->isChecked(); if (m_Controls->m_AddGhosts->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_GHOST"; parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_SignalGen.m_KspaceLineOffset)); } else parameters.m_SignalGen.m_KspaceLineOffset = 0; // Aliasing parameters.m_Misc.m_CheckAddAliasingBox = m_Controls->m_AddAliasing->isChecked(); if (m_Controls->m_AddAliasing->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_ALIASING"; parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); } // Spikes parameters.m_Misc.m_CheckAddSpikesBox = m_Controls->m_AddSpikes->isChecked(); if (m_Controls->m_AddSpikes->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value(); parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); parameters.m_Misc.m_ArtifactModelString += "_SPIKES"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_SignalGen.m_Spikes)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SignalGen.m_SpikeAmplitude)); } // gibbs ringing parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); if (m_Controls->m_AddGibbsRinging->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); parameters.m_Misc.m_ArtifactModelString += "_RINGING"; } // add distortions parameters.m_Misc.m_CheckAddDistortionsBox = m_Controls->m_AddDistortions->isChecked(); if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); mitk::Image* img = dynamic_cast(fMapNode->GetData()); ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); CastToItkImage< ItkDoubleImgType >(img, itkImg); if (m_SelectedImage.IsNull()) // use geometry of frequency map { parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); } if (parameters.m_SignalGen.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && parameters.m_SignalGen.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && parameters.m_SignalGen.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkImg); duplicator->Update(); parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput(); parameters.m_Misc.m_ArtifactModelString += "_DISTORTED"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); } } parameters.m_SignalGen.m_EddyStrength = 0; parameters.m_Misc.m_CheckAddEddyCurrentsBox = m_Controls->m_AddEddy->isChecked(); if (m_Controls->m_AddEddy->isChecked()) { parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); parameters.m_Misc.m_ArtifactModelString += "_EDDY"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_SignalGen.m_EddyStrength)); } // Motion parameters.m_SignalGen.m_DoAddMotion = m_Controls->m_AddMotion->isChecked(); parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); if ( m_Controls->m_AddMotion->isChecked() && m_SelectedBundles.size()>0 ) { parameters.m_Misc.m_ArtifactModelString += "_MOTION"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_SignalGen.m_DoRandomizeMotion)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_SignalGen.m_Translation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_SignalGen.m_Translation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_SignalGen.m_Translation[2])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[2])); } // other imaging parameters parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value(); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value(); parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value(); // adjust echo time if needed if ( parameters.m_SignalGen.m_tEcho < parameters.m_SignalGen.m_ImageRegion.GetSize(1)*parameters.m_SignalGen.m_tLine ) { this->m_Controls->m_TEbox->setValue( parameters.m_SignalGen.m_ImageRegion.GetSize(1)*parameters.m_SignalGen.m_tLine ); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(parameters.m_SignalGen.m_tEcho)+" ms"); } // Noise parameters.m_Misc.m_CheckAddNoiseBox = m_Controls->m_AddNoise->isChecked(); if (m_Controls->m_AddNoise->isChecked()) { double noiseVariance = m_Controls->m_NoiseLevel->value(); { switch (m_Controls->m_NoiseDistributionBox->currentIndex()) { case 0: { parameters.m_NoiseModel = new mitk::RicianNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); break; } case 1: { parameters.m_NoiseModel = new mitk::ChiSquareNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); break; } default: { parameters.m_NoiseModel = new mitk::RicianNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); } } } parameters.m_NoiseModel->SetNoiseVariance(noiseVariance); parameters.m_Misc.m_ArtifactModelString += QString::number(noiseVariance).toStdString(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); } // adjusting line readout time to the adapted image size needed for the DFT unsigned int y = parameters.m_SignalGen.m_ImageRegion.GetSize(1); y += y%2; if ( y>parameters.m_SignalGen.m_ImageRegion.GetSize(1) ) parameters.m_SignalGen.m_tLine *= (double)parameters.m_SignalGen.m_ImageRegion.GetSize(1)/y; // signal models { // compartment 1 switch (m_Controls->m_Compartment1Box->currentIndex()) { case 0: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget1->GetD()); model->SetT2(m_Controls->m_StickWidget1->GetT2()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); model->SetT2(m_Controls->m_TensorWidget1->GetT2()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget1->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget1->GetMinFa(), m_Controls->m_PrototypeWidget1->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget1->GetMinAdc(), m_Controls->m_PrototypeWidget1->GetMaxAdc()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") ); break; } } // compartment 2 switch (m_Controls->m_Compartment2Box->currentIndex()) { case 0: break; case 1: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget2->GetD()); model->SetT2(m_Controls->m_StickWidget2->GetT2()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); model->SetT2(m_Controls->m_TensorWidget2->GetT2()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } } // compartment 3 switch (m_Controls->m_Compartment3Box->currentIndex()) { case 0: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget1->GetD()); model->SetT2(m_Controls->m_BallWidget1->GetT2()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); break; } case 2: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget1->GetT2()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget3->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget3->GetMinFa(), m_Controls->m_PrototypeWidget3->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget3->GetMinAdc(), m_Controls->m_PrototypeWidget3->GetMaxAdc()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") ); break; } } // compartment 4 ItkDoubleImgType::Pointer comp4VolumeImage = NULL; ItkDoubleImgType::Pointer comp3VolumeImage = NULL; if (m_Controls->m_Compartment4Box->currentIndex()>0) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode(); if (volumeNode.IsNull()) { QMessageBox::information( NULL, "Information", "No volume fraction image selected! Second extra-axonal compartment has been disabled for this simultation."); MITK_WARN << "No volume fraction image selected! Second extra-axonal compartment has been disabled."; } else { MITK_INFO << "Rescaling volume fraction image..."; comp4VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp4VolumeImage); double max = itk::NumericTraits::min(); double min = itk::NumericTraits::max(); itk::ImageRegionIterator< ItkDoubleImgType > it(comp4VolumeImage, comp4VolumeImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { if (parameters.m_SignalGen.m_MaskImage.IsNotNull() && parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0) { it.Set(0.0); ++it; continue; } if (it.Get()>max) max = it.Get(); if (it.Get()::Pointer scaler = itk::ShiftScaleImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New(); scaler->SetInput(comp4VolumeImage); scaler->SetShift(-min); scaler->SetScale(1.0/(max-min)); scaler->Update(); comp4VolumeImage = scaler->GetOutput(); // itk::ImageFileWriter< ItkDoubleImgType >::Pointer wr = itk::ImageFileWriter< ItkDoubleImgType >::New(); // wr->SetInput(comp4VolumeImage); // wr->SetFileName("/local/comp4.nrrd"); // wr->Update(); // if (max>1 || min<0) // are volume fractions between 0 and 1? // { // itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); // rescaler->SetInput(0, comp4VolumeImage); // rescaler->SetOutputMaximum(1); // rescaler->SetOutputMinimum(0); // rescaler->Update(); // comp4VolumeImage = rescaler->GetOutput(); // } itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New(); inverter->SetMaximum(1.0); inverter->SetInput(comp4VolumeImage); inverter->Update(); comp3VolumeImage = inverter->GetOutput(); } } if (comp4VolumeImage.IsNotNull()) { switch (m_Controls->m_Compartment4Box->currentIndex()) { case 0: break; case 1: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget2->GetD()); model->SetT2(m_Controls->m_BallWidget2->GetT2()); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); break; } case 3: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget2->GetT2()); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 4: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc()); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); break; } } } } parameters.m_SignalGen.m_FiberSeparationThreshold = m_Controls->m_SeparationAngleBox->value(); switch (m_Controls->m_DiffusionDirectionBox->currentIndex()) { case 0: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; break; case 1: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::MAIN_FIBER_DIRECTIONS; break; case 2: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::RANDOM_DIRECTIONS; parameters.m_SignalGen.m_DoAddMotion = false; parameters.m_SignalGen.m_DoAddGibbsRinging = false; parameters.m_SignalGen.m_KspaceLineOffset = 0.0; parameters.m_SignalGen.m_FrequencyMap = NULL; parameters.m_SignalGen.m_CroppingFactor = 1.0; parameters.m_SignalGen.m_EddyStrength = 0; break; default: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; } parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalGen.m_SignalScale)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_SignalGen.m_AxonRadius)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_SignalGen.m_tInhom)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_SignalGen.m_tLine)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_SignalGen.m_tEcho)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_SignalGen.m_Bvalue)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_SignalGen.m_DoDisablePartialVolume)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_SignalGen.m_DoSimulateRelaxation)); parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); return parameters; } void QmitkFiberfoxView::SaveParameters() { FiberfoxParameters<> ffParamaters = UpdateImageParameters(); QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); bool ok = true; bool first = true; bool dosampling = false; mitk::DiffusionImage::Pointer diffImg; itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = NULL; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = NULL; ItkDoubleImgType::Pointer adcImage = NULL; for (unsigned int i=0; i* model = NULL; if (i* >(ffParamaters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(ffParamaters.m_NonFiberModelList.at(i-ffParamaters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { if (QMessageBox::question(NULL, "Prototype signal sampling", "Do you want to sample prototype signals from the selected diffusion-weighted imag and save them?",QMessageBox::Yes,QMessageBox::No)==QMessageBox::Yes) dosampling = true; first = false; if (dosampling && m_SelectedDWI.IsNull()) { QMessageBox::information(NULL, "Parameter file not saved", "No diffusion-weighted image selected to sample signal from."); return; } else if (dosampling) { diffImg = dynamic_cast*>(m_SelectedDWI->GetData()); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( diffImg->GetDirections(), diffImg->GetVectorImage() ); filter->SetBValue(diffImg->GetReferenceBValue()); filter->Update(); tensorImage = filter->GetOutput(); const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage( diffImg->GetDirections(), diffImg->GetVectorImage() ); qballfilter->SetBValue(diffImg->GetReferenceBValue()); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput(diffImg->GetVectorImage()); adcFilter->SetGradientDirections(diffImg->GetDirections()); adcFilter->SetB_value(diffImg->GetReferenceBValue()); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } } if (dosampling && m_SelectedDWI.IsNotNull()) { ok = model->SampleKernels(diffImg, ffParamaters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) { QMessageBox::information( NULL, "Parameter file not saved", "No valid prototype signals could be sampled."); return; } } } } ffParamaters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberfoxView::LoadParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; FiberfoxParameters<> parameters; parameters.LoadParameters(filename.toStdString()); m_Controls->m_RealTimeFibers->setChecked(parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(parameters.m_FiberGen.m_Scale[2]); // image generation parameters m_Controls->m_SizeX->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(0)); m_Controls->m_SizeY->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(1)); m_Controls->m_SizeZ->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(2)); m_Controls->m_SpacingX->setValue(parameters.m_SignalGen.m_ImageSpacing[0]); m_Controls->m_SpacingY->setValue(parameters.m_SignalGen.m_ImageSpacing[1]); m_Controls->m_SpacingZ->setValue(parameters.m_SignalGen.m_ImageSpacing[2]); m_Controls->m_NumGradientsBox->setValue(parameters.m_SignalGen.GetNumWeightedVolumes()); m_Controls->m_BvalueBox->setValue(parameters.m_SignalGen.m_Bvalue); m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); m_Controls->m_TEbox->setValue(parameters.m_SignalGen.m_tEcho); m_Controls->m_LineReadoutTimeBox->setValue(parameters.m_SignalGen.m_tLine); m_Controls->m_T2starBox->setValue(parameters.m_SignalGen.m_tInhom); m_Controls->m_FiberRadius->setValue(parameters.m_SignalGen.m_AxonRadius); m_Controls->m_RelaxationBox->setChecked(parameters.m_SignalGen.m_DoSimulateRelaxation); m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(parameters.m_SignalGen.m_DoDisablePartialVolume); if (parameters.m_NoiseModel!=NULL) { m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_CheckAddNoiseBox); if (dynamic_cast*>(parameters.m_NoiseModel)) m_Controls->m_NoiseDistributionBox->setCurrentIndex(0); else if (dynamic_cast*>(parameters.m_NoiseModel)) m_Controls->m_NoiseDistributionBox->setCurrentIndex(1); m_Controls->m_NoiseLevel->setValue(parameters.m_NoiseModel->GetNoiseVariance()); } else m_Controls->m_AddNoise->setChecked(false); m_Controls->m_VolumeFractionsBox->setChecked(parameters.m_Misc.m_CheckOutputVolumeFractionsBox); m_Controls->m_AdvancedOptionsBox_2->setChecked(parameters.m_Misc.m_CheckAdvancedSignalOptionsBox); m_Controls->m_AddGhosts->setChecked(parameters.m_Misc.m_CheckAddGhostsBox); m_Controls->m_AddAliasing->setChecked(parameters.m_Misc.m_CheckAddAliasingBox); m_Controls->m_AddDistortions->setChecked(parameters.m_Misc.m_CheckAddDistortionsBox); m_Controls->m_AddSpikes->setChecked(parameters.m_Misc.m_CheckAddSpikesBox); m_Controls->m_AddEddy->setChecked(parameters.m_Misc.m_CheckAddEddyCurrentsBox); m_Controls->m_kOffsetBox->setValue(parameters.m_SignalGen.m_KspaceLineOffset); m_Controls->m_WrapBox->setValue(100*(1-parameters.m_SignalGen.m_CroppingFactor)); m_Controls->m_SpikeNumBox->setValue(parameters.m_SignalGen.m_Spikes); m_Controls->m_SpikeScaleBox->setValue(parameters.m_SignalGen.m_SpikeAmplitude); m_Controls->m_EddyGradientStrength->setValue(parameters.m_SignalGen.m_EddyStrength); m_Controls->m_AddGibbsRinging->setChecked(parameters.m_SignalGen.m_DoAddGibbsRinging); m_Controls->m_AddMotion->setChecked(parameters.m_SignalGen.m_DoAddMotion); m_Controls->m_RandomMotion->setChecked(parameters.m_SignalGen.m_DoRandomizeMotion); m_Controls->m_MaxTranslationBoxX->setValue(parameters.m_SignalGen.m_Translation[0]); m_Controls->m_MaxTranslationBoxY->setValue(parameters.m_SignalGen.m_Translation[1]); m_Controls->m_MaxTranslationBoxZ->setValue(parameters.m_SignalGen.m_Translation[2]); m_Controls->m_MaxRotationBoxX->setValue(parameters.m_SignalGen.m_Rotation[0]); m_Controls->m_MaxRotationBoxY->setValue(parameters.m_SignalGen.m_Rotation[1]); m_Controls->m_MaxRotationBoxZ->setValue(parameters.m_SignalGen.m_Rotation[2]); m_Controls->m_DiffusionDirectionBox->setCurrentIndex(parameters.m_SignalGen.m_DiffusionDirectionMode); m_Controls->m_SeparationAngleBox->setValue(parameters.m_SignalGen.m_FiberSeparationThreshold); m_Controls->m_Compartment1Box->setCurrentIndex(0); m_Controls->m_Compartment2Box->setCurrentIndex(0); m_Controls->m_Compartment3Box->setCurrentIndex(0); m_Controls->m_Compartment4Box->setCurrentIndex(0); for (unsigned int i=0; i* signalModel = NULL; if (im_CompartmentId) { case 1: { if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget1->SetT2(model->GetT2()); m_Controls->m_StickWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment1Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget1->SetT2(model->GetT2()); m_Controls->m_TensorWidget1->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget1->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget1->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment1Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget1->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget1->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget1->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget1->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget1->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment1Box->setCurrentIndex(3); break; } break; } case 2: { if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget2->SetT2(model->GetT2()); m_Controls->m_StickWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment2Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget2->SetT2(model->GetT2()); m_Controls->m_TensorWidget2->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget2->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget2->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment2Box->setCurrentIndex(3); break; } break; } case 3: { if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget1->SetT2(model->GetT2()); m_Controls->m_BallWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment3Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget1->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget1->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment3Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget1->SetT2(model->GetT2()); m_Controls->m_Compartment3Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget3->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget3->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget3->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget3->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget3->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment3Box->setCurrentIndex(3); break; } break; } case 4: { if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget2->SetT2(model->GetT2()); m_Controls->m_BallWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment4Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget2->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget2->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment4Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget2->SetT2(model->GetT2()); m_Controls->m_Compartment4Box->setCurrentIndex(3); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget4->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget4->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget4->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget4->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget4->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment4Box->setCurrentIndex(4); break; } break; } } } } void QmitkFiberfoxView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); m_Controls->m_AdvancedOptionsBox_2->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); m_Controls->m_AdvancedOptionsBox_2->setChecked(false); } } void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index) { m_Controls->m_StickWidget1->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); switch (index) { case 0: m_Controls->m_StickWidget1->setVisible(true); break; case 1: m_Controls->m_ZeppelinWidget1->setVisible(true); break; case 2: m_Controls->m_TensorWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget1->setVisible(true); break; } } void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index) { m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_StickWidget2->setVisible(true); break; case 2: m_Controls->m_ZeppelinWidget2->setVisible(true); break; case 3: m_Controls->m_TensorWidget2->setVisible(true); break; } } void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index) { m_Controls->m_BallWidget1->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); switch (index) { case 0: m_Controls->m_BallWidget1->setVisible(true); break; case 1: m_Controls->m_AstrosticksWidget1->setVisible(true); break; case 2: m_Controls->m_DotWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget3->setVisible(true); break; } } void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index) { m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_BallWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 2: m_Controls->m_AstrosticksWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 3: m_Controls->m_DotWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 4: m_Controls->m_PrototypeWidget4->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnAddMotion(int value) { if (value>0) m_Controls->m_MotionArtifactFrame->setVisible(true); else m_Controls->m_MotionArtifactFrame->setVisible(false); } void QmitkFiberfoxView::OnAddAliasing(int value) { if (value>0) m_Controls->m_AliasingFrame->setVisible(true); else m_Controls->m_AliasingFrame->setVisible(false); } void QmitkFiberfoxView::OnAddSpikes(int value) { if (value>0) m_Controls->m_SpikeFrame->setVisible(true); else m_Controls->m_SpikeFrame->setVisible(false); } void QmitkFiberfoxView::OnAddEddy(int value) { if (value>0) m_Controls->m_EddyFrame->setVisible(true); else m_Controls->m_EddyFrame->setVisible(false); } void QmitkFiberfoxView::OnAddDistortions(int value) { if (value>0) m_Controls->m_DistortionsFrame->setVisible(true); else m_Controls->m_DistortionsFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGhosts(int value) { if (value>0) m_Controls->m_GhostFrame->setVisible(true); else m_Controls->m_GhostFrame->setVisible(false); } void QmitkFiberfoxView::OnAddNoise(int value) { if (value>0) m_Controls->m_NoiseFrame->setVisible(true); else m_Controls->m_NoiseFrame->setVisible(false); } void QmitkFiberfoxView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::AlignOnGrid() { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for(unsigned int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for(unsigned int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints) { NPoints *= 2; GradientListType pointshell; int numB0 = NPoints/20; if (numB0==0) numB0=1; GradientType g; g.Fill(0.0); for (int i=0; i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkFiberfoxView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); for (int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval.push_back(v); } return retval; } void QmitkFiberfoxView::OnAddBundle() { if (m_SelectedImage.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImage); mitk::FiberBundleX::Pointer bundle = mitk::FiberBundleX::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImage); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); node->SetBoolProperty("planarfigure.3drendering", true); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } FiberfoxParameters parameters = UpdateImageParameters(); for (unsigned int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); sort(childVector.begin(), childVector.end(), CompareLayer); vector< mitk::PlanarEllipse::Pointer > fib; vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); + ellipse->Modified(); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); + ellipse->Modified(); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { parameters.m_FiberGen.m_Fiducials.push_back(fib); parameters.m_FiberGen.m_FlipList.push_back(flip); } else if (fib.size()>0) m_SelectedBundles.at(i)->SetData( mitk::FiberBundleX::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(parameters.m_FiberGen); filter->Update(); vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles(); for (unsigned int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::GenerateImage() { if (m_SelectedBundles.empty() && m_SelectedDWI.IsNull()) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->value(), m_Controls->m_SizeY->value(), m_Controls->m_SizeZ->value(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); unsigned int window = m_Controls->m_SizeX->value()*m_Controls->m_SizeY->value()*m_Controls->m_SizeZ->value(); unsigned int level = window/2; mitk::LevelWindow lw; lw.SetLevelWindow(level, window); node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(node); m_SelectedImage = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); } else if (!m_SelectedBundles.empty()) SimulateImageFromFibers(m_SelectedBundles.at(0)); else if (m_SelectedDWI.IsNotNull()) SimulateForExistingDwi(m_SelectedDWI); } void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode) { if (!dynamic_cast*>(imageNode->GetData())) return; FiberfoxParameters parameters = UpdateImageParameters(); if (parameters.m_NoiseModel==NULL && parameters.m_SignalGen.m_Spikes==0 && parameters.m_SignalGen.m_FrequencyMap.IsNull() && parameters.m_SignalGen.m_KspaceLineOffset<=0.000001 && !parameters.m_SignalGen.m_DoAddGibbsRinging && !(parameters.m_SignalGen.m_EddyStrength>0) && parameters.m_SignalGen.m_CroppingFactor>0.999) { QMessageBox::information( NULL, "Simulation cancelled", "No valid artifact enabled! Motion artifacts and relaxation effects can NOT be added to an existing diffusion weighted image."); return; } mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(imageNode->GetData()); m_ArtifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New(); m_ArtifactsToDwiFilter->SetInput(diffImg->GetVectorImage()); parameters.m_Misc.m_ParentNode = imageNode; m_ArtifactsToDwiFilter->SetParameters(parameters); m_Worker.m_FilterType = 1; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode) { mitk::FiberBundleX::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); if (fiberBundle->GetNumFibers()<=0) return; FiberfoxParameters parameters = UpdateImageParameters(); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); parameters.m_Misc.m_ParentNode = fiberNode; if (m_SelectedDWI.IsNotNull()) { bool first = true; bool ok = true; mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(m_SelectedDWI->GetData()); itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = NULL; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = NULL; ItkDoubleImgType::Pointer adcImage = NULL; for (unsigned int i=0; i* model = NULL; if (i* >(parameters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(parameters.m_NonFiberModelList.at(i-parameters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( diffImg->GetDirections(), diffImg->GetVectorImage() ); filter->SetBValue(diffImg->GetReferenceBValue()); filter->Update(); tensorImage = filter->GetOutput(); const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage( diffImg->GetDirections(), diffImg->GetVectorImage() ); qballfilter->SetBValue(diffImg->GetReferenceBValue()); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput(diffImg->GetVectorImage()); adcFilter->SetGradientDirections(diffImg->GetDirections()); adcFilter->SetB_value(diffImg->GetReferenceBValue()); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } ok = model->SampleKernels(diffImg, parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) break; } } if (!ok) { QMessageBox::information( NULL, "Simulation cancelled", "No valid prototype signals could be sampled."); return; } } else if ( m_Controls->m_Compartment1Box->currentIndex()==3 || m_Controls->m_Compartment3Box->currentIndex()==3 || m_Controls->m_Compartment4Box->currentIndex()==4 ) { QMessageBox::information( NULL, "Simulation cancelled", "Prototype signal but no diffusion-weighted image selected to sample signal from."); return; } m_TractsToDwiFilter->SetParameters(parameters); m_TractsToDwiFilter->SetFiberBundle(fiberBundle); m_Worker.m_FilterType = 0; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::ApplyTransform() { vector< mitk::DataNode::Pointer > selectedBundles; for(unsigned int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) { mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); pe->Modified(); } } } } } else { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); pe->Modified(); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!"; return; } for (std::vector::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundleX::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = mitk::PlanarEllipse::New(); pe->DeepCopy(dynamic_cast(fiducialNode->GetData())); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); newNode->SetBoolProperty("planarfigure.3drendering", true); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (; it!=m_SelectedBundles.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::UpdateGui() { m_Controls->m_FiberBundleLabel->setText("mandatory"); m_Controls->m_GeometryFrame->setEnabled(true); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_BvalueBox->setEnabled(true); m_Controls->m_NumGradientsBox->setEnabled(true); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_SelectedImage.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_MaskImageNode.IsNotNull() || m_SelectedImage.IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (m_SelectedDWI.IsNotNull()) { m_Controls->m_DiffusionPropsMessage->setVisible(true); m_Controls->m_BvalueBox->setEnabled(false); m_Controls->m_NumGradientsBox->setEnabled(false); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (!m_SelectedBundles.empty()) { m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); m_Controls->m_FiberBundleLabel->setText(m_SelectedBundles.at(0)->GetName().c_str()); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } } void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList& nodes ) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = NULL; m_SelectedBundles.clear(); m_SelectedImage = NULL; m_SelectedDWI = NULL; m_MaskImageNode = NULL; m_Controls->m_TissueMaskLabel->setText("optional"); // iterate all selected objects, adjust warning visibility for( int i=0; i*>(node->GetData()) ) { m_SelectedDWI = node; m_SelectedImage = node; m_SelectedImages.push_back(node); } else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedImages.push_back(node); m_SelectedImage = node; bool isbinary = false; node->GetPropertyValue("binary", isbinary); if (isbinary) { m_MaskImageNode = node; m_Controls->m_TissueMaskLabel->setText(m_MaskImageNode->GetName().c_str()); } } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); mitk::FiberBundleX::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) m_SelectedBundles.push_back(pNode); } } } UpdateGui(); } void QmitkFiberfoxView::EnableCrosshairNavigation() { MITK_DEBUG << "EnableCrosshairNavigation"; // enable the crosshair navigation if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "enabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(true); // linkedRenderWindow->EnableSlicingPlanes(true); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::DisableCrosshairNavigation() { MITK_DEBUG << "DisableCrosshairNavigation"; // disable the crosshair navigation during the drawing if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "disabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(false); // linkedRenderWindow->EnableSlicingPlanes(false); } } void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node) { mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberfoxView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } void QmitkFiberfoxView::SetOutputPath() { // SELECT FOLDER DIALOG string outputPath = QFileDialog::getExistingDirectory(NULL, "Save images to...", QString(outputPath.c_str())).toStdString(); if (outputPath.empty()) m_Controls->m_SavePathEdit->setText("-"); else { outputPath += "/"; m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str())); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox index 9f679c8296..dad1bdf580 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox @@ -1,10 +1,10 @@ /** \page org_mitk_gui_qt_diffusionimagingapp Using The Diffusion Imaging Application \section QMitkDiffusionApplicationManualOverview What is the Diffusion Imaging Application -The Diffusion Imaging Application contains selected views for the analysis of images of the human brain. These encompass the views developed by the Neuroimaging Group of the Division Medical and Biological Informatics as well as basic image processing views such as segmentation and volumevisualization. +The Diffusion Imaging Application contains selected views for the analysis of images of the human brain. These encompass the views developed by the Medical Image Computing Group of the Division Medical and Biological Informatics as well as basic image processing views such as segmentation and volumevisualization. For a basic guide to MITK see \ref MITKUserManualPage . */ diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/index.theme b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/index.theme index 4a3ff343c3..25c2b08bec 100644 --- a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/index.theme +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/index.theme @@ -1,25 +1,46 @@ [Icon Theme] Name=tango Comment=An icon theme following the tango style guide Directories=scalable/actions scalable/status scalable/places [scalable/actions] Size=48 Type=Scalable MinSize=1 MaxSize=256 Context=Actions +[scalable/categories] +Size=48 +Type=Scalable +MinSize=1 +MaxSize=256 +Context=Categories + +[scalable/devices] +Size=48 +Type=Scalable +MinSize=1 +MaxSize=256 +Context=Devices + +[scalable/mimetypes] +Size=48 +Type=Scalable +MinSize=1 +MaxSize=256 +Context=MimeTypes + [scalable/status] Size=48 Type=Scalable MinSize=1 MaxSize=256 Context=Status [scalable/places] Size=48 Type=Scalable MinSize=1 MaxSize=256 Context=Places diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/list-add.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/list-add.svg new file mode 100644 index 0000000000..6eaed44811 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/list-add.svg @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Add + 2006-01-04 + + + Andreas Nilsson + + + http://tango-project.org + + + add + plus + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/list-remove.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/list-remove.svg new file mode 100644 index 0000000000..5f109a05c3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/list-remove.svg @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Remove + 2006-01-04 + + + Andreas Nilsson + + + http://tango-project.org + + + remove + delete + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-pause.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-pause.svg new file mode 100644 index 0000000000..8a434cabb1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-pause.svg @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Playback Pause + + + Lapo Calamandrei + + + + + + media + pause + playback + video + music + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-start.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-start.svg new file mode 100644 index 0000000000..75616de46f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-start.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Playback Start + + + Lapo Calamandrei + + + + + + play + media + music + video + player + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-stop.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-stop.svg new file mode 100644 index 0000000000..24bbfb52e5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-playback-stop.svg @@ -0,0 +1,651 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Playback Pause + + + Lapo Calamandrei + + + + + + media + stop + playback + video + music + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-record.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-record.svg new file mode 100644 index 0000000000..85bbb98f6e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-record.svg @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Record + + + Lapo Calamandrei + + + + + + media + player + record + music + sound + video + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-seek-backward.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-seek-backward.svg new file mode 100644 index 0000000000..75f49f1a82 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-seek-backward.svg @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Seek Backward + + + Lapo Calamandrei + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-seek-forward.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-seek-forward.svg new file mode 100644 index 0000000000..b1b9fe950b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-seek-forward.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Seek Forward + + + Lapo Calamandrei + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-skip-backward.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-skip-backward.svg new file mode 100644 index 0000000000..fccd7762cd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-skip-backward.svg @@ -0,0 +1,1025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Skip Backward + + + Lapo Calamandrei + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-skip-forward.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-skip-forward.svg new file mode 100644 index 0000000000..7c4d40054b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/actions/media-skip-forward.svg @@ -0,0 +1,1013 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Media Skip Forward + + + Lapo Calamandrei + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/categories/applications-multimedia.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/categories/applications-multimedia.svg new file mode 100644 index 0000000000..6844e8db1a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/categories/applications-multimedia.svg @@ -0,0 +1,498 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Multimedia Category + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + video + multimedia + category + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/devices/camera-photo.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/devices/camera-photo.svg new file mode 100644 index 0000000000..4911410136 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/devices/camera-photo.svg @@ -0,0 +1,681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + Photo Camera + + + camera + photo + SLR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/devices/camera-video.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/devices/camera-video.svg new file mode 100644 index 0000000000..e24713457f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/devices/camera-video.svg @@ -0,0 +1,1257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Camera / Video + + + Jakub Steiner + + + http://jimmac.musichall.cz/ + + + camera + camcorder + video + cam + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/mimetypes/image-x-generic.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/mimetypes/image-x-generic.svg new file mode 100644 index 0000000000..45dd641ae7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/mimetypes/image-x-generic.svg @@ -0,0 +1,581 @@ + + + + + + image/svg+xml + + + + + + + + Genric Image + + + Jakub Steiner + + + + imagepicturesnapshotphoto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/mimetypes/video-x-generic.svg b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/mimetypes/video-x-generic.svg new file mode 100644 index 0000000000..1f3a8b95a8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/icons/tango/scalable/mimetypes/video-x-generic.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + Generic Video + + + video + audio + multimedia + movie + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_icons.qrc b/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_icons.qrc index 56315b325f..08f6548161 100644 --- a/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_icons.qrc +++ b/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_icons.qrc @@ -1,51 +1,67 @@ icons/awesome/index.theme icons/awesome/scalable/actions/document-open.svg icons/awesome/scalable/actions/document-print.svg icons/awesome/scalable/actions/document-save.svg icons/awesome/scalable/actions/edit-delete.svg icons/awesome/scalable/actions/edit-redo.svg icons/awesome/scalable/actions/edit-undo.svg icons/awesome/scalable/actions/go-down.svg icons/awesome/scalable/actions/go-home.svg icons/awesome/scalable/actions/go-next.svg icons/awesome/scalable/actions/go-previous.svg icons/awesome/scalable/actions/go-up.svg icons/awesome/scalable/actions/system-log-out.svg icons/awesome/scalable/actions/view-list-details.svg icons/awesome/scalable/actions/view-list-icons.svg icons/awesome/scalable/actions/view-refresh.svg icons/awesome/scalable/places/folder.svg icons/awesome/scalable/status/dialog-error.svg icons/awesome/scalable/status/dialog-information.svg icons/awesome/scalable/status/dialog-question.svg icons/awesome/scalable/status/dialog-warning.svg icons/tango/index.theme icons/tango/scalable/actions/document-open.svg icons/tango/scalable/actions/document-print.svg icons/tango/scalable/actions/document-save.svg icons/tango/scalable/actions/edit-delete.svg icons/tango/scalable/actions/edit-redo.svg icons/tango/scalable/actions/edit-undo.svg icons/tango/scalable/actions/go-bottom.svg icons/tango/scalable/actions/go-down.svg icons/tango/scalable/actions/go-first.svg icons/tango/scalable/actions/go-home.svg icons/tango/scalable/actions/go-last.svg icons/tango/scalable/actions/go-next.svg icons/tango/scalable/actions/go-previous.svg icons/tango/scalable/actions/go-top.svg icons/tango/scalable/actions/go-up.svg icons/tango/scalable/actions/system-log-out.svg icons/tango/scalable/actions/view-list-details.svg icons/tango/scalable/actions/view-list-icons.svg icons/tango/scalable/actions/view-refresh.svg + icons/tango/scalable/actions/list-add.svg + icons/tango/scalable/actions/list-remove.svg + icons/tango/scalable/actions/media-playback-pause.svg + icons/tango/scalable/actions/media-playback-start.svg + icons/tango/scalable/actions/media-playback-stop.svg + icons/tango/scalable/actions/media-record.svg + icons/tango/scalable/actions/media-seek-backward.svg + icons/tango/scalable/actions/media-seek-forward.svg + icons/tango/scalable/actions/media-skip-backward.svg + icons/tango/scalable/actions/media-skip-forward.svg + icons/tango/scalable/actions/system-log-out.svg + icons/tango/scalable/categories/applications-multimedia.svg + icons/tango/scalable/devices/camera-photo.svg + icons/tango/scalable/devices/camera-video.svg + icons/tango/scalable/mimetypes/image-x-generic.svg + icons/tango/scalable/mimetypes/video-x-generic.svg icons/tango/scalable/places/folder.svg icons/tango/scalable/places/folder-remote.svg icons/tango/scalable/status/dialog-error.svg icons/tango/scalable/status/dialog-information.svg icons/tango/scalable/status/dialog-question.svg icons/tango/scalable/status/dialog-warning.svg diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.cpp b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.cpp index af8e485885..6e1f622a3c 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.cpp +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.cpp @@ -1,136 +1,190 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include "QmitkExternalProgramsPreferencePage.h" static berry::IPreferences::Pointer GetPreferences() { berry::IPreferencesService::Pointer preferencesService = berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); if (preferencesService.IsNotNull()) { berry::IPreferences::Pointer systemPreferences = preferencesService->GetSystemPreferences(); if (systemPreferences.IsNotNull()) return systemPreferences->Node("/org.mitk.gui.qt.ext.externalprograms"); } mitkThrow(); } QmitkExternalProgramsPreferencePage::QmitkExternalProgramsPreferencePage() : m_Preferences(GetPreferences()), m_Ui(new Ui::QmitkExternalProgramsPreferencePage), m_Control(NULL), + m_FFmpegProcess(NULL), m_GnuplotProcess(NULL) { } QmitkExternalProgramsPreferencePage::~QmitkExternalProgramsPreferencePage() { } void QmitkExternalProgramsPreferencePage::CreateQtControl(QWidget* parent) { m_Control = new QWidget(parent); + m_FFmpegProcess = new QProcess(m_Control); m_GnuplotProcess = new QProcess(m_Control); m_Ui->setupUi(m_Control); + connect(m_FFmpegProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(OnFFmpegProcessError(QProcess::ProcessError))); + connect(m_FFmpegProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(OnFFmpegProcessFinished(int, QProcess::ExitStatus))); + connect(m_Ui->ffmpegButton, SIGNAL(clicked()), this, SLOT(OnFFmpegButtonClicked())); + connect(m_GnuplotProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(OnGnuplotProcessError(QProcess::ProcessError))); connect(m_GnuplotProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(OnGnuplotProcessFinished(int, QProcess::ExitStatus))); connect(m_Ui->gnuplotButton, SIGNAL(clicked()), this, SLOT(OnGnuplotButtonClicked())); this->Update(); } +void QmitkExternalProgramsPreferencePage::OnFFmpegButtonClicked() +{ + QString filter = "ffmpeg/avconv executable "; + +#if defined(WIN32) + filter += "(ffmpeg.exe avconv.exe)"; +#else + filter += "(ffmpeg avconv)"; +#endif + + QString ffmpegPath = QFileDialog::getOpenFileName(m_Control, "FFmpeg/Libav", "", filter); + + if (!ffmpegPath.isEmpty()) + { + m_FFmpegPath = ffmpegPath; + m_FFmpegProcess->start(ffmpegPath, QStringList() << "-version", QProcess::ReadOnly); + } +} + +void QmitkExternalProgramsPreferencePage::OnFFmpegProcessError(QProcess::ProcessError) +{ + m_FFmpegPath.clear(); + m_Ui->ffmpegLineEdit->clear(); +} + +void QmitkExternalProgramsPreferencePage::OnFFmpegProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + if (exitStatus == QProcess::NormalExit && exitCode == 0) + { + QString output = QTextCodec::codecForName("UTF-8")->toUnicode(m_FFmpegProcess->readAllStandardOutput()); + + if (output.startsWith("ffmpeg") || output.startsWith("avconv")) + { + m_Ui->ffmpegLineEdit->setText(m_FFmpegPath); + return; + } + } + + m_FFmpegPath.clear(); + m_Ui->ffmpegLineEdit->clear(); +} + void QmitkExternalProgramsPreferencePage::OnGnuplotButtonClicked() { - QString filter = "Gnuplot executable "; + QString filter = "gnuplot executable "; #if defined(WIN32) filter += "(gnuplot.exe)"; #else filter += "(gnuplot)"; #endif QString gnuplotPath = QFileDialog::getOpenFileName(m_Control, "Gnuplot", "", filter); if (!gnuplotPath.isEmpty()) { m_GnuplotPath = gnuplotPath; m_GnuplotProcess->start(gnuplotPath, QStringList() << "--version", QProcess::ReadOnly); } } void QmitkExternalProgramsPreferencePage::OnGnuplotProcessError(QProcess::ProcessError) { m_GnuplotPath.clear(); m_Ui->gnuplotLineEdit->clear(); } void QmitkExternalProgramsPreferencePage::OnGnuplotProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitStatus == QProcess::NormalExit && exitCode == 0) { - QString version = QTextCodec::codecForName("UTF-8")->toUnicode(m_GnuplotProcess->readAllStandardOutput()).trimmed(); + QString output = QTextCodec::codecForName("UTF-8")->toUnicode(m_GnuplotProcess->readAllStandardOutput()); - if (version.startsWith("gnuplot")) + if (output.startsWith("gnuplot")) { - m_Ui->gnuplotLineEdit->setText(QString("%1 (%2)").arg(m_GnuplotPath).arg(version.trimmed())); + m_Ui->gnuplotLineEdit->setText(m_GnuplotPath); return; } } m_GnuplotPath.clear(); m_Ui->gnuplotLineEdit->clear(); } QWidget* QmitkExternalProgramsPreferencePage::GetQtControl() const { return m_Control; } void QmitkExternalProgramsPreferencePage::Init(berry::IWorkbench::Pointer) { } void QmitkExternalProgramsPreferencePage::PerformCancel() { } bool QmitkExternalProgramsPreferencePage::PerformOk() { + m_Preferences->Put("ffmpeg", m_FFmpegPath.toStdString()); m_Preferences->Put("gnuplot", m_GnuplotPath.toStdString()); return true; } void QmitkExternalProgramsPreferencePage::Update() { + m_FFmpegPath = QString::fromStdString(m_Preferences->Get("ffmpeg", "")); + + if (!m_FFmpegPath.isEmpty()) + m_FFmpegProcess->start(m_FFmpegPath, QStringList() << "-version", QProcess::ReadOnly); + m_GnuplotPath = QString::fromStdString(m_Preferences->Get("gnuplot", "")); if (!m_GnuplotPath.isEmpty()) m_GnuplotProcess->start(m_GnuplotPath, QStringList() << "--version", QProcess::ReadOnly); } diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.h b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.h index e766b3b400..fb4da45609 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.h +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.h @@ -1,59 +1,67 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkExternalProgramsPreferencePage_h #define QmitkExternalProgramsPreferencePage_h #include #include #include #include namespace Ui { class QmitkExternalProgramsPreferencePage; } class QmitkExternalProgramsPreferencePage : public QObject, public berry::IQtPreferencePage { Q_OBJECT Q_INTERFACES(berry::IPreferencePage) public: QmitkExternalProgramsPreferencePage(); ~QmitkExternalProgramsPreferencePage(); void CreateQtControl(QWidget* parent); QWidget* GetQtControl() const; void Init(berry::IWorkbench::Pointer); void PerformCancel(); bool PerformOk(); void Update(); private slots: + void OnFFmpegButtonClicked(); + void OnFFmpegProcessError(QProcess::ProcessError error); + void OnFFmpegProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void OnGnuplotButtonClicked(); void OnGnuplotProcessError(QProcess::ProcessError error); void OnGnuplotProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); private: berry::IPreferences::Pointer m_Preferences; QScopedPointer m_Ui; QWidget* m_Control; + + QProcess* m_FFmpegProcess; + QString m_FFmpegPath; + QProcess* m_GnuplotProcess; QString m_GnuplotPath; }; #endif diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.ui b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.ui index ace9d303c8..428b27c526 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.ui +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExternalProgramsPreferencePage.ui @@ -1,65 +1,92 @@ QmitkExternalProgramsPreferencePage 0 0 400 300 External Programs - - + + + + + FFmpeg/Libav: + + + Qt::PlainText + + + gnuplotButton + + + + + + + true + + + + + + + ... + + + + - Gnuplot &executable: + gnuplot: Qt::PlainText gnuplotButton - + true - + ... Qt::Vertical 20 248 diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp index 077752104f..1c09429e5f 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp @@ -1,996 +1,998 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkImageStatisticsView.h" // Qt includes #include #include // berry includes #include // mitk includes #include "mitkNodePredicateDataType.h" #include "mitkPlanarFigureInteractor.h" // itk includes #include "itksys/SystemTools.hxx" #include #include const std::string QmitkImageStatisticsView::VIEW_ID = "org.mitk.views.imagestatistics"; const int QmitkImageStatisticsView::STAT_TABLE_BASE_HEIGHT = 180; QmitkImageStatisticsView::QmitkImageStatisticsView(QObject* /*parent*/, const char* /*name*/) : m_Controls( NULL ), m_TimeStepperAdapter( NULL ), m_SelectedImage( NULL ), m_SelectedImageMask( NULL ), m_SelectedPlanarFigure( NULL ), m_ImageObserverTag( -1 ), m_ImageMaskObserverTag( -1 ), m_PlanarFigureObserverTag( -1 ), m_TimeObserverTag( -1 ), m_CurrentStatisticsValid( false ), m_StatisticsUpdatePending( false ), m_DataNodeSelectionChanged ( false ), m_Visible(false) { this->m_CalculationThread = new QmitkImageStatisticsCalculationThread; } QmitkImageStatisticsView::~QmitkImageStatisticsView() { if ( m_SelectedImage != NULL ) m_SelectedImage->RemoveObserver( m_ImageObserverTag ); if ( m_SelectedImageMask != NULL ) m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag ); if ( m_SelectedPlanarFigure != NULL ) m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag ); while(this->m_CalculationThread->isRunning()) // wait until thread has finished { itksys::SystemTools::Delay(100); } delete this->m_CalculationThread; } void QmitkImageStatisticsView::CreateQtPartControl(QWidget *parent) { if (m_Controls == NULL) { m_Controls = new Ui::QmitkImageStatisticsViewControls; m_Controls->setupUi(parent); CreateConnections(); m_Controls->m_ErrorMessageLabel->hide(); m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 ); m_Controls->m_BinSizeFrame->setVisible(false); } } void QmitkImageStatisticsView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(this->m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(OnClipboardHistogramButtonClicked()) ); connect( (QObject*)(this->m_Controls->m_ButtonCopyStatisticsToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(OnClipboardStatisticsButtonClicked()) ); connect( (QObject*)(this->m_Controls->m_IgnoreZerosCheckbox), SIGNAL(clicked()),(QObject*) this, SLOT(OnIgnoreZerosCheckboxClicked()) ); connect( (QObject*) this->m_CalculationThread, SIGNAL(finished()),this, SLOT( OnThreadedStatisticsCalculationEnds()),Qt::QueuedConnection); connect( (QObject*) this, SIGNAL(StatisticsUpdate()),this, SLOT( RequestStatisticsUpdate()), Qt::QueuedConnection); connect( (QObject*) this->m_Controls->m_StatisticsTable, SIGNAL(cellDoubleClicked(int,int)),this, SLOT( JumpToCoordinates(int,int)) ); connect( (QObject*) (this->m_Controls->m_barRadioButton), SIGNAL(clicked()), (QObject*) (this->m_Controls->m_JSHistogram), SLOT(OnBarRadioButtonSelected())); connect( (QObject*) (this->m_Controls->m_lineRadioButton), SIGNAL(clicked()), (QObject*) (this->m_Controls->m_JSHistogram), SLOT(OnLineRadioButtonSelected())); connect( (QObject*) (this->m_Controls->m_HistogramBinSizeSpinbox), SIGNAL(editingFinished()), this, SLOT(OnHistogramBinSizeBoxValueChanged())); connect( (QObject*)(this->m_Controls->m_UseDefaultBinSizeBox), SIGNAL(clicked()),(QObject*) this, SLOT(OnDefaultBinSizeBoxChanged()) ); } } void QmitkImageStatisticsView::OnDefaultBinSizeBoxChanged() { if (m_CalculationThread!=NULL) m_Controls->m_HistogramBinSizeSpinbox->setValue(m_CalculationThread->GetHistogramBinSize()); if (m_Controls->m_UseDefaultBinSizeBox->isChecked()) m_Controls->m_BinSizeFrame->setVisible(false); else m_Controls->m_BinSizeFrame->setVisible(true); } void QmitkImageStatisticsView::PartClosed( berry::IWorkbenchPartReference::Pointer ) { } void QmitkImageStatisticsView::OnTimeChanged(const itk::EventObject& e) { if (this->m_SelectedDataNodes.isEmpty() || this->m_SelectedImage == NULL) return; const mitk::SliceNavigationController::GeometryTimeEvent* timeEvent = dynamic_cast(&e); assert(timeEvent != NULL); unsigned int timestep = timeEvent->GetPos(); if (this->m_SelectedImage->GetTimeSteps() > 1) { for (unsigned int x = 0; x < this->m_Controls->m_StatisticsTable->columnCount(); x++) { for (unsigned int y = 0; y < this->m_Controls->m_StatisticsTable->rowCount(); y++) { QTableWidgetItem* item = this->m_Controls->m_StatisticsTable->item(y, x); if (item == NULL) break; if (x == timestep) { item->setBackgroundColor(Qt::yellow); } else { if (y % 2 == 0) item->setBackground(this->m_Controls->m_StatisticsTable->palette().base()); else item->setBackground(this->m_Controls->m_StatisticsTable->palette().alternateBase()); } } } this->m_Controls->m_StatisticsTable->viewport()->update(); } if ((this->m_SelectedImage->GetTimeSteps() == 1 && timestep == 0) || this->m_SelectedImage->GetTimeSteps() > 1) { // display histogram for selected timestep this->m_Controls->m_JSHistogram->ClearHistogram(); QmitkImageStatisticsCalculationThread::HistogramType::Pointer histogram = this->m_CalculationThread->GetTimeStepHistogram(timestep); if (histogram.IsNotNull()) { this->m_Controls->m_JSHistogram->ComputeHistogram(histogram.GetPointer()); // this->m_Controls->m_JSHistogram->SignalGraphChanged(); // hacky way to make sure the protected SignalGraphChanged() is called if (this->m_Controls->m_JSHistogram->GetUseLineGraph()) { this->m_Controls->m_JSHistogram->OnBarRadioButtonSelected(); this->m_Controls->m_JSHistogram->OnLineRadioButtonSelected(); } else { this->m_Controls->m_JSHistogram->OnLineRadioButtonSelected(); this->m_Controls->m_JSHistogram->OnBarRadioButtonSelected(); } } } } void QmitkImageStatisticsView::JumpToCoordinates(int row ,int col) { if(m_SelectedDataNodes.isEmpty()) { MITK_WARN("QmitkImageStatisticsView") << "No data node selected for statistics calculation." ; return; } mitk::Point3D world; if (row==4 && !m_WorldMinList.empty()) world = m_WorldMinList[col]; else if (row==3 && !m_WorldMaxList.empty()) world = m_WorldMaxList[col]; else return; mitk::IRenderWindowPart* part = this->GetRenderWindowPart(); if (part) { part->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SelectSliceByPoint(world); part->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SelectSliceByPoint(world); part->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SelectSliceByPoint(world); mitk::SliceNavigationController::GeometryTimeEvent timeEvent(this->m_SelectedImage->GetTimeGeometry(), col); part->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetGeometryTime(timeEvent); } } void QmitkImageStatisticsView::OnIgnoreZerosCheckboxClicked() { emit StatisticsUpdate(); } void QmitkImageStatisticsView::OnClipboardHistogramButtonClicked() { if ( m_CurrentStatisticsValid ) { const unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos(); typedef mitk::ImageStatisticsCalculator::HistogramType HistogramType; const HistogramType *histogram = this->m_CalculationThread->GetTimeStepHistogram(t).GetPointer(); QString clipboard( "Measurement \t Frequency\n" ); for ( HistogramType::ConstIterator it = histogram->Begin(); it != histogram->End(); ++it ) { if( m_Controls->m_HistogramBinSizeSpinbox->value() == 1) { clipboard = clipboard.append( "%L1 \t %L2\n" ) .arg( it.GetMeasurementVector()[0], 0, 'f', 0 ) .arg( it.GetFrequency() ); } else { clipboard = clipboard.append( "%L1 \t %L2\n" ) .arg( it.GetMeasurementVector()[0], 0, 'f', 2 ) .arg( it.GetFrequency() ); } } QApplication::clipboard()->setText( clipboard, QClipboard::Clipboard ); } else { QApplication::clipboard()->clear(); } } void QmitkImageStatisticsView::OnClipboardStatisticsButtonClicked() { QLocale tempLocal; QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); if ( this->m_CurrentStatisticsValid ) { const std::vector &statistics = this->m_CalculationThread->GetStatisticsData(); const unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()-> GetPos(); // Copy statistics to clipboard ("%Ln" will use the default locale for // number formatting) QString clipboard( "Mean \t StdDev \t RMS \t Max \t Min \t N \t V (mm³)\n" ); clipboard = clipboard.append( "%L1 \t %L2 \t %L3 \t %L4 \t %L5 \t %L6 \t %L7" ) .arg( statistics[t].GetMean(), 0, 'f', 10 ) .arg( statistics[t].GetSigma(), 0, 'f', 10 ) .arg( statistics[t].GetRMS(), 0, 'f', 10 ) .arg( statistics[t].GetMax(), 0, 'f', 10 ) .arg( statistics[t].GetMin(), 0, 'f', 10 ) .arg( statistics[t].GetN() ) .arg( m_Controls->m_StatisticsTable->item( 0, 6 )->text().toDouble(), 0, 'f', 10 ); QApplication::clipboard()->setText( clipboard, QClipboard::Clipboard ); } else { QApplication::clipboard()->clear(); } QLocale::setDefault(tempLocal); } void QmitkImageStatisticsView::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*part*/, const QList &selectedNodes ) { if (this->m_Visible) { this->SelectionChanged( selectedNodes ); } else { this->m_DataNodeSelectionChanged = true; } } void QmitkImageStatisticsView::SelectionChanged(const QList &selectedNodes) { if( this->m_StatisticsUpdatePending ) { this->m_DataNodeSelectionChanged = true; return; // not ready for new data now! } if (selectedNodes.size() == this->m_SelectedDataNodes.size()) { int i = 0; for (; i < selectedNodes.size(); ++i) { if (selectedNodes.at(i) != this->m_SelectedDataNodes.at(i)) { break; } } // node selection did not change if (i == selectedNodes.size()) return; } //reset the feature image and image mask field m_Controls->m_SelectedFeatureImageLabel->setText("None"); m_Controls->m_SelectedMaskLabel->setText("None"); this->ReinitData(); if (selectedNodes.isEmpty()) { m_Controls->m_JSHistogram->ClearHistogram(); m_Controls->m_lineRadioButton->setEnabled(true); m_Controls->m_barRadioButton->setEnabled(true); m_Controls->m_HistogramBinSizeSpinbox->setEnabled(true); m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true); // m_Controls->m_HistogramBinSizeLabel->setEnabled(true); m_Controls->m_InfoLabel->setText(QString("")); // m_Controls->horizontalLayout_3->setEnabled(false); m_Controls->groupBox->setEnabled(false); m_Controls->groupBox_3->setEnabled(false); } else { // m_Controls->horizontalLayout_3->setEnabled(true); m_Controls->groupBox->setEnabled(true); m_Controls->groupBox_3->setEnabled(true); } if(selectedNodes.size() == 1 || selectedNodes.size() == 2) { bool isBinary = false; selectedNodes.value(0)->GetBoolProperty("binary",isBinary); if(isBinary) { m_Controls->m_JSHistogram->ClearHistogram(); m_Controls->m_lineRadioButton->setEnabled(true); m_Controls->m_barRadioButton->setEnabled(true); m_Controls->m_HistogramBinSizeSpinbox->setEnabled(true); m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true); // m_Controls->m_HistogramBinSizeLabel->setEnabled(true); m_Controls->m_InfoLabel->setText(QString("")); } for (int i= 0; i< selectedNodes.size(); ++i) { this->m_SelectedDataNodes.push_back(selectedNodes.at(i)); } this->m_DataNodeSelectionChanged = false; this->m_Controls->m_ErrorMessageLabel->setText( "" ); this->m_Controls->m_ErrorMessageLabel->hide(); emit StatisticsUpdate(); } else { this->m_DataNodeSelectionChanged = false; } } void QmitkImageStatisticsView::ReinitData() { while( this->m_CalculationThread->isRunning()) // wait until thread has finished { itksys::SystemTools::Delay(100); } if(this->m_SelectedImage != NULL) { this->m_SelectedImage->RemoveObserver( this->m_ImageObserverTag); this->m_SelectedImage = NULL; } if(this->m_SelectedImageMask != NULL) { this->m_SelectedImageMask->RemoveObserver( this->m_ImageMaskObserverTag); this->m_SelectedImageMask = NULL; } if(this->m_SelectedPlanarFigure != NULL) { this->m_SelectedPlanarFigure->RemoveObserver( this->m_PlanarFigureObserverTag); this->m_SelectedPlanarFigure = NULL; } this->m_SelectedDataNodes.clear(); this->m_StatisticsUpdatePending = false; m_Controls->m_ErrorMessageLabel->setText( "" ); m_Controls->m_ErrorMessageLabel->hide(); this->InvalidateStatisticsTableView(); m_Controls->m_JSHistogram->ClearHistogram(); m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 ); } void QmitkImageStatisticsView::OnThreadedStatisticsCalculationEnds() { std::stringstream message; message << ""; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->hide(); this->WriteStatisticsToGUI(); } void QmitkImageStatisticsView::UpdateStatistics() { mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart(); if ( renderPart == NULL ) { this->m_StatisticsUpdatePending = false; return; } m_WorldMinList.clear(); m_WorldMaxList.clear(); // classify selected nodes mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image"); std::string maskName = std::string(); std::string maskType = std::string(); std::string featureImageName = std::string(); unsigned int maskDimension = 0; // reset data from last run ITKCommandType::Pointer changeListener = ITKCommandType::New(); changeListener->SetCallbackFunction( this, &QmitkImageStatisticsView::SelectedDataModified ); mitk::DataNode::Pointer planarFigureNode; for( int i= 0 ; i < this->m_SelectedDataNodes.size(); ++i) { mitk::PlanarFigure::Pointer planarFig = dynamic_cast(this->m_SelectedDataNodes.at(i)->GetData()); if( imagePredicate->CheckNode(this->m_SelectedDataNodes.at(i)) ) { bool isMask = false; this->m_SelectedDataNodes.at(i)->GetPropertyValue("binary", isMask); if( this->m_SelectedImageMask == NULL && isMask) { this->m_SelectedImageMask = dynamic_cast(this->m_SelectedDataNodes.at(i)->GetData()); this->m_ImageMaskObserverTag = this->m_SelectedImageMask->AddObserver(itk::ModifiedEvent(), changeListener); maskName = this->m_SelectedDataNodes.at(i)->GetName(); maskType = m_SelectedImageMask->GetNameOfClass(); maskDimension = 3; } else if( !isMask ) { if(this->m_SelectedImage == NULL) { this->m_SelectedImage = static_cast(this->m_SelectedDataNodes.at(i)->GetData()); this->m_ImageObserverTag = this->m_SelectedImage->AddObserver(itk::ModifiedEvent(), changeListener); } featureImageName = this->m_SelectedDataNodes.at(i)->GetName(); } } else if (planarFig.IsNotNull()) { if(this->m_SelectedPlanarFigure == NULL) { this->m_SelectedPlanarFigure = planarFig; this->m_PlanarFigureObserverTag = this->m_SelectedPlanarFigure->AddObserver(mitk::EndInteractionPlanarFigureEvent(), changeListener); maskName = this->m_SelectedDataNodes.at(i)->GetName(); maskType = this->m_SelectedPlanarFigure->GetNameOfClass(); maskDimension = 2; planarFigureNode = m_SelectedDataNodes.at(i); } } else { std::stringstream message; message << "" << "Invalid data node type!" << ""; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); } } if(maskName == "") { maskName = "None"; maskType = ""; maskDimension = 0; } if(featureImageName == "") { featureImageName = "None"; } if (m_SelectedPlanarFigure != NULL && m_SelectedImage == NULL) { mitk::DataStorage::SetOfObjects::ConstPointer parentSet = this->GetDataStorage()->GetSources(planarFigureNode); for (int i=0; iSize(); i++) { mitk::DataNode::Pointer node = parentSet->ElementAt(i); if( imagePredicate->CheckNode(node) ) { bool isMask = false; node->GetPropertyValue("binary", isMask); if( !isMask ) { if(this->m_SelectedImage == NULL) { this->m_SelectedImage = static_cast(node->GetData()); this->m_ImageObserverTag = this->m_SelectedImage->AddObserver(itk::ModifiedEvent(), changeListener); } } } } } unsigned int timeStep = renderPart->GetTimeNavigationController()->GetTime()->GetPos(); if ( m_SelectedImage != NULL && m_SelectedImage->IsInitialized()) { // Check if a the selected image is a multi-channel image. If yes, statistics // cannot be calculated currently. if ( m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1 ) { std::stringstream message; message << "Multi-component images not supported."; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); this->InvalidateStatisticsTableView(); m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 ); m_Controls->m_JSHistogram->ClearHistogram(); m_CurrentStatisticsValid = false; this->m_StatisticsUpdatePending = false; m_Controls->m_lineRadioButton->setEnabled(true); m_Controls->m_barRadioButton->setEnabled(true); m_Controls->m_HistogramBinSizeSpinbox->setEnabled(true); m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true); // m_Controls->m_HistogramBinSizeLabel->setEnabled(true); m_Controls->m_InfoLabel->setText(QString("")); return; } std::stringstream maskLabel; maskLabel << maskName; if ( maskDimension > 0 ) { maskLabel << " [" << maskDimension << "D " << maskType << "]"; } m_Controls->m_SelectedMaskLabel->setText( maskLabel.str().c_str() ); m_Controls->m_SelectedFeatureImageLabel->setText(featureImageName.c_str()); // check time step validity if(m_SelectedImage->GetDimension() <= 3 && timeStep > m_SelectedImage->GetDimension(3)-1) { timeStep = m_SelectedImage->GetDimension(3)-1; } // Add the used mask time step to the mask label so the user knows which mask time step was used // if the image time step is bigger than the total number of mask time steps (see // ImageStatisticsCalculator::ExtractImageAndMask) if (m_SelectedImageMask != NULL) { unsigned int maskTimeStep = timeStep; if (maskTimeStep >= m_SelectedImageMask->GetTimeSteps()) { maskTimeStep = m_SelectedImageMask->GetTimeSteps() - 1; } m_Controls->m_SelectedMaskLabel->setText(m_Controls->m_SelectedMaskLabel->text() + QString(" (t=") + QString::number(maskTimeStep) + QString(")")); } //// initialize thread and trigger it this->m_CalculationThread->SetIgnoreZeroValueVoxel( m_Controls->m_IgnoreZerosCheckbox->isChecked() ); this->m_CalculationThread->Initialize( m_SelectedImage, m_SelectedImageMask, m_SelectedPlanarFigure ); this->m_CalculationThread->SetTimeStep( timeStep ); this->m_CalculationThread->SetHistogramBinSize(m_Controls->m_HistogramBinSizeSpinbox->value()); std::stringstream message; message << "Calculating statistics..."; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); try { // Compute statistics this->m_CalculationThread->SetUseDefaultBinSize(m_Controls->m_UseDefaultBinSizeBox->isChecked()); this->m_CalculationThread->start(); } catch ( const mitk::Exception& e) { std::stringstream message; message << "" << e.GetDescription() << ""; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); this->m_StatisticsUpdatePending = false; } catch ( const std::runtime_error &e ) { // In case of exception, print error message on GUI std::stringstream message; message << "" << e.what() << ""; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); this->m_StatisticsUpdatePending = false; } catch ( const std::exception &e ) { MITK_ERROR << "Caught exception: " << e.what(); // In case of exception, print error message on GUI std::stringstream message; message << "Error! Unequal Dimensions of Image and Segmentation. No recompute possible "; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); this->m_StatisticsUpdatePending = false; } } else { this->m_StatisticsUpdatePending = false; } } void QmitkImageStatisticsView::SelectedDataModified() { if( !m_StatisticsUpdatePending ) { emit StatisticsUpdate(); } } void QmitkImageStatisticsView::NodeRemoved(const mitk::DataNode *node) { while(this->m_CalculationThread->isRunning()) // wait until thread has finished { itksys::SystemTools::Delay(100); } if (node->GetData() == m_SelectedImage) { m_SelectedImage = NULL; } } void QmitkImageStatisticsView::RequestStatisticsUpdate() { if ( !m_StatisticsUpdatePending ) { if(this->m_DataNodeSelectionChanged) { this->SelectionChanged(this->GetCurrentSelection()); } else { this->m_StatisticsUpdatePending = true; this->UpdateStatistics(); } } if (this->GetRenderWindowPart()) this->GetRenderWindowPart()->RequestUpdate(); } void QmitkImageStatisticsView::OnHistogramBinSizeBoxValueChanged() { this->UpdateStatistics(); } void QmitkImageStatisticsView::WriteStatisticsToGUI() { m_Controls->m_lineRadioButton->setEnabled(true); m_Controls->m_barRadioButton->setEnabled(true); m_Controls->m_HistogramBinSizeSpinbox->setEnabled(true); m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true); // m_Controls->m_HistogramBinSizeLabel->setEnabled(true); m_Controls->m_InfoLabel->setText(QString("")); if(m_DataNodeSelectionChanged) { this->m_StatisticsUpdatePending = false; this->RequestStatisticsUpdate(); return; // stop visualization of results and calculate statistics of new selection } if ( this->m_CalculationThread->GetStatisticsUpdateSuccessFlag()) { if ( this->m_CalculationThread->GetStatisticsChangedFlag() ) { // Do not show any error messages m_Controls->m_ErrorMessageLabel->hide(); m_CurrentStatisticsValid = true; } if (m_Controls->m_barRadioButton->isChecked()) { m_Controls->m_JSHistogram->OnBarRadioButtonSelected(); } m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 ); m_Controls->m_HistogramBinSizeSpinbox->setValue( this->m_CalculationThread->GetHistogramBinSize() ); //m_Controls->m_JSHistogram->ComputeHistogram( this->m_CalculationThread->GetTimeStepHistogram(this->m_CalculationThread->GetTimeStep()).GetPointer() ); this->FillStatisticsTableView( this->m_CalculationThread->GetStatisticsData(), this->m_CalculationThread->GetStatisticsImage()); } else { m_Controls->m_SelectedMaskLabel->setText( "None" ); m_Controls->m_ErrorMessageLabel->setText( m_CalculationThread->GetLastErrorMessage().c_str() ); m_Controls->m_ErrorMessageLabel->show(); // Clear statistics and histogram this->InvalidateStatisticsTableView(); m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 ); //m_Controls->m_JSHistogram->clearHistogram(); m_CurrentStatisticsValid = false; // If a (non-closed) PlanarFigure is selected, display a line profile widget if ( m_SelectedPlanarFigure != NULL ) { // Check if the (closed) planar figure is out of bounds and so no image mask could be calculated--> Intensity Profile can not be calculated bool outOfBounds = false; if ( m_SelectedPlanarFigure->IsClosed() && m_SelectedImageMask == NULL) { outOfBounds = true; std::stringstream message; message << "Planar figure is on a rotated image plane or outside the image bounds."; m_Controls->m_InfoLabel->setText(message.str().c_str()); } // check whether PlanarFigure is initialized const mitk::PlaneGeometry *planarFigurePlaneGeometry = m_SelectedPlanarFigure->GetPlaneGeometry(); if ( planarFigurePlaneGeometry == NULL || outOfBounds) { // Clear statistics, histogram, and GUI this->InvalidateStatisticsTableView(); m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 ); m_Controls->m_JSHistogram->ClearHistogram(); m_CurrentStatisticsValid = false; m_Controls->m_ErrorMessageLabel->hide(); m_Controls->m_SelectedMaskLabel->setText( "None" ); this->m_StatisticsUpdatePending = false; m_Controls->m_lineRadioButton->setEnabled(true); m_Controls->m_barRadioButton->setEnabled(true); m_Controls->m_HistogramBinSizeSpinbox->setEnabled(true); m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true); // m_Controls->m_HistogramBinSizeLabel->setEnabled(true); if (!outOfBounds) m_Controls->m_InfoLabel->setText(QString("")); return; } unsigned int timeStep = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos(); m_Controls->m_JSHistogram->SetImage(this->m_CalculationThread->GetStatisticsImage()); m_Controls->m_JSHistogram->SetPlanarFigure(m_SelectedPlanarFigure); m_Controls->m_JSHistogram->ComputeIntensityProfile(timeStep); m_Controls->m_lineRadioButton->setEnabled(false); m_Controls->m_barRadioButton->setEnabled(false); m_Controls->m_HistogramBinSizeSpinbox->setEnabled(false); m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(false); // m_Controls->m_HistogramBinSizeLabel->setEnabled(false); std::stringstream message; message << "Only linegraph available for an intesityprofile!"; m_Controls->m_InfoLabel->setText(message.str().c_str()); } } this->m_StatisticsUpdatePending = false; } void QmitkImageStatisticsView::FillStatisticsTableView( const std::vector &s, const mitk::Image *image ) { this->m_Controls->m_StatisticsTable->setColumnCount(image->GetTimeSteps()); this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(image->GetTimeSteps() > 1); int decimals = 2; mitk::PixelType doublePix = mitk::MakeScalarPixelType< double >(); mitk::PixelType floatPix = mitk::MakeScalarPixelType< float >(); if (image->GetPixelType()==doublePix || image->GetPixelType()==floatPix) { decimals = 5; } for (unsigned int t = 0; t < image->GetTimeSteps(); t++) { this->m_Controls->m_StatisticsTable->setHorizontalHeaderItem(t, new QTableWidgetItem(QString::number(t))); if (s[t].GetMaxIndex().size()==3) { mitk::Point3D index, max, min; index[0] = s[t].GetMaxIndex()[0]; index[1] = s[t].GetMaxIndex()[1]; index[2] = s[t].GetMaxIndex()[2]; m_SelectedImage->GetGeometry()->IndexToWorld(index, max); this->m_WorldMaxList.push_back(max); index[0] = s[t].GetMinIndex()[0]; index[1] = s[t].GetMinIndex()[1]; index[2] = s[t].GetMinIndex()[2]; m_SelectedImage->GetGeometry()->IndexToWorld(index, min); this->m_WorldMinList.push_back(min); } this->m_Controls->m_StatisticsTable->setItem( 0, t, new QTableWidgetItem( QString("%1").arg(s[t].GetMean(), 0, 'f', decimals) ) ); this->m_Controls->m_StatisticsTable->setItem( 1, t, new QTableWidgetItem( QString("%1").arg(s[t].GetSigma(), 0, 'f', decimals) ) ); this->m_Controls->m_StatisticsTable->setItem( 2, t, new QTableWidgetItem( QString("%1").arg(s[t].GetRMS(), 0, 'f', decimals) ) ); QString max; max.append(QString("%1").arg(s[t].GetMax(), 0, 'f', decimals)); max += " ("; for (int i=0; im_Controls->m_StatisticsTable->setItem( 3, t, new QTableWidgetItem( max ) ); QString min; min.append(QString("%1").arg(s[t].GetMin(), 0, 'f', decimals)); min += " ("; for (int i=0; im_Controls->m_StatisticsTable->setItem( 4, t, new QTableWidgetItem( min ) ); this->m_Controls->m_StatisticsTable->setItem( 5, t, new QTableWidgetItem( QString("%1").arg(s[t].GetN()) ) ); const mitk::BaseGeometry *geometry = image->GetGeometry(); if ( geometry != NULL ) { const mitk::Vector3D &spacing = image->GetGeometry()->GetSpacing(); double volume = spacing[0] * spacing[1] * spacing[2] * (double) s[t].GetN(); this->m_Controls->m_StatisticsTable->setItem( 6, t, new QTableWidgetItem( QString("%1").arg(volume, 0, 'f', decimals) ) ); } else { this->m_Controls->m_StatisticsTable->setItem( 6, t, new QTableWidgetItem( "NA" ) ); } } this->m_Controls->m_StatisticsTable->resizeColumnsToContents(); int height = STAT_TABLE_BASE_HEIGHT; if (this->m_Controls->m_StatisticsTable->horizontalHeader()->isVisible()) height += this->m_Controls->m_StatisticsTable->horizontalHeader()->height(); if (this->m_Controls->m_StatisticsTable->horizontalScrollBar()->isVisible()) height += this->m_Controls->m_StatisticsTable->horizontalScrollBar()->height(); this->m_Controls->m_StatisticsTable->setMinimumHeight(height); // make sure the current timestep's column is highlighted (and the correct histogram is displayed) unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()-> GetPos(); mitk::SliceNavigationController::GeometryTimeEvent timeEvent(this->m_SelectedImage->GetTimeGeometry(), t); this->OnTimeChanged(timeEvent); + t = std::min(image->GetTimeSteps() - 1, t); + QString hotspotMean; hotspotMean.append(QString("%1").arg(s[t].GetHotspotStatistics().GetMean(), 0, 'f', decimals)); hotspotMean += " ("; for (int i=0; im_Controls->m_StatisticsTable->setItem( 7, t, new QTableWidgetItem( hotspotMean ) ); QString hotspotMax; hotspotMax.append(QString("%1").arg(s[t].GetHotspotStatistics().GetMax(), 0, 'f', decimals)); hotspotMax += " ("; for (int i=0; im_Controls->m_StatisticsTable->setItem( 8, t, new QTableWidgetItem( hotspotMax ) ); QString hotspotMin; hotspotMin.append(QString("%1").arg(s[t].GetHotspotStatistics().GetMin(), 0, 'f', decimals)); hotspotMin += " ("; for (int i=0; im_Controls->m_StatisticsTable->setItem( 9, t, new QTableWidgetItem( hotspotMin ) ); } void QmitkImageStatisticsView::InvalidateStatisticsTableView() { this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(false); this->m_Controls->m_StatisticsTable->setColumnCount(1); for ( unsigned int i = 0; i < this->m_Controls->m_StatisticsTable->rowCount(); ++i ) { { this->m_Controls->m_StatisticsTable->setItem( i, 0, new QTableWidgetItem( "NA" ) ); } } this->m_Controls->m_StatisticsTable->setMinimumHeight(STAT_TABLE_BASE_HEIGHT); } void QmitkImageStatisticsView::Activated() { } void QmitkImageStatisticsView::Deactivated() { } void QmitkImageStatisticsView::Visible() { m_Visible = true; mitk::IRenderWindowPart* renderWindow = GetRenderWindowPart(); if (renderWindow) { itk::ReceptorMemberCommand::Pointer cmdTimeEvent = itk::ReceptorMemberCommand::New(); cmdTimeEvent->SetCallbackFunction(this, &QmitkImageStatisticsView::OnTimeChanged); // It is sufficient to add the observer to the axial render window since the GeometryTimeEvent // is always triggered by all views. m_TimeObserverTag = renderWindow->GetQmitkRenderWindow("axial")-> GetSliceNavigationController()-> AddObserver(mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), cmdTimeEvent); } if (m_DataNodeSelectionChanged) { if (this->IsCurrentSelectionValid()) { this->SelectionChanged(this->GetCurrentSelection()); } else { this->SelectionChanged(this->GetDataManagerSelection()); } m_DataNodeSelectionChanged = false; } } void QmitkImageStatisticsView::Hidden() { m_Visible = false; // The slice navigation controller observer is removed here instead of in the destructor. // If it was called in the destructor, the application would freeze because the view's // destructor gets called after the render windows have been destructed. if ( m_TimeObserverTag != NULL ) { mitk::IRenderWindowPart* renderWindow = GetRenderWindowPart(); if (renderWindow) { renderWindow->GetQmitkRenderWindow("axial")->GetSliceNavigationController()-> RemoveObserver( m_TimeObserverTag ); } m_TimeObserverTag = NULL; } } void QmitkImageStatisticsView::SetFocus() { } diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker.dox b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker.dox deleted file mode 100644 index 878627bddb..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker.dox +++ /dev/null @@ -1,44 +0,0 @@ -/** - -\page org_mitk_views_moviemaker The Movie Maker View - -\imageMacro{QmitkMovieMaker_Icon.png,"Icon of the Movie Maker View",2.00} - -Available sections: - - \ref QmitkMovieMakerUserManualOverview - - \ref QmitkMovieMakerUserManualFeatures - - \ref QmitkMovieMakerUserManualUsage - -\section QmitkMovieMakerUserManualOverview Overview - -MovieMaker is a functionality for easily creating fancy movies from scenes displayed in MITK widgets. -It is also possible to slide through your data, automatically rotate 3D scenes and take screenshots of widgets. - -\section QmitkMovieMakerUserManualFeatures Features - - The Movie Maker allows you to create movies and screenshots from within MITK. It can automatically scroll thorugh timesteps and slices while recording a movie. This way, you can record visualizations like a beating heart or a rotating skull. - -\section QmitkMovieMakerUserManualUsage Usage - -\imageMacro{QmitkMovieMaker_ControlArea.png,"A view of the command area of QmitkMovieMaker",9.84} - -\subsection QmitkMovieMakerUserManualWindowSelection Window selection -With the first two drop down boxes, you can choose which window you want to step through and which window you want to record in. Left clicking inside a window will set both drop down boxes to that window, but you can choose different windows for stepping and recording. - -The first drop down box defines the window along which slices will be stepped through if stepping is set to spatial (see below). The second denotes the window from which the content will be recorded. - -\subsection QmitkMovieMakerUserManualRecordingOptions Recording Options - -The slider can be used to step through the slices manually while not recording. Start and stop control a preview of what a video would look like. - -The buttons in the bottom part of this section can be used to create movies (windows only) or screenshots. Clicking opens a file %dialog where a name can be selected. After confirmation, a screenshot or movie is created according to the playing options. - -\subsection QmitkMovieMakerUserManualPlayingOptions Playing Options - -The first section controls whether the movie steps through slices (if a 2D view is selected), rotate the shown scene (if a 3D view is selected), or step through time steps (if set to temporal and a time resolved dataset is selected). If set to combined, a combination of both above options is used, with their speed relation set via the S/T Relation Spinbox. - -In the second section the direction of stepping can be set. Options are: Forward, backward and Ping-Pong, which is back-and-forth.The stepping speed can be set via the spinbox(total time in seconds). - -Although stepping speed is a total time in sec., this can not always be achieved. As a minimal frame rate of 25 fps is assumed to provide smooth movies, a dataset with only 25 slices will always be stepped through in 1 sec or faster. - -*/ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ControlArea.png b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ControlArea.png deleted file mode 100644 index ec8c0b8dca..0000000000 Binary files a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ControlArea.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_Icon.png b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_Icon.png deleted file mode 100644 index 92c8276a2a..0000000000 Binary files a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_Icon.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ScreenshotMakerInterface.png b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ScreenshotMakerInterface.png deleted file mode 100644 index 085dcbdea6..0000000000 Binary files a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ScreenshotMakerInterface.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkScreenshotMaker.dox b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkScreenshotMaker.dox deleted file mode 100644 index 05b657bdeb..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkScreenshotMaker.dox +++ /dev/null @@ -1,19 +0,0 @@ -/** -\page org_mitk_views_screenshotmaker The Screenshot Maker - -This view provides the functionality to create and save screenshots of the data. - -Available sections: - - \ref QmitkScreenshotMakerUserManualUse - -\imageMacro{QmitkMovieMaker_ScreenshotMakerInterface.png,"The Screenshot Maker User Interface",7.09} - -\section QmitkScreenshotMakerUserManualUse Usage - -The first section offers the option of creating a screenshot of the last activated render window (thus the one, which was last clicked into). Upon clicking the button, the Screenshot Maker asks for a filename in which the screenshot is to be stored. The multiplanar Screenshot button asks for a folder, where screenshots of the three 2D views will be stored with default names. - -The high resolution screenshot section works the same as the simple screenshot section, aside from the fact, that the user can choose a magnification factor. - -In the option section one can rotate the camera in the 3D view by using the buttons. Furthermore one can choose the background colour for the screenshots, default is black. - -*/ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.moviemaker/documentation/doxygen/modules.dox deleted file mode 100644 index 07f1421b2a..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/documentation/doxygen/modules.dox +++ /dev/null @@ -1,16 +0,0 @@ -/** - \defgroup org_mitk_gui_qt_moviemaker org.mitk.gui.qt.moviemaker - \ingroup MITKPlugins - - \brief Describe your plugin here. - -*/ - -/** - \defgroup org_mitk_gui_qt_moviemaker_internal Internal - \ingroup org_mitk_gui_qt_moviemaker - - \brief This subcategory includes the internal classes of the org.mitk.gui.qt.moviemaker plugin. Other - plugins must not rely on these classes. They contain implementation details and their interface - may change at any time. We mean it. -*/ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/files.cmake b/Plugins/org.mitk.gui.qt.moviemaker/files.cmake index c4e28db992..11d7677e23 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/files.cmake +++ b/Plugins/org.mitk.gui.qt.moviemaker/files.cmake @@ -1,46 +1,53 @@ set(SRC_CPP_FILES - ) set(INTERNAL_CPP_FILES - QmitkMovieMaker.cpp + QmitkAnimationItem.cpp + QmitkAnimationItemDelegate.cpp + QmitkAnimationWidget.cpp + QmitkFFmpegWriter.cpp + QmitkMovieMakerView.cpp + QmitkOrbitAnimationItem.cpp + QmitkOrbitAnimationWidget.cpp + QmitkSliceAnimationItem.cpp + QmitkSliceAnimationWidget.cpp mitkMovieMakerPluginActivator.cpp QmitkScreenshotMaker.cpp - ) set(UI_FILES - src/internal/QmitkMovieMakerControls.ui + src/internal/QmitkMovieMakerView.ui + src/internal/QmitkOrbitAnimationWidget.ui + src/internal/QmitkSliceAnimationWidget.ui src/internal/QmitkScreenshotMakerControls.ui ) set(MOC_H_FILES src/internal/mitkMovieMakerPluginActivator.h - src/internal/QmitkMovieMaker.h + src/internal/QmitkAnimationItemDelegate.h + src/internal/QmitkAnimationWidget.h + src/internal/QmitkFFmpegWriter.h + src/internal/QmitkMovieMakerView.h + src/internal/QmitkOrbitAnimationWidget.h + src/internal/QmitkSliceAnimationWidget.h src/internal/QmitkScreenshotMaker.h ) set(CACHED_RESOURCE_FILES - resources/icon.xpm - plugin.xml - resources/play.xpm - resources/stop.xpm - resources/pause.xpm + resources/camera-video.png resources/screenshot_maker.png + plugin.xml ) -set(RES_FILES +set(QRC_FILES resources/QmitkMovieMaker.qrc - resources/play.xpm - resources/stop.xpm - resources/pause.xpm ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.moviemaker/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.moviemaker/manifest_headers.cmake index 33c96b326e..0273e2802e 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.moviemaker/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Movie Maker") set(Plugin-Version "0.9") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.common.legacy) \ No newline at end of file +set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.common.legacy org.mitk.gui.qt.ext) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.moviemaker/plugin.xml b/Plugins/org.mitk.gui.qt.moviemaker/plugin.xml index 32c792be7d..d3fe235aa5 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/plugin.xml +++ b/Plugins/org.mitk.gui.qt.moviemaker/plugin.xml @@ -1,35 +1,35 @@ + class="QmitkMovieMakerView" + icon="resources/camera-video.png" > Take movies of your data Take screenshots of your data diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMaker.qrc b/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMaker.qrc index 8bdb515e34..61ad433b67 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMaker.qrc +++ b/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMaker.qrc @@ -1,10 +1,6 @@ - QmitkMovieMakerClasses.png - QmitkMovieMakerGUI.png - icon.xpm - pause.xpm - play.xpm - stop.xpm + delay.svg + duration.svg diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMakerClasses.png b/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMakerClasses.png deleted file mode 100644 index 9c26381a09..0000000000 Binary files a/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMakerClasses.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMakerGUI.png b/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMakerGUI.png deleted file mode 100644 index 02af724a9e..0000000000 Binary files a/Plugins/org.mitk.gui.qt.moviemaker/resources/QmitkMovieMakerGUI.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/camera-video.png b/Plugins/org.mitk.gui.qt.moviemaker/resources/camera-video.png new file mode 100644 index 0000000000..d9d484927f Binary files /dev/null and b/Plugins/org.mitk.gui.qt.moviemaker/resources/camera-video.png differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/delay.svg b/Plugins/org.mitk.gui.qt.moviemaker/resources/delay.svg new file mode 100644 index 0000000000..75e2310861 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/resources/delay.svg @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + appointment + new + meeting + rvsp + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/duration.svg b/Plugins/org.mitk.gui.qt.moviemaker/resources/duration.svg new file mode 100644 index 0000000000..01b1d129bd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/resources/duration.svg @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + appointment + new + meeting + rvsp + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/icon.png b/Plugins/org.mitk.gui.qt.moviemaker/resources/icon.png deleted file mode 100644 index 6ad519ea65..0000000000 Binary files a/Plugins/org.mitk.gui.qt.moviemaker/resources/icon.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/icon.xpm b/Plugins/org.mitk.gui.qt.moviemaker/resources/icon.xpm deleted file mode 100644 index 103ebf4b01..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/resources/icon.xpm +++ /dev/null @@ -1,47 +0,0 @@ -/* XPM */ -static const char * icon_xpm[] = { -"28 28 16 1", -" c None", -". c #000000", -"+ c #555555", -"@ c #222222", -"# c #777777", -"$ c #444444", -"% c #BBBBBB", -"& c #DDDDDD", -"* c #AAAAAA", -"= c #FFFFFF", -"- c #888888", -"; c #993366", -"> c #CC6666", -", c #663300", -"' c #440000", -") c #FFFF00", -" ... ", -" ..+@@. ", -" ..++@+@.. ", -" ..+++##@@.. ", -" ..+++##@@@@.. ", -" ..+++##@@@$$.. ", -" ..#++##@@@$...$ ", -" ..##++#@@@%&&.$ ", -" ...*@@+#@@%&&==&. ", -" ...*++++@@%&&==&&@@. ", -" ..$$==+#-%&&==&&@@$$@. ", -" .+##..=-&&==&&@@@$$+@. ", -" .##---*.=%=&&@@@@$$++@. ", -" .===%**%%$=*@@@@@$$+++@. ", -".=-@+=&%&&.&-@@@@$$++++@. ", -".&.;.+=&%%.%#@@@$$+++++@. ", -".&.>,.=&**.*+@$$====++@. ", -".&.,,.&&--.*+=$$&&&&====... ", -".&+.'.&%##.-=&$+%%%%&&&&===.", -".&%+.*&*++$=&$======%%%%&&&.", -" .&&&&&-++&**$&&&+++%===%%%.", -" .&==&*+++&*--.%%@))++++===.", -" .&**&*+++&-+@@@*+@@)))@&&&.", -" .@&&&*+++@@@@..----@@@+%%%.", -" .+@@$*+@@@@.. .....----***.", -" .+++$@@@.. ....---.", -" ..@+$@.. ... ", -" .... "}; diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/pause.xpm b/Plugins/org.mitk.gui.qt.moviemaker/resources/pause.xpm deleted file mode 100644 index 0ad2e7421c..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/resources/pause.xpm +++ /dev/null @@ -1,57 +0,0 @@ -/* XPM */ -static const char * pause_xpm[] = { -"24 24 30 1", -" c None", -". c #000000", -"+ c #FFFFFF", -"@ c #737372", -"# c #848483", -"$ c #888887", -"% c #7E7E7D", -"& c #A8A7A6", -"* c #A4A4A3", -"= c #A6A5A4", -"- c #B5B4B3", -"; c #858483", -"> c #AAA9A7", -", c #C0BFBE", -"' c #91908E", -") c #AFAEAC", -"! c #CACAC8", -"~ c #A6A5A2", -"{ c #BBBAB7", -"] c #D4D3D2", -"^ c #AEADA9", -"/ c #BFBDBA", -"( c #D7D5D3", -"_ c #B2B0AD", -": c #C3C1BE", -"< c #D9D8D6", -"[ c #B5B3B0", -"} c #D1CFCC", -"| c #DEDDDB", -"1 c #F3F3F3", -" ", -" ", -" ", -" ", -" ", -" .....+.....+ ", -" .@#$.+.@#$.+ ", -" .%&*.+.%&*.+ ", -" .%=-.+.%=-.+ ", -" .;>,.+.;>,.+ ", -" .')!.+.')!.+ ", -" .')!.+.')!.+ ", -" .')!.+.')!.+ ", -" .~{].+.~{].+ ", -" .~{].+.~{].+ ", -" .^/(.+.^/(.+ ", -" ._:<.+._:<.+ ", -" .[}|.+.[}|.+ ", -" .....+.....+ ", -" +++++1++++++ ", -" ", -" ", -" ", -" "}; diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/play.xpm b/Plugins/org.mitk.gui.qt.moviemaker/resources/play.xpm deleted file mode 100644 index 0bcda4f454..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/resources/play.xpm +++ /dev/null @@ -1,64 +0,0 @@ -/* XPM */ -static const char * play_xpm[] = { -"24 24 37 1", -" c None", -". c #000000", -"+ c #727170", -"@ c #7B7B7A", -"# c #6C6B6A", -"$ c #7F7E7D", -"% c #999996", -"& c #7D7C7B", -"* c #828180", -"= c #9D9C9A", -"- c #B0AFAC", -"; c #908F8D", -"> c #868583", -", c #A1A09E", -"' c #B4B3B1", -") c #B6B4B2", -"! c #A5A4A1", -"~ c #898886", -"{ c #B9B7B4", -"] c #BAB9B6", -"^ c #BCBAB7", -"/ c #C3C2BF", -"( c #FFFFFF", -"_ c #8C8B89", -": c #A9A8A5", -"< c #BDBCB9", -"[ c #C5C3C0", -"} c #D0CECC", -"| c #8F8E8C", -"1 c #B5B3B1", -"2 c #C7C6C3", -"3 c #D2D1CE", -"4 c #B9B6B4", -"5 c #D8D7D5", -"6 c #A19F9D", -"7 c #C7C6C4", -"8 c #A7A6A3", -" ", -" ", -" ", -" ", -" . ", -" .. ", -" .+. ", -" .@#. ", -" .$%&. ", -" .*=-;. ", -" .>,')!. ", -" .~!{]^/.( ", -" ._:<[}.( ", -" .|123.( ", -" .=45.( ", -" .67.( ", -" .8.( ", -" ..( ", -" .( ", -" ( ", -" ", -" ", -" ", -" "}; diff --git a/Plugins/org.mitk.gui.qt.moviemaker/resources/stop.xpm b/Plugins/org.mitk.gui.qt.moviemaker/resources/stop.xpm deleted file mode 100644 index 3b76b26157..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/resources/stop.xpm +++ /dev/null @@ -1,56 +0,0 @@ -/* XPM */ -static const char * stop_xpm[] = { -"24 24 29 1", -" c None", -". c #000000", -"+ c #FFFFFF", -"@ c #737372", -"# c #848483", -"$ c #888887", -"% c #7E7E7D", -"& c #A8A7A6", -"* c #A4A4A3", -"= c #A6A5A4", -"- c #B5B4B3", -"; c #858483", -"> c #AAA9A7", -", c #C0BFBE", -"' c #91908E", -") c #AFAEAC", -"! c #CACAC8", -"~ c #A6A5A2", -"{ c #BBBAB7", -"] c #D4D3D2", -"^ c #AEADA9", -"/ c #BFBDBA", -"( c #D7D5D3", -"_ c #B2B0AD", -": c #C3C1BE", -"< c #D9D8D6", -"[ c #B5B3B0", -"} c #D1CFCC", -"| c #DEDDDB", -" ", -" ", -" ", -" ", -" ", -" .............+ ", -" .@#$$$$$$$$$.+ ", -" .%&*********.+ ", -" .%=---------.+ ", -" .;>,,,,,,,,,.+ ", -" .')!!!!!!!!!.+ ", -" .')!!!!!!!!!.+ ", -" .~{]]]]]]]]].+ ", -" .~{]]]]]]]]].+ ", -" .^/(((((((((.+ ", -" ._:<<<<<<<<<.+ ", -" .[}|||||||||.+ ", -" .............+ ", -" ++++++++++++++ ", -" ", -" ", -" ", -" ", -" "}; diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItem.cpp new file mode 100644 index 0000000000..c55bb0808a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItem.cpp @@ -0,0 +1,71 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkAnimationItem.h" + +QmitkAnimationItem::QmitkAnimationItem(const QString& widgetKey, double duration, double delay, bool startWithPrevious) +{ + this->SetWidgetKey(widgetKey); + this->SetDuration(duration); + this->SetDelay(delay); + this->SetStartWithPrevious(startWithPrevious); + + this->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); +} + +QmitkAnimationItem::~QmitkAnimationItem() +{ +} + +QString QmitkAnimationItem::GetWidgetKey() const +{ + return this->data(WidgetKeyRole).toString(); +} + +void QmitkAnimationItem::SetWidgetKey(const QString& widgetKey) +{ + this->setData(widgetKey, WidgetKeyRole); +} + +double QmitkAnimationItem::GetDuration() const +{ + return this->data(DurationRole).toDouble(); +} + +void QmitkAnimationItem::SetDuration(double duration) +{ + this->setData(duration, DurationRole); +} + +double QmitkAnimationItem::GetDelay() const +{ + return this->data(DelayRole).toDouble(); +} + +void QmitkAnimationItem::SetDelay(double delay) +{ + this->setData(delay, DelayRole); +} + +bool QmitkAnimationItem::GetStartWithPrevious() const +{ + return this->data(StartWithPreviousRole).toBool(); +} + +void QmitkAnimationItem::SetStartWithPrevious(bool startWithPrevious) +{ + this->setData(startWithPrevious, StartWithPreviousRole); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItem.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItem.h new file mode 100644 index 0000000000..9e7fcec130 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItem.h @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkAnimationItem_h +#define QmitkAnimationItem_h + +#include + +class QmitkAnimationItem : public QStandardItem +{ +public: + enum AnimationItemDataRole + { + WidgetKeyRole = Qt::UserRole + 2, + DurationRole, + DelayRole, + StartWithPreviousRole, + RenderWindowRole, + FromRole, + ToRole, + ReverseRole, + StartAngleRole, + OrbitRole + }; + + explicit QmitkAnimationItem(const QString& widgetKey, double duration = 2.0, double delay = 0.0, bool startWithPrevious = false); + virtual ~QmitkAnimationItem(); + + QString GetWidgetKey() const; + void SetWidgetKey(const QString& widgetKey); + + double GetDuration() const; + void SetDuration(double duration); + + double GetDelay() const; + void SetDelay(double delay); + + bool GetStartWithPrevious() const; + void SetStartWithPrevious(bool startWithPrevious); + + virtual void Animate(double s) = 0; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItemDelegate.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItemDelegate.cpp new file mode 100644 index 0000000000..781aeb37af --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItemDelegate.cpp @@ -0,0 +1,123 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkAnimationItem.h" +#include "QmitkAnimationItemDelegate.h" +#include +#include +#include +#include + +QmitkAnimationItemDelegate::QmitkAnimationItemDelegate(QObject* parent) + : QStyledItemDelegate(parent) +{ +} + +QmitkAnimationItemDelegate::~QmitkAnimationItemDelegate() +{ +} + +void QmitkAnimationItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + painter->save(); + + if (option.state & QStyle::State_Selected) + painter->fillRect(option.rect, option.palette.highlight()); + + if (index.column() == 0) + { + QStyleOptionViewItem opt = option; + this->initStyleOption(&opt, index); + + QRect rect = QRect(opt.rect.x() + 3, opt.rect.y(), opt.rect.width() - 6, opt.rect.height()); + QString text = option.fontMetrics.elidedText(index.data().toString(), Qt::ElideRight, rect.width()); + QPalette::ColorRole colorRole = (option.state & QStyle::State_Selected) + ? QPalette::HighlightedText + : QPalette::Text; + + QApplication::style()->drawItemText(painter, rect, 0, option.palette, true, text, colorRole); + } + else if (index.column() == 1) + { + const QStandardItemModel* model = dynamic_cast(index.model()); + const QmitkAnimationItem* thisItem = dynamic_cast(model->item(index.row(), 1)); + QList items; + + const int rowCount = model->rowCount(); + + for (int i = 0; i < rowCount; ++i) + items << dynamic_cast(model->item(i, 1)); + + double totalDuration = 0.0; + double previousStart = 0.0; + double thisStart = 0.0; + + Q_FOREACH(const QmitkAnimationItem* item, items) + { + if (item->GetStartWithPrevious()) + { + totalDuration = std::max(totalDuration, previousStart + item->GetDelay() + item->GetDuration()); + } + else + { + previousStart = totalDuration; + totalDuration += item->GetDelay() + item->GetDuration(); + } + + if (item == thisItem) + thisStart = previousStart; + } + + const QRect& rect = option.rect; + const double widthPerSecond = rect.width() / totalDuration; + + QColor color = thisItem->GetStartWithPrevious() + ? QColor("DarkGray") + : QColor("DimGray"); + + painter->setBrush(color); + painter->setPen(Qt::NoPen); + + painter->drawRect( + rect.x() + static_cast(widthPerSecond * (thisStart + thisItem->GetDelay())), + rect.y() + 1, + static_cast(widthPerSecond * thisItem->GetDuration()), + rect.height() - 2); + + if (thisItem->GetDelay() > std::numeric_limits::min()) + { + QPen pen(color); + painter->setPen(pen); + + painter->drawLine( + rect.x() + static_cast(widthPerSecond * thisStart), + rect.y() + 1, + rect.x() + static_cast(widthPerSecond * thisStart), + rect.y() + rect.height() - 2); + + pen.setStyle(Qt::DashLine); + painter->setPen(pen); + + painter->drawLine( + rect.x() + static_cast(widthPerSecond * thisStart), + rect.y() + rect.height() / 2, + rect.x() + static_cast(widthPerSecond * (thisStart + thisItem->GetDelay())) - 1, + rect.y() + rect.height() / 2); + } + } + + painter->restore(); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItemDelegate.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItemDelegate.h new file mode 100644 index 0000000000..b1ad53c99a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationItemDelegate.h @@ -0,0 +1,33 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkAnimationItemDelegate_h +#define QmitkAnimationItemDelegate_h + +#include + +class QmitkAnimationItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit QmitkAnimationItemDelegate(QObject* parent = NULL); + ~QmitkAnimationItemDelegate(); + + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationWidget.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationWidget.cpp new file mode 100644 index 0000000000..45c861d9ab --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationWidget.cpp @@ -0,0 +1,26 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkAnimationWidget.h" + +QmitkAnimationWidget::QmitkAnimationWidget(QWidget* parent) + : QWidget(parent) +{ +} + +QmitkAnimationWidget::~QmitkAnimationWidget() +{ +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationWidget.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationWidget.h new file mode 100644 index 0000000000..103a7b5f6e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkAnimationWidget.h @@ -0,0 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkAnimationWidget_h +#define QmitkAnimationWidget_h + +#include + +class QmitkAnimationItem; + +class QmitkAnimationWidget : public QWidget +{ + Q_OBJECT + +public: + explicit QmitkAnimationWidget(QWidget* parent = NULL); + virtual ~QmitkAnimationWidget(); + + virtual void SetAnimationItem(QmitkAnimationItem* animationItem) = 0; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkFFmpegWriter.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkFFmpegWriter.cpp new file mode 100644 index 0000000000..ae332ba296 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkFFmpegWriter.cpp @@ -0,0 +1,176 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkFFmpegWriter.h" +#include +#include +#include + +QmitkFFmpegWriter::QmitkFFmpegWriter(QObject* parent) + : QObject(parent), + m_Process(new QProcess(this)), + m_Framerate(0), + m_IsRunning(false) +{ + this->connect(m_Process, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(OnProcessError(QProcess::ProcessError))); + + this->connect(m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(OnProcessFinished(int, QProcess::ExitStatus))); +} + +QmitkFFmpegWriter::~QmitkFFmpegWriter() +{ +} + +QString QmitkFFmpegWriter::GetFFmpegPath() const +{ + return m_FFmpegPath; +} + +void QmitkFFmpegWriter::SetFFmpegPath(const QString& path) +{ + m_FFmpegPath = path; +} + +QSize QmitkFFmpegWriter::GetSize() const +{ + return m_Size; +} + +void QmitkFFmpegWriter::SetSize(const QSize& size) +{ + m_Size = size; +} + +void QmitkFFmpegWriter::SetSize(int width, int height) +{ + m_Size = QSize(width, height); +} + +int QmitkFFmpegWriter::GetFramerate() const +{ + return m_Framerate; +} + +void QmitkFFmpegWriter::SetFramerate(int framerate) +{ + m_Framerate = framerate; +} + +QString QmitkFFmpegWriter::GetOutputPath() const +{ + return m_OutputPath; +} + +void QmitkFFmpegWriter::SetOutputPath(const QString& path) +{ + m_OutputPath = path; +} + +void QmitkFFmpegWriter::Start() +{ + if (m_FFmpegPath.isEmpty()) + mitkThrow() << "FFmpeg/Libav path is empty!"; + + if (m_Size.isNull()) + mitkThrow() << "Invalid video frame size!"; + + if (m_Framerate <= 0) + mitkThrow() << "Invalid framerate!"; + + if (m_OutputPath.isEmpty()) + mitkThrow() << "Output path is empty!"; + + m_Process->start(m_FFmpegPath, QStringList() + << "-y" + << "-f" << "rawvideo" + << "-pix_fmt" << "rgb24" + << "-s" << QString("%1x%2").arg(m_Size.width()).arg(m_Size.height()) + << "-r" << QString("%1").arg(m_Framerate) + << "-i" << "-" + << "-vf" << "vflip" + << "-pix_fmt" << "yuv420p" + << "-crf" << "18" + << m_OutputPath); + + m_Process->waitForStarted(); + m_IsRunning = true; +} + +bool QmitkFFmpegWriter::IsRunning() const +{ + return m_IsRunning; +} + +void QmitkFFmpegWriter::WriteFrame(const unsigned char* frame) +{ + if (frame == NULL || !m_Process->isOpen()) + return; + + m_Process->write(reinterpret_cast(frame), m_Size.width() * m_Size.height() * 3); + m_Process->waitForBytesWritten(); +} + +void QmitkFFmpegWriter::Stop() +{ + m_IsRunning = false; + m_Process->closeWriteChannel(); +} + +void QmitkFFmpegWriter::OnProcessError(QProcess::ProcessError error) +{ + m_IsRunning = false; + + MITK_ERROR << QString::fromLatin1(m_Process->readAllStandardError()).toStdString(); + + switch (error) + { + case QProcess::FailedToStart: + mitkThrow() << "FFmpeg/Libav failed to start!"; + + case QProcess::Crashed: + mitkThrow() << "FFmpeg/Libav crashed!"; + + case QProcess::Timedout: + mitkThrow() << "FFmpeg/Libav timed out!"; + + case QProcess::WriteError: + mitkThrow() << "Could not write to FFmpeg/Libav!"; + + case QProcess::ReadError: + mitkThrow() << "Could not read from FFmpeg/Libav!"; + + default: + mitkThrow() << "An unknown error occurred!"; + } +} + +void QmitkFFmpegWriter::OnProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + m_IsRunning = false; + + if (exitStatus != QProcess::CrashExit) + { + if (exitCode != 0) + { + m_Process->close(); + mitkThrow() << QString("FFmpeg/Libav exit code: %1").arg(exitCode).toStdString().c_str(); + } + } + + m_Process->close(); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkFFmpegWriter.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkFFmpegWriter.h new file mode 100644 index 0000000000..5527edb538 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkFFmpegWriter.h @@ -0,0 +1,62 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkFFmpegWriter_h +#define QmitkFFmpegWriter_h + +#include +#include + +class QmitkFFmpegWriter : public QObject +{ + Q_OBJECT + +public: + explicit QmitkFFmpegWriter(QObject* parent = NULL); + ~QmitkFFmpegWriter(); + + QString GetFFmpegPath() const; + void SetFFmpegPath(const QString& path); + + QSize GetSize() const; + void SetSize(const QSize& size); + void SetSize(int width, int height); + + int GetFramerate() const; + void SetFramerate(int framerate); + + QString GetOutputPath() const; + void SetOutputPath(const QString& path); + + void Start(); + bool IsRunning() const; + void WriteFrame(const unsigned char* frame); + void Stop(); + +private slots: + void OnProcessError(QProcess::ProcessError error); + void OnProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + +private: + QProcess* m_Process; + QString m_FFmpegPath; + QSize m_Size; + int m_Framerate; + QString m_OutputPath; + bool m_IsRunning; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMaker.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMaker.cpp deleted file mode 100644 index b11ea9e52c..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMaker.cpp +++ /dev/null @@ -1,769 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#include "QmitkMovieMaker.h" -//#include "QmitkMovieMakerControls.h" -#include "QmitkStepperAdapter.h" -#include "QmitkStdMultiWidget.h" -#include "QmitkMovieMaker.h" -//#include "QmitkMovieMakerControls.h" -#include "QmitkStepperAdapter.h" -#include "QmitkStdMultiWidget.h" - -#include "mitkVtkPropRenderer.h" -#include "mitkGlobalInteraction.h" - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "qapplication.h" - -#include "vtkImageWriter.h" -#include "vtkJPEGWriter.h" -#include "vtkPNGWriter.h" -#include "vtkRenderLargeImage.h" -#include "vtkRenderWindowInteractor.h" -#include "vtkRenderer.h" -#include "vtkTestUtilities.h" - -#include -#include "vtkMitkRenderProp.h" - -#include -#include -#include "vtkRenderWindowInteractor.h" -#include - -QmitkMovieMaker::QmitkMovieMaker(QObject *parent, const char * /*name*/) - -: - QmitkFunctionality(), m_Controls(NULL), - m_StepperAdapter(NULL), - m_FocusManagerCallback(0), m_Looping(true), m_Direction(0), m_Aspect(0) -{ - - parentWidget = parent; - - m_Timer = new QTimer(this); - m_Time = new QTime(); - - m_FocusManagerCallback = MemberCommand::New(); - m_FocusManagerCallback->SetCallbackFunction(this, &QmitkMovieMaker::FocusChange); - - m_movieGenerator = mitk::MovieGenerator::New(); - - if (m_movieGenerator.IsNull()) - { - MITK_ERROR << "Either mitk::MovieGenerator is not implemented for your"; - MITK_ERROR << " platform or an error occurred during"; - MITK_ERROR << " mitk::MovieGenerator::New()" ; - } - -} - -QmitkMovieMaker::~QmitkMovieMaker() -{ - delete m_StepperAdapter; - delete m_Timer; - delete m_Time; - //delete m_RecordingRenderer; - -} - -mitk::BaseController* QmitkMovieMaker::GetSpatialController() -{ - mitk::BaseRenderer* focusedRenderer = mitk::GlobalInteraction::GetInstance()->GetFocus(); - - if (mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget1->GetRenderWindow()) - == focusedRenderer) - { - return GetActiveStdMultiWidget()->mitkWidget1->GetController(); - } - else if (mitk::BaseRenderer::GetInstance( - GetActiveStdMultiWidget()->mitkWidget2->GetRenderWindow()) == focusedRenderer) - { - return GetActiveStdMultiWidget()->mitkWidget2->GetController(); - } - else if (mitk::BaseRenderer::GetInstance( - GetActiveStdMultiWidget()->mitkWidget3->GetRenderWindow()) == focusedRenderer) - { - return GetActiveStdMultiWidget()->mitkWidget3->GetController(); - } - else if (mitk::BaseRenderer::GetInstance( - GetActiveStdMultiWidget()->mitkWidget4->GetRenderWindow()) == focusedRenderer) - { - return GetActiveStdMultiWidget()->mitkWidget4->GetController(); - } - - return GetActiveStdMultiWidget()->mitkWidget4->GetController(); -} - -mitk::BaseController* QmitkMovieMaker::GetTemporalController() -{ - return GetActiveStdMultiWidget()->GetTimeNavigationController(); -} - -void QmitkMovieMaker::CreateConnections() -{ - if (m_Controls) - { - // start / pause / stop playing - connect((QObject*) m_Controls->btnPlay, SIGNAL(clicked()), (QObject*) this, - SLOT(StartPlaying())); - connect((QObject*) m_Controls->btnPause, SIGNAL(clicked()), this, SLOT(PausePlaying())); - connect((QObject*) m_Controls->btnStop, SIGNAL(clicked()), this, SLOT(StopPlaying())); - - connect((QObject*) m_Controls->rbtnForward, SIGNAL(clicked()), this, SLOT(RBTNForward())); - connect((QObject*) m_Controls->rbtnBackward, SIGNAL(clicked()), this, SLOT(RBTNBackward())); - connect((QObject*) m_Controls->rbtnPingPong, SIGNAL(clicked()), this, SLOT(RBTNPingPong())); - - // radio button group: forward, backward, ping-pong - connect( this, SIGNAL(SwitchDirection(int)), this, SLOT(SetDirection(int)) ); - - // radio button group: spatial, temporal - connect((QObject*) m_Controls->rbtnSpatial, SIGNAL(clicked()), this, SLOT(RBTNSpatial())); - connect((QObject*) m_Controls->rbtnTemporal, SIGNAL(clicked()), this, SLOT(RBTNTemporal())); - connect((QObject*) m_Controls->rbtnCombined, SIGNAL(clicked()), this, SLOT(RBTNCombined())); - connect( this, SIGNAL(SwitchAspect(int)), this, SLOT(SetAspect(int)) ); - - // stepper window selection - connect((QObject*) (m_Controls->cmbSelectedStepperWindow), SIGNAL ( activated ( int) ), (QObject*) this, SLOT ( SetStepperWindow (int) ) ); - - // recording window selection - connect((QObject*) (m_Controls->cmbSelectedRecordingWindow), SIGNAL ( activated ( int) ), (QObject*) this, SLOT ( SetRecordingWindow (int) ) ); - - // advance the animation - // every timer tick - connect((QObject*) m_Timer, SIGNAL(timeout()), this, SLOT(AdvanceAnimation())); - - // movie generation - // when the movie button is clicked - connect((QObject*) m_Controls->btnMovie, SIGNAL(clicked()), this, SLOT(GenerateMovie())); - - connect((QObject*) m_Controls->btnScreenshot, SIGNAL(clicked()), this, SLOT( - GenerateScreenshot())); - connect((QObject*) m_Controls->m_HRScreenshot, SIGNAL(clicked()), this, SLOT( - GenerateHR3DScreenshot())); - - // blocking of ui elements during movie generation - connect((QObject*) this, SIGNAL(StartBlockControls()), (QObject*) this, SLOT(BlockControls())); - - connect((QObject*) this, SIGNAL(EndBlockControls()), (QObject*) this, SLOT(UnBlockControls())); - - connect((QObject*) this, SIGNAL(EndBlockControlsMovieDeactive()), (QObject*) this, SLOT( - UnBlockControlsMovieDeactive())); - - // allow for change of spatialtime relation - connect((QObject*) m_Controls->spatialTimeRelation, SIGNAL(valueChanged ( int ) ), this, SLOT( DeleteMStepper() ) ); - - - m_Controls->btnScreenshot->setVisible(false); - m_Controls->m_HRScreenshot->setVisible(false); - } -} - -void QmitkMovieMaker::Activated() -{ - QmitkFunctionality::Activated(); - - // create a member command that will be executed from the observer - itk::SimpleMemberCommand::Pointer stepperChangedCommand; - stepperChangedCommand = itk::SimpleMemberCommand::New(); - // set the callback function of the member command - stepperChangedCommand->SetCallbackFunction(this, &QmitkMovieMaker::UpdateGUI); - // add an observer to the data tree node pointer connected to the above member command - MITK_INFO << "Add observer on insertion point node in NavigationPathController::AddObservers"; - m_StepperObserverTag = this->GetTemporalController()->GetTime()->AddObserver( - itk::ModifiedEvent(), stepperChangedCommand); - - m_FocusManagerObserverTag - = mitk::GlobalInteraction::GetInstance()->GetFocusManager()->AddObserver(mitk::FocusEvent(), - m_FocusManagerCallback); - this->UpdateGUI(); - // Initialize steppers etc. - this->FocusChange(); -} - -void QmitkMovieMaker::Deactivated() -{ - QmitkFunctionality::Deactivated(); - this->GetTemporalController()->GetTime()->RemoveObserver(m_StepperObserverTag); - mitk::GlobalInteraction::GetInstance()->GetFocusManager()->RemoveObserver( - m_FocusManagerObserverTag); // remove (if tag is invalid, nothing is removed) -} - -void QmitkMovieMaker::FocusChange() -{ - mitk::Stepper *stepper = this->GetAspectStepper(); - m_StepperAdapter->SetStepper(stepper); - - // Make the stepper movement non-inverted - stepper->InverseDirectionOff(); - - // Set stepping direction and aspect (spatial / temporal) for new stepper - this->UpdateLooping(); - this->UpdateDirection(); - - // Set newly focused window as active in "Selected Window" combo box - const mitk::RenderingManager::RenderWindowVector rwv = - mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); - - int i; - mitk::RenderingManager::RenderWindowVector::const_iterator iter; - for (iter = rwv.begin(), i = 0; iter != rwv.end(); ++iter, ++i) - { - mitk::BaseRenderer* focusedRenderer = - mitk::GlobalInteraction::GetInstance()->GetFocusManager()->GetFocused(); - - if (focusedRenderer == mitk::BaseRenderer::GetInstance((*iter))) - { - m_Controls->cmbSelectedStepperWindow->setCurrentIndex(i); - // this->cmbSelectedStepperWindow_activated(i); - this->SetStepperWindow(i); - m_Controls->cmbSelectedRecordingWindow->setCurrentIndex(i); - // this->cmbSelectedRecordWindow_activated(i); - this->SetRecordingWindow(i); - break; - } - } -} - -void QmitkMovieMaker::AdvanceAnimation() -{ - // This method is called when a timer timeout occurs. It increases the - // stepper value according to the elapsed time and the stepper interval. - // Note that a screen refresh is not forced, but merely requested, and may - // occur only after more calls to AdvanceAnimation(). - - mitk::Stepper* stepper = this->GetAspectStepper(); - - m_StepperAdapter->SetStepper(stepper); - - int elapsedTime = m_Time->elapsed(); - m_Time->restart(); - - static double increment = 0.0; - increment = increment - static_cast (increment); - increment += elapsedTime * stepper->GetSteps() / (m_Controls->spnDuration->value() * 1000.0); - - int i, n = static_cast (increment); - for (i = 0; i < n; ++i) - { - stepper->Next(); - } -} - -void QmitkMovieMaker::RenderSlot() -{ - int *i = widget->GetRenderWindow()->GetSize(); - m_PropRenderer->Resize(i[0], i[1]); - - widget->GetRenderWindow()->Render(); -} - -void QmitkMovieMaker::PausePlaying() -{ - - m_Controls->slidAngle->setDisabled(false); - m_Controls->btnMovie->setEnabled(true); - m_Controls->btnPlay->setEnabled(true); - m_Controls->btnScreenshot->setEnabled(true); - - m_Timer->stop(); - - m_Controls->btnPlay->setHidden(false); - m_Controls->btnPause->setHidden(true); - if (m_movieGenerator.IsNull()) - m_Controls->btnMovie->setEnabled(false); -} - -void QmitkMovieMaker::StopPlaying() -{ - m_Controls->slidAngle->setDisabled(false); - m_Controls->btnMovie->setEnabled(true); - m_Controls->btnPlay->setEnabled(true); - m_Controls->btnScreenshot->setEnabled(true); - - m_Controls->btnPlay->setHidden(false); - m_Controls->btnPause->setHidden(true); - - m_Timer->stop(); - switch (m_Direction) - { - case 0: - case 2: - this->GetAspectStepper()->First(); - break; - - case 1: - this->GetAspectStepper()->Last(); - break; - } - - // Reposition slider GUI element - m_StepperAdapter->SetStepper(this->GetAspectStepper()); - - if (m_movieGenerator.IsNull()) - m_Controls->btnMovie->setEnabled(false); - -} - -void QmitkMovieMaker::SetLooping(bool looping) -{ - m_Looping = looping; - this->UpdateLooping(); -} - -void QmitkMovieMaker::SetDirection(int direction) -{ - m_Direction = direction; - this->UpdateDirection(); -} - -void QmitkMovieMaker::SetAspect(int aspect) -{ - m_Aspect = aspect; - - m_StepperAdapter->SetStepper(this->GetAspectStepper()); - this->UpdateLooping(); - this->UpdateDirection(); -} - -void QmitkMovieMaker::SetStepperWindow(int window) -{ - // Set newly selected window / renderer as focused - const mitk::RenderingManager::RenderWindowVector rwv = - mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); - - //Delete MultiStepper - DeleteMStepper(); - - int i; - mitk::RenderingManager::RenderWindowVector::const_iterator iter; - for (iter = rwv.begin(), i = 0; iter != rwv.end(); ++iter, ++i) - { - if (i == window) - { - mitk::GlobalInteraction::GetInstance()->GetFocusManager() ->SetFocused( - mitk::BaseRenderer::GetInstance((*iter))); - break; - } - } -} - -void QmitkMovieMaker::SetRecordingWindow(int window) -{ - // Set newly selected window for recording - const mitk::RenderingManager::RenderWindowVector rwv = - mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); - - //Delete MultiStepper - DeleteMStepper(); - - int i; - mitk::RenderingManager::RenderWindowVector::const_iterator iter; - for (iter = rwv.begin(), i = 0; iter != rwv.end(); ++iter, ++i) - { - if (i == window) - { - m_RecordingRenderer = mitk::BaseRenderer::GetInstance((*iter)); - break; - } - } -} - -void QmitkMovieMaker::UpdateLooping() -{ - this->GetAspectStepper()->SetAutoRepeat(m_Looping); -} - -void QmitkMovieMaker::UpdateDirection() -{ - mitk::Stepper* stepper = this->GetAspectStepper(); - - switch (m_Direction) - { - case 0: - stepper->InverseDirectionOff(); - stepper->PingPongOff(); - break; - - case 1: - stepper->InverseDirectionOn(); - stepper->PingPongOff(); - break; - - case 2: - stepper->PingPongOn(); - break; - } -} - -mitk::Stepper* QmitkMovieMaker::GetAspectStepper() -{ - if (m_Aspect == 0) - { - m_Stepper = NULL; - return this->GetSpatialController()->GetSlice(); - } - else if (m_Aspect == 1) - { - m_Stepper = NULL; - return this->GetTemporalController()->GetTime(); - } - else if (m_Aspect == 2) - { - if (m_Stepper.IsNull()) - { - int rel = m_Controls->spatialTimeRelation->value(); - int timeRepeat = 1; - int sliceRepeat = 1; - if (rel < 0) - { - sliceRepeat = -rel; - } - else if (rel > 0) - { - timeRepeat = rel; - } - m_Stepper = mitk::MultiStepper::New(); - m_Stepper->AddStepper(this->GetSpatialController()->GetSlice(), sliceRepeat); - m_Stepper->AddStepper(this->GetTemporalController()->GetTime(), timeRepeat); - } - - return m_Stepper.GetPointer(); - } - else - { - // should never get here - return 0; - } -} - -void QmitkMovieMaker::GenerateMovie() -{ - emit StartBlockControls(); - - // provide the movie generator with the stepper and rotate the camera each step - if (m_movieGenerator.IsNotNull()) - { - m_movieGenerator->SetStepper(this->GetAspectStepper()); - m_movieGenerator->SetRenderer(m_RecordingRenderer); - m_movieGenerator->SetFrameRate(static_cast (360 - / (m_Controls->spnDuration->value()))); - - // QString movieFileName = QFileDialog::getSaveFileName( QString::null, "Movie (*.avi)", 0, "movie file dialog", "Choose a file name" ); - - QString movieFileName = QFileDialog::getSaveFileName(0, "Choose a file name", QString::null, - "Movie (*.avi)", 0, 0); - - if (movieFileName.isEmpty() == false) - { - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - m_movieGenerator->SetFileName(movieFileName.toLatin1()); - m_movieGenerator->WriteMovie(); - } - - emit EndBlockControls(); - } - else - { - MITK_ERROR << "Either mitk::MovieGenerator is not implemented for your"; - MITK_ERROR << " platform or an error occurred during"; - MITK_ERROR << " mitk::MovieGenerator::New()"; - - emit EndBlockControlsMovieDeactive(); - } -} - -void QmitkMovieMaker::GenerateScreenshot() -{ - emit StartBlockControls(); - - QString fileName = QFileDialog::getSaveFileName(NULL, "Save screenshot to...", QDir::currentPath(), "JPEG file (*.jpg);;PNG file (*.png)"); - - vtkRenderer* renderer = mitk::GlobalInteraction::GetInstance()->GetFocus()->GetVtkRenderer(); - if (renderer == NULL) - return; - this->TakeScreenshot(renderer, 1, fileName); - - if (m_movieGenerator.IsNotNull()) - emit EndBlockControls(); - else - emit EndBlockControlsMovieDeactive(); -} - -void QmitkMovieMaker::GenerateHR3DScreenshot() -{ - emit StartBlockControls(); - - QString fileName = QFileDialog::getSaveFileName(NULL, "Save screenshot to...", QDir::currentPath(), "JPEG file (*.jpg);;PNG file (*.png)"); - - // only works correctly for 3D RenderWindow - vtkRenderer* renderer = m_MultiWidget->mitkWidget4->GetRenderer()->GetVtkRenderer(); - if (renderer == NULL) - return; - this->TakeScreenshot(renderer, 4, fileName); - - if (m_movieGenerator.IsNotNull()) - emit EndBlockControls(); - else - emit EndBlockControlsMovieDeactive(); -} - -void QmitkMovieMaker::UpdateGUI() -{ - int bla = this->GetTemporalController()->GetTime()->GetSteps(); - if (bla < 2) - { - m_Controls->rbtnTemporal->setEnabled(false); - m_Controls->rbtnCombined->setEnabled(false); - m_Controls->spatialTimeRelation->setEnabled(false); - } - else - { - m_Controls->rbtnTemporal->setEnabled(true); - m_Controls->rbtnCombined->setEnabled(true); - m_Controls->spatialTimeRelation->setEnabled(true); - } - -} - -void QmitkMovieMaker::DataStorageChanged() -{ - // UpdateGUI(); -} - -void QmitkMovieMaker::CreateQtPartControl(QWidget *parent) -{ - if (!m_Controls) - { - m_Controls = new Ui::QmitkMovieMakerControls; - m_Controls->setupUi(parent); - - m_StepperAdapter = new QmitkStepperAdapter((QObject*) m_Controls->slidAngle, - this->GetSpatialController()->GetSlice(), "AngleStepperToMovieMakerFunctionality"); - - // Initialize "Selected Window" combo box - const mitk::RenderingManager::RenderWindowVector rwv = - mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); - - mitk::RenderingManager::RenderWindowVector::const_iterator iter; - unsigned int i = 0; - for (iter = rwv.begin(); iter != rwv.end(); ++iter) - { - QString name(mitk::BaseRenderer::GetInstance((*iter))->GetName()); - if (name=="stdmulti.widget1") - { - m_Controls->cmbSelectedStepperWindow->insertItem(i, "Axial"); - m_Controls->cmbSelectedRecordingWindow->insertItem(i++, "Axial"); - } - else if (name=="stdmulti.widget2") - { - m_Controls->cmbSelectedStepperWindow->insertItem(i, "Sagittal"); - m_Controls->cmbSelectedRecordingWindow->insertItem(i++, "Sagittal"); - } - else if (name=="stdmulti.widget3") - { - m_Controls->cmbSelectedStepperWindow->insertItem(i, "Coronal"); - m_Controls->cmbSelectedRecordingWindow->insertItem(i++, "Coronal"); - } - else if (name=="stdmulti.widget4") - { - m_Controls->cmbSelectedStepperWindow->insertItem(i, "3D Window"); - m_Controls->cmbSelectedRecordingWindow->insertItem(i++, "3D Window"); - } - else - { - m_Controls->cmbSelectedStepperWindow->insertItem(i, name); - m_Controls->cmbSelectedRecordingWindow->insertItem(i++, name); - } - } - - m_Controls->btnPause->setHidden(true); - if (m_movieGenerator.IsNull()) - m_Controls->btnMovie->setEnabled(false); - } - - this->CreateConnections(); - -} - -void QmitkMovieMaker::StartPlaying() -{ - m_Controls->slidAngle->setDisabled(true); - m_Controls->btnMovie->setEnabled(false); - m_Controls->btnPlay->setEnabled(false); - m_Controls->btnScreenshot->setEnabled(false); - - // Restart timer with 5 msec interval - this should be fine-grained enough - // even for high display refresh frequencies - m_Timer->start(5); - - m_Time->restart(); - - m_Controls->btnPlay->setHidden(true); - m_Controls->btnPause->setHidden(false); - if (m_movieGenerator.IsNull()) - m_Controls->btnMovie->setEnabled(false); - -} - -void QmitkMovieMaker::RBTNForward() -{ - emit SwitchDirection(0); -} - -void QmitkMovieMaker::RBTNBackward() -{ - emit SwitchDirection(1); -} - -void QmitkMovieMaker::RBTNPingPong() -{ - emit SwitchDirection(2); -} - -void QmitkMovieMaker::RBTNSpatial() -{ - emit SwitchAspect(0); -} - -void QmitkMovieMaker::RBTNTemporal() -{ - emit SwitchAspect(1); -} - -void QmitkMovieMaker::RBTNCombined() -{ - emit SwitchAspect(2); -} - -void QmitkMovieMaker::BlockControls() -{ - BlockControls(true); -} - -void QmitkMovieMaker::UnBlockControls() -{ - BlockControls(false); -} - -void QmitkMovieMaker::UnBlockControlsMovieDeactive() -{ - BlockControls(false); - - m_Controls->btnMovie->setEnabled(false); -} - -void QmitkMovieMaker::BlockControls(bool blocked) -{ - m_Controls->slidAngle->setDisabled(blocked); - m_Controls->spnDuration->setEnabled(!blocked); - m_Controls->btnPlay->setEnabled(!blocked); - m_Controls->btnMovie->setEnabled(!blocked); - m_Controls->btnScreenshot->setEnabled(!blocked); -} - -void QmitkMovieMaker::StdMultiWidgetAvailable(QmitkStdMultiWidget& stdMultiWidget) -{ - m_MultiWidget = &stdMultiWidget; - m_Parent->setEnabled(true); -} - -void QmitkMovieMaker::StdMultiWidgetNotAvailable() -{ - m_MultiWidget = NULL; - m_Parent->setEnabled(false); -} - -void QmitkMovieMaker::TakeScreenshot(vtkRenderer* renderer, unsigned int magnificationFactor, QString fileName) -{ - if ((renderer == NULL) ||(magnificationFactor < 1) || fileName.isEmpty()) - return; - - bool doubleBuffering( renderer->GetRenderWindow()->GetDoubleBuffer() ); - renderer->GetRenderWindow()->DoubleBufferOff(); - - vtkImageWriter* fileWriter; - - QFileInfo fi(fileName); - QString suffix = fi.suffix(); - if (suffix.compare("png", Qt::CaseInsensitive) == 0) - { - fileWriter = vtkPNGWriter::New(); - } - else // default is jpeg - { - vtkJPEGWriter* w = vtkJPEGWriter::New(); - w->SetQuality(100); - w->ProgressiveOff(); - fileWriter = w; - } - vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New(); - magnifier->SetInput(renderer); - magnifier->SetMagnification(magnificationFactor); - //magnifier->Update(); - fileWriter->SetInputConnection(magnifier->GetOutputPort()); - fileWriter->SetFileName(fileName.toLatin1()); - - // vtkRenderLargeImage has problems with different layers, therefore we have to - // temporarily deactivate all other layers. - // we set the background to white, because it is nicer than black... - double oldBackground[3]; - renderer->GetBackground(oldBackground); - double white[] = {1.0, 1.0, 1.0}; - renderer->SetBackground(white); - m_MultiWidget->DisableColoredRectangles(); - m_MultiWidget->DisableDepartmentLogo(); - m_MultiWidget->DisableGradientBackground(); - - m_MultiWidget->mitkWidget1->ActivateMenuWidget( false ); - m_MultiWidget->mitkWidget2->ActivateMenuWidget( false ); - m_MultiWidget->mitkWidget3->ActivateMenuWidget( false ); - m_MultiWidget->mitkWidget4->ActivateMenuWidget( false ); - - fileWriter->Write(); - fileWriter->Delete(); - - m_MultiWidget->mitkWidget1->ActivateMenuWidget( true ); - m_MultiWidget->mitkWidget2->ActivateMenuWidget( true ); - m_MultiWidget->mitkWidget3->ActivateMenuWidget( true ); - m_MultiWidget->mitkWidget4->ActivateMenuWidget( true ); - - m_MultiWidget->EnableColoredRectangles(); - m_MultiWidget->EnableDepartmentLogo(); - m_MultiWidget->EnableGradientBackground(); - renderer->SetBackground(oldBackground); - - renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); -} - -void QmitkMovieMaker::DeleteMStepper() -{ - m_Stepper = NULL; - UpdateLooping(); -} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMaker.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMaker.h deleted file mode 100644 index ea91684197..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMaker.h +++ /dev/null @@ -1,300 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#if !defined(QMITK_MOVIEMAKER_H__INCLUDED) -#define QMITK_MOVIEMAKER_H__INCLUDED - -#include "QmitkFunctionality.h" -#include "mitkCameraRotationController.h" -#include "mitkStepper.h" -#include "mitkMultiStepper.h" -#include "mitkMovieGenerator.h" -#include "itkCommand.h" - -#include "QVTKWidget.h" -#include "vtkEventQtSlotConnect.h" -#include "vtkRenderWindow.h" -#include "mitkVtkPropRenderer.h" - -#include "ui_QmitkMovieMakerControls.h" -//#include "../MovieMakerDll.h" - -//class QmitkStdMultiWidget; -//class QmitkMovieMakerControls; -class QmitkStepperAdapter; -class vtkCamera; -class QTimer; -class QTime; - -/** - * \brief Functionality for creating movies (AVIs) - * \ingroup Functionalities - * - * - * - \ref QmitkMovieMakerOverview - * - \ref QmitkMovieMakerImplementation - * - \ref QmitkMovieMakerTodo - * - * \section QmitkMovieMakerOverview Overview - * - * The MovieMaker functionality extends existing modes of data visualization - * with animation capabilities. The animation aspect determines which - * aspect of a visualization gets animated. This aspect can be spatial - * (i.e. the camera position and orientation in a 3D view, or the selected - * slice in a 2D view), temporal (the time step in a time-based dataset), or - * something more sophisticated (for example, volume rendering transfer - * functions might be changed dynamically as part of an animation to produce - * interesting effects). Currently, the following animation modes are - * supported: - * - * - Rotation of the camera around the dataset (3D views) - * - Stepping through the dataset slice by slice (2D views) - * - Stepping through a time-based dataset (2D and 3D views) - * - * As can be seen in the screenshot below, the functionality provides cine - * controls to start, pause and stop the animation. The direction of the - * animation can be selected (forward, backward or ping-pong). The animation - * can be set to either the spatial or the temporal aspect, or to both - * aspects combined. The cycle time determines the duration of one animation - * loop. - * - * In a multi-view scenario, the animation is applied to the currently - * focussed view. Other views which display the same data may be affected as - * well. - * - * Animations can be written on disk; the corresponding button creates an - * animation consisting of one single loop and writes every animation frame - * into an AVI file. - * - * \image html QmitkMovieMakerGUI.png - * - * \section QmitkMovieMakerImplementation Implementation - * - * The following diagram provides an overview over the classes collaborating - * with QmitkMovieMaker. - * - * \image html QmitkMovieMakerClasses.png - * - * The respective roles of these classes are: - * - QmitkMovieMaker - * - Provides a class interface for configuring and controlling the - * animation - * - Is associated with the user interface - * - As a Functionality, controls initialization and maintainance of the - * involved components - * - mitk::BaseController - * - Controls an animation aspect (slice selection, camera angle, ...) - * - Subclass mitk::SliceNavigationController: Transfers the animation - * requests to the associated Renderer for selecting a slice in a 3D - * dataset - * - Subclass mitk::CameraRotationController: Modifies the camera angle - * - mitk::Stepper - * - Link between MovieMaker and Controller - * - Holds the current step position of the associated animation aspect - * (e.g. the camera rotation angle, or the slice number) - * - mitk::FocusManager - * - Determines which of the available RenderWindows (and thereby which - * Renderers) the animation shall be applied to - * - mitk::BaseRenderer - * - Controls the rendering of a dataset - * - Target class of the animation - * - mitk::MovieGenerator - * - Writes an AVI file - * - * - * \section QmitkMovieMakerTodo Future plans - * - * The basic animation capabilities of this functionality could be extended - * to allow the creation of more sophisticated animations. Potentially useful - * features include: - * - * - Camera paths: Allow the definition of complex camera paths along - * which the camera can then be moved during an animation. This might be - * done by defining camera keyframes between which camera movements are - * interpolated (as in standard 3D animation applications). Paths derived - * from anatomical features (e.g. vessel graphs) could also serve as a - * basis for camera movements. - * - Color / transfer function animation: Choosing suitable color - * and transfer functions is critical to the quality and benefit of volume - * rendering. Dynamically changing transfer functions could visually enrich - * an animation. One way of achieving this could be to define transfer - * function keyframes between which an animation interpolates. - * - */ -class QmitkMovieMaker: public QmitkFunctionality -{ - Q_OBJECT - -public: - /** \brief Constructor. */ - QmitkMovieMaker(QObject *parent=0, const char *name=0); - - /** \brief Destructor. */ - virtual ~QmitkMovieMaker(); - - /** \brief Method for creating the widget containing the application - * controls, like sliders, buttons etc. - */ - void CreateQtPartControl(QWidget *parent); - // virtual QWidget * CreateControlWidget(QWidget *parent); - - /** \brief Method for creating the connections of main and control widget. - */ - virtual void CreateConnections(); - - /** \brief Method for creating an QAction object, i.e. button & menu entry. - * @param parent the parent QWidget - */ - // virtual QAction * CreateAction(QActionGroup *parent); - - virtual void Activated(); - - virtual void Deactivated(); - - /** \brief Called when another window receives the focus. */ - void FocusChange(); - - virtual void DataStorageChanged(); - - /// - /// Called when a StdMultiWidget is available. - /// - virtual void StdMultiWidgetAvailable(QmitkStdMultiWidget& stdMultiWidget); - /// - /// Called when no StdMultiWidget is available. - /// - virtual void StdMultiWidgetNotAvailable(); - - signals: - void StartBlockControls(); - void EndBlockControls(); - void EndBlockControlsMovieDeactive(); - -public slots: - - /** \brief Start playing the animation by restarting the timer. */ - void StartPlaying(); - - /** \brief Pauses playing the animation by stopping the timer. */ - void PausePlaying(); - - /** \brief Stops playing the animation and resets the stepper. */ - void StopPlaying(); - - /** \brief Sets animation looping ON/OFF. */ - void SetLooping(bool looping); - - /** \brief Sets the direction: 0 = forward, 1 = backward, 2 = pingpong. */ - void SetDirection(int direction); - - /** \brief Sets the animation aspect: - * 0 = spatial, 1 = temporal, 2 = combined. - */ - void SetAspect(int aspect); - - /** \brief Sets a specified stepper window, which is moving. */ - void SetStepperWindow(int window); - - /** \brief Sets a specified recording window, from which the movie is generated. */ - void SetRecordingWindow(int window); - - /** \brief Advances the animation by one frame. - * Exactly how much the stepper advances depends on the time elapsed since - * the last call to this function. - */ - void AdvanceAnimation(); - -protected slots: - - void RenderSlot(); - void GenerateMovie(); - - void GenerateScreenshot(); - void GenerateHR3DScreenshot(); - void RBTNForward(); - void RBTNBackward(); - void RBTNPingPong(); - void RBTNSpatial(); - void RBTNTemporal(); - void RBTNCombined(); - void BlockControls(); - void UnBlockControls(); - void UnBlockControlsMovieDeactive(); - void BlockControls(bool blocked); - - void DeleteMStepper(); - - signals: - - void SwitchDirection(int); - void SwitchAspect(int); - void SwitchSelectedStepperWindow(int); - void SwitchSelectedRecordingWindow(int); - -protected: - - QObject *parentWidget; - QVTKWidget * widget; - QmitkStdMultiWidget* m_MultiWidget; - vtkEventQtSlotConnect * connections; - vtkRenderWindow * renderWindow; - mitk::VtkPropRenderer::Pointer m_PropRenderer; - - Ui::QmitkMovieMakerControls* m_Controls; - -private: - mitk::BaseController* GetSpatialController(); - - mitk::BaseController* GetTemporalController(); - - void UpdateLooping(); - - void UpdateDirection(); - - void UpdateGUI(); - - mitk::Stepper* GetAspectStepper(); - - /*! - \brief taking a screenshot "from" the specified renderer - \param magnificationFactor specifying the quality of the screenshot (the magnification of the actual RenderWindow size) - \param fileName file location and name where the screenshot should be saved - */ - void TakeScreenshot(vtkRenderer* renderer, unsigned int magnificationFactor, QString fileName); - - QmitkStepperAdapter* m_StepperAdapter; - - typedef itk::SimpleMemberCommand MemberCommand; - MemberCommand::Pointer m_FocusManagerCallback; - - QTimer* m_Timer; - - QTime* m_Time; - - bool m_Looping; - int m_Direction; - - int m_Aspect; - mitk::MultiStepper::Pointer m_Stepper; - mitk::BaseRenderer * m_RecordingRenderer; - - mitk::MovieGenerator::Pointer m_movieGenerator; - - unsigned long m_FocusManagerObserverTag; - unsigned long m_StepperObserverTag; - -}; -#endif // !defined(QMITK_MOVIEMAKER_H__INCLUDED) diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerControls.ui b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerControls.ui deleted file mode 100644 index 68dd4a6fa2..0000000000 --- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerControls.ui +++ /dev/null @@ -1,454 +0,0 @@ - - - QmitkMovieMakerControls - - - - 0 - 0 - 423 - 665 - - - - MovieMaker - - - - - - - 0 - 0 - - - - - 75 - true - - - - Window for stepping - - - false - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Window for recording - - - false - - - - - - - - 0 - 0 - - - - - - - - - 75 - true - - - - Recording options - - - - - - - - - 0 - 0 - - - - - - - Step - - - false - - - - - - - - - - - - - - - 0 - 0 - - - - - - - Start stepper - - - - - - - :/org.mitk.gui.qt.moviemaker/resources/play.xpm:/org.mitk.gui.qt.moviemaker/resources/play.xpm - - - - - - - - 0 - 0 - - - - - - - Pause stepper - - - - - - - :/org.mitk.gui.qt.moviemaker/resources/pause.xpm:/org.mitk.gui.qt.moviemaker/resources/pause.xpm - - - - - - - - 0 - 0 - - - - - - - Stop stepper - - - - - - - :/org.mitk.gui.qt.moviemaker/resources/stop.xpm:/org.mitk.gui.qt.moviemaker/resources/stop.xpm - - - - - - - - - - 0 - 0 - - - - - - - Write Movie (MS Windows only) ... - - - - - - - - 0 - 0 - - - - - - - Writes a screenshot of the selected window. - - - Write Screenshot - - - - - - - - 0 - 0 - - - - - - - Writes a screenshot of the selected window. - - - Write high resolution 3D Screenshot - - - - - - - - - - - 75 - true - - - - Playing options - - - - - - - - - - - - Spatial - - - true - - - - - - - - - - Temporal - - - - - - - - - - Combined - - - - - - - - - - - - S/T Relation - - - false - - - - - - - - - - -10 - - - 10 - - - 0 - - - - - - - - - - - - QFrame::HLine - - - QFrame::Sunken - - - - - - - - - - - - - Forward - - - true - - - - - - - - - - Backward - - - - - - - - - - Ping-Pong - - - - - - - - - - - - Cycle (sec) - - - false - - - - - - - - - - 1 - - - 200 - - - 5 - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 31 - - - - - - - - - - QmitkSliderNavigatorWidget - QWidget -
QmitkSliderNavigatorWidget.h
- 1 -
-
- - rbtnForward - rbtnBackward - rbtnPingPong - rbtnSpatial - rbtnTemporal - cmbSelectedStepperWindow - - - - - -
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp new file mode 100644 index 0000000000..2e6735528a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp @@ -0,0 +1,666 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkAnimationItemDelegate.h" +#include "QmitkFFmpegWriter.h" +#include "QmitkMovieMakerView.h" +#include "QmitkOrbitAnimationItem.h" +#include "QmitkOrbitAnimationWidget.h" +#include "QmitkSliceAnimationItem.h" +#include "QmitkSliceAnimationWidget.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static QmitkAnimationItem* CreateDefaultAnimation(const QString& widgetKey) +{ + if (widgetKey == "Orbit") + return new QmitkOrbitAnimationItem; + + if (widgetKey == "Slice") + return new QmitkSliceAnimationItem; + + return NULL; +} + +static QString GetFFmpegPath() +{ + berry::IPreferencesService::Pointer preferencesService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer preferences = preferencesService->GetSystemPreferences()->Node("/org.mitk.gui.qt.ext.externalprograms"); + + return QString::fromStdString(preferences->Get("ffmpeg", "")); +} + +static unsigned char* ReadPixels(vtkRenderWindow* renderWindow, int x, int y, int width, int height) +{ + if (renderWindow == NULL) + return NULL; + + unsigned char* frame = new unsigned char[width * height * 3]; + + renderWindow->MakeCurrent(); + glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, frame); + + return frame; +} + +const std::string QmitkMovieMakerView::VIEW_ID = "org.mitk.views.moviemaker"; + +QmitkMovieMakerView::QmitkMovieMakerView() + : m_FFmpegWriter(NULL), + m_Ui(new Ui::QmitkMovieMakerView), + m_AnimationModel(NULL), + m_AddAnimationMenu(NULL), + m_RecordMenu(NULL), + m_Timer(NULL), + m_TotalDuration(0.0), + m_NumFrames(0), + m_CurrentFrame(0) +{ +} + +QmitkMovieMakerView::~QmitkMovieMakerView() +{ +} + +void QmitkMovieMakerView::CreateQtPartControl(QWidget* parent) +{ + m_FFmpegWriter = new QmitkFFmpegWriter(parent); + + m_Ui->setupUi(parent); + + this->InitializeAnimationWidgets(); + this->InitializeAnimationTreeViewWidgets(); + this->InitializePlaybackAndRecordWidgets(); + this->InitializeTimer(parent); + + m_Ui->animationWidgetGroupBox->setVisible(false); +} + +void QmitkMovieMakerView::InitializeAnimationWidgets() +{ + m_AnimationWidgets["Orbit"] = new QmitkOrbitAnimationWidget; + m_AnimationWidgets["Slice"] = new QmitkSliceAnimationWidget; + + Q_FOREACH(QWidget* widget, m_AnimationWidgets.values()) + { + if (widget != NULL) + { + widget->setVisible(false); + m_Ui->animationWidgetGroupBoxLayout->addWidget(widget); + } + } + + this->ConnectAnimationWidgets(); +} + +void QmitkMovieMakerView::InitializeAnimationTreeViewWidgets() +{ + this->InitializeAnimationModel(); + this->InitializeAddAnimationMenu(); + this->ConnectAnimationTreeViewWidgets(); +} + +void QmitkMovieMakerView::InitializePlaybackAndRecordWidgets() +{ + this->InitializeRecordMenu(); + this->ConnectPlaybackAndRecordWidgets(); +} + +void QmitkMovieMakerView::InitializeAnimationModel() +{ + m_AnimationModel = new QStandardItemModel(m_Ui->animationTreeView); + m_AnimationModel->setHorizontalHeaderLabels(QStringList() << "Animation" << "Timeline"); + m_Ui->animationTreeView->setModel(m_AnimationModel); + + m_Ui->animationTreeView->setItemDelegate(new QmitkAnimationItemDelegate(m_Ui->animationTreeView)); +} + +void QmitkMovieMakerView::InitializeAddAnimationMenu() +{ + m_AddAnimationMenu = new QMenu(m_Ui->addAnimationButton); + + Q_FOREACH(const QString& key, m_AnimationWidgets.keys()) + { + m_AddAnimationMenu->addAction(key); + } +} + +void QmitkMovieMakerView::InitializeRecordMenu() +{ + typedef QPair PairOfStrings; + + m_RecordMenu = new QMenu(m_Ui->recordButton); + + QVector renderWindows; + renderWindows.push_back(qMakePair(QString("Axial"), QString("stdmulti.widget1"))); + renderWindows.push_back(qMakePair(QString("Sagittal"), QString("stdmulti.widget2"))); + renderWindows.push_back(qMakePair(QString("Coronal"), QString("stdmulti.widget3"))); + renderWindows.push_back(qMakePair(QString("3D"), QString("stdmulti.widget4"))); + + Q_FOREACH(const PairOfStrings& renderWindow, renderWindows) + { + QAction* action = new QAction(m_RecordMenu); + action->setText(renderWindow.first); + action->setData(renderWindow.second); + + m_RecordMenu->addAction(action); + } +} + +void QmitkMovieMakerView::InitializeTimer(QWidget* parent) +{ + m_Timer = new QTimer(parent); + + this->OnFPSSpinBoxValueChanged(m_Ui->fpsSpinBox->value()); + this->ConnectTimer(); +} + +void QmitkMovieMakerView::ConnectAnimationTreeViewWidgets() +{ + this->connect(m_AnimationModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), + this, SLOT(OnAnimationTreeViewRowsInserted(const QModelIndex&, int, int))); + + this->connect(m_AnimationModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), + this, SLOT(OnAnimationTreeViewRowsRemoved(const QModelIndex&, int, int))); + + this->connect(m_Ui->animationTreeView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT(OnAnimationTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&))); + + this->connect(m_Ui->moveAnimationUpButton, SIGNAL(clicked()), + this, SLOT(OnMoveAnimationUpButtonClicked())); + + this->connect(m_Ui->moveAnimationDownButton, SIGNAL(clicked()), + this, SLOT(OnMoveAnimationDownButtonClicked())); + + this->connect(m_Ui->addAnimationButton, SIGNAL(clicked()), + this, SLOT(OnAddAnimationButtonClicked())); + + this->connect(m_Ui->removeAnimationButton, SIGNAL(clicked()), + this, SLOT(OnRemoveAnimationButtonClicked())); +} + +void QmitkMovieMakerView::ConnectAnimationWidgets() +{ + this->connect(m_Ui->startComboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(OnStartComboBoxCurrentIndexChanged(int))); + + this->connect(m_Ui->durationSpinBox, SIGNAL(valueChanged(double)), + this, SLOT(OnDurationSpinBoxValueChanged(double))); + + this->connect(m_Ui->delaySpinBox, SIGNAL(valueChanged(double)), + this, SLOT(OnDelaySpinBoxValueChanged(double))); +} + +void QmitkMovieMakerView::ConnectPlaybackAndRecordWidgets() +{ + this->connect(m_Ui->playButton, SIGNAL(toggled(bool)), + this, SLOT(OnPlayButtonToggled(bool))); + + this->connect(m_Ui->stopButton, SIGNAL(clicked()), + this, SLOT(OnStopButtonClicked())); + + this->connect(m_Ui->recordButton, SIGNAL(clicked()), + this, SLOT(OnRecordButtonClicked())); + + this->connect(m_Ui->fpsSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(OnFPSSpinBoxValueChanged(int))); +} + +void QmitkMovieMakerView::ConnectTimer() +{ + this->connect(m_Timer, SIGNAL(timeout()), + this, SLOT(OnTimerTimeout())); +} + +void QmitkMovieMakerView::SetFocus() +{ + m_Ui->addAnimationButton->setFocus(); +} + +void QmitkMovieMakerView::OnMoveAnimationUpButtonClicked() +{ + const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); + + if (!selection.isEmpty()) + { + const int selectedRow = selection[0].top(); + + if (selectedRow > 0) + m_AnimationModel->insertRow(selectedRow - 1, m_AnimationModel->takeRow(selectedRow)); + } + + this->CalculateTotalDuration(); +} + +void QmitkMovieMakerView::OnMoveAnimationDownButtonClicked() +{ + const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); + + if (!selection.isEmpty()) + { + const int rowCount = m_AnimationModel->rowCount(); + const int selectedRow = selection[0].top(); + + if (selectedRow < rowCount - 1) + m_AnimationModel->insertRow(selectedRow + 1, m_AnimationModel->takeRow(selectedRow)); + } + + this->CalculateTotalDuration(); +} + +void QmitkMovieMakerView::OnAddAnimationButtonClicked() +{ + QAction* action = m_AddAnimationMenu->exec(QCursor::pos()); + + if (action != NULL) + { + const QString widgetKey = action->text(); + + m_AnimationModel->appendRow(QList() + << new QStandardItem(widgetKey) + << CreateDefaultAnimation(widgetKey)); + + m_Ui->playbackAndRecordingGroupBox->setEnabled(true); + } +} + +void QmitkMovieMakerView::OnPlayButtonToggled(bool checked) +{ + if (checked) + { + m_Ui->playButton->setIcon(QIcon(":/org_mitk_icons/icons/tango/scalable/actions/media-playback-pause.svg")); + m_Ui->playButton->repaint(); + + m_Timer->start(static_cast(1000.0 / m_Ui->fpsSpinBox->value())); + } + else + { + m_Timer->stop(); + + m_Ui->playButton->setIcon(QIcon(":/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg")); + m_Ui->playButton->repaint(); + } +} + +void QmitkMovieMakerView::OnStopButtonClicked() +{ + m_Ui->playButton->setChecked(false); + m_Ui->stopButton->setEnabled(false); + + m_CurrentFrame = 0; + this->RenderCurrentFrame(); +} + +void QmitkMovieMakerView::OnRecordButtonClicked() // TODO: Refactor +{ + const QString ffmpegPath = GetFFmpegPath(); + + if (ffmpegPath.isEmpty()) + { + QMessageBox::information(NULL, "Movie Maker", "Set path to FFmpeg or Libav (avconv) in preferences (Window -> Preferences... (Ctrl+P) -> External Programs) to be able to record your movies to video files."); + return; + } + + m_FFmpegWriter->SetFFmpegPath(GetFFmpegPath()); + + QAction* action = m_RecordMenu->exec(QCursor::pos()); + + if (action == NULL) + return; + + vtkRenderWindow* renderWindow = mitk::BaseRenderer::GetRenderWindowByName(action->data().toString().toStdString()); + + if (renderWindow == NULL) + return; + + const int border = 3; + const int x = border; + const int y = border; + int width = renderWindow->GetSize()[0] - border * 2; + int height = renderWindow->GetSize()[1] - border * 2; + + if (width & 1) + --width; + + if (height & 1) + --height; + + if (width < 16 || height < 16) + return; + + m_FFmpegWriter->SetSize(width, height); + m_FFmpegWriter->SetFramerate(m_Ui->fpsSpinBox->value()); + + QString saveFileName = QFileDialog::getSaveFileName(NULL, "Specify a filename", "", "Movie (*.mp4)"); + + if (saveFileName.isEmpty()) + return; + + if(!saveFileName.endsWith(".mp4")) + saveFileName += ".mp4"; + + m_FFmpegWriter->SetOutputPath(saveFileName); + + try + { + m_FFmpegWriter->Start(); + + for (m_CurrentFrame = 0; m_CurrentFrame < m_NumFrames; ++m_CurrentFrame) + { + this->RenderCurrentFrame(); + + renderWindow->MakeCurrent(); + unsigned char* frame = ReadPixels(renderWindow, x, y, width, height); + m_FFmpegWriter->WriteFrame(frame); + delete[] frame; + } + + m_FFmpegWriter->Stop(); + + m_CurrentFrame = 0; + this->RenderCurrentFrame(); + } + catch (const mitk::Exception& exception) + { + m_CurrentFrame = 0; + this->RenderCurrentFrame(); + + QMessageBox::critical(NULL, "Movie Maker", exception.GetDescription()); + } +} + +void QmitkMovieMakerView::OnRemoveAnimationButtonClicked() +{ + const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); + + if (!selection.isEmpty()) + m_AnimationModel->removeRow(selection[0].top()); +} + +void QmitkMovieMakerView::OnAnimationTreeViewRowsInserted(const QModelIndex& parent, int start, int) +{ + this->CalculateTotalDuration(); + + m_Ui->animationTreeView->selectionModel()->select( + m_AnimationModel->index(start, 0, parent), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); +} + +void QmitkMovieMakerView::OnAnimationTreeViewRowsRemoved(const QModelIndex&, int, int) +{ + this->CalculateTotalDuration(); + this->UpdateWidgets(); +} + +void QmitkMovieMakerView::OnAnimationTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&) +{ + this->UpdateWidgets(); +} + +void QmitkMovieMakerView::OnStartComboBoxCurrentIndexChanged(int index) +{ + QmitkAnimationItem* item = this->GetSelectedAnimationItem(); + + if (item != NULL) + { + item->SetStartWithPrevious(index); + this->RedrawTimeline(); + this->CalculateTotalDuration(); + } +} + +void QmitkMovieMakerView::OnDurationSpinBoxValueChanged(double value) +{ + QmitkAnimationItem* item = this->GetSelectedAnimationItem(); + + if (item != NULL) + { + item->SetDuration(value); + this->RedrawTimeline(); + this->CalculateTotalDuration(); + } +} + +void QmitkMovieMakerView::OnDelaySpinBoxValueChanged(double value) +{ + QmitkAnimationItem* item = this->GetSelectedAnimationItem(); + + if (item != NULL) + { + item->SetDelay(value); + this->RedrawTimeline(); + this->CalculateTotalDuration(); + } +} + +void QmitkMovieMakerView::OnFPSSpinBoxValueChanged(int value) +{ + this->CalculateTotalDuration(); + m_Timer->setInterval(static_cast(1000.0 / value)); +} + +void QmitkMovieMakerView::OnTimerTimeout() +{ + this->RenderCurrentFrame(); + + m_CurrentFrame = std::min(m_NumFrames, m_CurrentFrame + 1); + + if (m_CurrentFrame >= m_NumFrames) + { + m_Ui->playButton->setChecked(false); + + m_CurrentFrame = 0; + this->RenderCurrentFrame(); + } + + m_Ui->stopButton->setEnabled(m_CurrentFrame != 0); +} + +void QmitkMovieMakerView::RenderCurrentFrame() +{ + typedef QPair AnimationIterpolationFactorPair; + + const double deltaT = m_TotalDuration / (m_NumFrames - 1); + const QVector activeAnimations = this->GetActiveAnimations(m_CurrentFrame * deltaT); + + Q_FOREACH(const AnimationIterpolationFactorPair& animation, activeAnimations) + { + animation.first->Animate(animation.second); + } + + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); +} + +void QmitkMovieMakerView::UpdateWidgets() +{ + const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); + + if (selection.isEmpty()) + { + m_Ui->moveAnimationUpButton->setEnabled(false); + m_Ui->moveAnimationDownButton->setEnabled(false); + m_Ui->removeAnimationButton->setEnabled(false); + m_Ui->playbackAndRecordingGroupBox->setEnabled(false); + + this->HideCurrentAnimationWidget(); + } + else + { + const int rowCount = m_AnimationModel->rowCount(); + const int selectedRow = selection[0].top(); + + m_Ui->moveAnimationUpButton->setEnabled(rowCount > 1 && selectedRow != 0); + m_Ui->moveAnimationDownButton->setEnabled(rowCount > 1 && selectedRow < rowCount - 1); + m_Ui->removeAnimationButton->setEnabled(true); + m_Ui->playbackAndRecordingGroupBox->setEnabled(true); + + this->ShowAnimationWidget(dynamic_cast(m_AnimationModel->item(selectedRow, 1))); + } + + this->UpdateAnimationWidgets(); +} + +void QmitkMovieMakerView::UpdateAnimationWidgets() +{ + QmitkAnimationItem* item = this->GetSelectedAnimationItem(); + + if (item != NULL) + { + m_Ui->startComboBox->setCurrentIndex(item->GetStartWithPrevious()); + m_Ui->durationSpinBox->setValue(item->GetDuration()); + m_Ui->delaySpinBox->setValue(item->GetDelay()); + + m_Ui->animationGroupBox->setEnabled(true); + } + else + { + m_Ui->animationGroupBox->setEnabled(false); + } +} + +void QmitkMovieMakerView::HideCurrentAnimationWidget() +{ + if (m_Ui->animationWidgetGroupBox->isVisible()) + { + m_Ui->animationWidgetGroupBox->setVisible(false); + + int numWidgets = m_Ui->animationWidgetGroupBoxLayout->count(); + + for (int i = 0; i < numWidgets; ++i) + m_Ui->animationWidgetGroupBoxLayout->itemAt(i)->widget()->setVisible(false); + } +} + +void QmitkMovieMakerView::ShowAnimationWidget(QmitkAnimationItem* animationItem) +{ + this->HideCurrentAnimationWidget(); + + if (animationItem == NULL) + return; + + const QString widgetKey = animationItem->GetWidgetKey(); + QmitkAnimationWidget* animationWidget = NULL; + + if (m_AnimationWidgets.contains(widgetKey)) + { + animationWidget = m_AnimationWidgets[widgetKey]; + + if (animationWidget != NULL) + { + m_Ui->animationWidgetGroupBox->setTitle(widgetKey); + animationWidget->SetAnimationItem(animationItem); + animationWidget->setVisible(true); + } + } + + m_Ui->animationWidgetGroupBox->setVisible(animationWidget != NULL); +} + +void QmitkMovieMakerView::RedrawTimeline() +{ + if (m_AnimationModel->rowCount() > 1) + { + m_Ui->animationTreeView->dataChanged( + m_AnimationModel->index(0, 1), + m_AnimationModel->index(m_AnimationModel->rowCount() - 1, 1)); + } +} + +QmitkAnimationItem* QmitkMovieMakerView::GetSelectedAnimationItem() const +{ + const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); + + return !selection.isEmpty() + ? dynamic_cast(m_AnimationModel->item(selection[0].top(), 1)) + : NULL; +} + +void QmitkMovieMakerView::CalculateTotalDuration() +{ + const int rowCount = m_AnimationModel->rowCount(); + + double totalDuration = 0.0; + double previousStart = 0.0; + + for (int i = 0; i < rowCount; ++i) + { + QmitkAnimationItem* item = dynamic_cast(m_AnimationModel->item(i, 1)); + + if (item == NULL) + continue; + + if (item->GetStartWithPrevious()) + { + totalDuration = std::max(totalDuration, previousStart + item->GetDelay() + item->GetDuration()); + } + else + { + previousStart = totalDuration; + totalDuration += item->GetDelay() + item->GetDuration(); + } + } + + m_TotalDuration = totalDuration; // TODO totalDuration == 0 + m_NumFrames = static_cast(totalDuration * m_Ui->fpsSpinBox->value()); // TODO numFrames < 2 +} + +QVector > QmitkMovieMakerView::GetActiveAnimations(double t) const +{ + const int rowCount = m_AnimationModel->rowCount(); + + QVector > activeAnimations; + + double totalDuration = 0.0; + double previousStart = 0.0; + + for (int i = 0; i < rowCount; ++i) + { + QmitkAnimationItem* item = dynamic_cast(m_AnimationModel->item(i, 1)); + + if (item == NULL) + continue; + + if (item->GetDuration() > 0.0) + { + double start = item->GetStartWithPrevious() + ? previousStart + item->GetDelay() + : totalDuration + item->GetDelay(); + + if (start <= t && t <= start + item->GetDuration()) + activeAnimations.push_back(qMakePair(item, (t - start) / item->GetDuration())); + } + + if (item->GetStartWithPrevious()) + { + totalDuration = std::max(totalDuration, previousStart + item->GetDelay() + item->GetDuration()); + } + else + { + previousStart = totalDuration; + totalDuration += item->GetDelay() + item->GetDuration(); + } + } + + return activeAnimations; +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.h new file mode 100644 index 0000000000..f686ba79b9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.h @@ -0,0 +1,98 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkMovieMakerView_h +#define QmitkMovieMakerView_h + +#include + +class QmitkAnimationItem; +class QmitkAnimationWidget; +class QmitkFFmpegWriter; +class QMenu; +class QStandardItemModel; +class QTimer; + +namespace Ui +{ + class QmitkMovieMakerView; +} + +class QmitkMovieMakerView : public QmitkAbstractView +{ + Q_OBJECT + +public: + static const std::string VIEW_ID; + + QmitkMovieMakerView(); + ~QmitkMovieMakerView(); + + void CreateQtPartControl(QWidget* parent); + void SetFocus(); + +private slots: + void OnMoveAnimationUpButtonClicked(); + void OnMoveAnimationDownButtonClicked(); + void OnAddAnimationButtonClicked(); + void OnRemoveAnimationButtonClicked(); + void OnAnimationTreeViewRowsInserted(const QModelIndex& parent, int start, int end); + void OnAnimationTreeViewRowsRemoved(const QModelIndex& parent, int start, int end); + void OnAnimationTreeViewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); + void OnStartComboBoxCurrentIndexChanged(int index); + void OnDurationSpinBoxValueChanged(double value); + void OnDelaySpinBoxValueChanged(double value); + void OnPlayButtonToggled(bool checked); + void OnStopButtonClicked(); + void OnRecordButtonClicked(); + void OnFPSSpinBoxValueChanged(int value); + void OnTimerTimeout(); + +private: + void InitializeAnimationWidgets(); + void InitializeAnimationTreeViewWidgets(); + void InitializeAnimationModel(); + void InitializeAddAnimationMenu(); + void InitializePlaybackAndRecordWidgets(); + void InitializeRecordMenu(); + void InitializeTimer(QWidget* parent); + void ConnectAnimationTreeViewWidgets(); + void ConnectAnimationWidgets(); + void ConnectPlaybackAndRecordWidgets(); + void ConnectTimer(); + void RenderCurrentFrame(); + void UpdateWidgets(); + void UpdateAnimationWidgets(); + void HideCurrentAnimationWidget(); + void ShowAnimationWidget(QmitkAnimationItem* animationItem); + void RedrawTimeline(); + void CalculateTotalDuration(); + QmitkAnimationItem* GetSelectedAnimationItem() const; + QVector > GetActiveAnimations(double t) const; + + QmitkFFmpegWriter* m_FFmpegWriter; + Ui::QmitkMovieMakerView* m_Ui; + QStandardItemModel* m_AnimationModel; + QMap m_AnimationWidgets; + QMenu* m_AddAnimationMenu; + QMenu* m_RecordMenu; + QTimer* m_Timer; + double m_TotalDuration; + int m_NumFrames; + int m_CurrentFrame; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.ui b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.ui new file mode 100644 index 0000000000..ccbd70bb83 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.ui @@ -0,0 +1,507 @@ + + + QmitkMovieMakerView + + + true + + + + 0 + 0 + 320 + 640 + + + + Movie Maker + + + + + + + + false + + + Move animation up + + + + :/org_mitk_icons/icons/tango/scalable/actions/go-up.svg:/org_mitk_icons/icons/tango/scalable/actions/go-up.svg + + + + 24 + 24 + + + + true + + + + + + + false + + + Move animation down + + + + :/org_mitk_icons/icons/tango/scalable/actions/go-down.svg:/org_mitk_icons/icons/tango/scalable/actions/go-down.svg + + + + 24 + 24 + + + + true + + + + + + + Add animation + + + + :/org_mitk_icons/icons/tango/scalable/actions/list-add.svg:/org_mitk_icons/icons/tango/scalable/actions/list-add.svg + + + + 24 + 24 + + + + true + + + + + + + false + + + Remove animation + + + + :/org_mitk_icons/icons/tango/scalable/actions/list-remove.svg:/org_mitk_icons/icons/tango/scalable/actions/list-remove.svg + + + + 24 + 24 + + + + true + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + + + 16777215 + 100 + + + + false + + + true + + + 80 + + + + + + + + + false + + + Animation + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + + + + :/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg + + + true + + + + + + + + 0 + 0 + + + + Start: + + + startComboBox + + + + + + + + 0 + 0 + + + + + After previous + + + + + With previous + + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + + + + :/QmitkMovieMakerView/duration.svg + + + true + + + + + + + + 0 + 0 + + + + Duration: + + + durationSpinBox + + + + + + + + 0 + 0 + + + + s + + + 100.000000000000000 + + + 0.500000000000000 + + + 2.000000000000000 + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + + + + :/QmitkMovieMakerView/delay.svg + + + true + + + + + + + + 0 + 0 + + + + Delay: + + + delaySpinBox + + + + + + + + 0 + 0 + + + + s + + + 100.000000000000000 + + + 0.500000000000000 + + + + + + + + + + + + + + + false + + + Playback && Recording + + + + + + Play + + + + :/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg:/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg + + + + 24 + 24 + + + + true + + + true + + + + + + + false + + + Stop + + + + :/org_mitk_icons/icons/tango/scalable/actions/media-playback-stop.svg:/org_mitk_icons/icons/tango/scalable/actions/media-playback-stop.svg + + + + 24 + 24 + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Record + + + + :/org_mitk_icons/icons/tango/scalable/actions/media-record.svg:/org_mitk_icons/icons/tango/scalable/actions/media-record.svg + + + + 24 + 24 + + + + true + + + + + + + Frames per second + + + FPS + + + 1 + + + 120 + + + 30 + + + + + + + + + + Qt::Vertical + + + + 20 + 227 + + + + + + + + animationTreeView + moveAnimationUpButton + moveAnimationDownButton + addAnimationButton + removeAnimationButton + startComboBox + durationSpinBox + delaySpinBox + playButton + stopButton + recordButton + fpsSpinBox + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp new file mode 100644 index 0000000000..a65c898f31 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp @@ -0,0 +1,85 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkOrbitAnimationItem.h" +#include + +QmitkOrbitAnimationItem::QmitkOrbitAnimationItem(int startAngle, int orbit, bool reverse, double duration, double delay, bool startWithPrevious) + : QmitkAnimationItem("Orbit", duration, delay, startWithPrevious) +{ + this->SetStartAngle(startAngle); + this->SetOrbit(orbit); + this->SetReverse(reverse); +} + +QmitkOrbitAnimationItem::~QmitkOrbitAnimationItem() +{ +} + +int QmitkOrbitAnimationItem::GetStartAngle() const +{ + return this->data(StartAngleRole).toInt(); +} + +void QmitkOrbitAnimationItem::SetStartAngle(int angle) +{ + this->setData(angle, StartAngleRole); +} + +int QmitkOrbitAnimationItem::GetOrbit() const +{ + return this->data(OrbitRole).toInt(); +} + +void QmitkOrbitAnimationItem::SetOrbit(int angle) +{ + this->setData(angle, OrbitRole); +} + +bool QmitkOrbitAnimationItem::GetReverse() const +{ + return this->data(ReverseRole).toBool(); +} + +void QmitkOrbitAnimationItem::SetReverse(bool reverse) +{ + this->setData(reverse, ReverseRole); +} + +void QmitkOrbitAnimationItem::Animate(double s) +{ + vtkRenderWindow* renderWindow = mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"); + + if (renderWindow == NULL) + return; + + mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(renderWindow)->GetCameraRotationController()->GetSlice(); + + if (stepper == NULL) + return; + + int newPos = this->GetReverse() + ? this->GetStartAngle() - this->GetOrbit() * s + : this->GetStartAngle() + this->GetOrbit() * s; + + while (newPos < 0) + newPos += 360; + + while (newPos > 360) + newPos -= 360; + + stepper->SetPos(static_cast(newPos)); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.h new file mode 100644 index 0000000000..4198afba73 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.h @@ -0,0 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkOrbitAnimationItem_h +#define QmitkOrbitAnimationItem_h + +#include "QmitkAnimationItem.h" + +class QmitkOrbitAnimationItem : public QmitkAnimationItem +{ +public: + explicit QmitkOrbitAnimationItem(int startAngle = 180, int orbit = 360, bool reverse = false, double duration = 2.0, double delay = 0.0, bool startWithPrevious = false); + virtual ~QmitkOrbitAnimationItem(); + + int GetStartAngle() const; + void SetStartAngle(int angle); + + int GetOrbit() const; + void SetOrbit(int angle); + + bool GetReverse() const; + void SetReverse(bool reverse); + + void Animate(double s); +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.cpp new file mode 100644 index 0000000000..0daae05426 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.cpp @@ -0,0 +1,89 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkOrbitAnimationItem.h" +#include "QmitkOrbitAnimationWidget.h" +#include +#include + +QmitkOrbitAnimationWidget::QmitkOrbitAnimationWidget(QWidget* parent) + : QmitkAnimationWidget(parent), + m_Ui(new Ui::QmitkOrbitAnimationWidget) +{ + m_Ui->setupUi(this); + + m_Ui->orbitLineEdit->setValidator(new QIntValidator(0, std::numeric_limits::max(), this)); + + this->connect(m_Ui->startAngleSlider, SIGNAL(valueChanged(int)), + m_Ui->startAngleSpinBox, SLOT(setValue(int))); + + this->connect(m_Ui->startAngleSpinBox, SIGNAL(valueChanged(int)), + m_Ui->startAngleSlider, SLOT(setValue(int))); + + this->connect(m_Ui->startAngleSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(OnStartAngleChanged(int))); + + this->connect(m_Ui->orbitLineEdit, SIGNAL(editingFinished()), + this, SLOT(OnOrbitEditingFinished())); + + this->connect(m_Ui->reverseCheckBox, SIGNAL(clicked(bool)), + this, SLOT(OnReverseChanged(bool))); +} + +QmitkOrbitAnimationWidget::~QmitkOrbitAnimationWidget() +{ +} + +void QmitkOrbitAnimationWidget::SetAnimationItem(QmitkAnimationItem* orbitAnimationItem) +{ + m_AnimationItem = dynamic_cast(orbitAnimationItem); + + if (m_AnimationItem == NULL) + return; + + m_Ui->startAngleSlider->setValue(m_AnimationItem->GetStartAngle()); + m_Ui->orbitLineEdit->setText(QString("%1").arg(m_AnimationItem->GetOrbit())); + m_Ui->reverseCheckBox->setChecked(m_AnimationItem->GetReverse()); +} + +void QmitkOrbitAnimationWidget::OnStartAngleChanged(int angle) +{ + if (m_AnimationItem == NULL) + return; + + if (m_AnimationItem->GetStartAngle() != angle) + m_AnimationItem->SetStartAngle(angle); +} + +void QmitkOrbitAnimationWidget::OnOrbitEditingFinished() +{ + if (m_AnimationItem == NULL) + return; + + int angle = m_Ui->orbitLineEdit->text().toInt(); + + if (m_AnimationItem->GetOrbit() != angle) + m_AnimationItem->SetOrbit(angle); +} + +void QmitkOrbitAnimationWidget::OnReverseChanged(bool reverse) +{ + if (m_AnimationItem == NULL) + return; + + if (m_AnimationItem->GetReverse() != reverse) + m_AnimationItem->SetReverse(reverse); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.h new file mode 100644 index 0000000000..e343cfd47f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.h @@ -0,0 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkOrbitAnimationWidget_h +#define QmitkOrbitAnimationWidget_h + +#include "QmitkAnimationWidget.h" + +class QmitkOrbitAnimationItem; + +namespace Ui +{ + class QmitkOrbitAnimationWidget; +} + +class QmitkOrbitAnimationWidget : public QmitkAnimationWidget +{ + Q_OBJECT + +public: + explicit QmitkOrbitAnimationWidget(QWidget* parent = NULL); + ~QmitkOrbitAnimationWidget(); + + void SetAnimationItem(QmitkAnimationItem* orbitAnimationItem); + +private slots: + void OnStartAngleChanged(int angle); + void OnOrbitEditingFinished(); + void OnReverseChanged(bool reverse); + +private: + Ui::QmitkOrbitAnimationWidget* m_Ui; + QmitkOrbitAnimationItem* m_AnimationItem; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.ui b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.ui new file mode 100644 index 0000000000..d07661f51c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationWidget.ui @@ -0,0 +1,107 @@ + + + QmitkOrbitAnimationWidget + + + + 0 + 0 + 192 + 87 + + + + QmitkOrbitAnimationWidget + + + + + + + 0 + 0 + + + + Start angle: + + + startAngleSlider + + + + + + + 360 + + + 180 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + 360 + + + 180 + + + + + + + + 0 + 0 + + + + Orbit: + + + startAngleSlider + + + + + + + 360 + + + + + + + + 0 + 0 + + + + Reverse + + + + + + + startAngleSlider + startAngleSpinBox + reverseCheckBox + + + + diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp new file mode 100644 index 0000000000..624512a7ec --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp @@ -0,0 +1,91 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkSliceAnimationItem.h" +#include + +QmitkSliceAnimationItem::QmitkSliceAnimationItem(int renderWindow, int from, int to, bool reverse, double duration, double delay, bool startWithPrevious) + : QmitkAnimationItem("Slice", duration, delay, startWithPrevious) +{ + this->SetRenderWindow(renderWindow); + this->SetFrom(from); + this->SetTo(to); + this->SetReverse(reverse); +} + +QmitkSliceAnimationItem::~QmitkSliceAnimationItem() +{ +} + +int QmitkSliceAnimationItem::GetRenderWindow() const +{ + return this->data(RenderWindowRole).toInt(); +} + +void QmitkSliceAnimationItem::SetRenderWindow(int renderWindow) +{ + this->setData(renderWindow, RenderWindowRole); +} + +int QmitkSliceAnimationItem::GetFrom() const +{ + return this->data(FromRole).toInt(); +} + +void QmitkSliceAnimationItem::SetFrom(int from) +{ + this->setData(from, FromRole); +} + +int QmitkSliceAnimationItem::GetTo() const +{ + return this->data(ToRole).toInt(); +} + +void QmitkSliceAnimationItem::SetTo(int to) +{ + this->setData(to, ToRole); +} + +bool QmitkSliceAnimationItem::GetReverse() const +{ + return this->data(ReverseRole).toBool(); +} + +void QmitkSliceAnimationItem::SetReverse(bool reverse) +{ + this->setData(reverse, ReverseRole); +} + +void QmitkSliceAnimationItem::Animate(double s) +{ + const QString renderWindowName = QString("stdmulti.widget%1").arg(this->GetRenderWindow() + 1); + vtkRenderWindow* renderWindow = mitk::BaseRenderer::GetRenderWindowByName(renderWindowName.toStdString()); + + if (renderWindow == NULL) + return; + + mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController()->GetSlice(); + + if (stepper == NULL) + return; + + int newPos = this->GetReverse() + ? this->GetTo() - static_cast((this->GetTo() - this->GetFrom()) * s) + : this->GetFrom() + static_cast((this->GetTo() - this->GetFrom()) * s); + + stepper->SetPos(static_cast(newPos)); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.h new file mode 100644 index 0000000000..2626740387 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.h @@ -0,0 +1,43 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkSliceAnimationItem_h +#define QmitkSliceAnimationItem_h + +#include "QmitkAnimationItem.h" + +class QmitkSliceAnimationItem : public QmitkAnimationItem +{ +public: + explicit QmitkSliceAnimationItem(int renderWindow = 0, int from = 0, int to = 0, bool reverse = false, double duration = 2.0, double delay = 0.0, bool startWithPrevious = false); + virtual ~QmitkSliceAnimationItem(); + + int GetRenderWindow() const; + void SetRenderWindow(int renderWindow); + + int GetFrom() const; + void SetFrom(int from); + + int GetTo() const; + void SetTo(int to); + + bool GetReverse() const; + void SetReverse(bool reverse); + + void Animate(double s); +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp new file mode 100644 index 0000000000..525022fd49 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp @@ -0,0 +1,120 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkSliceAnimationItem.h" +#include "QmitkSliceAnimationWidget.h" +#include +#include + +static unsigned int GetNumberOfSlices(int renderWindow) +{ + const QString renderWindowName = QString("stdmulti.widget%1").arg(renderWindow + 1); + vtkRenderWindow* theRenderWindow = mitk::BaseRenderer::GetRenderWindowByName(renderWindowName.toStdString()); + + if (theRenderWindow != NULL) + { + mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(theRenderWindow)->GetSliceNavigationController()->GetSlice(); + + if (stepper != NULL) + return std::max(1U, stepper->GetSteps()); + } + + return 1; +} + +QmitkSliceAnimationWidget::QmitkSliceAnimationWidget(QWidget* parent) + : QmitkAnimationWidget(parent), + m_Ui(new Ui::QmitkSliceAnimationWidget) +{ + m_Ui->setupUi(this); + + this->connect(m_Ui->windowComboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(OnRenderWindowChanged(int))); + + this->connect(m_Ui->sliceRangeWidget, SIGNAL(minimumValueChanged(double)), + this, SLOT(OnFromChanged(double))); + + this->connect(m_Ui->sliceRangeWidget, SIGNAL(maximumValueChanged(double)), + this, SLOT(OnToChanged(double))); + + this->connect(m_Ui->reverseCheckBox, SIGNAL(clicked(bool)), + this, SLOT(OnReverseChanged(bool))); +} + +QmitkSliceAnimationWidget::~QmitkSliceAnimationWidget() +{ +} + +void QmitkSliceAnimationWidget::SetAnimationItem(QmitkAnimationItem* sliceAnimationItem) +{ + m_AnimationItem = dynamic_cast(sliceAnimationItem); + + if (m_AnimationItem == NULL) + return; + + m_Ui->windowComboBox->setCurrentIndex(m_AnimationItem->GetRenderWindow()); + m_Ui->sliceRangeWidget->setMaximum(GetNumberOfSlices(m_AnimationItem->GetRenderWindow()) - 1); + m_Ui->sliceRangeWidget->setValues(m_AnimationItem->GetFrom(), m_AnimationItem->GetTo()); + m_Ui->reverseCheckBox->setChecked(m_AnimationItem->GetReverse()); +} + +void QmitkSliceAnimationWidget::OnRenderWindowChanged(int renderWindow) +{ + if (m_AnimationItem == NULL) + return; + + const int lastSlice = static_cast(GetNumberOfSlices(renderWindow) - 1); + + m_AnimationItem->SetFrom(0); + m_AnimationItem->SetTo(lastSlice); + + m_Ui->sliceRangeWidget->setMaximum(lastSlice); + m_Ui->sliceRangeWidget->setValues(m_AnimationItem->GetFrom(), m_AnimationItem->GetTo()); + + if (m_AnimationItem->GetRenderWindow() != renderWindow) + m_AnimationItem->SetRenderWindow(renderWindow); +} + +void QmitkSliceAnimationWidget::OnFromChanged(double from) +{ + if (m_AnimationItem == NULL) + return; + + int intFrom = static_cast(from); + + if (m_AnimationItem->GetFrom() != intFrom) + m_AnimationItem->SetFrom(intFrom); +} + +void QmitkSliceAnimationWidget::OnToChanged(double to) +{ + if (m_AnimationItem == NULL) + return; + + int intTo = static_cast(to); + + if (m_AnimationItem->GetTo() != intTo) + m_AnimationItem->SetTo(intTo); +} + +void QmitkSliceAnimationWidget::OnReverseChanged(bool reverse) +{ + if (m_AnimationItem == NULL) + return; + + if (m_AnimationItem->GetReverse() != reverse) + m_AnimationItem->SetReverse(reverse); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.h new file mode 100644 index 0000000000..a12de9ed58 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.h @@ -0,0 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkSliceAnimationWidget_h +#define QmitkSliceAnimationWidget_h + +#include "QmitkAnimationWidget.h" + +class QmitkSliceAnimationItem; + +namespace Ui +{ + class QmitkSliceAnimationWidget; +} + +class QmitkSliceAnimationWidget : public QmitkAnimationWidget +{ + Q_OBJECT + +public: + explicit QmitkSliceAnimationWidget(QWidget* parent = NULL); + ~QmitkSliceAnimationWidget(); + + void SetAnimationItem(QmitkAnimationItem* sliceAnimationItem); + +private slots: + void OnRenderWindowChanged(int renderWindow); + void OnFromChanged(double from); + void OnToChanged(double to); + void OnReverseChanged(bool reverse); + +private: + Ui::QmitkSliceAnimationWidget* m_Ui; + QmitkSliceAnimationItem* m_AnimationItem; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.ui b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.ui new file mode 100644 index 0000000000..86f72fc9d9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.ui @@ -0,0 +1,112 @@ + + + QmitkSliceAnimationWidget + + + + 0 + 0 + 304 + 96 + + + + QmitkSliceAnimationWidget + + + + + + + 0 + 0 + + + + Window: + + + windowComboBox + + + + + + + + 0 + 0 + + + + + Axial + + + + + Sagittal + + + + + Coronal + + + + + + + + + 0 + 0 + + + + Slice range: + + + + + + + 0 + + + 999.000000000000000 + + + 999.000000000000000 + + + + + + + + 0 + 0 + + + + Reverse + + + + + + + + ctkRangeWidget + QWidget +
ctkRangeWidget.h
+
+
+ + windowComboBox + reverseCheckBox + + + +
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp index 78a3d6eee4..81f7742a7b 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp @@ -1,40 +1,40 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMovieMakerPluginActivator.h" -#include "QmitkMovieMaker.h" +#include "QmitkMovieMakerView.h" #include "QmitkScreenshotMaker.h" #include namespace mitk { void MovieMakerPluginActivator::start(ctkPluginContext* context) { - BERRY_REGISTER_EXTENSION_CLASS(QmitkMovieMaker, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkMovieMakerView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkScreenshotMaker, context) } void MovieMakerPluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_gui_qt_moviemaker, mitk::MovieMakerPluginActivator) #endif