diff --git a/Modules/Core/TestingHelper/src/mitkTestDynamicImageGenerator.cpp b/Modules/Core/TestingHelper/src/mitkTestDynamicImageGenerator.cpp
index 73a8af779d..bca01c2eeb 100644
--- a/Modules/Core/TestingHelper/src/mitkTestDynamicImageGenerator.cpp
+++ b/Modules/Core/TestingHelper/src/mitkTestDynamicImageGenerator.cpp
@@ -1,253 +1,212 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "mitkTestDynamicImageGenerator.h"
 #include "mitkArbitraryTimeGeometry.h"
 #include "mitkImageCast.h"
+#include "mitkTemporalJoinImagesFilter.h"
 
 namespace mitk
 {
   typedef itk::Image<double, 3> FrameITKImageType;
   typedef itk::Image<double, 4> DynamicITKImageType;
   typedef itk::Image<unsigned char, 3> MaskITKImageType;
 
   TestImageType::Pointer GenerateTestImage(int factor)
   {
     TestImageType::Pointer image = TestImageType::New();
 
     TestImageType::IndexType start;
     start[0] =   0;  // first index on X
     start[1] =   0;  // first index on Y
 
     TestImageType::SizeType  size;
     size[0]  = 3;  // size along X
     size[1]  = 3;  // size along Y
 
     TestImageType::RegionType region;
     region.SetSize(size);
     region.SetIndex(start);
 
     image->SetRegions(region);
     image->Allocate();
 
     itk::ImageRegionIterator<TestImageType> it = itk::ImageRegionIterator<TestImageType>(image,
         image->GetLargestPossibleRegion());
 
     int count = 1;
 
     while (!it.IsAtEnd())
     {
       it.Set(count * factor);
       ++it;
       ++count;
     }
 
     return image;
   }
 
   TestMaskType::Pointer GenerateTestMask()
   {
     TestMaskType::Pointer image = TestMaskType::New();
 
     TestMaskType::IndexType start;
     start[0] =   0;  // first index on X
     start[1] =   0;  // first index on Y
 
     TestMaskType::SizeType  size;
     size[0]  = 3;  // size along X
     size[1]  = 3;  // size along Y
 
     TestMaskType::RegionType region;
     region.SetSize(size);
     region.SetIndex(start);
 
     image->SetRegions(region);
     image->Allocate();
 
     itk::ImageRegionIterator<TestMaskType> it = itk::ImageRegionIterator<TestMaskType>(image,
         image->GetLargestPossibleRegion());
 
     int count = 1;
 
     while (!it.IsAtEnd())
     {
       if (count > 1 && count < 5)
       {
         it.Set(1);
       }
       else
       {
         it.Set(0);
       }
 
       ++it;
       ++count;
     }
 
     return image;
   }
 
   Image::Pointer GenerateTestFrame(double timePoint)
   {
     FrameITKImageType::Pointer image = FrameITKImageType::New();
 
     FrameITKImageType::IndexType start;
     start[0] =   0;  // first index on X
     start[1] =   0;  // first index on Y
     start[2] =   0;  // first index on Z
 
     FrameITKImageType::SizeType  size;
     size[0]  = 3;  // size along X
     size[1]  = 3;  // size along Y
     size[2]  = 3;  // size along Z
 
     FrameITKImageType::RegionType region;
     region.SetSize(size);
     region.SetIndex(start);
 
     image->SetRegions(region);
     image->Allocate();
 
     itk::ImageRegionIterator<FrameITKImageType> it = itk::ImageRegionIterator<FrameITKImageType>(image,
         image->GetLargestPossibleRegion());
 
     int count = 0;
 
     while (!it.IsAtEnd())
     {
       double slope = count % (size[0] * size[1]);
       double offset = itk::Math::Floor<double, double>(count / (size[0] * size[1])) * 10;
 
       it.Set(slope * timePoint + offset);
       ++it;
       ++count;
     }
 
     mitk::Image::Pointer mitkImage = mitk::Image::New();
     mitkImage->InitializeByItk(image.GetPointer());
     mitkImage->SetVolume(image->GetBufferPointer());
 
     return mitkImage;
   }
 
   Image::Pointer GenerateTestMaskMITK()
   {
     MaskITKImageType::Pointer image = MaskITKImageType::New();
 
     MaskITKImageType::IndexType start;
     start[0] =   0;  // first index on X
     start[1] =   0;  // first index on Y
     start[2] =   0;  // first index on Z
 
     MaskITKImageType::SizeType  size;
     size[0]  = 3;  // size along X
     size[1]  = 3;  // size along Y
     size[2]  = 3;  // size along Z
 
     MaskITKImageType::RegionType region;
     region.SetSize(size);
     region.SetIndex(start);
 
     image->SetRegions(region);
     image->Allocate();
 
     itk::ImageRegionIterator<MaskITKImageType> it = itk::ImageRegionIterator<MaskITKImageType>(image,
         image->GetLargestPossibleRegion());
 
     int count = 0;
 
     while (!it.IsAtEnd())
     {
       if (count < 14)
       {
         it.Set(1);
       }
       else
       {
         it.Set(0);
       }
 
       ++it;
       ++count;
     }
 
     mitk::Image::Pointer mitkImage = mitk::Image::New();
     mitkImage->InitializeByItk(image.GetPointer());
     mitkImage->SetVolume(image->GetBufferPointer());
 
     return mitkImage;
   }
 
 
   Image::Pointer GenerateDynamicTestImageMITK()
   {
+    auto filter = mitk::TemporalJoinImagesFilter::New();
 
-    mitk::Image::Pointer tempImage = GenerateTestFrame(1);
-    mitk::Image::Pointer dynamicImage = mitk::Image::New();
-
-    DynamicITKImageType::Pointer dynamicITKImage = DynamicITKImageType::New();
-    DynamicITKImageType::RegionType dynamicITKRegion;
-    DynamicITKImageType::PointType dynamicITKOrigin;
-    DynamicITKImageType::IndexType dynamicITKIndex;
-    DynamicITKImageType::SpacingType dynamicITKSpacing;
-
-    dynamicITKSpacing[0] = tempImage->GetGeometry()->GetSpacing()[0];
-    dynamicITKSpacing[1] = tempImage->GetGeometry()->GetSpacing()[1];
-    dynamicITKSpacing[2] = tempImage->GetGeometry()->GetSpacing()[2];
-    dynamicITKSpacing[3] = 5.0;
-
-    dynamicITKIndex[0] = 0;  // The first pixel of the REGION
-    dynamicITKIndex[1] = 0;
-    dynamicITKIndex[2] = 0;
-    dynamicITKIndex[3] = 0;
-
-    dynamicITKRegion.SetSize(0, tempImage->GetDimension(0));
-    dynamicITKRegion.SetSize(1, tempImage->GetDimension(1));
-    dynamicITKRegion.SetSize(2, tempImage->GetDimension(2));
-    dynamicITKRegion.SetSize(3, 10);
-
-    dynamicITKRegion.SetIndex(dynamicITKIndex);
-
-    dynamicITKOrigin[0] = tempImage->GetGeometry()->GetOrigin()[0];
-    dynamicITKOrigin[1] = tempImage->GetGeometry()->GetOrigin()[1];
-    dynamicITKOrigin[2] = tempImage->GetGeometry()->GetOrigin()[2];
-
-    dynamicITKImage->SetOrigin(dynamicITKOrigin);
-    dynamicITKImage->SetSpacing(dynamicITKSpacing);
-    dynamicITKImage->SetRegions(dynamicITKRegion);
-    dynamicITKImage->Allocate();
-    dynamicITKImage->FillBuffer(0); //not sure if this is necessary
-
-    // Convert
-    mitk::CastToMitkImage(dynamicITKImage, dynamicImage);
-
-    ArbitraryTimeGeometry::Pointer timeGeometry = ArbitraryTimeGeometry::New();
-    timeGeometry->ClearAllGeometries();
-
-
+    mitk::TemporalJoinImagesFilter::TimeBoundsVectorType bounds;
     for (int i = 0; i < 10; ++i)
     {
-      mitk::Image::Pointer frameImage = GenerateTestFrame(1 + (dynamicITKSpacing[3] * i));
-      mitk::ImageReadAccessor accessor(frameImage);
-      dynamicImage->SetVolume(accessor.GetData(), i);
-
-      timeGeometry->AppendNewTimeStepClone(frameImage->GetGeometry(), 1 + (dynamicITKSpacing[3] * i),
-                                        1 + (dynamicITKSpacing[3]*(i+1)));
+      filter->SetInput(i, GenerateTestFrame(1 + (5.0 * i)));
+      bounds.push_back(1 + (5.0 * (i + 1)));
     }
 
-    dynamicImage->SetTimeGeometry(timeGeometry);
+    filter->SetFirstMinTimeBound(1.);
+    filter->SetMaxTimeBounds(bounds);
+
+    filter->Update();
 
-    return dynamicImage;
+    return filter->GetOutput();
   }
 
 }
 
