diff --git a/Examples/Tutorial/Step2/Step2.cpp b/Examples/Tutorial/Step2/Step2.cpp index e40fbd0610..2dac5068de 100644 --- a/Examples/Tutorial/Step2/Step2.cpp +++ b/Examples/Tutorial/Step2/Step2.cpp @@ -1,102 +1,102 @@ /*=================================================================== 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 "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include #include #include #include //##Documentation //## @brief Load one or more data sets (many image, surface //## and other formats) and display it in a 2D view int main(int argc, char *argv[]) { QApplication qtapplication(argc, argv); if (argc < 2) { fprintf( stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str()); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a data storage object. We will use it as a singleton mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for (i = 1; i < argc; ++i) { // For testing if (strcmp(argv[i], "-testing") == 0) continue; //********************************************************************* // Part III: Put the data into the datastorage //********************************************************************* // Add the node to the DataStorage mitk::IOUtil::Load(argv[i], *storage); } //************************************************************************* // Part IV: Create window and pass the datastorage to it //************************************************************************* // Create a RenderWindow QmitkRenderWindow renderWindow; // Tell the RenderWindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(storage); // Initialize the RenderWindow mitk::TimeGeometry::Pointer geo = storage->ComputeBoundingGeometry3D(storage->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews(geo); // Select a slice mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); if (sliceNaviController) sliceNaviController->GetSlice()->SetPos(2); //************************************************************************* // Part V: Qt-specific initialization //************************************************************************* renderWindow.show(); renderWindow.resize(256, 256); -// for testing + // for testing #include "QtTesting.h" if (strcmp(argv[argc - 1], "-testing") != 0) return qtapplication.exec(); else return QtTesting(); } /** \example Step2.cpp -*/ +*/ \ No newline at end of file diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index 12dc97e8fe..eefbe4035e 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,81 +1,83 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core CommandLine AppUtil DCMTesting RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction LegacyAdaptors SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QtWidgets QtWidgetsExt C3js QmlItems SegmentationUI Classification DiffusionImaging GPGPU OpenIGTLink IGTBase IGT CameraCalibration OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI US USUI DicomUI Simulation Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI VtkShaders DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware TumorInvasionAnalysis MatchPointRegistration MatchPointRegistrationUI BoundingShape RenderWindowManager RenderWindowManagerUI CEST DICOMQI + MyAwesomeLib + SurfaceRegistration ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/MyAwesomeLib/CMakeLists.txt b/Modules/MyAwesomeLib/CMakeLists.txt new file mode 100644 index 0000000000..0198c5b80c --- /dev/null +++ b/Modules/MyAwesomeLib/CMakeLists.txt @@ -0,0 +1,3 @@ +mitk_create_module( MyAwesomeLib + DEPENDS PUBLIC MitkCore +) diff --git a/Modules/MyAwesomeLib/files.cmake b/Modules/MyAwesomeLib/files.cmake new file mode 100644 index 0000000000..a578fb19e3 --- /dev/null +++ b/Modules/MyAwesomeLib/files.cmake @@ -0,0 +1,9 @@ +set(CPP_FILES + AwesomeImageFilter.cpp + AwesomeImageInteractor.cpp +) + +set(RESOURCE_FILES + Interactions/Paint.xml + Interactions/PaintConfig.xml +) diff --git a/Modules/MyAwesomeLib/include/AwesomeImageFilter.h b/Modules/MyAwesomeLib/include/AwesomeImageFilter.h new file mode 100644 index 0000000000..f821bf1a82 --- /dev/null +++ b/Modules/MyAwesomeLib/include/AwesomeImageFilter.h @@ -0,0 +1,52 @@ +/*=================================================================== + +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 AwesomeImageFilter_h +#define AwesomeImageFilter_h + +#include + +// The following header file is generated by CMake and thus it's located in +// the build directory. It provides an export macro for classes and functions +// that you want to be part of the public interface of your module. +#include + +// While you are free to derive directly from ITK filter base classes, +// MITK filter base classes provide typed accessor methods for the inputs +// and outputs, which will save you and your clients lots of manual casting. +class MITKMYAWESOMELIB_EXPORT AwesomeImageFilter final : public mitk::ImageToImageFilter +{ +public: + // All classes that derive from an ITK-based MITK class need at least the + // following two macros. Make sure you don't declare the constructor public + // to force clients of your class to follow the ITK convention for + // instantiating classes via the static New() method. + mitkClassMacro(AwesomeImageFilter, mitk::ImageToImageFilter) + itkFactorylessNewMacro(Self) + + itkSetMacro(Offset, int) + itkGetMacro(Offset, int) + +private: + AwesomeImageFilter(); + ~AwesomeImageFilter(); + + void GenerateData() override; + + int m_Offset; +}; + +#endif diff --git a/Modules/MyAwesomeLib/include/AwesomeImageInteractor.h b/Modules/MyAwesomeLib/include/AwesomeImageInteractor.h new file mode 100644 index 0000000000..d5d98885e7 --- /dev/null +++ b/Modules/MyAwesomeLib/include/AwesomeImageInteractor.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 AwesomeImageInteractor_h +#define AwesomeImageInteractor_h + +#include +#include + +#include +namespace mitk +{ + + // See AwesomeImageFilter.h for details on typical class declarations + // in MITK. The actual functionality of this class is commented in its + // implementation file. + + class MITKMYAWESOMELIB_EXPORT AwesomeImageInteractor final : public mitk::DataInteractor + { + public: + mitkClassMacro(AwesomeImageInteractor, DataInteractor) + itkFactorylessNewMacro(Self) + + private: + AwesomeImageInteractor(); + ~AwesomeImageInteractor(); + + void ConnectActionsAndFunctions() override; + void DataNodeChanged() override; + + void Paint(mitk::StateMachineAction* action, mitk::InteractionEvent* event); + + itk::Index<3> m_LastPixelIndex; + }; + +#endif +} \ No newline at end of file diff --git a/Modules/MyAwesomeLib/resource/Interactions/Paint.xml b/Modules/MyAwesomeLib/resource/Interactions/Paint.xml new file mode 100644 index 0000000000..c63efb3683 --- /dev/null +++ b/Modules/MyAwesomeLib/resource/Interactions/Paint.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/Modules/MyAwesomeLib/resource/Interactions/PaintConfig.xml b/Modules/MyAwesomeLib/resource/Interactions/PaintConfig.xml new file mode 100644 index 0000000000..e141844565 --- /dev/null +++ b/Modules/MyAwesomeLib/resource/Interactions/PaintConfig.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Modules/MyAwesomeLib/src/AwesomeImageFilter.cpp b/Modules/MyAwesomeLib/src/AwesomeImageFilter.cpp new file mode 100644 index 0000000000..2f91a99430 --- /dev/null +++ b/Modules/MyAwesomeLib/src/AwesomeImageFilter.cpp @@ -0,0 +1,100 @@ +/*=================================================================== + +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 + +// See definition of AwesomeImageFilter::GenerateData() further below for +// a rationale behind this function template. +template +static void AddOffset(const itk::Image* inputImage, int offset, mitk::Image::Pointer outputImage) +{ + typedef itk::Image ImageType; + typedef itk::ShiftScaleImageFilter FilterType; + + auto filter = FilterType::New(); + filter->SetInput(inputImage); + filter->SetShift(offset); + + filter->Update(); + + // This is the tricky part that is done wrong very often. As the image data + // of ITK images and MITK images are binary compatible, we don't need to + // cast or copy the ITK output image. Instead, we just want to reference + // the image data and tell ITK that we took the ownership. + mitk::GrabItkImageMemory(filter->GetOutput(), outputImage); +} + +AwesomeImageFilter::AwesomeImageFilter() + : m_Offset(0) +{ + this->SetNumberOfRequiredInputs(1); + this->SetNumberOfRequiredOutputs(1); +} + +AwesomeImageFilter::~AwesomeImageFilter() +{ +} + +void AwesomeImageFilter::GenerateData() +{ + mitk::Image::Pointer inputImage = this->GetInput(0); + + if (m_Offset == 0) + { + // Nothing to calculate in this case, just copy the input image. + this->SetPrimaryOutput(inputImage->Clone().GetPointer()); + } + else + { + mitk::Image::Pointer outputImage = this->GetOutput(); + + try + { + // We want to apply an ITK filter to the MITK input image. While MITK + // images are not templated, ITK images are templated by both pixel type + // and image dimension. The actual image data is binary compatible, though. + // MITK provides ITK access macros that enable you to directly operate + // on MITK images without any superfluous copying. + // To allow ITK filters to work with different image types at runtime you + // would be required to instantiate your function templates for each and + // every expected combination of pixel type and image dimension. Luckily, + // MITK provides a whole bunch of multiplexer macros to save you doing this + // manually (see mitkImageAccessByItk.h). + // These macros range from being completely generic to partly constrained + // variants. For example, you may want to constrain the image dimension or + // the pixel type. As your function template is compiled for each allowed + // combination, compile time and code size may increase dramatically. + // As a rule of thumb, use a suitable multiplexer macro that is as + // constrained as possible and yet as generic as necessary. + // To prevent a combinatorial explosion, image dimension is restricted to + // 2 and 3 even for the dimension-variable multiplexer macros. + // Thus, the following multiplexer macro allows for 2-dimensional and + // 3-dimensional images with an integer pixel type, for example, + // (un)signed char, short, and int, resulting in a total of 12 distinct + // combinations. + AccessIntegralPixelTypeByItk_n(inputImage, AddOffset, (m_Offset, outputImage)); + } + catch (const mitk::AccessByItkException& e) + { + MITK_ERROR << "Unsupported pixel type or image dimension: " << e.what(); + } + } +} diff --git a/Modules/MyAwesomeLib/src/AwesomeImageInteractor.cpp b/Modules/MyAwesomeLib/src/AwesomeImageInteractor.cpp new file mode 100644 index 0000000000..71fd1753bf --- /dev/null +++ b/Modules/MyAwesomeLib/src/AwesomeImageInteractor.cpp @@ -0,0 +1,185 @@ +/*=================================================================== + +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 + + + + // Helper function to get an image from a data node. + static mitk::Image::Pointer GetImage(mitk::DataNode::Pointer dataNode) + { + if (dataNode.IsNull()) + mitkThrow(); + + mitk::Image::Pointer image = dynamic_cast(dataNode->GetData()); + + if (image.IsNull()) + mitkThrow(); + + return image; + } + + // Helper function to get a geometry of an image for a specific time step. + static mitk::BaseGeometry::Pointer GetGeometry(mitk::Image::Pointer image, unsigned int timeStep) + { + mitk::TimeGeometry::Pointer timeGeometry = image->GetTimeGeometry(); + + if (timeGeometry.IsNull()) + mitkThrow(); + + auto geometry = timeGeometry->GetGeometryForTimeStep(timeStep); + + if (geometry.IsNull()) + mitkThrow(); + + return geometry; + } + + // The actual painting happens here. We're using a write accessor to gain safe + // write access to our image. The whole image volume for a given time step is + // locked. However, it's also possible - and preferable - to lock the slice of + // interest only. + template + static void Paint(mitk::Image::Pointer image, itk::Index<3> index, unsigned int timeStep) + { + // As soon as the ImagePixelWriteAccessor object goes out of scope at the + // end of this function, the image will be unlocked again (RAII). + mitk::ImagePixelWriteAccessor writeAccessor(image, image->GetVolumeData(timeStep)); + writeAccessor.SetPixelByIndex(index, std::numeric_limits::min()); + + // Don't forget to update the modified time stamp of the image. Otherwise, + // everything downstream wouldn't recognize that the image changed, + // including the rendering system. + image->Modified(); + } + + // Helper function to multiplex the actual Paint function call for different + // pixel types. As it's cumbersome and ugly, you may want to avoid such + // functions by using ITK for the actual painting and use the ITK access + // macros like we did for the AwesomeImageFilter. + static void Paint(mitk::Image::Pointer image, itk::Index<3> index, unsigned int timeStep) + { + switch (image->GetPixelType().GetComponentType()) + { + case itk::ImageIOBase::CHAR: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::UCHAR: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::SHORT: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::USHORT: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::INT: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::UINT: + Paint(image, index, timeStep); + break; + + default: + mitkThrow(); + } + } + + mitk::AwesomeImageInteractor::AwesomeImageInteractor() + { + } + + mitk::AwesomeImageInteractor::~AwesomeImageInteractor() + { + } + + void mitk::AwesomeImageInteractor::ConnectActionsAndFunctions() + { + // Wire up this interactor with the state machine that is described by + // resource/Interactions/Paint.xml. + CONNECT_FUNCTION("paint", Paint) + } + + void mitk::AwesomeImageInteractor::DataNodeChanged() + { + // You almost always want to reset the state machine when the interactor + // has been attached to another data node. + this->ResetToStartState(); + } + + // The state machine is wired up with this Paint method. We wrote a few helper + // functions at the top of this files to keep this method clear and easy to + // read. + void mitk::AwesomeImageInteractor::Paint(mitk::StateMachineAction* action, mitk::InteractionEvent* event) + { + try + { + auto renderer = event->GetSender(); + + auto image = GetImage(this->GetDataNode()); + auto timeStep = renderer->GetTimeStep(); + auto geometry = GetGeometry(image, timeStep); + + // This method is wired up to mouse events. Thus, we can safely assume + // that the following cast will succeed and we have access to the mouse + // position and the first intersection point of a ray originating at the + // mouse position and shot into the scene. Convenient, isn't it? :-) + auto positionEvent = dynamic_cast(event); + auto position = positionEvent->GetPositionInWorld(); + + if (!geometry->IsInside(position)) + return; // Nothing to paint, as we're not inside the image bounds. + + // Okay, we're safe. Convert the mouse position to the index of the pixel + // we're pointing at. + itk::Index<3> index; + geometry->WorldToIndex<3>(position, index); + + // We don't need to paint over and over again while moving the mouse + // pointer inside the same pixel. That's especially relevant when operating + // on zoomed images. + if (index != m_LastPixelIndex) + { + // And finally... + ::Paint(image, index, timeStep); + + // Nearly done. We request the renderer to update the render window in + // order to see the result immediately. Actually, we should update all + // of the render windows by caling RequestUpdateAll() instead, as the + // painted pixels are possibly visible in other render windows, too. + // However, we decided to prefer performance here. + mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); + MITK_INFO << index[0] << " " << index[1] << " " << index[2]; + + m_LastPixelIndex = index; + } + } + catch (...) + { + return; + } + } diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 69a9b62e79..920186045b 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,98 +1,100 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:OFF org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.diffusionimaging.connectomics:OFF org.mitk.gui.qt.diffusionimaging.denoising:OFF org.mitk.gui.qt.diffusionimaging.fiberfox:OFF org.mitk.gui.qt.diffusionimaging.fiberprocessing:OFF org.mitk.gui.qt.diffusionimaging.ivim:OFF org.mitk.gui.qt.diffusionimaging.odfpeaks:OFF org.mitk.gui.qt.diffusionimaging.partialvolume:OFF org.mitk.gui.qt.diffusionimaging.preprocessing:OFF org.mitk.gui.qt.diffusionimaging.reconstruction:OFF org.mitk.gui.qt.diffusionimaging.registration:OFF org.mitk.gui.qt.diffusionimaging.tbss:OFF org.mitk.gui.qt.diffusionimaging.tractography:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.renderwindowmanager:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF org.mitk.gui.qt.multilabelsegmentation:OFF org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF org.mitk.gui.qt.cest:OFF + org.mitk.gui.qt.exampleplugin:OFF + org.mitk.gui.qt.surfaceregistration:OFF ) diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/CMakeLists.txt b/Plugins/org.mitk.gui.qt.exampleplugin/CMakeLists.txt new file mode 100644 index 0000000000..aed63c1627 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_exampleplugin) + +mitk_create_plugin( + EXPORT_DIRECTIVE AWESOME_EXPORTS + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS PRIVATE MitkQtWidgetsExt MitkMyAwesomeLib +) diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.exampleplugin/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..74e21d8648 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/documentation/UserManual/Manual.dox @@ -0,0 +1,20 @@ +/** +\page my_awesomeproject_exampleplugin The Awesome Example Plugin + +\imageMacro{icon.xpm,"Icon of Awesome Example Plugin",2.00} + +\tableofcontents + +\section my_awesomeproject_examplepluginOverview Overview + +Describe the features of your awesome plugin here + +
    +
  • Increases productivity
  • +
  • Creates beautiful images
  • +
  • Generates PhD thesis
  • +
  • Brings world peace
  • +
+ +*/ + diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.exampleplugin/documentation/UserManual/icon.xpm new file mode 100644 index 0000000000..83e48be4d8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/documentation/UserManual/icon.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static const char * icon_xpm[] = { +"16 16 2 1", +" c #FF0000", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.exampleplugin/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..0a267aec8e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup my_awesomeproject_exampleplugin my.awesomeproject.exampleplugin Plugin + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup my_awesomeproject_exampleplugin_internal Internal + \ingroup my_awesomeproject_exampleplugin + + \brief This subcategory includes the internal classes of the my.awesomeproject.exampleplugin 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.exampleplugin/files.cmake b/Plugins/org.mitk.gui.qt.exampleplugin/files.cmake new file mode 100644 index 0000000000..cadf2b0605 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/files.cmake @@ -0,0 +1,24 @@ +set(CPP_FILES + src/internal/AwesomePluginActivator.cpp + src/internal/AwesomeView.cpp +) + +set(UI_FILES + src/internal/AwesomeViewControls.ui +) + +set(MOC_H_FILES + src/internal/AwesomePluginActivator.h + src/internal/AwesomeView.h +) + +# List of resource files that can be used by the plugin system without loading +# the actual plugin. For example, the icon that is typically displayed in the +# plugin view menu at the top of the application window. +set(CACHED_RESOURCE_FILES + resources/AwesomeIcon.png + plugin.xml +) + +set(QRC_FILES +) diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/plugin.xml b/Plugins/org.mitk.gui.qt.exampleplugin/plugin.xml new file mode 100644 index 0000000000..7b868c6b46 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/plugin.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/resources/AwesomeIcon.png b/Plugins/org.mitk.gui.qt.exampleplugin/resources/AwesomeIcon.png new file mode 100644 index 0000000000..a858653b2a Binary files /dev/null and b/Plugins/org.mitk.gui.qt.exampleplugin/resources/AwesomeIcon.png differ diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomePluginActivator.cpp b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomePluginActivator.cpp new file mode 100644 index 0000000000..ceb9979915 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomePluginActivator.cpp @@ -0,0 +1,27 @@ +/*=================================================================== + +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 "AwesomePluginActivator.h" +#include "AwesomeView.h" + +void my_awesomeproject_exampleplugin_PluginActivator::start(ctkPluginContext* context) +{ + BERRY_REGISTER_EXTENSION_CLASS(AwesomeView, context) +} + +void my_awesomeproject_exampleplugin_PluginActivator::stop(ctkPluginContext*) +{ +} diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomePluginActivator.h b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomePluginActivator.h new file mode 100644 index 0000000000..2471f4d1d8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomePluginActivator.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 my_awesomeproject_exampleplugin_PluginActivator_h +#define my_awesomeproject_exampleplugin_PluginActivator_h + +#include + +class my_awesomeproject_exampleplugin_PluginActivator + : public QObject, + public ctkPluginActivator +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.exampleplugin") + Q_INTERFACES(ctkPluginActivator) + +public: + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeView.cpp b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeView.cpp new file mode 100644 index 0000000000..ef2ca51cec --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeView.cpp @@ -0,0 +1,178 @@ +/*=================================================================== + +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 "AwesomeView.h" + +#include +#include + +#include + +#include + +#include + +#include +#include + + + + //Helper function to create a fully set up instance of our + //AwesomeImageInteractor, based on the state machine specified in Paint.xml + //as well as its configuration in PaintConfig.xml. Both files are compiled + //into our MyAwesomeLib module as resources. + static mitk::AwesomeImageInteractor::Pointer CreateAwesomeImageInteractor() + { + auto myAwesomeLib = us::ModuleRegistry::GetModule("MitkMyAwesomeLib");//wichtig ist hier das Mitk noch dran zu schreiben + + auto interactor = mitk::AwesomeImageInteractor::New(); + interactor->LoadStateMachine("Paint.xml", myAwesomeLib); + interactor->SetEventConfig("PaintConfig.xml", myAwesomeLib); + + return interactor; + } + + // Don't forget to initialize the VIEW_ID. + const std::string AwesomeView::VIEW_ID = "my.awesomeproject.views.awesomeview"; + + void AwesomeView::CreateQtPartControl(QWidget* parent) + { + // Setting up the UI is a true pleasure when using .ui files, isn't it? + m_Controls.setupUi(parent); + + // Wire up the UI widgets with our functionality. + connect(m_Controls.processImageButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedImage())); + } + + void AwesomeView::SetFocus() + { + m_Controls.processImageButton->setFocus(); + } + + void AwesomeView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& dataNodes) + { + for (const auto& dataNode : dataNodes) + { + // Write robust code. Always check pointers before using them. If the + // data node pointer is null, the second half of our condition isn't + // even evaluated and we're safe (C++ short-circuit evaluation). + if (dataNode.IsNotNull() && dynamic_cast(dataNode->GetData()) != nullptr) + { + m_Controls.selectImageLabel->setVisible(false); + return; + } + } + + // Nothing is selected or the selection doesn't contain an image. + m_Controls.selectImageLabel->setVisible(true); + } + + void AwesomeView::ProcessSelectedImage() + { + MITK_INFO << "Process start"; + // Before we even think about processing something, we need to make sure + // that we have valid input. Don't be sloppy, this is a main reason + // for application crashes if neglected. + + auto selectedDataNodes = this->GetDataManagerSelection(); + + if (selectedDataNodes.empty()) + return; + + auto firstSelectedDataNode = selectedDataNodes.front(); + + if (firstSelectedDataNode.IsNull()) + { + QMessageBox::information(nullptr, "Awesome View", "Please load and select an image before starting image processing."); + return; + } + MITK_INFO << "Process data"; + auto data = firstSelectedDataNode->GetData(); + + // Something is selected, but does it contain data? + if (data != nullptr) + { + // We don't use the auto keyword here, which would evaluate to a native + // image pointer. Instead, we want a smart pointer in order to ensure that + // the image isn't deleted somewhere else while we're using it. + mitk::Image::Pointer image = dynamic_cast(data); + + // Something is selected and it contains data, but is it an image? + if (image.IsNotNull()) + { + auto imageName = firstSelectedDataNode->GetName(); + auto offset = m_Controls.offsetSpinBox->value(); + + MITK_INFO << "Process image \"" << imageName << "\" ..."; + + // We're finally using the AwesomeImageFilter from our AwesomeLib module. + auto filter = AwesomeImageFilter::New(); + filter->SetInput(image); + filter->SetOffset(offset); + + filter->Update(); + + mitk::Image::Pointer processedImage = filter->GetOutput(); + + if (processedImage.IsNull() || !processedImage->IsInitialized()) + return; + + MITK_INFO << " done"; + + //// Stuff the resulting image into a data node, set some properties, + //// and add it to the data storage, which will eventually display the + //// image in the application. + auto processedImageDataNode = mitk::DataNode::New(); + processedImageDataNode->SetData(processedImage); + + QString name = QString("%1 (Offset: %2)").arg(imageName.c_str()).arg(offset); + processedImageDataNode->SetName(name.toStdString()); + + //// We don't really need to copy the level window, but if we wouldn't + //// do it, the new level window would be initialized to display the image + //// with optimal contrast in order to capture the whole range of pixel + //// values. This is also true for the input image as long as one didn't + //// modify its level window manually. Thus, the images would appear + //// identical unless you compare the level window widget for both images. + mitk::LevelWindow levelWindow; + + if (firstSelectedDataNode->GetLevelWindow(levelWindow)) + processedImageDataNode->SetLevelWindow(levelWindow); + + // We also attach our AwesomeImageInteractor, which allows us to paint + // on the resulting images by using the mouse as long as the CTRL key + // is pressed. + auto interactor = CreateAwesomeImageInteractor(); + + if (interactor.IsNotNull()) + interactor->SetDataNode(processedImageDataNode); + + this->GetDataStorage()->Add(processedImageDataNode); + } + } + + // Now it's your turn. This class/method has lots of room for improvements, + // for example: + // + // - What happens when multiple items are selected but the first one isn't + // an image? - There isn't any feedback for the user at all. + // - What's the front item of a selection? Does it depend on the order + // of selection or the position in the Data Manager? - Isn't it + // better to process all selected images? Don't forget to adjust the + // titles of the UI widgets. + // - In addition to the the displayed label, it's probably a good idea to + // enable or disable the button depending on the selection. + } diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeView.h b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeView.h new file mode 100644 index 0000000000..2a545080b5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeView.h @@ -0,0 +1,69 @@ +/*=================================================================== + +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 AwesomeView_h +#define AwesomeView_h + +#include +#include + +// There's an item "AwesomeViewControls.ui" in the UI_FILES list in +// files.cmake. The Qt UI Compiler will parse this file and generate a +// header file prefixed with "ui_", which is located in the build directory. +// Use Qt Creator to view and edit .ui files. The generated header file +// provides a class that contains all of the UI widgets. +#include + +// All views in MITK derive from QmitkAbstractView. You have to override +// at least the two methods CreateQtPartControl() and SetFocus(). +class AwesomeView : public QmitkAbstractView +{ + // As QmitkAbstractView derives from QObject and we want to use the Qt + // signal and slot mechanism, we must not forget the Q_OBJECT macro. + // This header file also has to be listed in MOC_H_FILES in files.cmake, + // in order that the Qt Meta-Object Compiler can find and process this + // class declaration. + Q_OBJECT + +public: + // This is a tricky one and will give you some headache later on in + // your debug sessions if it has been forgotten. Also, don't forget + // to initialize it in the implementation file. + static const std::string VIEW_ID; + + // In this method we initialize the GUI components and connect the + // associated signals and slots. + void CreateQtPartControl(QWidget* parent) override; + +private slots: + void ProcessSelectedImage(); + +private: + // Typically a one-liner. Set the focus to the default widget. + void SetFocus() override; + + // This method is conveniently called whenever the selection of Data Manager + // items changes. + void OnSelectionChanged( + berry::IWorkbenchPart::Pointer source, + const QList& dataNodes) override; + + // Generated from the associated UI file, it encapsulates all the widgets + // of our view. + Ui::AwesomeViewControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeViewControls.ui b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeViewControls.ui new file mode 100644 index 0000000000..600c1d46a7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/src/internal/AwesomeViewControls.ui @@ -0,0 +1,96 @@ + + + AwesomeViewControls + + + + 0 + 0 + 398 + 636 + + + + Awesome View + + + + + + QLabel { color: rgb(255, 0, 0) } + + + Please select image. + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Offset + + + + + + + + 0 + 0 + + + + 9999 + + + + + + + + + + Process selected image + + + add Offset + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 220 + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/Advanced_ImageCropperView.png b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/Advanced_ImageCropperView.png new file mode 100644 index 0000000000..cd9fa4e650 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/Advanced_ImageCropperView.png differ diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/Basic_ImageCropperView.png b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/Basic_ImageCropperView.png new file mode 100644 index 0000000000..85b78cbb87 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/Basic_ImageCropperView.png differ diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/BoundingBox_ImageCropperView.png b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/BoundingBox_ImageCropperView.png new file mode 100644 index 0000000000..b2b870f138 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/BoundingBox_ImageCropperView.png differ diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/QmitkImageCropper.dox b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/QmitkImageCropper.dox new file mode 100644 index 0000000000..584790fbde --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/QmitkImageCropper.dox @@ -0,0 +1,40 @@ +/** +\page org_mitk_gui_qt_imagecropper Image Cropper Plugin + +\imageMacro{QmitkImageCropper_Icon.png,"Icon of the Image Cropper Plugin.",20} + +\tableofcontents + +\section org_mitk_gui_qt_imagecropperUsage Usage + +The Image Cropper Plugin allows you to crop subvolumes out of your orginial image volume by defining a cubic bounding box. + +This box can be placed at an arbitrary position in the volume and can be easily adjusted by using the handles on each of the faces. +Touching the handles changes the size of the box whereas touching the box itself changes its position. + +As soon as the bounding box is placed at the desired position, pressing the button 'Crop' creates a new image assigned to the orginal image +as child node containing only the selected subvolume. The size of the subvolume equals the size of the bounding box. +Pressing the "Mask" button keeps the original image size but masks out the area not contained within the bounding box bounds. +In case of 3D+t images the whole timeseries is cropped by default. + +\imageMacro{BoundingBox_ImageCropperView.png,"Bounding Box.",12.00} +\imageMacro{Basic_ImageCropperView.png,"Basic Settings.",7.09} + +\section org_mitk_gui_qt_imagecropperAdvanced Advanced settings +In the advanced settings view you find additional features to manipulate the bounding box. +\imageMacro{Advanced_ImageCropperView.png,"Advanced Settings.",7.09} + +\subsection org_mitk_gui_qt_imagecropperAdvancedColor Bounding Shape Color +By pressing the two color buttons you may change the color for the selected and unselected state of the box. +\subsection org_mitk_gui_qt_imagecropperAdvancedOverwrite Overwrite original image +By enabling this checkbox the image is replaced by the cropped subvolume. Be careful to use this option since there is now Redo action available. +\subsection org_mitk_gui_qt_imagecropperAdvancedTimestep Crop current timestep only +If this checkbox is enabled the xD + t image is reduced to a xD image (3D+t --> 3D) with the timestep visible in the widget. This is useful if you want to extract a single image or its corresponding +subvolume of the timeseries. The whole timeseries is cropped by default using the timeGeometry of the timestep visible in the widget. + +\section org_mitk_gui_qt_imagecropperIssues Current issues +Due to the latest changes in MITK slicegeometry is it currently not supported to crop 2D images unless the are 3D +images containing only a single slice. The user will be notified by a warning and and the input is handled as a single lable image. + +Right now changing the shape or rotation of the bounding box is not supported but might be integrated in the future. +*/ \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/QmitkImageCropper_Icon.png b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/QmitkImageCropper_Icon.png new file mode 100644 index 0000000000..10649b8e8f Binary files /dev/null and b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/UserManual/QmitkImageCropper_Icon.png differ diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..89ff4bc555 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_surfaceregistration org.mitk.gui.qt.surfaceregistration + \ingroup MITKPlugins + + \brief TODO + +*/ + +/** + \defgroup org_mitk_gui_qt_surfaceregistration_internal Internal + \ingroup org_mitk_gui_qt_surfaceregistration + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.surfaceregistration plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ \ No newline at end of file