diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp
index 6996b7483f056f6c92c3910b821d52c1f3f08968..a3089922a80caeec3a75287e5861bb8a9b5c8d1b 100644
--- a/src/pe/raytracing/Raytracer.cpp
+++ b/src/pe/raytracing/Raytracer.cpp
@@ -90,7 +90,8 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
    localImageOutputEnabled_(false),
    filenameTimestepWidth_(5),
    bodyToShadingParamsFunction_(bodyToShadingParamsFunction),
-   raytracingAlgorithm_(RAYTRACE_HASHGRIDS) {
+   raytracingAlgorithm_(RAYTRACE_HASHGRIDS),
+   reductionMethod_(MPI_REDUCE) {
    
    setupView_();
    setupFilenameRankWidth_();
@@ -118,7 +119,8 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
                      std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction)
    : forest_(forest), storageID_(storageID), globalBodyStorage_(globalBodyStorage), ccdID_(ccdID),
    bodyToShadingParamsFunction_(bodyToShadingParamsFunction),
-   raytracingAlgorithm_(RAYTRACE_HASHGRIDS) {
+   raytracingAlgorithm_(RAYTRACE_HASHGRIDS),
+   reductionMethod_(MPI_REDUCE) {
    WALBERLA_CHECK(config.isValid(), "No valid config passed to raytracer");
    
    pixelsHorizontal_ = config.getParameter<uint16_t>("image_x");
diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h
index 2901fca22659526a341292bc6ec8ba057a5236bf..9b5008e1774ca8c1a23bdbdb686cb882a9f6f964 100644
--- a/src/pe/raytracing/Raytracer.h
+++ b/src/pe/raytracing/Raytracer.h
@@ -60,10 +60,9 @@ struct BodyIntersectionInfo {
    double b;                     //!< Blue value for the pixel.                              -> MPI_DOUBLE
 };
    
-class Raytracer {
-   enum ReductionMethod { MPI_REDUCE, MPI_GATHER };
-   
+class Raytracer {   
 public:
+   enum ReductionMethod { MPI_REDUCE, MPI_GATHER };
    enum Algorithm { RAYTRACE_HASHGRIDS, RAYTRACE_NAIVE, RAYTRACE_COMPARE_BOTH };
    
    /*!\name Constructors */
@@ -120,6 +119,7 @@ private:
                                                                                   * ShadingParameters struct
                                                                                   * given the specified body. */
    Algorithm raytracingAlgorithm_;    //!< Algorithm to use while intersection testing.
+   ReductionMethod reductionMethod_; //!< Reduction method used for assembling the image from all processes.
    //@}
    
    /*!\name Member variables for raytracing geometry */
@@ -167,6 +167,7 @@ public:
    inline void setImageOutputDirectory(const std::string& path);
    inline void setFilenameTimestepWidth(uint8_t width);
    inline void setRaytracingAlgorithm(Algorithm algorithm);
+   inline void setReductionMethod(ReductionMethod reductionMethod);
    //@}
    
    /*!\name Functions */
@@ -381,6 +382,10 @@ inline void Raytracer::setRaytracingAlgorithm(Algorithm algorithm) {
    raytracingAlgorithm_ = algorithm;
 }
    
+inline void Raytracer::setReductionMethod(ReductionMethod reductionMethod) {
+   reductionMethod_ = reductionMethod;
+}
+   
 /*!\brief Checks if a plane should get rendered.
  * \param plane Plane to check for visibility.
  * \param ray Ray which is intersected with plane.
@@ -505,8 +510,10 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) {
    
    std::vector<real_t> tBuffer(pixelsVertical_ * pixelsHorizontal_, inf);
    std::vector<Color> imageBuffer(pixelsVertical_ * pixelsHorizontal_);
-   std::vector<BodyIntersectionInfo> intersections; // contains for each pixel information about an intersection, if existent
-   
+
+   std::vector<BodyIntersectionInfo> intersections;
+   std::vector<BodyIntersectionInfo> intersectionsBuffer(pixelsVertical_ * pixelsHorizontal_); // contains for each pixel information about an intersection, if existent
+
    if (raytracingAlgorithm_ == RAYTRACE_HASHGRIDS || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH) {
       if (tt != NULL) tt->start("HashGrids Update");
       for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
@@ -616,43 +623,14 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) {
       WALBERLA_LOG_WARNING(" problematic bodies: " << ss.str());
 #endif
    }
-
-   if (tt != NULL) tt->start("Reduction");
-   // intersections synchronisieren
-   mpi::SendBuffer sendBuffer;
-   for (auto& info: intersections) {
-      sendBuffer << info.imageX << info.imageY
-      << info.bodySystemID << info.t
-      << info.color[0] << info.color[1] << info.color[2];
-   }
-   int gatheredIntersectionCount = 0;
-   std::vector<real_t> fullTBuffer(pixelsHorizontal_ * pixelsVertical_, inf);
-   std::vector<Color> fullImageBuffer(pixelsHorizontal_ * pixelsVertical_, backgroundColor_);
-   mpi::RecvBuffer recvBuffer;
-   
-   mpi::gathervBuffer(sendBuffer, recvBuffer, 0);
-   //mpi::allGathervBuffer(sendBuffer, recvBuffer);
-   
-   WALBERLA_ROOT_SECTION() {
-      BodyIntersectionInfo info;
-      while (!recvBuffer.isEmpty()) {
-         recvBuffer >> info.imageX;
-         recvBuffer >> info.imageY;
-         recvBuffer >> info.bodySystemID;
-         recvBuffer >> info.t;
-         recvBuffer >> info.color[0];
-         recvBuffer >> info.color[1];
-         recvBuffer >> info.color[2];
-         
-         size_t i = coordinateToArrayIndex(info.imageX, info.imageY);
-         real_t currentFullTBufferT = fullTBuffer[i];
-         if (currentFullTBufferT > info.t) {
-            fullTBuffer[i] = info.t;
-            fullImageBuffer[i] = info.color;
-         }
-         
-         gatheredIntersectionCount++;
-      }
+   
+   switch(reductionMethod_) {
+      case MPI_REDUCE:
+         syncImageUsingMPIReduce(intersectionsBuffer, tt);
+         break;
+      case MPI_GATHER:
+         syncImageUsingMPIGather(intersections, intersectionsBuffer, tt);
+         break;
    }
    
    if (tt != NULL) tt->start("Output");