diff --git a/Modules/Core/files.cmake b/Modules/Core/files.cmake
index e13405173c..78ae1b7ad2 100644
--- a/Modules/Core/files.cmake
+++ b/Modules/Core/files.cmake
@@ -1,323 +1,324 @@
 file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
 
 set(CPP_FILES
   mitkCoreActivator.cpp
   mitkCoreObjectFactoryBase.cpp
   mitkCoreObjectFactory.cpp
   mitkCoreServices.cpp
   mitkException.cpp
 
   Algorithms/mitkBaseDataSource.cpp
   Algorithms/mitkClippedSurfaceBoundsCalculator.cpp
   Algorithms/mitkCompareImageDataFilter.cpp
   Algorithms/mitkCompositePixelValueToString.cpp
   Algorithms/mitkConvert2Dto3DImageFilter.cpp
   Algorithms/mitkDataNodeSource.cpp
   Algorithms/mitkExtractSliceFilter.cpp
   Algorithms/mitkExtractSliceFilter2.cpp
   Algorithms/mitkHistogramGenerator.cpp
   Algorithms/mitkImageChannelSelector.cpp
   Algorithms/mitkImageSliceSelector.cpp
   Algorithms/mitkImageSource.cpp
   Algorithms/mitkImageTimeSelector.cpp
   Algorithms/mitkImageToImageFilter.cpp
   Algorithms/mitkImageToSurfaceFilter.cpp
   Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp
   Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp
   Algorithms/mitkPointSetSource.cpp
   Algorithms/mitkPointSetToPointSetFilter.cpp
   Algorithms/mitkRGBToRGBACastImageFilter.cpp
   Algorithms/mitkSubImageSelector.cpp
   Algorithms/mitkSurfaceSource.cpp
   Algorithms/mitkSurfaceToImageFilter.cpp
   Algorithms/mitkSurfaceToSurfaceFilter.cpp
   Algorithms/mitkUIDGenerator.cpp
   Algorithms/mitkVolumeCalculator.cpp
+  Algorithms/mitkTemporalJoinImagesFilter.cpp
 
   Controllers/mitkBaseController.cpp
   Controllers/mitkCallbackFromGUIThread.cpp
   Controllers/mitkCameraController.cpp
   Controllers/mitkCameraRotationController.cpp
   Controllers/mitkLimitedLinearUndo.cpp
   Controllers/mitkOperationEvent.cpp
   Controllers/mitkPlanePositionManager.cpp
   Controllers/mitkProgressBar.cpp
   Controllers/mitkRenderingManager.cpp
   Controllers/mitkSliceNavigationController.cpp
   Controllers/mitkSlicesCoordinator.cpp
   Controllers/mitkStatusBar.cpp
   Controllers/mitkStepper.cpp
   Controllers/mitkTestManager.cpp
   Controllers/mitkUndoController.cpp
   Controllers/mitkVerboseLimitedLinearUndo.cpp
   Controllers/mitkVtkLayerController.cpp
   DataManagement/mitkAnatomicalStructureColorPresets.cpp
   DataManagement/mitkArbitraryTimeGeometry.cpp
   DataManagement/mitkAbstractTransformGeometry.cpp
   DataManagement/mitkAnnotationProperty.cpp
   DataManagement/mitkApplicationCursor.cpp
   DataManagement/mitkApplyTransformMatrixOperation.cpp
   DataManagement/mitkBaseData.cpp
   DataManagement/mitkBaseGeometry.cpp
   DataManagement/mitkBaseProperty.cpp
   DataManagement/mitkChannelDescriptor.cpp
   DataManagement/mitkClippingProperty.cpp
   DataManagement/mitkColorProperty.cpp
   DataManagement/mitkDataNode.cpp
   DataManagement/mitkDataStorage.cpp
   DataManagement/mitkEnumerationProperty.cpp
   DataManagement/mitkFloatPropertyExtension.cpp
   DataManagement/mitkGeometry3D.cpp
   DataManagement/mitkGeometryData.cpp
   DataManagement/mitkGeometryTransformHolder.cpp
   DataManagement/mitkGroupTagProperty.cpp
   DataManagement/mitkGenericIDRelationRule.cpp
   DataManagement/mitkIdentifiable.cpp
   DataManagement/mitkImageAccessorBase.cpp
   DataManagement/mitkImageCaster.cpp
   DataManagement/mitkImageCastPart1.cpp
   DataManagement/mitkImageCastPart2.cpp
   DataManagement/mitkImageCastPart3.cpp
   DataManagement/mitkImageCastPart4.cpp
   DataManagement/mitkImage.cpp
   DataManagement/mitkImageDataItem.cpp
   DataManagement/mitkImageDescriptor.cpp
   DataManagement/mitkImageReadAccessor.cpp
   DataManagement/mitkImageStatisticsHolder.cpp
   DataManagement/mitkImageVtkAccessor.cpp
   DataManagement/mitkImageVtkReadAccessor.cpp
   DataManagement/mitkImageVtkWriteAccessor.cpp
   DataManagement/mitkImageWriteAccessor.cpp
   DataManagement/mitkIntPropertyExtension.cpp
   DataManagement/mitkIPersistenceService.cpp
   DataManagement/mitkIPropertyAliases.cpp
   DataManagement/mitkIPropertyDescriptions.cpp
   DataManagement/mitkIPropertyExtensions.cpp
   DataManagement/mitkIPropertyFilters.cpp
   DataManagement/mitkIPropertyOwner.cpp
   DataManagement/mitkIPropertyPersistence.cpp
   DataManagement/mitkIPropertyProvider.cpp
   DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp
   DataManagement/mitkLandmarkProjector.cpp
   DataManagement/mitkLevelWindow.cpp
   DataManagement/mitkLevelWindowManager.cpp
   DataManagement/mitkLevelWindowPreset.cpp
   DataManagement/mitkLevelWindowProperty.cpp
   DataManagement/mitkLine.cpp
   DataManagement/mitkLookupTable.cpp
   DataManagement/mitkLookupTableProperty.cpp
   DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable
   DataManagement/mitkMaterial.cpp
   DataManagement/mitkMemoryUtilities.cpp
   DataManagement/mitkModalityProperty.cpp
   DataManagement/mitkModifiedLock.cpp
   DataManagement/mitkNodePredicateAnd.cpp
   DataManagement/mitkNodePredicateBase.cpp
   DataManagement/mitkNodePredicateCompositeBase.cpp
   DataManagement/mitkNodePredicateData.cpp
   DataManagement/mitkNodePredicateDataType.cpp
   DataManagement/mitkNodePredicateDataUID.cpp
   DataManagement/mitkNodePredicateDimension.cpp
   DataManagement/mitkNodePredicateFirstLevel.cpp
   DataManagement/mitkNodePredicateFunction.cpp
   DataManagement/mitkNodePredicateGeometry.cpp
   DataManagement/mitkNodePredicateNot.cpp
   DataManagement/mitkNodePredicateOr.cpp
   DataManagement/mitkNodePredicateProperty.cpp
   DataManagement/mitkNodePredicateDataProperty.cpp
   DataManagement/mitkNodePredicateSource.cpp
   DataManagement/mitkNumericConstants.cpp
   DataManagement/mitkPlaneGeometry.cpp
   DataManagement/mitkPlaneGeometryData.cpp
   DataManagement/mitkPlaneOperation.cpp
   DataManagement/mitkPlaneOrientationProperty.cpp
   DataManagement/mitkPointOperation.cpp
   DataManagement/mitkPointSet.cpp
   DataManagement/mitkPointSetShapeProperty.cpp
   DataManagement/mitkProperties.cpp
   DataManagement/mitkPropertyAliases.cpp
   DataManagement/mitkPropertyDescriptions.cpp
   DataManagement/mitkPropertyExtension.cpp
   DataManagement/mitkPropertyExtensions.cpp
   DataManagement/mitkPropertyFilter.cpp
   DataManagement/mitkPropertyFilters.cpp
   DataManagement/mitkPropertyKeyPath.cpp
   DataManagement/mitkPropertyList.cpp
   DataManagement/mitkPropertyListReplacedObserver.cpp
   DataManagement/mitkPropertyNameHelper.cpp
   DataManagement/mitkPropertyObserver.cpp
   DataManagement/mitkPropertyPersistence.cpp
   DataManagement/mitkPropertyPersistenceInfo.cpp
   DataManagement/mitkPropertyRelationRuleBase.cpp
   DataManagement/mitkProportionalTimeGeometry.cpp
   DataManagement/mitkRenderingModeProperty.cpp
   DataManagement/mitkResliceMethodProperty.cpp
   DataManagement/mitkRestorePlanePositionOperation.cpp
   DataManagement/mitkRotationOperation.cpp
   DataManagement/mitkScaleOperation.cpp
   DataManagement/mitkSlicedData.cpp
   DataManagement/mitkSlicedGeometry3D.cpp
   DataManagement/mitkSmartPointerProperty.cpp
   DataManagement/mitkStandaloneDataStorage.cpp
   DataManagement/mitkStringProperty.cpp
   DataManagement/mitkSurface.cpp
   DataManagement/mitkSurfaceOperation.cpp
   DataManagement/mitkSourceImageRelationRule.cpp
   DataManagement/mitkThinPlateSplineCurvedGeometry.cpp
   DataManagement/mitkTimeGeometry.cpp
   DataManagement/mitkTransferFunction.cpp
   DataManagement/mitkTransferFunctionInitializer.cpp
   DataManagement/mitkTransferFunctionProperty.cpp
   DataManagement/mitkTemporoSpatialStringProperty.cpp
   DataManagement/mitkUIDManipulator.cpp
   DataManagement/mitkVector.cpp
   DataManagement/mitkVectorProperty.cpp
   DataManagement/mitkVtkInterpolationProperty.cpp
   DataManagement/mitkVtkRepresentationProperty.cpp
   DataManagement/mitkVtkResliceInterpolationProperty.cpp
   DataManagement/mitkVtkScalarModeProperty.cpp
   DataManagement/mitkVtkVolumeRenderingProperty.cpp
   DataManagement/mitkWeakPointerProperty.cpp
   DataManagement/mitkIPropertyRelations.cpp
   DataManagement/mitkPropertyRelations.cpp
 
   Interactions/mitkAction.cpp
   Interactions/mitkBindDispatcherInteractor.cpp
   Interactions/mitkCrosshairPositionEvent.cpp
   Interactions/mitkDataInteractor.cpp
   Interactions/mitkDispatcher.cpp
   Interactions/mitkDisplayActionEventBroadcast.cpp
   Interactions/mitkDisplayActionEventFunctions.cpp
   Interactions/mitkDisplayActionEventHandler.cpp
   Interactions/mitkDisplayActionEventHandlerDesynchronized.cpp
   Interactions/mitkDisplayActionEventHandlerStd.cpp
   Interactions/mitkDisplayActionEventHandlerSynchronized.cpp
   Interactions/mitkDisplayCoordinateOperation.cpp
   Interactions/mitkDisplayInteractor.cpp
   Interactions/mitkEventConfig.cpp
   Interactions/mitkEventFactory.cpp
   Interactions/mitkEventRecorder.cpp
   Interactions/mitkEventStateMachine.cpp
   Interactions/mitkInteractionEventConst.cpp
   Interactions/mitkInteractionEvent.cpp
   Interactions/mitkInteractionEventHandler.cpp
   Interactions/mitkInteractionEventObserver.cpp
   Interactions/mitkInteractionKeyEvent.cpp
   Interactions/mitkInteractionPositionEvent.cpp
   Interactions/mitkInteractionSchemeSwitcher.cpp
   Interactions/mitkInternalEvent.cpp
   Interactions/mitkMouseDoubleClickEvent.cpp
   Interactions/mitkMouseModeSwitcher.cpp
   Interactions/mitkMouseMoveEvent.cpp
   Interactions/mitkMousePressEvent.cpp
   Interactions/mitkMouseReleaseEvent.cpp
   Interactions/mitkMouseWheelEvent.cpp
   Interactions/mitkPointSetDataInteractor.cpp
   Interactions/mitkSinglePointDataInteractor.cpp
   Interactions/mitkStateMachineAction.cpp
   Interactions/mitkStateMachineCondition.cpp
   Interactions/mitkStateMachineContainer.cpp
   Interactions/mitkStateMachineState.cpp
   Interactions/mitkStateMachineTransition.cpp
   Interactions/mitkVtkEventAdapter.cpp
   Interactions/mitkVtkInteractorStyle.cxx
   Interactions/mitkXML2EventParser.cpp
 
   IO/mitkAbstractFileIO.cpp
   IO/mitkAbstractFileReader.cpp
   IO/mitkAbstractFileWriter.cpp
   IO/mitkCustomMimeType.cpp
   IO/mitkFileReader.cpp
   IO/mitkFileReaderRegistry.cpp
   IO/mitkFileReaderSelector.cpp
   IO/mitkFileReaderWriterBase.cpp
   IO/mitkFileWriter.cpp
   IO/mitkFileWriterRegistry.cpp
   IO/mitkFileWriterSelector.cpp
   IO/mitkGeometry3DToXML.cpp
   IO/mitkIFileIO.cpp
   IO/mitkIFileReader.cpp
   IO/mitkIFileWriter.cpp
   IO/mitkGeometryDataReaderService.cpp
   IO/mitkGeometryDataWriterService.cpp
   IO/mitkImageGenerator.cpp
   IO/mitkImageVtkLegacyIO.cpp
   IO/mitkImageVtkXmlIO.cpp
   IO/mitkIMimeTypeProvider.cpp
   IO/mitkIOConstants.cpp
   IO/mitkIOMimeTypes.cpp
   IO/mitkIOUtil.cpp
   IO/mitkItkImageIO.cpp
   IO/mitkItkLoggingAdapter.cpp
   IO/mitkLegacyFileReaderService.cpp
   IO/mitkLegacyFileWriterService.cpp
   IO/mitkLocaleSwitch.cpp
   IO/mitkLog.cpp
   IO/mitkMimeType.cpp
   IO/mitkMimeTypeProvider.cpp
   IO/mitkOperation.cpp
   IO/mitkPixelType.cpp
   IO/mitkPointSetReaderService.cpp
   IO/mitkPointSetWriterService.cpp
   IO/mitkProportionalTimeGeometryToXML.cpp
   IO/mitkRawImageFileReader.cpp
   IO/mitkStandardFileLocations.cpp
   IO/mitkSurfaceStlIO.cpp
   IO/mitkSurfaceVtkIO.cpp
   IO/mitkSurfaceVtkLegacyIO.cpp
   IO/mitkSurfaceVtkXmlIO.cpp
   IO/mitkVtkLoggingAdapter.cpp
   IO/mitkPreferenceListReaderOptionsFunctor.cpp
 
   Rendering/mitkAbstractAnnotationRenderer.cpp
   Rendering/mitkAnnotationUtils.cpp
   Rendering/mitkBaseRenderer.cpp
   #Rendering/mitkGLMapper.cpp Moved to deprecated LegacyGL Module
   Rendering/mitkGradientBackground.cpp
   Rendering/mitkImageVtkMapper2D.cpp
   Rendering/mitkMapper.cpp
   Rendering/mitkAnnotation.cpp
   Rendering/mitkPlaneGeometryDataMapper2D.cpp
   Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp
   Rendering/mitkPointSetVtkMapper2D.cpp
   Rendering/mitkPointSetVtkMapper3D.cpp
   Rendering/mitkRenderWindowBase.cpp
   Rendering/mitkRenderWindow.cpp
   Rendering/mitkRenderWindowFrame.cpp
   #Rendering/mitkSurfaceGLMapper2D.cpp Moved to deprecated LegacyGL Module
   Rendering/mitkSurfaceVtkMapper2D.cpp
   Rendering/mitkSurfaceVtkMapper3D.cpp
   Rendering/mitkVtkEventProvider.cpp
   Rendering/mitkVtkMapper.cpp
   Rendering/mitkVtkPropRenderer.cpp
   Rendering/mitkVtkWidgetRendering.cpp
   Rendering/vtkMitkLevelWindowFilter.cpp
   Rendering/vtkMitkRectangleProp.cpp
   Rendering/vtkMitkRenderProp.cpp
   Rendering/vtkMitkThickSlicesFilter.cpp
   Rendering/vtkNeverTranslucentTexture.cpp
 )
 
 set(RESOURCE_FILES
 Interactions/globalConfig.xml
 Interactions/DisplayInteraction.xml
 Interactions/DisplayConfig.xml
 Interactions/DisplayConfigPACS.xml
 Interactions/DisplayConfigPACSPan.xml
 Interactions/DisplayConfigPACSScroll.xml
 Interactions/DisplayConfigPACSZoom.xml
 Interactions/DisplayConfigPACSLevelWindow.xml
 Interactions/DisplayConfigMITK.xml
 Interactions/DisplayConfigMITKNoCrosshair.xml
 Interactions/DisplayConfigMITKRotation.xml
 Interactions/DisplayConfigMITKRotationUnCoupled.xml
 Interactions/DisplayConfigMITKSwivel.xml
 Interactions/DisplayConfigMITKLimited.xml
 Interactions/PointSet.xml
 Interactions/Legacy/StateMachine.xml
 Interactions/Legacy/DisplayConfigMITKTools.xml
 Interactions/PointSetConfig.xml
 
 mitkLevelWindowPresets.xml
 mitkAnatomicalStructureColorPresets.xml
 )
diff --git a/Modules/Core/include/mitkLocaleSwitch.h b/Modules/Core/include/mitkLocaleSwitch.h
index 96af6c09b6..601ac02d63 100644
--- a/Modules/Core/include/mitkLocaleSwitch.h
+++ b/Modules/Core/include/mitkLocaleSwitch.h
@@ -1,61 +1,72 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef __mitkLocaleSwitch_h
 #define __mitkLocaleSwitch_h
 
 #include "MitkCoreExports.h"
 
 namespace mitk
 {
   /**
     \brief Convenience class to temporarily change the current locale.
 
     This helper class can be used to switch to a specific locale
     for a couple of operations. Once the class is destroyed, the previous
     locale will be restored. This avoids calling or forgetting to call
     setlocale() in multiple return locations.
 
     Typically this is used to switch to a "C" locale when parsing or
     printing numbers, in order to consistently get "." and not "," as
     a decimal separator.
 
+    WARNING: Please be aware that using setlocale and there for is not thread
+    safe. So use this class with care (see tast T24295 for more information.
+    This switch is especially use full if you have to deal with third party code
+    where you have to controll the locale via set locale
     \code
-
-    std::string toString(int number)
     {
       mitk::LocaleSwitch localeSwitch("C");// installs C locale until the end of the function
 
-      std::stringstream parser;
-      parser << number;
+      ExternalLibraryCall(); //that might throw or what ever.
+    }
+    \endcode
 
+    If you just want to control you own stringstream operations use imbue instead, as it is
+    threadsafe. E.G.:
+    \code
+    std::string toString(int number)
+    {
+      std::ostringstream parser;
+      parser.imbue(std::locale("C"));
+      parser << number;
       return parser.str();
     }
     \endcode
   */
 
   struct MITKCORE_EXPORT LocaleSwitch
   {
     explicit LocaleSwitch(const char *newLocale);
 
     ~LocaleSwitch();
 
     LocaleSwitch(LocaleSwitch &) = delete;
     LocaleSwitch operator=(LocaleSwitch &) = delete;
 
   private:
     struct Impl;
     Impl *m_LocaleSwitchImpl;
   };
 }
 
 #endif // __mitkLocaleSwitch_h
diff --git a/Modules/Core/include/mitkTemporalJoinImagesFilter.h b/Modules/Core/include/mitkTemporalJoinImagesFilter.h
new file mode 100644
index 0000000000..b03f905221
--- /dev/null
+++ b/Modules/Core/include/mitkTemporalJoinImagesFilter.h
@@ -0,0 +1,62 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#ifndef TEMPORALJOINIMAGESFILTER_H
+#define TEMPORALJOINIMAGESFILTER_H
+
+
+#include "mitkImageToImageFilter.h"
+#include "mitkCommon.h"
+
+#include "MitkCoreExports.h"
+
+namespace mitk
+{
+  /** Filter that takes n mitk images as inputs and fuse them to a new image (with n time points).
+  Preconditions of this filter are, that all input images have the same pixel type and geometry.
+  The sequence of frames in the output image is the same then the sequence of inputs.
+  It no time bounds are defined the dynamic image will start at 0 ms and each time step has a duration
+  of 1 ms.*/
+  class MITKCORE_EXPORT TemporalJoinImagesFilter : public ImageToImageFilter
+  {
+  public:
+    mitkClassMacro(TemporalJoinImagesFilter, ImageToImageFilter);
+    itkFactorylessNewMacro(TemporalJoinImagesFilter);
+
+    typedef std::vector<mitk::TimePointType> TimeBoundsVectorType;
+
+    itkGetConstMacro(FirstMinTimeBound, mitk::TimePointType);
+    /**Set custom min time bound for the first time step.*/
+    itkSetMacro(FirstMinTimeBound, mitk::TimePointType);
+
+    itkGetConstMacro(MaxTimeBounds, TimeBoundsVectorType);
+    /**Set custom max time bounds for all time steps.*/
+    void SetMaxTimeBounds(const TimeBoundsVectorType &bounds);
+
+  protected:
+    TemporalJoinImagesFilter(){};
+    ~TemporalJoinImagesFilter() override{};
+
+    void GenerateInputRequestedRegion() override;
+
+    void GenerateOutputInformation() override;
+
+    void GenerateData() override;
+
+  private:
+    TimeBoundsVectorType m_MaxTimeBounds;
+    mitk::TimePointType m_FirstMinTimeBound = 0.0;
+  };
+}
+
+
+#endif // MODELSIGNALIMAGEGENERATOR_H
diff --git a/Modules/Core/src/Algorithms/mitkTemporalJoinImagesFilter.cpp b/Modules/Core/src/Algorithms/mitkTemporalJoinImagesFilter.cpp
new file mode 100644
index 0000000000..7b22a3760f
--- /dev/null
+++ b/Modules/Core/src/Algorithms/mitkTemporalJoinImagesFilter.cpp
@@ -0,0 +1,122 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#include "mitkTemporalJoinImagesFilter.h"
+
+#include <numeric>
+
+#include "mitkArbitraryTimeGeometry.h"
+#include "mitkImageReadAccessor.h"
+#include "mitkTemporoSpatialStringProperty.h"
+
+void mitk::TemporalJoinImagesFilter::SetMaxTimeBounds(const TimeBoundsVectorType& timeBounds)
+{
+  m_MaxTimeBounds = timeBounds;
+  this->Modified();
+}
+
+void mitk::TemporalJoinImagesFilter::GenerateInputRequestedRegion()
+{
+  Superclass::GenerateInputRequestedRegion();
+  const auto nrOfInputs = this->GetNumberOfInputs();
+  for (DataObjectPointerArraySizeType pos = 0; pos < nrOfInputs; ++pos)
+  {
+    this->GetInput(pos)->SetRequestedRegionToLargestPossibleRegion();
+  }
+}
+
+void mitk::TemporalJoinImagesFilter::GenerateOutputInformation()
+{
+  mitk::Image::ConstPointer input = this->GetInput();
+  mitk::Image::Pointer output = this->GetOutput();
+
+  const auto nrOfInputs = this->GetNumberOfInputs();
+  auto timeBounds = m_MaxTimeBounds;
+
+  if (timeBounds.empty())
+  {
+    timeBounds.resize(nrOfInputs);
+    std::iota(timeBounds.begin(), timeBounds.end(), 1.0);
+  }
+  else if(timeBounds.size() != nrOfInputs)
+  {
+    mitkThrow() << "User defined max time bounds do not match the number if inputs (" << nrOfInputs << "). Size of max timebounds is " << timeBounds.size() << ", but it should be " << nrOfInputs << ".";
+  }
+
+  timeBounds.insert(timeBounds.begin(), m_FirstMinTimeBound);
+
+  auto timeGeo = mitk::ArbitraryTimeGeometry::New();
+  timeGeo->ReserveSpaceForGeometries(nrOfInputs);
+
+  for (DataObjectPointerArraySizeType pos = 0; pos < nrOfInputs; ++pos)
+  {
+    timeGeo->AppendNewTimeStepClone(this->GetInput(pos)->GetGeometry(), timeBounds[pos], timeBounds[pos + 1]);
+  }
+  output->Initialize(input->GetPixelType(), *timeGeo);
+
+  auto newPropList = input->GetPropertyList()->Clone();
+  for (DataObjectPointerArraySizeType pos = 1; pos < nrOfInputs; ++pos)
+  {
+    const auto otherList = this->GetInput(pos)->GetPropertyList();
+    for (const auto& key : otherList->GetPropertyKeys())
+    {
+      auto prop = newPropList->GetProperty(key);
+      if (prop == nullptr)
+      {
+        newPropList->SetProperty(key, otherList->GetProperty(key)->Clone());
+      }
+      else
+      {
+        auto tempoSpatialProp = dynamic_cast<mitk::TemporoSpatialStringProperty*>(prop);
+        auto oTempoSpatialProp = dynamic_cast<mitk::TemporoSpatialStringProperty*>(otherList->GetProperty(key));
+        if (prop != nullptr && oTempoSpatialProp != nullptr)
+        {
+          auto availabelSlices = oTempoSpatialProp->GetAvailableSlices(0);
+
+          for (const auto& sliceID : availabelSlices)
+          {
+            tempoSpatialProp->SetValue(pos, sliceID, oTempoSpatialProp->GetValueBySlice(sliceID));
+          }
+        }
+        //other prop types can be ignored, we only use the values of the first frame.
+      }
+    }
+  }
+
+  output->SetPropertyList(newPropList);
+}
+
+
+void mitk::TemporalJoinImagesFilter::GenerateData()
+{
+  mitk::Image::Pointer output = this->GetOutput();
+  mitk::Image::ConstPointer refInput = this->GetInput();
+  const auto nrOfInputs = this->GetNumberOfInputs();
+
+  for (DataObjectPointerArraySizeType pos = 0; pos < nrOfInputs; ++pos)
+  {
+    if (!Equal(*(refInput->GetGeometry()), *(this->GetInput(pos)->GetGeometry()), mitk::eps, false))
+    {
+      mitkThrow() << "Cannot fuse images. At least image #" << pos << " has another geometry than the first image.";
+    }
+    if (refInput->GetPixelType() != this->GetInput(pos)->GetPixelType())
+    {
+      mitkThrow() << "Cannot fuse images. At least image #" << pos << " has another pixeltype than the first image.";
+    }
+  }
+
+  for (DataObjectPointerArraySizeType pos = 0; pos < nrOfInputs; ++pos)
+  {
+    mitk::ImageReadAccessor accessor(this->GetInput(pos));
+    output->SetVolume(accessor.GetData(), pos);
+  }
+}
diff --git a/Modules/Core/test/files.cmake b/Modules/Core/test/files.cmake
index f98fb8a5df..5efc282bfa 100644
--- a/Modules/Core/test/files.cmake
+++ b/Modules/Core/test/files.cmake
@@ -1,193 +1,194 @@
 # tests with no extra command line parameter
 set(MODULE_TESTS
   # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code.
   #
   #     Example: #mitkMyTest #this test is commented out because of bug 12345
   #
   # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that
   # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and
   # mark it as critical.
 
   ################## DISABLED TESTS #################################################
   #mitkAbstractTransformGeometryTest.cpp #seems as tested class mitkExternAbstractTransformGeometry doesnt exist any more
   #mitkStateMachineContainerTest.cpp #rewrite test, indirect since no longer exported Bug 14529
   #mitkRegistrationBaseTest.cpp #tested class  mitkRegistrationBase doesn't exist any more
   #mitkSegmentationInterpolationTest.cpp #file doesn't exist!
   #mitkPipelineSmartPointerCorrectnessTest.cpp #file doesn't exist!
   #mitkITKThreadingTest.cpp #test outdated because itk::Semaphore was removed from ITK
   #mitkAbstractTransformPlaneGeometryTest.cpp #mitkVtkAbstractTransformPlaneGeometry doesn't exist any more
   #mitkTestUtilSharedLibrary.cpp #Linker problem with this test...
   #mitkTextOverlay2DSymbolsRenderingTest.cpp #Implementation of the tested feature is not finished yet. Ask Christoph or see bug 15104 for details.
 
   ################# RUNNING TESTS ###################################################
   mitkAccessByItkTest.cpp
   mitkCoreObjectFactoryTest.cpp
   mitkDataNodeTest.cpp
   mitkMaterialTest.cpp
   mitkActionTest.cpp
   mitkDispatcherTest.cpp
   mitkEnumerationPropertyTest.cpp
   mitkFileReaderRegistryTest.cpp
   #mitkFileWriterRegistryTest.cpp
   mitkFloatToStringTest.cpp
   mitkGenericPropertyTest.cpp
   mitkGeometry3DTest.cpp
   mitkGeometry3DEqualTest.cpp
   mitkGeometryDataIOTest.cpp
   mitkGeometryDataToSurfaceFilterTest.cpp
   mitkImageCastTest.cpp
   mitkImageDataItemTest.cpp
   mitkImageGeneratorTest.cpp
   mitkIOUtilTest.cpp
   mitkBaseDataTest.cpp
   mitkImportItkImageTest.cpp
   mitkGrabItkImageMemoryTest.cpp
   mitkInstantiateAccessFunctionTest.cpp
   mitkLevelWindowTest.cpp
   mitkMessageTest.cpp
   mitkPixelTypeTest.cpp
   mitkPlaneGeometryTest.cpp
   mitkPointSetTest.cpp
   mitkPointSetEqualTest.cpp
   mitkPointSetFileIOTest.cpp
   mitkPointSetOnEmptyTest.cpp
   mitkPointSetLocaleTest.cpp
   mitkPointSetWriterTest.cpp
   mitkPointSetPointOperationsTest.cpp
   mitkProgressBarTest.cpp
   mitkPropertyTest.cpp
   mitkPropertyListTest.cpp
   mitkPropertyPersistenceTest.cpp
   mitkPropertyPersistenceInfoTest.cpp
   mitkPropertyRelationRuleBaseTest.cpp
   mitkPropertyRelationsTest.cpp
   mitkSlicedGeometry3DTest.cpp
   mitkSliceNavigationControllerTest.cpp
   mitkSurfaceTest.cpp
   mitkSurfaceEqualTest.cpp
   mitkSurfaceToSurfaceFilterTest.cpp
   mitkTimeGeometryTest.cpp
   mitkProportionalTimeGeometryTest.cpp
   mitkUndoControllerTest.cpp
   mitkVtkWidgetRenderingTest.cpp
   mitkVerboseLimitedLinearUndoTest.cpp
   mitkWeakPointerTest.cpp
   mitkTransferFunctionTest.cpp
   mitkStepperTest.cpp
   mitkRenderingManagerTest.cpp
   mitkCompositePixelValueToStringTest.cpp
   vtkMitkThickSlicesFilterTest.cpp
   mitkNodePredicateSourceTest.cpp
   mitkNodePredicateDataPropertyTest.cpp
   mitkNodePredicateFunctionTest.cpp
   mitkVectorTest.cpp
   mitkClippedSurfaceBoundsCalculatorTest.cpp
   mitkExceptionTest.cpp
   mitkExtractSliceFilterTest.cpp
   mitkLogTest.cpp
   mitkImageDimensionConverterTest.cpp
   mitkLoggingAdapterTest.cpp
   mitkUIDGeneratorTest.cpp
   mitkPlanePositionManagerTest.cpp
   mitkAffineTransformBaseTest.cpp
   mitkPropertyAliasesTest.cpp
   mitkPropertyDescriptionsTest.cpp
   mitkPropertyExtensionsTest.cpp
   mitkPropertyFiltersTest.cpp
   mitkPropertyKeyPathTest.cpp
   mitkTinyXMLTest.cpp
   mitkRawImageFileReaderTest.cpp
   mitkInteractionEventTest.cpp
   mitkLookupTableTest.cpp
   mitkSTLFileReaderTest.cpp
   mitkPointTypeConversionTest.cpp
   mitkVectorTypeConversionTest.cpp
   mitkMatrixTypeConversionTest.cpp
   mitkArrayTypeConversionTest.cpp
   mitkSurfaceToImageFilterTest.cpp
   mitkBaseGeometryTest.cpp
   mitkImageToSurfaceFilterTest.cpp
   mitkEqualTest.cpp
   mitkLineTest.cpp
   mitkArbitraryTimeGeometryTest.cpp
   mitkItkImageIOTest.cpp
   mitkLevelWindowManagerCppUnitTest.cpp
   mitkVectorPropertyTest.cpp
   mitkTemporoSpatialStringPropertyTest.cpp
   mitkPropertyNameHelperTest.cpp
   mitkNodePredicateGeometryTest.cpp
   mitkPreferenceListReaderOptionsFunctorTest.cpp
   mitkGenericIDRelationRuleTest.cpp
   mitkSourceImageRelationRuleTest.cpp
   mitkPointSetDataInteractorTest.cpp #since mitkInteractionTestHelper is currently creating a vtkRenderWindow
   mitkSurfaceVtkMapper2DTest.cpp #new rendering test in CppUnit style
   mitkSurfaceVtkMapper2D3DTest.cpp # comparisons/consistency 2D/3D
+  mitkTemporalJoinImagesFilterTest.cpp
 )
 
 # test with image filename as an extra command line parameter
 set(MODULE_IMAGE_TESTS
   mitkImageTimeSelectorTest.cpp #only runs on images
   mitkImageAccessorTest.cpp #only runs on images
 )
 
 set(MODULE_SURFACE_TESTS
   mitkSurfaceVtkWriterTest.cpp #only runs on surfaces
 )
 
 # list of images for which the tests are run
 set(MODULE_TESTIMAGE
   US4DCyl.nrrd
   Pic3D.nrrd
   Pic2DplusT.nrrd
   BallBinary30x30x30.nrrd
   Png2D-bw.png
 )
 set(MODULE_TESTSURFACE
   binary.stl
   ball.stl
 )
 
 set(MODULE_CUSTOM_TESTS
     mitkDataStorageTest.cpp
     mitkDataNodeTest.cpp
     mitkEventConfigTest.cpp
     mitkPointSetLocaleTest.cpp
     mitkImageTest.cpp
     mitkImageVtkMapper2DTest.cpp
     mitkImageVtkMapper2DLevelWindowTest.cpp
     mitkImageVtkMapper2DOpacityTest.cpp
     mitkImageVtkMapper2DResliceInterpolationPropertyTest.cpp
     mitkImageVtkMapper2DColorTest.cpp
     mitkImageVtkMapper2DSwivelTest.cpp
     mitkImageVtkMapper2DTransferFunctionTest.cpp
     mitkImageVtkMapper2DOpacityTransferFunctionTest.cpp
     mitkImageVtkMapper2DLookupTableTest.cpp
     mitkSurfaceVtkMapper3DTest.cpp
     mitkVolumeCalculatorTest.cpp
     mitkLevelWindowManagerTest.cpp
     mitkPointSetVtkMapper2DTest.cpp
     mitkPointSetVtkMapper2DImageTest.cpp
     mitkPointSetVtkMapper2DGlyphTypeTest.cpp
     mitkPointSetVtkMapper2DTransformedPointsTest.cpp
     mitkVTKRenderWindowSizeTest.cpp
     mitkMultiComponentImageDataComparisonFilterTest.cpp
     mitkImageToItkTest.cpp
     mitkImageSliceSelectorTest.cpp
     mitkPointSetReaderTest.cpp
     mitkImageEqualTest.cpp
     mitkRotatedSlice4DTest.cpp
     mitkPlaneGeometryDataMapper2DTest.cpp
 )
 
 # Currently not working on windows because of a rendering timing issue
 # see bug 18083 for details
 if(NOT WIN32)
  set(MODULE_CUSTOM_TESTS ${MODULE_CUSTOM_TESTS} mitkSurfaceDepthSortingTest.cpp)
 endif()
 
 set(RESOURCE_FILES
   Interactions/AddAndRemovePoints.xml
   Interactions/globalConfig.xml
   Interactions/StatemachineTest.xml
   Interactions/StatemachineConfigTest.xml
 )
diff --git a/Modules/Core/test/mitkTemporalJoinImagesFilterTest.cpp b/Modules/Core/test/mitkTemporalJoinImagesFilterTest.cpp
new file mode 100644
index 0000000000..4f2035ef7e
--- /dev/null
+++ b/Modules/Core/test/mitkTemporalJoinImagesFilterTest.cpp
@@ -0,0 +1,188 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#include "mitkImagePixelReadAccessor.h"
+
+#include "mitkTemporalJoinImagesFilter.h"
+#include "mitkTestFixture.h"
+#include "mitkTestingMacros.h"
+
+#include <limits>
+#include "mitkTestDynamicImageGenerator.h"
+#include "mitkStringProperty.h"
+#include "mitkTemporoSpatialStringProperty.h"
+
+class mitkTemporalJoinImagesFilterTestSuite : public mitk::TestFixture
+{
+  CPPUNIT_TEST_SUITE(mitkTemporalJoinImagesFilterTestSuite);
+
+  MITK_TEST(InvalidUsage);
+  MITK_TEST(FuseDefault);
+  MITK_TEST(FuseUseDefinedTimeBounds);
+
+  CPPUNIT_TEST_SUITE_END();
+
+private:
+  mitk::Image::Pointer t0;
+  mitk::Image::Pointer t1;
+  mitk::Image::Pointer t2;
+
+  mitk::Image::Pointer invalidPixel;
+  mitk::Image::Pointer invalidGeometry;
+
+public:
+  void setUp() override
+  {
+    t0 = mitk::GenerateTestFrame(1);
+    t0->SetProperty("all", mitk::StringProperty::New("all_0"));
+    t0->SetProperty("ts", mitk::TemporoSpatialStringProperty::New("ts_0"));
+
+    t1 = mitk::GenerateTestFrame(20);
+    t1->SetProperty("all", mitk::StringProperty::New("all_1"));
+    t1->SetProperty("ts", mitk::TemporoSpatialStringProperty::New("ts_1"));
+    t1->SetProperty("special", mitk::StringProperty::New("special_1"));
+
+    t2 = mitk::GenerateTestFrame(300);
+    t2->SetProperty("all", mitk::StringProperty::New("all_2"));
+    t2->SetProperty("ts", mitk::TemporoSpatialStringProperty::New("ts_2"));
+
+    invalidPixel = mitk::Image::New();
+    invalidPixel->Initialize(mitk::MakePixelType<int, int, 1>(), *(t0->GetTimeGeometry()));
+
+    invalidGeometry = mitk::Image::New();
+    invalidGeometry->Initialize(t0);
+    invalidGeometry->SetGeometry(mitk::Geometry3D::New());
+  }
+
+  void tearDown() override {}
+
+  void InvalidUsage()
+  {
+    auto filter = mitk::TemporalJoinImagesFilter::New();
+
+    filter->SetInput(0, t0);
+    filter->SetInput(1, invalidPixel);
+
+    CPPUNIT_ASSERT_THROW(filter->Update(), mitk::Exception);
+
+    filter = mitk::TemporalJoinImagesFilter::New();
+
+    filter->SetInput(0, t0);
+    filter->SetInput(1, invalidGeometry);
+
+    CPPUNIT_ASSERT_THROW(filter->Update(), mitk::Exception);
+
+    filter = mitk::TemporalJoinImagesFilter::New();
+
+    filter->SetInput(0, t0);
+    filter->SetInput(1, t1);
+    filter->SetMaxTimeBounds({ 3 });
+
+    CPPUNIT_ASSERT_THROW(filter->Update(), mitk::Exception);
+  }
+
+  void FuseDefault()
+  {
+    auto filter = mitk::TemporalJoinImagesFilter::New();
+
+    filter->SetInput(0, t0);
+    filter->SetInput(1, t1);
+    filter->SetInput(2, t2);
+
+    filter->Update();
+    auto output = filter->GetOutput();
+
+    CPPUNIT_ASSERT(output->GetTimeSteps() == 3);
+    auto allProp = output->GetProperty("all");
+    CPPUNIT_ASSERT(allProp->GetValueAsString() == "all_0");
+    auto specialProp = output->GetProperty("special");
+    CPPUNIT_ASSERT(specialProp->GetValueAsString() == "special_1");
+    auto tsProp = dynamic_cast<const mitk::TemporoSpatialStringProperty*>(output->GetProperty("ts").GetPointer());
+    CPPUNIT_ASSERT(tsProp->GetValueByTimeStep(0) == "ts_0");
+    CPPUNIT_ASSERT(tsProp->GetValueByTimeStep(1) == "ts_1");
+    CPPUNIT_ASSERT(tsProp->GetValueByTimeStep(2) == "ts_2");
+
+    CPPUNIT_ASSERT(mitk::Equal(*(t0->GetGeometry()), *(output->GetGeometry()), mitk::eps, true));
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMinimumTimePoint(0) == 0.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMaximumTimePoint(0) == 1.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMinimumTimePoint(1) == 1.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMaximumTimePoint(1) == 2.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMinimumTimePoint(2) == 2.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMaximumTimePoint(2) == 3.);
+
+    mitk::ImagePixelReadAccessor<mitk::ScalarType, 4> accessor(output);
+    itk::Index<4> testIndex0;
+    testIndex0.Fill(2);
+    testIndex0[3] = 0;
+    itk::Index<4> testIndex1;
+    testIndex1.Fill(2);
+    testIndex1[3] = 1;
+    itk::Index<4> testIndex2;
+    testIndex2.Fill(2);
+    testIndex2[3] = 2;
+
+    CPPUNIT_ASSERT_EQUAL(28., accessor.GetPixelByIndex(testIndex0));
+    CPPUNIT_ASSERT_EQUAL(180., accessor.GetPixelByIndex(testIndex1));
+    CPPUNIT_ASSERT_EQUAL(2420., accessor.GetPixelByIndex(testIndex2));
+  }
+
+  void FuseUseDefinedTimeBounds()
+  {
+    auto filter = mitk::TemporalJoinImagesFilter::New();
+
+    filter->SetInput(0, t0);
+    filter->SetInput(1, t1);
+    filter->SetInput(2, t2);
+
+    filter->SetFirstMinTimeBound(10);
+    filter->SetMaxTimeBounds({ 20,30,40 });
+
+    filter->Update();
+    auto output = filter->GetOutput();
+
+    CPPUNIT_ASSERT(output->GetTimeSteps() == 3);
+    auto allProp = output->GetProperty("all");
+    CPPUNIT_ASSERT(allProp->GetValueAsString() == "all_0");
+    auto specialProp = output->GetProperty("special");
+    CPPUNIT_ASSERT(specialProp->GetValueAsString() == "special_1");
+    auto tsProp = dynamic_cast<const mitk::TemporoSpatialStringProperty*>(output->GetProperty("ts").GetPointer());
+    CPPUNIT_ASSERT(tsProp->GetValueByTimeStep(0) == "ts_0");
+    CPPUNIT_ASSERT(tsProp->GetValueByTimeStep(1) == "ts_1");
+    CPPUNIT_ASSERT(tsProp->GetValueByTimeStep(2) == "ts_2");
+
+    CPPUNIT_ASSERT(mitk::Equal(*(t0->GetGeometry()), *(output->GetGeometry()), mitk::eps, true));
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMinimumTimePoint(0) == 10.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMaximumTimePoint(0) == 20.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMinimumTimePoint(1) == 20.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMaximumTimePoint(1) == 30.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMinimumTimePoint(2) == 30.);
+    CPPUNIT_ASSERT(output->GetTimeGeometry()->GetMaximumTimePoint(2) == 40.);
+
+    mitk::ImagePixelReadAccessor<mitk::ScalarType, 4> accessor(output);
+    itk::Index<4> testIndex0;
+    testIndex0.Fill(2);
+    testIndex0[3] = 0;
+    itk::Index<4> testIndex1;
+    testIndex1.Fill(2);
+    testIndex1[3] = 1;
+    itk::Index<4> testIndex2;
+    testIndex2.Fill(2);
+    testIndex2[3] = 2;
+
+    CPPUNIT_ASSERT_EQUAL(28., accessor.GetPixelByIndex(testIndex0));
+    CPPUNIT_ASSERT_EQUAL(180., accessor.GetPixelByIndex(testIndex1));
+    CPPUNIT_ASSERT_EQUAL(2420., accessor.GetPixelByIndex(testIndex2));
+  }
+
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkTemporalJoinImagesFilter)
diff --git a/Modules/ModelFit/cmdapps/CMakeLists.txt b/Modules/ModelFit/cmdapps/CMakeLists.txt
index f78ad56dda..cda6e31973 100644
--- a/Modules/ModelFit/cmdapps/CMakeLists.txt
+++ b/Modules/ModelFit/cmdapps/CMakeLists.txt
@@ -1,34 +1,35 @@
 option(BUILD_ModelFitMiniApps "Build commandline tools for the ModelFit module" OFF)
 
 if(BUILD_ModelFitMiniApps OR MITK_BUILD_ALL_APPS)
 
   # needed include directories
   include_directories(
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_BINARY_DIR}
     )
     # list of miniapps
     # if an app requires additional dependencies
     # they are added after a "^^" and separated by "_"
     set( miniapps
     GenericFittingMiniApp^^
     PixelDumpMiniApp^^
+    Fuse3Dto4DImageMiniApp^^
     )
 
     foreach(miniapp ${miniapps})
       # extract mini app name and dependencies
       string(REPLACE "^^" "\\;" miniapp_info ${miniapp})
       set(miniapp_info_list ${miniapp_info})
       list(GET miniapp_info_list 0 appname)
       list(GET miniapp_info_list 1 raw_dependencies)
       string(REPLACE "_" "\\;" dependencies "${raw_dependencies}")
       set(dependencies_list ${dependencies})
 
       mitkFunctionCreateCommandLineApp(
         NAME ${appname}
         DEPENDS MitkCore MitkModelFit ${dependencies_list}
         PACKAGE_DEPENDS ITK
       )
     endforeach()
 
 endif(BUILD_ModelFitMiniApps OR MITK_BUILD_ALL_APPS)
diff --git a/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp b/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp
new file mode 100644
index 0000000000..a2cd40129f
--- /dev/null
+++ b/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp
@@ -0,0 +1,167 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+// std includes
+#include <string>
+#include <numeric>
+
+// itk includes
+#include "itksys/SystemTools.hxx"
+
+// CTK includes
+#include "mitkCommandLineParser.h"
+
+// MITK includes
+#include <mitkIOUtil.h>
+#include <mitkPreferenceListReaderOptionsFunctor.h>
+#include <mitkTemporalJoinImagesFilter.h>
+
+mitkCommandLineParser::StringContainerType inFilenames;
+std::string outFileName;
+
+std::vector<mitk::Image::Pointer> images;
+std::vector<mitk::TimePointType> timebounds;
+
+void setupParser(mitkCommandLineParser& parser)
+{
+    // set general information about your MiniApp
+    parser.setCategory("Dynamic Data Analysis Tools");
+    parser.setTitle("Fuse 3D to 4D Image");
+    parser.setDescription("MiniApp that allows to fuse several 3D images (with same geometry) into a 3D+t (4D) image that can be processed as dynamic data.");
+    parser.setContributor("DKFZ MIC");
+    //! [create parser]
+
+    //! [add arguments]
+    // how should arguments be prefixed
+    parser.setArgumentPrefix("--", "-");
+    // add each argument, unless specified otherwise each argument is optional
+    // see mitkCommandLineParser::addArgument for more information
+    parser.beginGroup("Required I/O parameters");
+    parser.addArgument(
+        "inputs", "i", mitkCommandLineParser::StringList, "Input files", "Pathes to the input images that should be fused", us::Any(), false, false, false, mitkCommandLineParser::Input);
+    parser.addArgument("output",
+        "o",
+        mitkCommandLineParser::File,
+        "Output file path",
+        "Path to the fused 3D+t image.",
+        us::Any(),
+        false, false, false, mitkCommandLineParser::Output);
+    parser.endGroup();
+
+    parser.beginGroup("Optional parameters");
+    parser.addArgument(
+        "time", "t", mitkCommandLineParser::StringList, "Time bounds", "Defines the time geometry of the resulting dynamic image in [ms]. The first number is the start time point of the first time step. All other numbers are the max bound of a time step. So the structure is [minBound0 maxBound1 [maxBound2 [... maxBoundN]]]; e.g. \"2 3.5 10\" encodes a time geometry with two time steps and that starts at 2 ms and the second time step starts at 3.5 ms and ends at 10 ms. If not set e propertional time geometry with 1 ms duration will be generated!", us::Any(), true, false, false, mitkCommandLineParser::Input);
+    parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text");
+    parser.endGroup();
+    //! [add arguments]
+}
+
+bool configureApplicationSettings(std::map<std::string, us::Any> parsedArgs)
+{
+    if (parsedArgs.size() == 0)
+        return false;
+
+    inFilenames = us::any_cast<mitkCommandLineParser::StringContainerType>(parsedArgs["inputs"]);
+    outFileName = us::any_cast<std::string>(parsedArgs["output"]);
+
+    if (parsedArgs.count("time"))
+    {
+        auto timeBoundsStr = us::any_cast<mitkCommandLineParser::StringContainerType>(parsedArgs["time"]);
+        for (const auto& timeBoundStr : timeBoundsStr)
+        {
+          std::istringstream stream;
+          stream.imbue(std::locale("C"));
+          stream.str(timeBoundStr);
+          mitk::TimePointType time = 0 ;
+          stream >> time;
+          timebounds.emplace_back(time);
+        }
+    }
+
+    return true;
+}
+
+int main(int argc, char* argv[])
+{
+    mitkCommandLineParser parser;
+    setupParser(parser);
+
+    mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" });
+
+    const std::map<std::string, us::Any>& parsedArgs = parser.parseArguments(argc, argv);
+    if (!configureApplicationSettings(parsedArgs))
+    {
+        return EXIT_FAILURE;
+    };
+
+    // Show a help message
+    if (parsedArgs.count("help") || parsedArgs.count("h"))
+    {
+        std::cout << parser.helpText();
+        return EXIT_SUCCESS;
+    }
+
+    if (timebounds.empty())
+    {
+      timebounds.resize(inFilenames.size()+1);
+      std::iota(timebounds.begin(), timebounds.end(), 0.0);
+    }
+    else if (inFilenames.size() + 1 != timebounds.size())
+    {
+      std::cerr << "Cannot fuse images. Explicitly specified time bounds do not match. Use --help for more information on how to specify time bounds correctly.";
+      return EXIT_FAILURE;
+    };
+
+    //! [do processing]
+    try
+    {
+      std::cout << "Load images:" << std::endl;
+
+      auto filter = mitk::TemporalJoinImagesFilter::New();
+
+      unsigned int step = 0;
+      for (auto path : inFilenames)
+      {
+        std::cout << "Time step #"<<step<<" @ "<<timebounds[step]<< " ms: " << path << std::endl;
+        auto image = mitk::IOUtil::Load<mitk::Image>(path, &readerFilterFunctor);
+        images.push_back(image);
+        filter->SetInput(step, image);
+        ++step;
+      }
+
+      filter->SetFirstMinTimeBound(timebounds[0]);
+      filter->SetMaxTimeBounds({ timebounds.begin() + 1, timebounds.end() });
+
+      std::cout << "Fuse the images ..." << std::endl;
+
+      filter->Update();
+      auto output = filter->GetOutput();
+
+      std::cout << "Save output image: " << outFileName << std::endl;
+
+      mitk::IOUtil::Save(output, outFileName);
+
+      std::cout << "Processing finished." << std::endl;
+
+      return EXIT_SUCCESS;
+    }
+    catch (const std::exception& e)
+    {
+        MITK_ERROR << e.what();
+        return EXIT_FAILURE;
+    }
+    catch (...)
+    {
+        MITK_ERROR << "Unexpected error encountered.";
+        return EXIT_FAILURE;
+    }
+}