diff --git a/Grinder/Version.h b/Grinder/Version.h
index bca1fccb125e94cf4fd85c982fb9aaa3bd9c6c0d..b68f9ad20739bedd097682db2564b1cc4b4861fc 100644
--- a/Grinder/Version.h
+++ b/Grinder/Version.h
@@ -10,14 +10,14 @@
 
 #define GRNDR_INFO_TITLE		"Grinder"
 #define GRNDR_INFO_COPYRIGHT	"Copyright (c) WWU Muenster"
-#define GRNDR_INFO_DATE			"14.10.2019"
+#define GRNDR_INFO_DATE			"28.10.2019"
 #define GRNDR_INFO_COMPANY		"WWU Muenster"
 #define GRNDR_INFO_WEBSITE		"http://www.uni-muenster.de"
 
 #define GRNDR_VERSION_MAJOR		0
 #define GRNDR_VERSION_MINOR		16
 #define GRNDR_VERSION_REVISION	0
-#define GRNDR_VERSION_BUILD		404
+#define GRNDR_VERSION_BUILD		407
 
 namespace grndr
 {
diff --git a/Grinder/controller/ImageEditorController.cpp b/Grinder/controller/ImageEditorController.cpp
index 1be8674e46500384b01f1b0b318b661b8791e806..d837f731e26349770352243caf42d4b71b5d818c 100644
--- a/Grinder/controller/ImageEditorController.cpp
+++ b/Grinder/controller/ImageEditorController.cpp
@@ -9,6 +9,7 @@
 #include "image/ImageTags.h"
 #include "image/ImageExceptions.h"
 #include "image/draftitems/PixelsDraftItem.h"
+#include "cv/Pixel.h"
 #include "ui/image/ImageEditor.h"
 #include "ui/image/DraftItemNode.h"
 #include "ui/image/LayersListWidget.h"
@@ -547,11 +548,43 @@ void ImageEditorController::convertSelectedPixelsToItem(Layer* layer, const Laye
 		callControllerFunction("Converting selected pixels to an item", [this](Layer* layer, const LayerPixelsData::Selection& selection) {
 			LongOperation opConvertPixels{"Converting selected pixels to an item"};
 
-			auto selectedPixels = layer->layerPixels().data().getSelectedPixels(selection);
+			LayerPixelsData selectedPixels = layer->layerPixels().data().getSelectedPixels(selection);
+
+			switch (_imageEditor->environment().getSamplingMode())
+			{
+			case ImageEditorEnvironment::SamplingMode::Layer:
+				selectedPixels = layer->layerPixels().data().getSelectedPixels(selection);
+				break;
+
+			case ImageEditorEnvironment::SamplingMode::Image:
+				selectedPixels = getSelectedImagePixels(selection);
+				break;
+			}
 
 			if (!selectedPixels.empty())
 			{
-				clearSelectedPixels(layer, selection);
+				std::vector<Layer*> layers;
+
+				switch (_imageEditor->environment().getSamplingMode())
+				{
+				case ImageEditorEnvironment::SamplingMode::Layer:
+					layers.push_back(layer);
+					break;
+
+				case ImageEditorEnvironment::SamplingMode::Image:
+					// Add all visible and editable layers
+					for (auto layer : _activeImageBuild->layers())
+					{
+						if (layer->isVisible() && checkLayerEditability(layer.get(), false))
+							layers.push_back(layer.get());
+					}
+
+					break;
+				}
+
+				for (auto layer : layers)
+					clearSelectedPixels(layer, selection);
+
 				activateDefaultEditorTool();
 
 				if (auto draftItem = createDraftItem(DraftItemType::Pixels, layer))
@@ -643,9 +676,20 @@ void ImageEditorController::floodFillPixels(Layer* layer, QPoint seedPos, QColor
 
 	if (layer && checkLayerEditability(layer))
 	{
-		callControllerFunction("Filling pixels", [](Layer* layer, QPoint seedPos, QColor color, float tolerance, bool perceivedDifference) {
+		callControllerFunction("Filling pixels", [this](Layer* layer, QPoint seedPos, QColor color, float tolerance, bool perceivedDifference) {
 			layer->layerPixels().data().beginPainting();
-			layer->layerPixels().data().floodFill(seedPos, color, tolerance, perceivedDifference);
+
+			switch (_imageEditor->environment().getSamplingMode())
+			{
+			case ImageEditorEnvironment::SamplingMode::Layer:
+				layer->layerPixels().data().floodFill(seedPos, color, tolerance, perceivedDifference);
+				break;
+
+			case ImageEditorEnvironment::SamplingMode::Image:
+				layer->layerPixels().data().floodFill(seedPos, color, tolerance, perceivedDifference, _imageEditor->getDisplayedImage());
+				break;
+			}
+
 			layer->layerPixels().data().endPainting();
 			return true;
 		}, layer, seedPos, color, tolerance, perceivedDifference);
@@ -879,6 +923,32 @@ void ImageEditorController::connectLayerSignals(Layer* layer, bool connectSignal
 		disconnect(layer, nullptr, this, nullptr);
 }
 
+LayerPixelsData ImageEditorController::getSelectedImagePixels(const LayerPixelsData::Selection& selection) const
+{
+	auto imageData = _imageEditor->getDisplayedImage();
+	ConstPixelAccessor pixels{imageData};
+	auto bounds = selection.bounds();
+	auto checkBounds = [&imageData](int x, int y) { return x >= 0 && x < imageData.cols && y >= 0 && y < imageData.rows; };
+
+	if (checkBounds(bounds.left(), bounds.top()) && checkBounds(bounds.right(), bounds.bottom()))
+	{
+		LayerPixelsData selectedPixels{QSize{bounds.right() - bounds.left() + 1, bounds.bottom() - bounds.top() + 1}};
+
+		for (int y = bounds.top(); y <= bounds.bottom(); ++y)
+		{
+			for (int x = bounds.left(); x <= bounds.right(); ++x)
+			{
+				if (selection.isSet(x, y) && pixels.at(y, x).get().rgba() != 0)
+					selectedPixels.set(x - bounds.left(), y - bounds.top(), pixels.at(y, x));
+			}
+		}
+
+		return selectedPixels;
+	}
+	else
+		return {};
+}
+
 void ImageEditorController::autoGenerateImageTag(ImageBuild* imageBuild, QColor color) const
 {
 	if (!imageBuild)
diff --git a/Grinder/controller/ImageEditorController.h b/Grinder/controller/ImageEditorController.h
index 5ba2ac7f4e4462b5526165fd895e7baed7557583..e21183b844801bedeaaaad92f4fc06b3063d5f9a 100644
--- a/Grinder/controller/ImageEditorController.h
+++ b/Grinder/controller/ImageEditorController.h
@@ -119,6 +119,8 @@ namespace grndr
 		void connectLayerSignals(Layer* layer, bool connectSignals = true) const;
 
 	private:
+		LayerPixelsData getSelectedImagePixels(const LayerPixelsData::Selection& selection) const;
+
 		void autoGenerateImageTag(ImageBuild* imageBuild, QColor color) const;
 
 	private slots:
diff --git a/Grinder/cv/Pixel.h b/Grinder/cv/Pixel.h
index 9abb99551dc7b349feb6dc9e2ed9ed2fefb6c345..a72ac3f8e33d233fd5b62e86943f7ec56f829ae0 100644
--- a/Grinder/cv/Pixel.h
+++ b/Grinder/cv/Pixel.h
@@ -1,234 +1,234 @@
-/******************************************************************************
- * File: Pixel.h
- * Date: 19.6.2018
- *****************************************************************************/
-
-#ifndef PIXEL_H
-#define PIXEL_H
-
-#include <QColor>
-#include <QPoint>
-#include <opencv2/core.hpp>
-
-namespace grndr
-{
-	class ColorPixel
-	{
-	public:
-		ColorPixel() { }
-		ColorPixel(uint8_t r, uint8_t g, uint8_t b) : _b{b}, _g{g}, _r{r} { }
-		ColorPixel(const QColor& color) { setColor(color); }
-		ColorPixel(const ColorPixel& other) = default;
-		ColorPixel(ColorPixel&& other) = default;
-
-		ColorPixel& operator =(const QColor& color) { setColor(color); return *this; }
-
-	public:
-		QColor getColor() const;
-		void setColor(const QColor& color);
-
-		operator QColor() const { return getColor(); }
-
-	public:
-		bool operator ==(const ColorPixel& other) const;
-		bool operator ==(const QColor& other) const { return ColorPixel{other} == *this; }
-
-	private:
-		uint8_t _b{0};
-		uint8_t _g{0};
-		uint8_t _r{0};
-	};
-
-	class ColorAlphaPixel
-	{
-	public:
-		ColorAlphaPixel() { }
-		ColorAlphaPixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : _b{b}, _g{g}, _r{r}, _a{a} { }
-		ColorAlphaPixel(const QColor& color) { setColor(color); }
-		ColorAlphaPixel(const ColorAlphaPixel& other) = default;
-		ColorAlphaPixel(ColorAlphaPixel&& other) = default;
-
-		ColorAlphaPixel& operator =(const QColor& color) { setColor(color); return *this; }
-
-	public:
-		QColor getColor() const;
-		void setColor(const QColor& color);
-
-		operator QColor() const { return getColor(); }
-
-	public:
-		bool operator ==(const ColorAlphaPixel& other) const;
-		bool operator ==(const QColor& other) const { return ColorAlphaPixel{other} == *this; }
-
-	private:
-		uint8_t _b{0};
-		uint8_t _g{0};
-		uint8_t _r{0};
-		uint8_t _a{0};
-	};
-
-	class GrayscalePixel
-	{
-	public:
-		GrayscalePixel() { }
-		GrayscalePixel(uint8_t p) : _p{p} { }
-		GrayscalePixel(const QColor& color) { setColor(color); }
-		GrayscalePixel(const GrayscalePixel& other) = default;
-		GrayscalePixel(GrayscalePixel&& other) = default;
-
-		GrayscalePixel& operator =(uint8_t p) { _p = p; return *this; }
-		GrayscalePixel& operator =(const QColor& color) { setColor(color); return *this; }
-		GrayscalePixel& operator =(const GrayscalePixel& other) = default;
-		GrayscalePixel& operator =(GrayscalePixel&& other) = default;
-
-	public:
-		QColor getColor() const;
-		void setColor(const QColor& color);
-
-		operator uint8_t() const { return _p; }
-		operator QColor() const { return getColor(); }
-
-	public:
-		bool operator ==(const GrayscalePixel& other) const { return _p == other._p; }
-		bool operator ==(const QColor& other) const { return GrayscalePixel{other} == *this; }
-
-	private:
-		uint8_t _p{0};
-	};
-
-	template<bool ConstAccess>
-	class PixelRef
-	{
-	public:
-		using color_pixel_type = std::conditional_t<ConstAccess, const ColorPixel, ColorPixel>;
-		using coloralpha_pixel_type = std::conditional_t<ConstAccess, const ColorAlphaPixel, ColorAlphaPixel>;
-		using grayscale_pixel_type = std::conditional_t<ConstAccess, const GrayscalePixel, GrayscalePixel>;
-
-	public:
-		PixelRef(color_pixel_type* pixel) : _pixel{pixel} { }
-		PixelRef(coloralpha_pixel_type* pixel) : _alphaPixel{pixel} { }
-		PixelRef(grayscale_pixel_type* grayscalePixel) : _grayscalePixel{grayscalePixel} { }
-
-	public:
-		template<bool hasWriteAccess = !ConstAccess>
-		std::enable_if_t<hasWriteAccess, PixelRef&> operator =(const QColor& color) { set(color); return *this; }
-
-	public:
-		QColor get() const;
-		template<bool hasWriteAccess = !ConstAccess>
-		std::enable_if_t<hasWriteAccess, void> set(const QColor& color);
-
-		operator QColor() const { return get(); }
-
-	private:
-		color_pixel_type* _pixel{nullptr};
-		coloralpha_pixel_type* _alphaPixel{nullptr};
-		grayscale_pixel_type* _grayscalePixel{nullptr};
-	};
-
-	template<bool ConstAccess>
-	class GenericPixelAccessor
-	{
-	public:
-		using matrix_type = std::conditional_t<ConstAccess, const cv::Mat, cv::Mat>;
-		using pixel_ref_type = PixelRef<ConstAccess>;
-
-	public:
-		GenericPixelAccessor(matrix_type& matrix);
-
-	public:
-		pixel_ref_type at(int r, int c);
-		pixel_ref_type at(QPoint pos) { return at(pos.y(), pos.x()); }
-		void forEach(std::function<void(pixel_ref_type, QPoint)> callback);
-
-		auto operator [](QPoint pos) { return at(pos); }
-
-	private:
-		void verifyMatrix();
-
-	private:
-		matrix_type& _matrix;
-	};
-
-	using PixelAccessor = GenericPixelAccessor<false>;
-	using ConstPixelAccessor = GenericPixelAccessor<true>;
-}
-
-namespace cv
-{
-	template<>
-	class DataType<grndr::ColorPixel>
-	{
-	public:
-		using value_type = grndr::ColorPixel;
-		using work_type = typename cv::DataType<uint8_t>::work_type;
-		using channel_type = uint8_t;
-
-		enum
-		{
-			generic_type = 0,
-			channels = 3,
-			fmt = cv::traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
-		};
-
-		using vec_type = Vec<channel_type, channels>;
-	};
-
-	template<>
-	class DataType<grndr::ColorAlphaPixel>
-	{
-	public:
-		using value_type = grndr::ColorAlphaPixel;
-		using work_type = typename cv::DataType<uint8_t>::work_type;
-		using channel_type = uint8_t;
-
-		enum
-		{
-			generic_type = 0,
-			channels = 4,
-			fmt = cv::traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
-		};
-
-		using vec_type = Vec<channel_type, channels>;
-	};
-
-	template<>
-	class DataType<grndr::GrayscalePixel>
-	{
-	public:
-		using value_type = grndr::GrayscalePixel;
-		using work_type = typename cv::DataType<uint8_t>::work_type;
-		using channel_type = uint8_t;
-
-		enum
-		{
-			generic_type = 0,
-			channels = 1,
-			fmt = cv::traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
-		};
-
-		using vec_type = Vec<channel_type, channels>;
-	};
-
-	namespace traits
-	{
-		template<>
-		struct Depth<grndr::ColorPixel> { enum { value = Depth<uint8_t>::value }; };
-		template<>
-		struct Type<grndr::ColorPixel> { enum { value = CV_MAKETYPE(Depth<uint8_t>::value, 3) }; };
-
-		template<>
-		struct Depth<grndr::ColorAlphaPixel> { enum { value = Depth<uint8_t>::value }; };
-		template<>
-		struct Type<grndr::ColorAlphaPixel> { enum { value = CV_MAKETYPE(Depth<uint8_t>::value, 4) }; };
-
-		template<>
-		struct Depth<grndr::GrayscalePixel> { enum { value = Depth<uint8_t>::value }; };
-		template<>
-		struct Type<grndr::GrayscalePixel> { enum { value = CV_MAKETYPE(Depth<uint8_t>::value, 1) }; };
-	}
-}
-
-#include "Pixel.impl.h"
-
-#endif
+/******************************************************************************
+ * File: Pixel.h
+ * Date: 19.6.2018
+ *****************************************************************************/
+
+#ifndef PIXEL_H
+#define PIXEL_H
+
+#include <QColor>
+#include <QPoint>
+#include <opencv2/core.hpp>
+
+namespace grndr
+{
+	class ColorPixel
+	{
+	public:
+		ColorPixel() { }
+		ColorPixel(uint8_t r, uint8_t g, uint8_t b) : _b{b}, _g{g}, _r{r} { }
+		ColorPixel(const QColor& color) { setColor(color); }
+		ColorPixel(const ColorPixel& other) = default;
+		ColorPixel(ColorPixel&& other) = default;
+
+		ColorPixel& operator =(const QColor& color) { setColor(color); return *this; }
+
+	public:
+		QColor getColor() const;
+		void setColor(const QColor& color);
+
+		operator QColor() const { return getColor(); }
+
+	public:
+		bool operator ==(const ColorPixel& other) const;
+		bool operator ==(const QColor& other) const { return ColorPixel{other} == *this; }
+
+	private:
+		uint8_t _b{0};
+		uint8_t _g{0};
+		uint8_t _r{0};
+	};
+
+	class ColorAlphaPixel
+	{
+	public:
+		ColorAlphaPixel() { }
+		ColorAlphaPixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : _b{b}, _g{g}, _r{r}, _a{a} { }
+		ColorAlphaPixel(const QColor& color) { setColor(color); }
+		ColorAlphaPixel(const ColorAlphaPixel& other) = default;
+		ColorAlphaPixel(ColorAlphaPixel&& other) = default;
+
+		ColorAlphaPixel& operator =(const QColor& color) { setColor(color); return *this; }
+
+	public:
+		QColor getColor() const;
+		void setColor(const QColor& color);
+
+		operator QColor() const { return getColor(); }
+
+	public:
+		bool operator ==(const ColorAlphaPixel& other) const;
+		bool operator ==(const QColor& other) const { return ColorAlphaPixel{other} == *this; }
+
+	private:
+		uint8_t _b{0};
+		uint8_t _g{0};
+		uint8_t _r{0};
+		uint8_t _a{0};
+	};
+
+	class GrayscalePixel
+	{
+	public:
+		GrayscalePixel() { }
+		GrayscalePixel(uint8_t p) : _p{p} { }
+		GrayscalePixel(const QColor& color) { setColor(color); }
+		GrayscalePixel(const GrayscalePixel& other) = default;
+		GrayscalePixel(GrayscalePixel&& other) = default;
+
+		GrayscalePixel& operator =(uint8_t p) { _p = p; return *this; }
+		GrayscalePixel& operator =(const QColor& color) { setColor(color); return *this; }
+		GrayscalePixel& operator =(const GrayscalePixel& other) = default;
+		GrayscalePixel& operator =(GrayscalePixel&& other) = default;
+
+	public:
+		QColor getColor() const;
+		void setColor(const QColor& color);
+
+		operator uint8_t() const { return _p; }
+		operator QColor() const { return getColor(); }
+
+	public:
+		bool operator ==(const GrayscalePixel& other) const { return _p == other._p; }
+		bool operator ==(const QColor& other) const { return GrayscalePixel{other} == *this; }
+
+	private:
+		uint8_t _p{0};
+	};
+
+	template<bool ConstAccess>
+	class PixelRef
+	{
+	public:
+		using color_pixel_type = std::conditional_t<ConstAccess, const ColorPixel, ColorPixel>;
+		using coloralpha_pixel_type = std::conditional_t<ConstAccess, const ColorAlphaPixel, ColorAlphaPixel>;
+		using grayscale_pixel_type = std::conditional_t<ConstAccess, const GrayscalePixel, GrayscalePixel>;
+
+	public:
+		PixelRef(color_pixel_type* pixel) : _pixel{pixel} { }
+		PixelRef(coloralpha_pixel_type* pixel) : _alphaPixel{pixel} { }
+		PixelRef(grayscale_pixel_type* grayscalePixel) : _grayscalePixel{grayscalePixel} { }
+
+	public:
+		template<bool hasWriteAccess = !ConstAccess>
+		std::enable_if_t<hasWriteAccess, PixelRef&> operator =(const QColor& color) { set(color); return *this; }
+
+	public:
+		QColor get() const;
+		template<bool hasWriteAccess = !ConstAccess>
+		std::enable_if_t<hasWriteAccess, void> set(const QColor& color);
+
+		operator QColor() const { return get(); }
+
+	private:
+		color_pixel_type* _pixel{nullptr};
+		coloralpha_pixel_type* _alphaPixel{nullptr};
+		grayscale_pixel_type* _grayscalePixel{nullptr};
+	};
+
+	template<bool ConstAccess>
+	class GenericPixelAccessor
+	{
+	public:
+		using matrix_type = std::conditional_t<ConstAccess, const cv::Mat, cv::Mat>;
+		using pixel_ref_type = PixelRef<ConstAccess>;
+
+	public:
+		GenericPixelAccessor(matrix_type& matrix);
+
+	public:
+		pixel_ref_type at(int r, int c);
+		pixel_ref_type at(QPoint pos) { return at(pos.y(), pos.x()); }
+		void forEach(std::function<void(pixel_ref_type, QPoint)> callback);
+
+		auto operator [](QPoint pos) { return at(pos); }
+
+	private:
+		void verifyMatrix();
+
+	private:
+		matrix_type& _matrix;
+	};
+
+	using PixelAccessor = GenericPixelAccessor<false>;
+	using ConstPixelAccessor = GenericPixelAccessor<true>;
+}
+
+namespace cv
+{
+	template<>
+	class DataType<grndr::ColorPixel>
+	{
+	public:
+		using value_type = grndr::ColorPixel;
+		using work_type = typename cv::DataType<uint8_t>::work_type;
+		using channel_type = uint8_t;
+
+		enum
+		{
+			generic_type = 0,
+			channels = 3,
+			fmt = cv::traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
+		};
+
+		using vec_type = Vec<channel_type, channels>;
+	};
+
+	template<>
+	class DataType<grndr::ColorAlphaPixel>
+	{
+	public:
+		using value_type = grndr::ColorAlphaPixel;
+		using work_type = typename cv::DataType<uint8_t>::work_type;
+		using channel_type = uint8_t;
+
+		enum
+		{
+			generic_type = 0,
+			channels = 4,
+			fmt = cv::traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
+		};
+
+		using vec_type = Vec<channel_type, channels>;
+	};
+
+	template<>
+	class DataType<grndr::GrayscalePixel>
+	{
+	public:
+		using value_type = grndr::GrayscalePixel;
+		using work_type = typename cv::DataType<uint8_t>::work_type;
+		using channel_type = uint8_t;
+
+		enum
+		{
+			generic_type = 0,
+			channels = 1,
+			fmt = cv::traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
+		};
+
+		using vec_type = Vec<channel_type, channels>;
+	};
+
+	namespace traits
+	{
+		template<>
+		struct Depth<grndr::ColorPixel> { enum { value = Depth<uint8_t>::value }; };
+		template<>
+		struct Type<grndr::ColorPixel> { enum { value = CV_MAKETYPE(Depth<uint8_t>::value, 3) }; };
+
+		template<>
+		struct Depth<grndr::ColorAlphaPixel> { enum { value = Depth<uint8_t>::value }; };
+		template<>
+		struct Type<grndr::ColorAlphaPixel> { enum { value = CV_MAKETYPE(Depth<uint8_t>::value, 4) }; };
+
+		template<>
+		struct Depth<grndr::GrayscalePixel> { enum { value = Depth<uint8_t>::value }; };
+		template<>
+		struct Type<grndr::GrayscalePixel> { enum { value = CV_MAKETYPE(Depth<uint8_t>::value, 1) }; };
+	}
+}
+
+#include "Pixel.impl.h"
+
+#endif
diff --git a/Grinder/cv/algorithms/FloodFill.cpp b/Grinder/cv/algorithms/FloodFill.cpp
index 08c4d74e64ae73b51757e4b09a63da4108de7887..6d2b71722cfd6a6bc7584561bdbb6d5091bb423a 100644
--- a/Grinder/cv/algorithms/FloodFill.cpp
+++ b/Grinder/cv/algorithms/FloodFill.cpp
@@ -1,34 +1,32 @@
-/******************************************************************************
- * File: FloodFill.cpp
- * Date: 13.7.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "FloodFill.h"
-#include "cv/CVUtils.h"
-
-#include <stack>
-
-FloodFill::FloodFill(cv::Mat& matrix, QPoint pos, QColor fromColor, QColor toColor, float tolerance, bool perceivedDifference) : SeedFill(matrix, pos, fromColor, tolerance, perceivedDifference),
-	_toColor{toColor}
-{
-
-}
-
-void FloodFill::execute()
-{
-	if (_color == _toColor)
-		return;
-
-	seedFill(_seedPos.x(), _seedPos.y());
-
-	// Colorize all filled pixels
-	for (int x = 0; x < _filledPixels.size().width(); ++x)
-	{
-		for (int y = 0; y < _filledPixels.size().height(); ++y)
-		{
-			if (_filledPixels.getFlag(x, y))
-				_pixels.at(y, x) = _toColor.isValid() ? _toColor : QColor{0, 0, 0, 0};
-		}
-	}
-}
+/******************************************************************************
+ * File: FloodFill.cpp
+ * Date: 13.7.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "FloodFill.h"
+#include "cv/CVUtils.h"
+
+FloodFill::FloodFill(const cv::Mat& sourceMatrix, cv::Mat& targetMatrix, QPoint pos, QColor fromColor, QColor toColor, float tolerance, bool perceivedDifference) : SeedFill(sourceMatrix, targetMatrix, pos, fromColor, tolerance, perceivedDifference),
+	_toColor{toColor}
+{
+
+}
+
+void FloodFill::execute()
+{
+	if (_color == _toColor)
+		return;
+
+	seedFill(_seedPos.x(), _seedPos.y());
+
+	// Colorize all filled pixels
+	for (int x = 0; x < _filledPixels.size().width(); ++x)
+	{
+		for (int y = 0; y < _filledPixels.size().height(); ++y)
+		{
+			if (_filledPixels.getFlag(x, y))
+				_targetPixels.at(y, x) = _toColor.isValid() ? _toColor : QColor{0, 0, 0, 0};
+		}
+	}
+}
diff --git a/Grinder/cv/algorithms/FloodFill.h b/Grinder/cv/algorithms/FloodFill.h
index cc0b41cf421098812291d4f0843a5a3396d0afa6..3fbbbb4e7311b503e6c4ae16600d96931f2f958b 100644
--- a/Grinder/cv/algorithms/FloodFill.h
+++ b/Grinder/cv/algorithms/FloodFill.h
@@ -1,30 +1,30 @@
-/******************************************************************************
- * File: FloodFill.h
- * Date: 13.7.2018
- *****************************************************************************/
-
-#ifndef FLOODFILL_H
-#define FLOODFILL_H
-
-#include <QColor>
-#include <QPoint>
-
-#include "SeedFill.h"
-#include "cv/Pixel.h"
-
-namespace grndr
-{
-	class FloodFill : public SeedFill
-	{
-	public:
-		FloodFill(cv::Mat& matrix, QPoint pos, QColor fromColor, QColor toColor, float tolerance, bool perceivedDifference = true);
-
-	public:
-		virtual void execute() override;
-
-	private:
-		QColor _toColor;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: FloodFill.h
+ * Date: 13.7.2018
+ *****************************************************************************/
+
+#ifndef FLOODFILL_H
+#define FLOODFILL_H
+
+#include <QColor>
+#include <QPoint>
+
+#include "SeedFill.h"
+#include "cv/Pixel.h"
+
+namespace grndr
+{
+	class FloodFill : public SeedFill
+	{
+	public:
+		FloodFill(const cv::Mat& sourceMatrix, cv::Mat& targetMatrix, QPoint pos, QColor fromColor, QColor toColor, float tolerance, bool perceivedDifference = true);
+
+	public:
+		virtual void execute() override;
+
+	private:
+		QColor _toColor;
+	};
+}
+
+#endif
diff --git a/Grinder/cv/algorithms/SeedFill.cpp b/Grinder/cv/algorithms/SeedFill.cpp
index 873469df415138ba22bbfd839769bfc6e3f5ad8e..5c8ec45d418ec6ba3cc9cb367ffe2a16c3ce20ca 100644
--- a/Grinder/cv/algorithms/SeedFill.cpp
+++ b/Grinder/cv/algorithms/SeedFill.cpp
@@ -1,114 +1,114 @@
-/******************************************************************************
- * File: SeedFill.cpp
- * Date: 08.8.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "SeedFill.h"
-#include "cv/CVUtils.h"
-
-#include <stack>
-
-SeedFill::SeedFill(cv::Mat& matrix, QPoint pos, QColor color, float tolerance, bool perceivedDifference) : CVAlgorithm(matrix),
-	_seedPos{pos}, _color{color}, _tolerance{tolerance}, _perceivedDifference{perceivedDifference}, _pixels{matrix}
-{
-
-}
-
-void SeedFill::execute()
-{
-	seedFill(_seedPos.x(), _seedPos.y());
-}
-
-void SeedFill::seedFill(int x, int y)
-{
-	_filledPixels.reset(QSize{_matrix.cols, _matrix.rows});
-
-	// Based on Paul Heckbert's Seed Fill Algorithm (crude & ugly, but reasonably fast)
-	std::stack<LineSegment> stack;
-
-	auto push = [&stack, this](int y, int xl, int xr, int dy) {
-		if (y + dy >= 0 && y + dy < _matrix.rows)
-			stack.push(LineSegment{y, xl, xr, dy});
-	};
-
-	auto checkColor = [this](int x, int y, QColor pixelColor) {
-		if (_filledPixels.isSet(x, y))
-			return false;
-
-		return ((_color.isValid() && CVUtils::compareColors(pixelColor, _color, _tolerance, _perceivedDifference)) || (!_color.isValid() && pixelColor.alpha() == 0));
-	};
-
-	push(y, x, x, 1);
-	push(y + 1, x, x, -1);
-
-	while (!stack.empty())
-	{
-		auto lineSegment = stack.top();
-		stack.pop();
-
-		int y = lineSegment.y + lineSegment.dy;
-		int l = 0;
-
-		for (x = lineSegment.xl; x >= 0; --x)
-		{
-			auto pixel = _pixels.at(y, x);
-			auto pixelColor = pixel.get();
-
-			if (checkColor(x, y, pixelColor))
-				_filledPixels.set(x, y);
-			else
-				break;
-		}
-
-		bool skip = false;
-
-		if (x >= lineSegment.xl)
-			skip = true;
-
-		if (!skip)
-		{
-			l = x + 1;
-
-			if (l < lineSegment.xl)
-				push(y, l, lineSegment.xl - 1, -lineSegment.dy);
-
-			x = lineSegment.xl + 1;
-		}
-
-		do
-		{
-			if (!skip)
-			{
-				for (; x < _matrix.cols; ++x)
-				{
-					auto pixel = _pixels.at(y, x);
-					auto pixelColor = pixel.get();
-
-					if (checkColor(x, y, pixelColor))
-						_filledPixels.set(x, y);
-					else
-						break;
-				}
-
-				push(y, l, x - 1, lineSegment.dy);
-
-				if (x > lineSegment.xr + 1)
-					push(y, lineSegment.xr + 1, x - 1, -lineSegment.dy);
-			}
-
-			skip = false;
-
-			for (x++; x <= lineSegment.xr; ++x)
-			{
-				auto pixel = _pixels.at(y, x);
-				auto pixelColor = pixel.get();
-
-				if (checkColor(x, y, pixelColor))
-					break;
-			}
-
-			l = x;
-		} while (x <= lineSegment.xr);
-	}
-}
+/******************************************************************************
+ * File: SeedFill.cpp
+ * Date: 08.8.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "SeedFill.h"
+#include "cv/CVUtils.h"
+
+#include <stack>
+
+SeedFill::SeedFill(const cv::Mat& sourceMatrix, cv::Mat& targetMatrix, QPoint pos, QColor color, float tolerance, bool perceivedDifference) : CVAlgorithm(targetMatrix),
+	_sourceMatrix{sourceMatrix}, _sourcePixels{sourceMatrix}, _targetMatrix{targetMatrix}, _targetPixels{targetMatrix}, _seedPos{pos}, _color{color}, _tolerance{tolerance}, _perceivedDifference{perceivedDifference}
+{
+
+}
+
+void SeedFill::execute()
+{
+	seedFill(_seedPos.x(), _seedPos.y());
+}
+
+void SeedFill::seedFill(int x, int y)
+{
+	_filledPixels.reset(QSize{_targetMatrix.cols, _targetMatrix.rows});
+
+	// Based on Paul Heckbert's Seed Fill Algorithm (crude & ugly, but reasonably fast)
+	std::stack<LineSegment> stack;
+
+	auto push = [&stack, this](int y, int xl, int xr, int dy) {
+		if (y + dy >= 0 && y + dy < _targetMatrix.rows)
+			stack.push(LineSegment{y, xl, xr, dy});
+	};
+
+	auto checkColor = [this](int x, int y, QColor pixelColor) {
+		if (_filledPixels.isSet(x, y))
+			return false;
+
+		return ((_color.isValid() && CVUtils::compareColors(pixelColor, _color, _tolerance, _perceivedDifference)) || (!_color.isValid() && pixelColor.alpha() == 0));
+	};
+
+	push(y, x, x, 1);
+	push(y + 1, x, x, -1);
+
+	while (!stack.empty())
+	{
+		auto lineSegment = stack.top();
+		stack.pop();
+
+		int y = lineSegment.y + lineSegment.dy;
+		int l = 0;
+
+		for (x = lineSegment.xl; x >= 0; --x)
+		{
+			auto pixel = _sourcePixels.at(y, x);
+			auto pixelColor = pixel.get();
+
+			if (checkColor(x, y, pixelColor))
+				_filledPixels.set(x, y);
+			else
+				break;
+		}
+
+		bool skip = false;
+
+		if (x >= lineSegment.xl)
+			skip = true;
+
+		if (!skip)
+		{
+			l = x + 1;
+
+			if (l < lineSegment.xl)
+				push(y, l, lineSegment.xl - 1, -lineSegment.dy);
+
+			x = lineSegment.xl + 1;
+		}
+
+		do
+		{
+			if (!skip)
+			{
+				for (; x < _targetMatrix.cols; ++x)
+				{
+					auto pixel = _sourcePixels.at(y, x);
+					auto pixelColor = pixel.get();
+
+					if (checkColor(x, y, pixelColor))
+						_filledPixels.set(x, y);
+					else
+						break;
+				}
+
+				push(y, l, x - 1, lineSegment.dy);
+
+				if (x > lineSegment.xr + 1)
+					push(y, lineSegment.xr + 1, x - 1, -lineSegment.dy);
+			}
+
+			skip = false;
+
+			for (x++; x <= lineSegment.xr; ++x)
+			{
+				auto pixel = _sourcePixels.at(y, x);
+				auto pixelColor = pixel.get();
+
+				if (checkColor(x, y, pixelColor))
+					break;
+			}
+
+			l = x;
+		} while (x <= lineSegment.xr);
+	}
+}
diff --git a/Grinder/cv/algorithms/SeedFill.h b/Grinder/cv/algorithms/SeedFill.h
index afd03329295d6c390ef0c9cb8f62bcf1025ad1d5..52aac4d036071bbd815eb7c1b007dfc9fb5cc93d 100644
--- a/Grinder/cv/algorithms/SeedFill.h
+++ b/Grinder/cv/algorithms/SeedFill.h
@@ -1,47 +1,50 @@
-/******************************************************************************
- * File: SeedFill.h
- * Date: 08.8.2018
- *****************************************************************************/
-
-#ifndef SEEDFILL_H
-#define SEEDFILL_H
-
-#include "CVAlgorithm.h"
-#include "common/RangeMap.h"
-#include "common/FlagMatrix.h"
-#include "cv/Pixel.h"
-
-namespace grndr
-{
-	class SeedFill : public CVAlgorithm
-	{
-	public:
-		SeedFill(cv::Mat& matrix, QPoint pos, QColor color, float tolerance, bool perceivedDifference = true);
-
-	public:
-		virtual void execute() override;
-
-	public:
-		const FlagMatrix<>& filledPixels() const { return _filledPixels; }
-
-	protected:
-		struct LineSegment
-		{
-			int y, xl, xr, dy;
-		};
-
-		void seedFill(int x, int y);
-
-	protected:
-		QPoint _seedPos{0, 0};
-		QColor _color;
-		float _tolerance{0.0f};
-		bool _perceivedDifference{true};
-
-		PixelAccessor _pixels;
-
-		FlagMatrix<> _filledPixels;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: SeedFill.h
+ * Date: 08.8.2018
+ *****************************************************************************/
+
+#ifndef SEEDFILL_H
+#define SEEDFILL_H
+
+#include "CVAlgorithm.h"
+#include "common/RangeMap.h"
+#include "common/FlagMatrix.h"
+#include "cv/Pixel.h"
+
+namespace grndr
+{
+	class SeedFill : public CVAlgorithm
+	{
+	public:
+		SeedFill(const cv::Mat& sourceMatrix, cv::Mat& targetMatrix, QPoint pos, QColor color, float tolerance, bool perceivedDifference = true);
+
+	public:
+		virtual void execute() override;
+
+	public:
+		const FlagMatrix<>& filledPixels() const { return _filledPixels; }
+
+	protected:
+		struct LineSegment
+		{
+			int y, xl, xr, dy;
+		};
+
+		void seedFill(int x, int y);
+
+	protected:
+		const cv::Mat& _sourceMatrix;
+		ConstPixelAccessor _sourcePixels;
+		cv::Mat& _targetMatrix;
+		PixelAccessor _targetPixels;
+
+		QPoint _seedPos{0, 0};
+		QColor _color;
+		float _tolerance{0.0f};
+		bool _perceivedDifference{true};
+
+		FlagMatrix<> _filledPixels;
+	};
+}
+
+#endif
diff --git a/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.cpp b/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.cpp
index 9dd2855775598fbab7bc3da4620bda97ebb85508..b4b8edc98231b130ae209c9aeb3fde5619d5c3f3 100644
--- a/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.cpp
+++ b/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.cpp
@@ -10,13 +10,21 @@
 
 const WandAlgorithm::AlgorithmType ColorDistanceWandAlgorithm::type_value = WandAlgorithm::AlgorithmType::ColorDistance;
 
-LayerPixelsData::Selection ColorDistanceWandAlgorithm::execute(QPoint seed, const Layer& layer)
+LayerPixelsData::Selection ColorDistanceWandAlgorithm::execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage)
 {
 	const auto& layerPixels = layer.layerPixels().data();
 	auto pixelsMatrix = layerPixels.toMatrix(true);
 
 	// Use the seed fill algorithm to get all pixels in the region around the seed position
-	SeedFill seedFill{pixelsMatrix, seed, layerPixels.get(seed), tolerance()->getRelativeValue(), *usePerceivedDistance()};
+	QColor sourceColor = layerPixels.get(seed);
+
+	if (!sourceImage.empty())
+	{
+		ConstPixelAccessor pixels{sourceImage};
+		sourceColor = pixels.at(seed);
+	}
+
+	SeedFill seedFill{!sourceImage.empty() ? sourceImage : pixelsMatrix, pixelsMatrix, seed, sourceColor, tolerance()->getRelativeValue(), *usePerceivedDistance()};
 	seedFill.execute();
 	return seedFill.filledPixels();
 }
diff --git a/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.h b/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.h
index eb7e560d1b5fc244045d6d44bdf35235653df7af..7b6b48a63f76319484f492a58744e6981e7f99c6 100644
--- a/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.h
+++ b/Grinder/cv/algorithms/wand/ColorDistanceWandAlgorithm.h
@@ -18,7 +18,7 @@ namespace grndr
 		static const WandAlgorithm::AlgorithmType type_value;
 
 	public:
-		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer) override;
+		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage) override;
 
 	public:
 		auto tolerance() { return dynamic_cast<PercentProperty*>(_tolerance.get()); }
diff --git a/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.cpp b/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.cpp
index b4debf2db6727056a774fe27af42e5a0a5a32de5..f4b8bea31765f045816cd608e5acb824c7c1637c 100644
--- a/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.cpp
+++ b/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.cpp
@@ -11,10 +11,15 @@
 
 const WandAlgorithm::AlgorithmType EdgesWandAlgorithm::type_value = WandAlgorithm::AlgorithmType::Edges;
 
-LayerPixelsData::Selection EdgesWandAlgorithm::execute(QPoint seed, const Layer& layer)
+LayerPixelsData::Selection EdgesWandAlgorithm::execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage)
 {
 	const auto& layerPixels = layer.layerPixels().data();
-	auto pixelsMatrix = layerPixels.toMatrix(true);
+	cv::Mat pixelsMatrix;
+
+	if (!sourceImage.empty())
+		pixelsMatrix = sourceImage.clone();
+	else
+		pixelsMatrix = layerPixels.toMatrix(true);
 
 	// Use the Canny algorithm to detect edges
 	cv::cvtColor(pixelsMatrix, pixelsMatrix, cv::COLOR_BGR2GRAY);
@@ -38,7 +43,7 @@ LayerPixelsData::Selection EdgesWandAlgorithm::execute(QPoint seed, const Layer&
 
 	// Get the contour under the seed position
 	uint8_t edgeValue = contourRegions.at<uint8_t>(seed.y(), seed.x());
-	LayerPixelsData::Selection selection{layer.getLayerSize()};
+	LayerPixelsData::Selection selection{pixelsMatrix.cols, pixelsMatrix.rows};
 
 	for (int x = 0; x < contourRegions.cols; ++x)
 	{
diff --git a/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.h b/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.h
index b8906e55d2643c0dda8d702e93dd467a66f0d071..2f501e07923a17dc9ac3f2e245cfa3446367afb3 100644
--- a/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.h
+++ b/Grinder/cv/algorithms/wand/EdgesWandAlgorithm.h
@@ -1,38 +1,38 @@
-/******************************************************************************
- * File: EdgesWandAlgorithm.h
- * Date: 08.8.2018
- *****************************************************************************/
-
-#ifndef EDGESWANDALGORITHM_H
-#define EDGESWANDALGORITHM_H
-
-#include "WandAlgorithm.h"
-
-namespace grndr
-{
-	class EdgesWandAlgorithm : public WandAlgorithm
-	{
-		Q_OBJECT
-
-	public:
-		static const WandAlgorithm::AlgorithmType type_value;
-
-	public:
-		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer) override;
-
-	public:
-		auto thresholdLow() { return dynamic_cast<UIntProperty*>(_thresholdLow.get()); }
-		auto thresholdLow() const { return dynamic_cast<const UIntProperty*>(_thresholdLow.get()); }
-		auto thresholdHigh() { return dynamic_cast<UIntProperty*>(_thresholdHigh.get()); }
-		auto thresholdHigh() const { return dynamic_cast<const UIntProperty*>(_thresholdHigh.get()); }
-
-	protected:
-		virtual void createProperties() override;
-
-	private:
-		std::shared_ptr<PropertyBase> _thresholdLow;
-		std::shared_ptr<PropertyBase> _thresholdHigh;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: EdgesWandAlgorithm.h
+ * Date: 08.8.2018
+ *****************************************************************************/
+
+#ifndef EDGESWANDALGORITHM_H
+#define EDGESWANDALGORITHM_H
+
+#include "WandAlgorithm.h"
+
+namespace grndr
+{
+	class EdgesWandAlgorithm : public WandAlgorithm
+	{
+		Q_OBJECT
+
+	public:
+		static const WandAlgorithm::AlgorithmType type_value;
+
+	public:
+		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage) override;
+
+	public:
+		auto thresholdLow() { return dynamic_cast<UIntProperty*>(_thresholdLow.get()); }
+		auto thresholdLow() const { return dynamic_cast<const UIntProperty*>(_thresholdLow.get()); }
+		auto thresholdHigh() { return dynamic_cast<UIntProperty*>(_thresholdHigh.get()); }
+		auto thresholdHigh() const { return dynamic_cast<const UIntProperty*>(_thresholdHigh.get()); }
+
+	protected:
+		virtual void createProperties() override;
+
+	private:
+		std::shared_ptr<PropertyBase> _thresholdLow;
+		std::shared_ptr<PropertyBase> _thresholdHigh;
+	};
+}
+
+#endif
diff --git a/Grinder/cv/algorithms/wand/WandAlgorithm.h b/Grinder/cv/algorithms/wand/WandAlgorithm.h
index b720ee4529f013272365d616abeb478087a23df6..72009df54bb3dcf7986bba7f286741584a88c598 100644
--- a/Grinder/cv/algorithms/wand/WandAlgorithm.h
+++ b/Grinder/cv/algorithms/wand/WandAlgorithm.h
@@ -1,34 +1,34 @@
-/******************************************************************************
- * File: WandAlgorithm.h
- * Date: 07.8.2018
- *****************************************************************************/
-
-#ifndef WANDALGORITHM_H
-#define WANDALGORITHM_H
-
-#include "common/properties/PropertyObject.h"
-#include "image/Layer.h"
-
-namespace grndr
-{
-	class WandAlgorithm : public PropertyObject
-	{
-		Q_OBJECT
-
-	public:
-		enum class AlgorithmType
-		{
-			ColorDistance,
-			Edges,
-			Watershed,
-		};
-
-	public:
-		virtual void initWandAlgorithm();
-
-	public:
-		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer) = 0;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: WandAlgorithm.h
+ * Date: 07.8.2018
+ *****************************************************************************/
+
+#ifndef WANDALGORITHM_H
+#define WANDALGORITHM_H
+
+#include "common/properties/PropertyObject.h"
+#include "image/Layer.h"
+
+namespace grndr
+{
+	class WandAlgorithm : public PropertyObject
+	{
+		Q_OBJECT
+
+	public:
+		enum class AlgorithmType
+		{
+			ColorDistance,
+			Edges,
+			Watershed,
+		};
+
+	public:
+		virtual void initWandAlgorithm();
+
+	public:
+		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage) = 0;
+	};
+}
+
+#endif
diff --git a/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.cpp b/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.cpp
index fbc61e02d9d102a38f7ffd004e1f1f9aa9c47bd4..b68f78ced3fb5362404cb7600acd1e5286d815b5 100644
--- a/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.cpp
+++ b/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.cpp
@@ -11,9 +11,9 @@
 
 const WandAlgorithm::AlgorithmType WatershedWandAlgorithm::type_value = WandAlgorithm::AlgorithmType::Watershed;
 
-LayerPixelsData::Selection WatershedWandAlgorithm::execute(QPoint seed, const Layer& layer)
+LayerPixelsData::Selection WatershedWandAlgorithm::execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage)
 {
-	auto layerSize = layer.getLayerSize();
+	QSize layerSize = !sourceImage.empty() ? QSize{sourceImage.cols, sourceImage.rows} : layer.getLayerSize();
 
 	// Create markers for the Watershed algorithm
 	cv::Mat markers = cv::Mat::zeros(layerSize.height(), layerSize.width(), CV_32SC1);
@@ -21,7 +21,13 @@ LayerPixelsData::Selection WatershedWandAlgorithm::execute(QPoint seed, const La
 	cv::circle(markers, cv::Point{0, 0}, 3, cv::Scalar::all(1), -1);	// Extra marker to make Watershed work
 
 	// Use the Watershed algorithm to extract the clicked region
-	auto pixelsMatrix = layer.layerPixels().data().toMatrix();
+	cv::Mat pixelsMatrix;
+
+	if (!sourceImage.empty())
+		pixelsMatrix = sourceImage.clone();
+	else
+		pixelsMatrix = layer.layerPixels().data().toMatrix();
+
 	cv::watershed(pixelsMatrix, markers);
 
 	// Get the correct marker
diff --git a/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.h b/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.h
index 775fba8571af9f0649bb34607366bb12baed6fdb..eedb076e623dcff6ebb8b454d60309c1df5e213b 100644
--- a/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.h
+++ b/Grinder/cv/algorithms/wand/WatershedWandAlgorithm.h
@@ -1,28 +1,28 @@
-/******************************************************************************
- * File: WatershedWandAlgorithm.h
- * Date: 08.8.2018
- *****************************************************************************/
-
-#ifndef WATERSHEDWANDALGORITHM_H
-#define WATERSHEDWANDALGORITHM_H
-
-#include "WandAlgorithm.h"
-
-namespace grndr
-{
-	class WatershedWandAlgorithm : public WandAlgorithm
-	{
-		Q_OBJECT
-
-	public:
-		static const WandAlgorithm::AlgorithmType type_value;
-
-	public:
-		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer) override;
-
-	protected:
-		virtual void createProperties() override;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: WatershedWandAlgorithm.h
+ * Date: 08.8.2018
+ *****************************************************************************/
+
+#ifndef WATERSHEDWANDALGORITHM_H
+#define WATERSHEDWANDALGORITHM_H
+
+#include "WandAlgorithm.h"
+
+namespace grndr
+{
+	class WatershedWandAlgorithm : public WandAlgorithm
+	{
+		Q_OBJECT
+
+	public:
+		static const WandAlgorithm::AlgorithmType type_value;
+
+	public:
+		virtual LayerPixelsData::Selection execute(QPoint seed, const Layer& layer, const cv::Mat& sourceImage) override;
+
+	protected:
+		virtual void createProperties() override;
+	};
+}
+
+#endif
diff --git a/Grinder/image/ImageBuild.cpp b/Grinder/image/ImageBuild.cpp
index 173af86659fb9d98dff31040e7387ea0757ec9a4..401f63541d788c3aadcba887151fd04cd0b991f3 100644
--- a/Grinder/image/ImageBuild.cpp
+++ b/Grinder/image/ImageBuild.cpp
@@ -153,7 +153,7 @@ void ImageBuild::autoGenerateImageTag(QColor color)
 	}
 }
 
-cv::Mat ImageBuild::renderImageBuild(std::vector<const Layer*> allowedLayers, bool renderableOnly) const
+cv::Mat ImageBuild::renderImageBuild(std::vector<const Layer*> allowedLayers, bool renderableOnly, bool ignoreAlpha) const
 {
 	// Make sure that the rendered image is an 8-bit color one
 	cv::Mat renderedImage;
@@ -168,7 +168,7 @@ cv::Mat ImageBuild::renderImageBuild(std::vector<const Layer*> allowedLayers, bo
 		if (allowedLayers.empty() || std::find(allowedLayers.cbegin(), allowedLayers.cend(), layer.get()) != allowedLayers.cend())
 		{
 			if (layer->hasFlag(Layer::Flag::Renderable) || !renderableOnly)
-				layer->renderLayer(renderedImage);
+				layer->renderLayer(renderedImage, true, ignoreAlpha);
 		}
 	}
 
diff --git a/Grinder/image/ImageBuild.h b/Grinder/image/ImageBuild.h
index b7e41dc9d82b551846263bd01d302eaf7f698316..7f28e941483674b9ec073c99ae4e2a63d6043ea0 100644
--- a/Grinder/image/ImageBuild.h
+++ b/Grinder/image/ImageBuild.h
@@ -48,7 +48,7 @@ namespace grndr
 		void autoGenerateImageTag(QColor color);
 
 	public:
-		cv::Mat renderImageBuild(std::vector<const Layer*> allowedLayers = {}, bool renderableOnly = true) const;
+		cv::Mat renderImageBuild(std::vector<const Layer*> allowedLayers = {}, bool renderableOnly = true, bool ignoreAlpha = true) const;
 		cv::Mat renderImageBuildItems(QColor backgroundColor, std::vector<const Layer*> allowedLayers = {}, bool renderableOnly = true) const;
 		ImageTagsBitmap renderImageTagsBitmap(bool renderableOnly = true) const;
 
diff --git a/Grinder/image/Layer.cpp b/Grinder/image/Layer.cpp
index d22f0fc5cc34424270770329a720fcdc357e7f55..80d2af0a0175ca759dd1a680e0722359851ed742 100644
--- a/Grinder/image/Layer.cpp
+++ b/Grinder/image/Layer.cpp
@@ -94,7 +94,7 @@ void Layer::removeDraftItem(const DraftItem* item)
 	}
 }
 
-void Layer::renderLayer(cv::Mat& image, bool renderBackground) const
+void Layer::renderLayer(cv::Mat& image, bool renderBackground, bool ignoreAlpha) const
 {
 	LayerPixels renderedPixels = _layerPixels;	
 
@@ -120,7 +120,7 @@ void Layer::renderLayer(cv::Mat& image, bool renderBackground) const
 	}
 
 	// Render the pixels to the target image
-	renderedPixels.data().renderPixels(image, 1.0f);
+	renderedPixels.data().renderPixels(image, ignoreAlpha ? 1.0f : static_cast<float>(_alpha) / 100.0f);
 }
 
 void Layer::renderImageTag(const ImageTag* imageTag, ImageTagsBitmap& imageTagsBitmap) const
diff --git a/Grinder/image/Layer.h b/Grinder/image/Layer.h
index 4db5c8933504a1fb20be9c45b7d8d4dde0fb888f..892bd26eb70b5b4c5f5b070811bd5ebe3df10813 100644
--- a/Grinder/image/Layer.h
+++ b/Grinder/image/Layer.h
@@ -56,7 +56,7 @@ namespace grndr
 		void removeDraftItem(const DraftItem* item);
 
 	public:
-		void renderLayer(cv::Mat& image, bool renderBackground = true) const;
+		void renderLayer(cv::Mat& image, bool renderBackground = true, bool ignoreAlpha = true) const;
 		void renderImageTag(const ImageTag* imageTag, ImageTagsBitmap& imageTagsBitmap) const;
 
 	public:
diff --git a/Grinder/image/LayerPixelsData.cpp b/Grinder/image/LayerPixelsData.cpp
index 8cd690bb3ebeffbad90e85d5d6d56bb2971dfe85..efdc5cef285c0c3a079e4bffb7db9fef01753be4 100644
--- a/Grinder/image/LayerPixelsData.cpp
+++ b/Grinder/image/LayerPixelsData.cpp
@@ -65,17 +65,40 @@ void LayerPixelsData::fill(const LayerPixelsData::Selection& selection, QColor c
 	emitDataModified();
 }
 
-void LayerPixelsData::floodFill(int x, int y, QColor color, float tolerance, bool perceivedDifference)
+void LayerPixelsData::floodFill(int x, int y, QColor color, float tolerance, bool perceivedDifference, const cv::Mat& sourceImage)
 {
 	// Perform the flood fill on a Matrix for simplicity & efficiency
+	QColor sourceColor = get(x, y);
+
+	if (!sourceImage.empty())
+	{
+		ConstPixelAccessor pixels{sourceImage};
+		sourceColor = pixels.at(y, x);
+	}
+
 	cv::Mat matrix = toMatrix(true);
-	FloodFill floodFill{matrix, QPoint{x, y}, get(x, y), color, tolerance, perceivedDifference};
+	FloodFill floodFill{!sourceImage.empty() ? sourceImage : matrix, matrix, QPoint{x, y}, sourceColor, color, tolerance, perceivedDifference};
 	floodFill.execute();
 
 	// Clear the original pixels data and draw the modified image
 	fromMatrix(matrix);
 }
 
+void LayerPixelsData::copy(const LayerPixelsData& source)
+{
+	for (int y = 0; y < std::min(_pixels->height(), source._pixels->height()); ++y)
+	{
+		auto rgbIn = reinterpret_cast<const QRgb*>(source._pixels->constScanLine(y));
+		auto rgbOut = reinterpret_cast<QRgb*>(_pixels->scanLine(y));
+
+		for (int x = 0; x < std::min(_pixels->width(), source._pixels->width()); ++x)
+		{
+			if (rgbIn[x] != 0)
+				rgbOut[x] = rgbIn[x];
+		}
+	}
+}
+
 void LayerPixelsData::clear(int x, int y)
 {
 	if (checkBounds(x, y))
@@ -99,7 +122,6 @@ void LayerPixelsData::resize(QSize newSize)
 			createPixels(newSize);
 			emitDataModified();
 		}
-
 	}
 }
 
diff --git a/Grinder/image/LayerPixelsData.h b/Grinder/image/LayerPixelsData.h
index 6eac07c9a48b2b1c4bbfe7ffabd47df4ae66714a..625ca62eacafbc27a6f977cb5dcf6afc0a6c74a5 100644
--- a/Grinder/image/LayerPixelsData.h
+++ b/Grinder/image/LayerPixelsData.h
@@ -44,8 +44,9 @@ namespace grndr
 		void set(int x, int y, QColor color);
 		void set(QPoint pos, QColor color) { set(pos.x(), pos.y(), color); }		
 		void fill(const Selection& selection, QColor color);
-		void floodFill(int x, int y, QColor color, float tolerance, bool perceivedDifference);
-		void floodFill(QPoint seedPos, QColor color, float tolerance, bool perceivedDifference) { floodFill(seedPos.x(), seedPos.y(), color, tolerance, perceivedDifference); }
+		void floodFill(int x, int y, QColor color, float tolerance, bool perceivedDifference, const cv::Mat& sourceImage = {});
+		void floodFill(QPoint seedPos, QColor color, float tolerance, bool perceivedDifference, const cv::Mat& inputImage = {}) { floodFill(seedPos.x(), seedPos.y(), color, tolerance, perceivedDifference, inputImage); }
+		void copy(const LayerPixelsData& source);
 		void clear(int x, int y);
 		void clear(QPoint pos) { clear(pos.x(), pos.y()); }
 		void clear(const Selection& selection) { fill(selection, QColor{}); }
diff --git a/Grinder/res/Grinder.qrc b/Grinder/res/Grinder.qrc
index 2be16db5fa5bb7259338ec5df96b6280ce1f8fae..e5b1be04d4ecf50c16d128b14cf4a5c83d3ffd9d 100644
--- a/Grinder/res/Grinder.qrc
+++ b/Grinder/res/Grinder.qrc
@@ -76,6 +76,7 @@
         <file>icons/overlay-tagged.png</file>
         <file>icons/batch.png</file>
         <file>icons/folder-out-interface-symbol.png</file>
+        <file>icons/sampling-image.png</file>
     </qresource>
     <qresource prefix="/">
         <file>css/global.css</file>
diff --git a/Grinder/res/Resources.h b/Grinder/res/Resources.h
index c1f1539e9b9f63007cc0588dbba6cfad6943ac19..d6e7f6d9a8bf455c77fb354843d0a2dbb08f3799 100644
--- a/Grinder/res/Resources.h
+++ b/Grinder/res/Resources.h
@@ -88,6 +88,7 @@
 #define FILE_ICON_EDITOR_LASSO ":/icons/icons/lasso.png"
 #define FILE_ICON_EDITOR_GRABCUT ":/icons/icons/painting/scissors.png"
 #define FILE_ICON_EDITOR_MORPH ":/icons/icons/arrows-group-interface-symbol-to-expand.png"
+#define FILE_ICON_EDITOR_SAMPLING_IMAGE ":/icons/icons/sampling-image.png"
 
 /* Cursors */
 
diff --git a/Grinder/res/icons/sampling-image.png b/Grinder/res/icons/sampling-image.png
new file mode 100644
index 0000000000000000000000000000000000000000..b42bac8735d1d09fabc9ada69323c4c1c3080899
Binary files /dev/null and b/Grinder/res/icons/sampling-image.png differ
diff --git a/Grinder/ui/image/ImageEditor.cpp b/Grinder/ui/image/ImageEditor.cpp
index 53cbac622972b061de6fa2a02b333e90acba375c..a64801b97f27605aa2a0bc92fc9d367085bcb35f 100644
--- a/Grinder/ui/image/ImageEditor.cpp
+++ b/Grinder/ui/image/ImageEditor.cpp
@@ -1,66 +1,86 @@
-/******************************************************************************
- * File: ImageEditor.cpp
- * Date: 27.3.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "ImageEditor.h"
-#include "core/GrinderApplication.h"
-
-const char* ImageEditor::Serialization_Value_Block = "Block";
-
-ImageEditor::ImageEditor() :
-	_editorController{this}, _editorEnvironment{&_editorController}, _editorTools{this}, _editorDockWidget{new ImageEditorDockWidget{}}, _editorWidget{new ImageEditorWidget{this, _editorDockWidget}}
-{
-	// Assign the editor widget to the dock widget
-	_editorDockWidget->setWidget(_editorWidget);
-}
-
-void ImageEditor::setImageBuild(const std::shared_ptr<ImageBuild>& imageBuild)
-{
-	_editorWidget->setImageBuild(imageBuild);
-	_editorDockWidget->updateDockName(imageBuild->block());
-	_editorEnvironment.selection().setImageBuild(imageBuild);
-}
-
-void ImageEditor::serialize(SerializationContext& ctx) const
-{
-	// Serialize environment
-	ctx.beginGroup(ImageEditorEnvironment::Serialization_Group);
-	_editorEnvironment.serialize(ctx);
-	ctx.endGroup();
-
-	// Serialize tools
-	ctx.beginGroup(ImageEditorToolList::Serialization_Group, true);
-	_editorTools.serialize(ctx);
-	ctx.endGroup();
-
-	// Serialize editor widget
-	ctx.beginGroup(ImageEditorWidget::Serialization_Group);
-	_editorWidget->serialize(ctx);
-	ctx.endGroup();
-}
-
-void ImageEditor::deserialize(DeserializationContext& ctx)
-{
-	// Deserialize environment
-	if (ctx.beginGroup(ImageEditorEnvironment::Serialization_Group))
-	{
-		_editorEnvironment.deserialize(ctx);
-		ctx.endGroup();
-	}
-
-	// Deserialize tools
-	if (ctx.beginGroup(ImageEditorToolList::Serialization_Group))
-	{
-		_editorTools.deserialize(ctx);
-		ctx.endGroup();
-	}
-
-	// Deserialize editor widget
-	if (ctx.beginGroup(ImageEditorWidget::Serialization_Group))
-	{
-		_editorWidget->deserialize(ctx);
-		ctx.endGroup();
-	}
-}
+/******************************************************************************
+ * File: ImageEditor.cpp
+ * Date: 27.3.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "ImageEditor.h"
+#include "core/GrinderApplication.h"
+
+const char* ImageEditor::Serialization_Value_Block = "Block";
+
+ImageEditor::ImageEditor() :
+	_editorController{this}, _editorEnvironment{&_editorController}, _editorTools{this}, _editorDockWidget{new ImageEditorDockWidget{}}, _editorWidget{new ImageEditorWidget{this, _editorDockWidget}}
+{
+	// Assign the editor widget to the dock widget
+	_editorDockWidget->setWidget(_editorWidget);
+}
+
+void ImageEditor::setImageBuild(const std::shared_ptr<ImageBuild>& imageBuild)
+{
+	_editorWidget->setImageBuild(imageBuild);
+	_editorDockWidget->updateDockName(imageBuild->block());
+	_editorEnvironment.selection().setImageBuild(imageBuild);
+}
+
+cv::Mat ImageEditor::getDisplayedImage(bool ignoreLayersAlpha)
+{
+	if (auto imageBuild = _editorController.activeImageBuild())
+	{
+		// Only include currently displayed layers
+		std::vector<const Layer*> visibleLayers;
+
+		for (auto layer : imageBuild->layers())
+		{
+			if (layer->isVisible())
+				visibleLayers.push_back(layer.get());
+		}
+
+		// Render the current image as it is currently displayed to the user
+		return imageBuild->renderImageBuild(visibleLayers, false, ignoreLayersAlpha);
+	}
+	else
+		return {};
+}
+
+void ImageEditor::serialize(SerializationContext& ctx) const
+{
+	// Serialize environment
+	ctx.beginGroup(ImageEditorEnvironment::Serialization_Group);
+	_editorEnvironment.serialize(ctx);
+	ctx.endGroup();
+
+	// Serialize tools
+	ctx.beginGroup(ImageEditorToolList::Serialization_Group, true);
+	_editorTools.serialize(ctx);
+	ctx.endGroup();
+
+	// Serialize editor widget
+	ctx.beginGroup(ImageEditorWidget::Serialization_Group);
+	_editorWidget->serialize(ctx);
+	ctx.endGroup();
+}
+
+void ImageEditor::deserialize(DeserializationContext& ctx)
+{
+	// Deserialize environment
+	if (ctx.beginGroup(ImageEditorEnvironment::Serialization_Group))
+	{
+		_editorEnvironment.deserialize(ctx);
+		ctx.endGroup();
+	}
+
+	// Deserialize tools
+	if (ctx.beginGroup(ImageEditorToolList::Serialization_Group))
+	{
+		_editorTools.deserialize(ctx);
+		ctx.endGroup();
+	}
+
+	// Deserialize editor widget
+	if (ctx.beginGroup(ImageEditorWidget::Serialization_Group))
+	{
+		_editorWidget->deserialize(ctx);
+		ctx.endGroup();
+	}
+}
diff --git a/Grinder/ui/image/ImageEditor.h b/Grinder/ui/image/ImageEditor.h
index 614d46a0badbd380be42c50e7e0df503a3fdfe8d..c50a3b4a3cb215f38008d57d0c927322febfb6c3 100644
--- a/Grinder/ui/image/ImageEditor.h
+++ b/Grinder/ui/image/ImageEditor.h
@@ -1,59 +1,62 @@
-/******************************************************************************
- * File: ImageEditor.h
- * Date: 27.3.2018
- *****************************************************************************/
-
-#ifndef IMAGEEDITOR_H
-#define IMAGEEDITOR_H
-
-#include "controller/ImageEditorController.h"
-#include "ImageEditorEnvironment.h"
-#include "ImageEditorDockWidget.h"
-#include "ImageEditorWidget.h"
-#include "ImageEditorToolList.h"
-
-namespace grndr
-{
-	class Block;
-
-	class ImageEditor : public QObject
-	{
-		Q_OBJECT
-
-	public:
-		static const char* Serialization_Value_Block;
-
-	public:
-		ImageEditor();
-
-	public:
-		void setImageBuild(const std::shared_ptr<ImageBuild>& imageBuild);
-
-	public:
-		ImageEditorController& controller() { return _editorController; }
-		const ImageEditorController& controller() const { return _editorController; }
-		ImageEditorEnvironment& environment() { return _editorEnvironment; }
-		const ImageEditorEnvironment& environment() const { return _editorEnvironment; }
-		ImageEditorToolList& editorTools() { return _editorTools; }
-		const ImageEditorToolList& editorTools() const { return _editorTools; }
-
-		ImageEditorDockWidget* dockWidget() { return _editorDockWidget; }
-		const ImageEditorDockWidget* dockWidget() const { return _editorDockWidget; }
-		ImageEditorWidget* editorWidget() { return _editorWidget; }
-		const ImageEditorWidget* editorWidget() const { return _editorWidget; }
-
-	public:
-		void serialize(SerializationContext& ctx) const;
-		void deserialize(DeserializationContext& ctx);
-
-	private:
-		ImageEditorController _editorController;
-		ImageEditorEnvironment _editorEnvironment;
-		ImageEditorToolList _editorTools;
-
-		ImageEditorDockWidget* _editorDockWidget{nullptr};
-		ImageEditorWidget* _editorWidget{nullptr};		
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: ImageEditor.h
+ * Date: 27.3.2018
+ *****************************************************************************/
+
+#ifndef IMAGEEDITOR_H
+#define IMAGEEDITOR_H
+
+#include "controller/ImageEditorController.h"
+#include "ImageEditorEnvironment.h"
+#include "ImageEditorDockWidget.h"
+#include "ImageEditorWidget.h"
+#include "ImageEditorToolList.h"
+
+namespace grndr
+{
+	class Block;
+
+	class ImageEditor : public QObject
+	{
+		Q_OBJECT
+
+	public:
+		static const char* Serialization_Value_Block;
+
+	public:
+		ImageEditor();
+
+	public:
+		void setImageBuild(const std::shared_ptr<ImageBuild>& imageBuild);
+
+	public:
+		cv::Mat getDisplayedImage(bool ignoreLayersAlpha = true);
+
+	public:
+		ImageEditorController& controller() { return _editorController; }
+		const ImageEditorController& controller() const { return _editorController; }
+		ImageEditorEnvironment& environment() { return _editorEnvironment; }
+		const ImageEditorEnvironment& environment() const { return _editorEnvironment; }
+		ImageEditorToolList& editorTools() { return _editorTools; }
+		const ImageEditorToolList& editorTools() const { return _editorTools; }
+
+		ImageEditorDockWidget* dockWidget() { return _editorDockWidget; }
+		const ImageEditorDockWidget* dockWidget() const { return _editorDockWidget; }
+		ImageEditorWidget* editorWidget() { return _editorWidget; }
+		const ImageEditorWidget* editorWidget() const { return _editorWidget; }
+
+	public:
+		void serialize(SerializationContext& ctx) const;
+		void deserialize(DeserializationContext& ctx);
+
+	private:
+		ImageEditorController _editorController;
+		ImageEditorEnvironment _editorEnvironment;
+		ImageEditorToolList _editorTools;
+
+		ImageEditorDockWidget* _editorDockWidget{nullptr};
+		ImageEditorWidget* _editorWidget{nullptr};		
+	};
+}
+
+#endif
diff --git a/Grinder/ui/image/ImageEditorEnvironment.cpp b/Grinder/ui/image/ImageEditorEnvironment.cpp
index e55b56d6f0caddf97a5054ced7b3ffa6f54947b7..1d8ebb0bea683a0c37b0ba0ed872e7fadb60dd24 100644
--- a/Grinder/ui/image/ImageEditorEnvironment.cpp
+++ b/Grinder/ui/image/ImageEditorEnvironment.cpp
@@ -1,76 +1,88 @@
-/******************************************************************************
- * File: ImageEditorEnvironment.cpp
- * Date: 26.3.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "ImageEditorEnvironment.h"
-#include "controller/ImageEditorController.h"
-
-const char* ImageEditorEnvironment::Serialization_Group = "Environment";
-
-const char* ImageEditorEnvironment::Serialization_Value_PrimaryColor = "PrimaryColor";
-const char* ImageEditorEnvironment::Serialization_Value_ShowDirectionArrows = "ShowDirectionArrows";
-const char* ImageEditorEnvironment::Serialization_Value_ShowTags = "ShowTags";
-const char* ImageEditorEnvironment::Serialization_Value_SnapToEdges = "SnapToEdges";
-
-ImageEditorEnvironment::ImageEditorEnvironment(ImageEditorController* controller) :
-	_editorController{controller}, _selection{controller->imageEditor()}
-{
-	if (!controller)
-		throw std::invalid_argument{_EXCPT("controller may not be null")};
-}
-
-void ImageEditorEnvironment::setPrimaryColor(QColor color)
-{
-	if (color != _primaryColor)
-	{
-		_primaryColor = color;
-		emit primaryColorChanged(color);
-	}
-}
-
-void ImageEditorEnvironment::setShowDirectionArrows(bool show)
-{
-	if (show != _showDirectionArrows)
-	{
-		_showDirectionArrows = show;
-		emit showDirectionArrowsChanged(show);
-	}
-}
-
-void ImageEditorEnvironment::setShowTags(bool show)
-{
-	if (show != _showTags)
-	{
-		_showTags = show;
-		emit showTagsChanged(show);
-	}
-}
-
-void ImageEditorEnvironment::setSnapToEdges(bool snap)
-{
-	if (snap != _snapToEdges)
-	{
-		_snapToEdges = snap;
-		emit snapToEdgesChanged(snap);
-	}
-}
-
-void ImageEditorEnvironment::serialize(SerializationContext& ctx) const
-{
-	// Serialize values
-	ctx.settings()(Serialization_Value_PrimaryColor) = _primaryColor.name();
-	ctx.settings()(Serialization_Value_ShowDirectionArrows) = _showDirectionArrows;
-	ctx.settings()(Serialization_Value_ShowTags) = _showTags;
-	ctx.settings()(Serialization_Value_SnapToEdges) = _snapToEdges;
-}
-
-void ImageEditorEnvironment::deserialize(DeserializationContext& ctx)
-{
-	// Deserialize values
-	setPrimaryColor(QColor{ctx.settings()(Serialization_Value_PrimaryColor).toString()});
-	setShowDirectionArrows(ctx.settings()(Serialization_Value_ShowDirectionArrows, true).toBool());
-	setShowTags(ctx.settings()(Serialization_Value_ShowTags, true).toBool());
-	setSnapToEdges(ctx.settings()(Serialization_Value_SnapToEdges, true).toBool());
-}
+/******************************************************************************
+ * File: ImageEditorEnvironment.cpp
+ * Date: 26.3.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "ImageEditorEnvironment.h"
+#include "controller/ImageEditorController.h"
+
+const char* ImageEditorEnvironment::Serialization_Group = "Environment";
+
+const char* ImageEditorEnvironment::Serialization_Value_PrimaryColor = "PrimaryColor";
+const char* ImageEditorEnvironment::Serialization_Value_ShowDirectionArrows = "ShowDirectionArrows";
+const char* ImageEditorEnvironment::Serialization_Value_ShowTags = "ShowTags";
+const char* ImageEditorEnvironment::Serialization_Value_SnapToEdges = "SnapToEdges";
+const char* ImageEditorEnvironment::Serialization_Value_SamplingMode = "SamplingMode";
+
+ImageEditorEnvironment::ImageEditorEnvironment(ImageEditorController* controller) :
+	_editorController{controller}, _selection{controller->imageEditor()}
+{
+	if (!controller)
+		throw std::invalid_argument{_EXCPT("controller may not be null")};
+}
+
+void ImageEditorEnvironment::setPrimaryColor(QColor color)
+{
+	if (color != _primaryColor)
+	{
+		_primaryColor = color;
+		emit primaryColorChanged(color);
+	}
+}
+
+void ImageEditorEnvironment::setShowDirectionArrows(bool show)
+{
+	if (show != _showDirectionArrows)
+	{
+		_showDirectionArrows = show;
+		emit showDirectionArrowsChanged(show);
+	}
+}
+
+void ImageEditorEnvironment::setShowTags(bool show)
+{
+	if (show != _showTags)
+	{
+		_showTags = show;
+		emit showTagsChanged(show);
+	}
+}
+
+void ImageEditorEnvironment::setSnapToEdges(bool snap)
+{
+	if (snap != _snapToEdges)
+	{
+		_snapToEdges = snap;
+		emit snapToEdgesChanged(snap);
+	}
+}
+
+void ImageEditorEnvironment::setSamplingMode(SamplingMode mode)
+{
+	if (mode != _samplingMode)
+	{
+		_samplingMode = mode;
+		emit samplingModeChanged(mode);
+	}
+}
+
+void ImageEditorEnvironment::serialize(SerializationContext& ctx) const
+{
+	// Serialize values
+	ctx.settings()(Serialization_Value_PrimaryColor) = _primaryColor.name();
+	ctx.settings()(Serialization_Value_ShowDirectionArrows) = _showDirectionArrows;
+	ctx.settings()(Serialization_Value_ShowTags) = _showTags;
+	ctx.settings()(Serialization_Value_SnapToEdges) = _snapToEdges;
+	ctx.settings()(Serialization_Value_SamplingMode) = static_cast<int>(_samplingMode);
+}
+
+void ImageEditorEnvironment::deserialize(DeserializationContext& ctx)
+{
+	// Deserialize values
+	setPrimaryColor(QColor{ctx.settings()(Serialization_Value_PrimaryColor).toString()});
+	setShowDirectionArrows(ctx.settings()(Serialization_Value_ShowDirectionArrows, true).toBool());
+	setShowTags(ctx.settings()(Serialization_Value_ShowTags, true).toBool());
+	setSnapToEdges(ctx.settings()(Serialization_Value_SnapToEdges, true).toBool());
+	setSamplingMode(static_cast<SamplingMode>(ctx.settings()(Serialization_Value_SamplingMode, static_cast<int>(SamplingMode::Layer)).toInt()));
+}
diff --git a/Grinder/ui/image/ImageEditorEnvironment.h b/Grinder/ui/image/ImageEditorEnvironment.h
index 478f5d70e4cb784276adfeac8ae38f47c96a0597..f89e9d499cbeb17b0f71fda727e83ebe8f9ccc41 100644
--- a/Grinder/ui/image/ImageEditorEnvironment.h
+++ b/Grinder/ui/image/ImageEditorEnvironment.h
@@ -1,72 +1,86 @@
-/******************************************************************************
- * File: ImageEditorEnvironment.h
- * Date: 26.3.2018
- *****************************************************************************/
-
-#ifndef IMAGEEDITORENVIRONMENT_H
-#define IMAGEEDITORENVIRONMENT_H
-
-#include <QColor>
-
-#include "ImageEditorSelection.h"
-#include "common/serialization/SerializationContext.h"
-#include "common/serialization/DeserializationContext.h"
-
-namespace grndr
-{
-	class ImageEditorController;
-
-	class ImageEditorEnvironment : public QObject
-	{
-		Q_OBJECT
-
-	public:
-		static const char* Serialization_Group;
-
-		static const char* Serialization_Value_PrimaryColor;
-		static const char* Serialization_Value_ShowDirectionArrows;
-		static const char* Serialization_Value_ShowTags;
-		static const char* Serialization_Value_SnapToEdges;
-
-	public:
-		ImageEditorEnvironment(ImageEditorController* controller);
-
-	public:
-		ImageEditorSelection& selection() { return _selection; }
-		const ImageEditorSelection& selection() const { return _selection; }
-
-		QColor getPrimaryColor() const { return _primaryColor; }
-		void setPrimaryColor(QColor color);
-
-		bool showDirectionArrows() const { return _showDirectionArrows; }
-		void setShowDirectionArrows(bool show);
-		bool showTags() const { return _showTags; }		
-		void setShowTags(bool show);
-		bool snapToEdges() const { return _snapToEdges; }
-		void setSnapToEdges(bool snap);
-
-	public:
-		void serialize(SerializationContext& ctx) const;
-		void deserialize(DeserializationContext& ctx);
-
-	signals:
-		void primaryColorChanged(QColor);
-		void showDirectionArrowsChanged(bool);
-		void showTagsChanged(bool);
-		void snapToEdgesChanged(bool);
-
-	private:
-		ImageEditorController* _editorController{nullptr};
-
-	private:
-		ImageEditorSelection _selection;
-
-		QColor _primaryColor{255, 255, 255};
-
-		bool _showDirectionArrows{true};
-		bool _showTags{true};
-		bool _snapToEdges{true};
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: ImageEditorEnvironment.h
+ * Date: 26.3.2018
+ *****************************************************************************/
+
+#ifndef IMAGEEDITORENVIRONMENT_H
+#define IMAGEEDITORENVIRONMENT_H
+
+#include <QColor>
+
+#include "ImageEditorSelection.h"
+#include "common/serialization/SerializationContext.h"
+#include "common/serialization/DeserializationContext.h"
+
+namespace grndr
+{
+	class ImageEditorController;
+
+	class ImageEditorEnvironment : public QObject
+	{
+		Q_OBJECT
+
+	public:
+		static const char* Serialization_Group;
+
+		static const char* Serialization_Value_PrimaryColor;
+		static const char* Serialization_Value_ShowDirectionArrows;
+		static const char* Serialization_Value_ShowTags;
+		static const char* Serialization_Value_SnapToEdges;
+		static const char* Serialization_Value_SamplingMode;
+
+	public:
+		enum class SamplingMode
+		{
+			Image,
+			Layer,
+		};
+
+	public:
+		ImageEditorEnvironment(ImageEditorController* controller);
+
+	public:
+		ImageEditorSelection& selection() { return _selection; }
+		const ImageEditorSelection& selection() const { return _selection; }
+
+		QColor getPrimaryColor() const { return _primaryColor; }
+		void setPrimaryColor(QColor color);
+
+		bool showDirectionArrows() const { return _showDirectionArrows; }
+		void setShowDirectionArrows(bool show);
+		bool showTags() const { return _showTags; }		
+		void setShowTags(bool show);
+		bool snapToEdges() const { return _snapToEdges; }
+		void setSnapToEdges(bool snap);
+
+		SamplingMode getSamplingMode() const { return _samplingMode; }
+		void setSamplingMode(SamplingMode mode);
+
+	public:
+		void serialize(SerializationContext& ctx) const;
+		void deserialize(DeserializationContext& ctx);
+
+	signals:
+		void primaryColorChanged(QColor);
+		void showDirectionArrowsChanged(bool);
+		void showTagsChanged(bool);
+		void snapToEdgesChanged(bool);
+		void samplingModeChanged(SamplingMode);
+
+	private:
+		ImageEditorController* _editorController{nullptr};
+
+	private:
+		ImageEditorSelection _selection;
+
+		QColor _primaryColor{255, 255, 255};
+
+		bool _showDirectionArrows{true};
+		bool _showTags{true};
+		bool _snapToEdges{true};
+
+		SamplingMode _samplingMode{SamplingMode::Layer};
+	};
+}
+
+#endif
diff --git a/Grinder/ui/image/ImageEditorSelection.cpp b/Grinder/ui/image/ImageEditorSelection.cpp
index 9add74d17cfc98bf0b188d6246f71af69a74da2f..106a18babce37de2341fb6dd04e4d19a35bb4c25 100644
--- a/Grinder/ui/image/ImageEditorSelection.cpp
+++ b/Grinder/ui/image/ImageEditorSelection.cpp
@@ -95,7 +95,14 @@ void ImageEditorSelection::grabCutSelection(int iterations)
 	{
 		if (auto layer = _imageEditor->controller().activeLayer())
 		{
-			auto layerSize = layer->getLayerSize();
+			cv::Mat pixelsMatrix;
+
+			if (_imageEditor->environment().getSamplingMode() == ImageEditorEnvironment::SamplingMode::Image)
+				pixelsMatrix = _imageEditor->getDisplayedImage();
+			else
+				pixelsMatrix = layer->layerPixels().data().toMatrix();
+
+			auto layerSize = QSize{pixelsMatrix.cols, pixelsMatrix.rows};
 			cv::Mat mask{layerSize.height(), layerSize.width(), CV_8UC1, cv::Scalar::all(cv::GC_BGD)};
 
 			for (int x = 0; x < mask.cols; ++x)
@@ -108,7 +115,6 @@ void ImageEditorSelection::grabCutSelection(int iterations)
 			}
 
 			// Run the GrabCut algorithm
-			auto pixelsMatrix = layer->layerPixels().data().toMatrix();
 			cv::Mat backgroundModel = cv::Mat::zeros(1, 65, CV_64FC1);
 			cv::Mat foregroundModel = cv::Mat::zeros(1, 65, CV_64FC1);
 
diff --git a/Grinder/ui/image/ImageEditorTool.cpp b/Grinder/ui/image/ImageEditorTool.cpp
index 31ca6a1e233beab8a371cc965829fb83356af0f8..6dd889f8d0b611d89329f72b7740e744df2e1d81 100644
--- a/Grinder/ui/image/ImageEditorTool.cpp
+++ b/Grinder/ui/image/ImageEditorTool.cpp
@@ -1,87 +1,87 @@
-/******************************************************************************
- * File: ImageEditorTool.cpp
- * Date: 22.3.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "ImageEditorTool.h"
-#include "ImageEditor.h"
-#include "ui/visscene/RubberBandNode.h"
-
-const char* ImageEditorTool::Serialization_Value_Type = "Type";
-
-ImageEditorTool::ImageEditorTool(ImageEditor* imageEditor, QString name, QString icon, QString shortcut, QCursor cursor) : ImageEditorComponent(imageEditor),
-	_name{name}, _icon{icon}, _shortcut{shortcut}, _cursor{cursor}
-{
-	if (!imageEditor)
-		throw std::invalid_argument{_EXCPT("imageEditor may not be null")};
-}
-
-void ImageEditorTool::initImageEditorTool()
-{
-	createProperties();
-	updateProperties();
-}
-
-void ImageEditorTool::toolActivated(ImageEditorTool* prevTool)
-{
-	Q_UNUSED(prevTool);
-
-	_isActive = true;
-
-	if (_supportRightMouseButton && _imageEditor->controller().activeScene())
-	{
-		// If the tool supports the right mouse button, we need to disable the view's context menu
-		_prevContextMenuPolicy = _imageEditor->controller().activeScene()->view()->contextMenuPolicy();
-		_imageEditor->controller().activeScene()->view()->setContextMenuPolicy(Qt::NoContextMenu);
-	}
-}
-
-void ImageEditorTool::toolDeactivated(ImageEditorTool* nextTool)
-{
-	Q_UNUSED(nextTool);
-
-	_isActive = false;
-
-	if (_supportRightMouseButton && _imageEditor->controller().activeScene())
-		_imageEditor->controller().activeScene()->view()->setContextMenuPolicy(_prevContextMenuPolicy);
-
-	removeRubberBand();
-}
-
-void ImageEditorTool::serialize(SerializationContext& ctx) const
-{
-	PropertyObject::serialize(ctx);
-
-	// Serialize values
-	ctx.settings()(Serialization_Value_Type) = getToolType();
-}
-
-void ImageEditorTool::deserialize(DeserializationContext& ctx)
-{
-	PropertyObject::deserialize(ctx);
-}
-
-void ImageEditorTool::createRubberBand(QPointF pos)
-{
-	if (!_rubberBandNode)
-	{
-		if (auto scene = _imageEditor->controller().activeScene())
-			_rubberBandNode = new RubberBandNode{scene, pos};
-	}
-}
-
-void ImageEditorTool::removeRubberBand()
-{
-	if (_rubberBandNode)
-	{
-		delete _rubberBandNode;
-		_rubberBandNode = nullptr;
-
-		if (auto scene = _imageEditor->controller().activeScene())
-		{
-			scene->view()->setDragMode(QGraphicsView::ScrollHandDrag);
-			scene->view()->setDragMode(QGraphicsView::RubberBandDrag);
-		}
-	}
-}
+/******************************************************************************
+ * File: ImageEditorTool.cpp
+ * Date: 22.3.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "ImageEditorTool.h"
+#include "ImageEditor.h"
+#include "ui/visscene/RubberBandNode.h"
+
+const char* ImageEditorTool::Serialization_Value_Type = "Type";
+
+ImageEditorTool::ImageEditorTool(ImageEditor* imageEditor, QString name, QString icon, QString shortcut, QCursor cursor) : ImageEditorComponent(imageEditor),
+	_name{name}, _icon{icon}, _shortcut{shortcut}, _cursor{cursor}
+{
+	if (!imageEditor)
+		throw std::invalid_argument{_EXCPT("imageEditor may not be null")};
+}
+
+void ImageEditorTool::initImageEditorTool()
+{
+	createProperties();
+	updateProperties();
+}
+
+void ImageEditorTool::toolActivated(ImageEditorTool* prevTool)
+{
+	Q_UNUSED(prevTool);
+
+	_isActive = true;
+
+	if (_supportRightMouseButton && _imageEditor->controller().activeScene())
+	{
+		// If the tool supports the right mouse button, we need to disable the view's context menu
+		_prevContextMenuPolicy = _imageEditor->controller().activeScene()->view()->contextMenuPolicy();
+		_imageEditor->controller().activeScene()->view()->setContextMenuPolicy(Qt::NoContextMenu);
+	}
+}
+
+void ImageEditorTool::toolDeactivated(ImageEditorTool* nextTool)
+{
+	Q_UNUSED(nextTool);
+
+	_isActive = false;
+
+	if (_supportRightMouseButton && _imageEditor->controller().activeScene())
+		_imageEditor->controller().activeScene()->view()->setContextMenuPolicy(_prevContextMenuPolicy);
+
+	removeRubberBand();
+}
+
+void ImageEditorTool::serialize(SerializationContext& ctx) const
+{
+	PropertyObject::serialize(ctx);
+
+	// Serialize values
+	ctx.settings()(Serialization_Value_Type) = getToolType();
+}
+
+void ImageEditorTool::deserialize(DeserializationContext& ctx)
+{
+	PropertyObject::deserialize(ctx);
+}
+
+void ImageEditorTool::createRubberBand(QPointF pos)
+{
+	if (!_rubberBandNode)
+	{
+		if (auto scene = _imageEditor->controller().activeScene())
+			_rubberBandNode = new RubberBandNode{scene, pos};
+	}
+}
+
+void ImageEditorTool::removeRubberBand()
+{
+	if (_rubberBandNode)
+	{
+		delete _rubberBandNode;
+		_rubberBandNode = nullptr;
+
+		if (auto scene = _imageEditor->controller().activeScene())
+		{
+			scene->view()->setDragMode(QGraphicsView::ScrollHandDrag);
+			scene->view()->setDragMode(QGraphicsView::RubberBandDrag);
+		}
+	}
+}
diff --git a/Grinder/ui/image/ImageEditorTool.h b/Grinder/ui/image/ImageEditorTool.h
index 3c9747c40fed6ca55fe1a2f33f0a8e5bee6e05a9..f9b0b6da0914587315355268f7da78bdd2b1cdb3 100644
--- a/Grinder/ui/image/ImageEditorTool.h
+++ b/Grinder/ui/image/ImageEditorTool.h
@@ -1,84 +1,84 @@
-/******************************************************************************
- * File: ImageEditorTool.h
- * Date: 22.3.2018
- *****************************************************************************/
-
-#ifndef IMAGEEDITORTOOL_H
-#define IMAGEEDITORTOOL_H
-
-#include <QIcon>
-#include <QCursor>
-#include <QKeySequence>
-
-#include "common/properties/PropertyObject.h"
-#include "ui/visscene/VisualSceneInputHandler.h"
-#include "ImageEditorComponent.h"
-
-namespace grndr
-{
-	class ImageEditor;
-	class RubberBandNode;
-
-	class ImageEditorTool : public PropertyObject, public ImageEditorComponent, public VisualSceneInputHandler
-	{
-		Q_OBJECT
-
-	public:
-		static const char* Serialization_Value_Type;
-
-	public:
-		ImageEditorTool(ImageEditor* imageEditor, QString name, QString icon, QString shortcut, QCursor cursor = QCursor{Qt::ArrowCursor});
-
-	public:
-		void initImageEditorTool();
-
-	public:
-		virtual void toolActivated(ImageEditorTool* prevTool);
-		virtual void toolDeactivated(ImageEditorTool* nextTool);
-
-	public:
-		virtual void serialize(SerializationContext& ctx) const override;
-		virtual void deserialize(DeserializationContext& ctx) override;
-
-	public:
-		virtual QString getToolType() const = 0;
-
-		QString getName() const { return _name; }
-		QIcon getIcon() const { return _icon; }
-		QString getShortcut() const { return _shortcut; }
-		bool isActionShortcut() const { return _isActionShortcut; }
-		QCursor getCursor() const { return _cursor; }
-
-		bool isActive() const { return _isActive; }
-
-		virtual PropertyObject* getExternalProperties() const { return nullptr; }
-
-	signals:
-		void changeCursor(const QCursor&);
-
-		void externalPropertiesInvalidated(const PropertyObject*);
-
-	protected:
-		void createRubberBand(QPointF pos);
-		void removeRubberBand();
-
-	protected:
-		QString _name{""};
-		QIcon _icon;
-		QString _shortcut;
-		bool _isActionShortcut{true};
-		QCursor _cursor;
-
-		bool _supportRightMouseButton{false};
-
-		bool _isActive{false};
-
-	protected:
-		RubberBandNode* _rubberBandNode{nullptr};
-
-	private:
-		Qt::ContextMenuPolicy _prevContextMenuPolicy;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: ImageEditorTool.h
+ * Date: 22.3.2018
+ *****************************************************************************/
+
+#ifndef IMAGEEDITORTOOL_H
+#define IMAGEEDITORTOOL_H
+
+#include <QIcon>
+#include <QCursor>
+#include <QKeySequence>
+
+#include "common/properties/PropertyObject.h"
+#include "ui/visscene/VisualSceneInputHandler.h"
+#include "ImageEditorComponent.h"
+
+namespace grndr
+{
+	class ImageEditor;
+	class RubberBandNode;
+
+	class ImageEditorTool : public PropertyObject, public ImageEditorComponent, public VisualSceneInputHandler
+	{
+		Q_OBJECT
+
+	public:
+		static const char* Serialization_Value_Type;
+
+	public:
+		ImageEditorTool(ImageEditor* imageEditor, QString name, QString icon, QString shortcut, QCursor cursor = QCursor{Qt::ArrowCursor});
+
+	public:
+		void initImageEditorTool();
+
+	public:
+		virtual void toolActivated(ImageEditorTool* prevTool);
+		virtual void toolDeactivated(ImageEditorTool* nextTool);
+
+	public:
+		virtual void serialize(SerializationContext& ctx) const override;
+		virtual void deserialize(DeserializationContext& ctx) override;
+
+	public:
+		virtual QString getToolType() const = 0;
+
+		QString getName() const { return _name; }
+		QIcon getIcon() const { return _icon; }
+		QString getShortcut() const { return _shortcut; }
+		bool isActionShortcut() const { return _isActionShortcut; }
+		QCursor getCursor() const { return _cursor; }
+
+		bool isActive() const { return _isActive; }
+
+		virtual PropertyObject* getExternalProperties() const { return nullptr; }
+
+	signals:
+		void changeCursor(const QCursor&);
+
+		void externalPropertiesInvalidated(const PropertyObject*);
+
+	protected:
+		void createRubberBand(QPointF pos);
+		void removeRubberBand();
+
+	protected:
+		QString _name{""};
+		QIcon _icon;
+		QString _shortcut;
+		bool _isActionShortcut{true};
+		QCursor _cursor;
+
+		bool _supportRightMouseButton{false};
+
+		bool _isActive{false};
+
+	protected:
+		RubberBandNode* _rubberBandNode{nullptr};
+
+	private:
+		Qt::ContextMenuPolicy _prevContextMenuPolicy;
+	};
+}
+
+#endif
diff --git a/Grinder/ui/image/ImageEditorToolList.cpp b/Grinder/ui/image/ImageEditorToolList.cpp
index 7336363c29f0da9636b8835baa7171a74d18914e..bb459c9b855e133f6a16dc8a08c600dccbd3d655 100644
--- a/Grinder/ui/image/ImageEditorToolList.cpp
+++ b/Grinder/ui/image/ImageEditorToolList.cpp
@@ -32,6 +32,7 @@ ImageEditorToolList::ImageEditorToolList(ImageEditor* imageEditor) : ImageEditor
 	_tools.reserve(30);	// Reserve enough space so that no resizing occurs when adding all tools (can be problematic under Linux)
 	_tools.push_back(ToolEntry{createTool<DefaultImageEditorTool>(imageEditor), nullptr});
 	_tools.push_back(ToolEntry{createTool<ColorPickerTool>(imageEditor), nullptr});
+	_tools.push_back(ToolEntry{});
 	_tools.push_back(ToolEntry{createTool<BoxDraftItemTool>(imageEditor), nullptr});
 	_tools.push_back(ToolEntry{createTool<EllipseDraftItemTool>(imageEditor), nullptr});
 	_tools.push_back(ToolEntry{createTool<LineDraftItemTool>(imageEditor), nullptr});
diff --git a/Grinder/ui/image/ImageEditorView.cpp b/Grinder/ui/image/ImageEditorView.cpp
index 2f0b2cdfd95d8d447bf22dc7354680e0e29e0c9c..7fc3b10c049db7fd4e022644ab944b0f96f609c8 100644
--- a/Grinder/ui/image/ImageEditorView.cpp
+++ b/Grinder/ui/image/ImageEditorView.cpp
@@ -1,334 +1,418 @@
-/******************************************************************************
- * File: ImageEditorView.cpp
- * Date: 15.3.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "ImageEditorView.h"
-#include "ImageEditorScene.h"
-#include "ImageEditor.h"
-#include "DraftItemNode.h"
-#include "core/GrinderApplication.h"
-#include "controller/ImageEditorController.h"
-#include "ui/UIUtils.h"
-#include "res/Resources.h"
-
-ImageEditorView::ImageEditorView(QWidget* parent) : VisualSceneView(parent)
-{
-	// Set the background of the view to a checkerboard pattern
-	setBackgroundBrush(QPixmap{FILE_ICON_EDITOR_BACKGROUND});
-
-	// Set widget border
-	setStyleSheet(QString{"QGraphicsView { border: 1px solid %1; }"}.arg(QPalette{}.color(QPalette::Dark).name()));
-
-	// Create view actions
-	_showDirectionsAction = UIUtils::createAction(this, "&Show direction arrows", FILE_ICON_EDITOR_SHOWDIRECTIONS, SLOT(showDirectionArrows()), "Show direction arrows on items");
-	_showDirectionsAction->setCheckable(true);
-	_showDirectionsAction->setChecked(true);
-	_showTagsAction = UIUtils::createAction(this, "&Show tags", FILE_ICON_EDITOR_SHOWTAGS, SLOT(showTags()), "Show tags on items");
-	_showTagsAction->setCheckable(true);
-	_showTagsAction->setChecked(true);
-	_snapToEdgesAction = UIUtils::createAction(this, "Sna&p to edges", FILE_ICON_EDITOR_SNAPTOEDGES, SLOT(snapToEdges()), "Snap items to the image edges");
-	_snapToEdgesAction->setCheckable(true);
-	_snapToEdgesAction->setChecked(true);
-
-	_zoomFitAction = UIUtils::createAction(this, "Zoom to &window", FILE_ICON_ZOOMFIT, SLOT(fitImageToWindow()), "Zoom the view to fit the image to its window", "Ctrl+Alt+A");
-
-	_copyDraftItems = UIUtils::createAction(this, "&Copy item(s)", FILE_ICON_COPY, SLOT(copyDraftItems()), "Copy the selected items to the clipboard");
-	_copyDraftItems->setShortcut(QKeySequence{QKeySequence::Copy});
-	_pasteDraftItems = UIUtils::createAction(this, "&Paste item(s)", FILE_ICON_PASTE, SLOT(pasteDraftItems()), "Paste items from the clipboard");
-	_pasteDraftItems->setShortcut(QKeySequence{QKeySequence::Paste});
-	_cutDraftItems = UIUtils::createAction(this, "Cu&t item(s)", FILE_ICON_CUT, SLOT(cutDraftItems()), "Copy the selected items to the clipboard and remove them afterwards");
-	_cutDraftItems->setShortcut(QKeySequence{QKeySequence::Cut});
-	_convertDraftItemsAction = UIUtils::createAction(this, "&Convert to pixels", FILE_ICON_EDITOR_CONVERTTOPIXELS, SLOT(convertDraftItems()), "Converts the selected items to pixels", "Return");
-
-	// Listen for clipboard changes to update our actions
-	connect(&grinder()->clipboardManager(), &ClipboardManager::dataChanged, this, &ImageEditorView::updateActions);
-
-	updateActions();	
-}
-
-void ImageEditorView::setEditorScene(ImageEditorScene* scene)
-{
-	if (_editorScene)
-	{
-		disconnect(_editorScene, nullptr, this, nullptr);
-		disconnect(&_editorScene->imageEditor()->editorTools(), nullptr, this, nullptr);
-		disconnect(&_editorScene->imageEditor()->environment(), nullptr, this, nullptr);
-	}
-
-	_editorScene = scene;
-	VisualSceneView::setScene(scene);
-
-	if (_editorScene)
-	{		
-		// Update the view's cursor when the active draft item in-place editor has changed
-		connect(_editorScene, &ImageEditorScene::draftItemInPlaceEditorActivated, this, &ImageEditorView::draftItemInPlaceEditorActivated);
-		connect(_editorScene, &ImageEditorScene::draftItemInPlaceEditorDeactivated, this, &ImageEditorView::draftItemInPlaceEditorDeactivated);
-
-		// Update the view's cursor when the active image editor tool has changed
-		connect(&_editorScene->imageEditor()->editorTools(), &ImageEditorToolList::activeToolChanging, this, &ImageEditorView::imageEditorToolChanging);
-		connect(&_editorScene->imageEditor()->editorTools(), &ImageEditorToolList::activeToolChanged, this, &ImageEditorView::imageEditorToolChanged);
-
-		// Update the view's actions when the image editor environment has changed
-		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::showDirectionArrowsChanged, this, &ImageEditorView::showDirectionArrowsChanged);
-		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::showTagsChanged, this, &ImageEditorView::showTagsChanged);
-		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::snapToEdgesChanged, this, &ImageEditorView::snapToEdgesChanged);
-	}
-}
-
-void ImageEditorView::removeSelectedItems() const
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->controller().removeSelectedNodes();
-}
-
-void ImageEditorView::resizeSelectedItems(QSize delta)
-{
-	if (_editorScene)
-	{
-		for (auto item : _editorScene->getNodes<DraftItemNode>(true))
-		{
-			if (auto draftItem = item->draftItem().lock())	// Make sure the underlying draft item still exists
-			{
-				if (auto sizeProperty = draftItem->properties().property<SizeProperty>(PropertyID::Size))
-					sizeProperty->setValue(*sizeProperty + delta);
-			}
-		}
-	}
-}
-
-void ImageEditorView::prepareNodeContextMenu(QMenu& menu) const
-{
-	QAction* firstAction = !menu.actions().isEmpty() ? menu.actions().first() : nullptr;
-
-	menu.insertAction(firstAction, _cutDraftItems);
-	menu.insertAction(firstAction, _copyDraftItems);
-	menu.insertAction(firstAction, _pasteDraftItems);
-	menu.insertSeparator(firstAction);
-	menu.insertAction(firstAction, _convertDraftItemsAction);
-}
-
-void ImageEditorView::prepareNodesContextMenu(QMenu& menu) const
-{
-	prepareNodeContextMenu(menu);
-}
-
-std::vector<QAction*> ImageEditorView::getActions(AddActionsMode mode) const
-{
-	std::vector<QAction*> actions;
-
-	if (mode != AddActionsMode::Toolbar)
-	{
-		actions.push_back(_cutDraftItems);
-		actions.push_back(_copyDraftItems);
-		actions.push_back(_pasteDraftItems);
-		actions.push_back(nullptr);
-
-		actions.push_back(_selectAllAction);
-		actions.push_back(_deleteSelectedAction);
-		actions.push_back(nullptr);
-	}
-
-	actions.push_back(_snapToEdgesAction);
-	actions.push_back(nullptr);
-	actions.push_back(_showDirectionsAction);
-	actions.push_back(_showTagsAction);
-	actions.push_back(nullptr);
-	actions.push_back(_zoomInAction);
-	actions.push_back(_zoomOutAction);
-	actions.push_back(_zoomFullAction);
-	actions.push_back(_zoomFitAction);
-
-	return actions;
-}
-
-void ImageEditorView::drawBackground(QPainter* painter, const QRectF& rect)
-{
-	// Draw scale-invariant background
-	auto scaleFactor = painter->transform().m11();
-	auto bgRect = rect;
-
-	bgRect.setTopLeft(bgRect.topLeft() * scaleFactor);
-	bgRect.setBottomRight(bgRect.bottomRight() * scaleFactor);
-
-	painter->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
-	painter->fillRect(bgRect, backgroundBrush());
-	painter->scale(scaleFactor, scaleFactor);
-}
-
-void ImageEditorView::keyPressEvent(QKeyEvent* event)
-{
-	if (dynamic_cast<QGraphicsProxyWidget*>(_scene ? _scene->focusItem() : nullptr) == nullptr)	// If a widget inside the scene has the input focus, do not process key events here
-	{
-		if ((event->key() == Qt::Key_Up || event->key() == Qt::Key_Down || event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) && (event->modifiers() == Qt::ShiftModifier))	// Enable item resizing via cursor keys
-		{
-			QSize delta{0, 0};
-			int offset = 1;
-
-			switch (event->key())
-			{
-			case Qt::Key_Left:
-				delta.setWidth(-offset);
-				break;
-
-			case Qt::Key_Right:
-				delta.setWidth(offset);
-				break;
-
-			case Qt::Key_Up:
-				delta.setHeight(-offset);
-				break;
-
-			case Qt::Key_Down:
-				delta.setHeight(offset);
-				break;
-
-			default:
-				break;
-			}
-
-			if (!delta.isNull())
-			{
-				resizeSelectedItems(delta);
-				return;
-			}
-		}
-	}
-
-	VisualSceneView::keyPressEvent(event);
-}
-
-void ImageEditorView::updateActions()
-{
-	VisualSceneView::updateActions();
-
-	bool draftItemSelected = false;
-	bool editableItemSelected = false;
-	bool activeLayerEditable = false;
-
-	if (_editorScene)
-	{
-		auto selectedNodes = _editorScene->getNodes<DraftItemNode>(true);
-		draftItemSelected = !selectedNodes.empty();
-
-		for (const auto& selectedNode : selectedNodes)
-		{
-			if (!selectedNode->isLocked())
-			{
-				editableItemSelected = true;
-				break;
-			}
-		}
-
-		auto activeLayer = _editorScene->imageEditor()->controller().activeLayer();
-		activeLayerEditable = activeLayer ? !activeLayer->hasFlag(Layer::Flag::Locked) : false;
-	}
-
-	_zoomFitAction->setEnabled(_scene);		
-
-	_copyDraftItems->setEnabled(_scene && draftItemSelected);
-	_pasteDraftItems->setEnabled(_scene && grinder()->clipboardManager().hasData(DraftItemVector::Serialization_Element) && activeLayerEditable);
-	_cutDraftItems->setEnabled(_scene && draftItemSelected && editableItemSelected);
-	_convertDraftItemsAction->setEnabled(_scene && draftItemSelected && editableItemSelected);
-	_deleteSelectedAction->setEnabled(_deleteSelectedAction->isEnabled() && draftItemSelected && editableItemSelected);
-}
-
-void ImageEditorView::updateCursor(const QCursor& cursor)
-{
-	setCursor(cursor);
-	viewport()->setCursor(cursor);
-}
-
-void ImageEditorView::showDirectionArrows()
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->environment().setShowDirectionArrows(_showDirectionsAction->isChecked());
-}
-
-void ImageEditorView::showTags()
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->environment().setShowTags(_showTagsAction->isChecked());
-}
-
-void ImageEditorView::snapToEdges()
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->environment().setSnapToEdges(_snapToEdgesAction->isChecked());
-}
-
-void ImageEditorView::fitImageToWindow()
-{
-	if (_editorScene)
-		_editorScene->fitViewToImage();
-}
-
-void ImageEditorView::imageEditorToolChanging(ImageEditorTool* oldTool, ImageEditorTool* newTool)
-{
-	if (oldTool)
-		disconnect(oldTool, &ImageEditorTool::changeCursor, this, &ImageEditorView::updateCursor);
-
-	if (newTool)
-		connect(newTool, &ImageEditorTool::changeCursor, this, &ImageEditorView::updateCursor);
-}
-
-void ImageEditorView::imageEditorToolChanged(ImageEditorTool* tool)
-{
-	updateCursor(tool->getCursor());
-
-	if (_editorScene)
-		_editorScene->clearSelection();
-}
-
-void ImageEditorView::draftItemInPlaceEditorActivated(InPlaceEditorBase* editor)
-{
-	connect(editor, &InPlaceEditorBase::changeCursor, this, &ImageEditorView::updateCursor);
-}
-
-void ImageEditorView::draftItemInPlaceEditorDeactivated(InPlaceEditorBase* editor)
-{
-	disconnect(editor, &InPlaceEditorBase::changeCursor, this, &ImageEditorView::updateCursor);
-}
-
-void ImageEditorView::showDirectionArrowsChanged(bool show)
-{
-	_showDirectionsAction->setChecked(show);
-	update();
-}
-
-void ImageEditorView::showTagsChanged(bool show)
-{
-	_showTagsAction->setChecked(show);
-	update();
-}
-
-void ImageEditorView::snapToEdgesChanged(bool snap)
-{
-	_snapToEdgesAction->setChecked(snap);
-	update();
-}
-
-void ImageEditorView::copyDraftItems() const
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->controller().copySelectedNodes();
-}
-
-void ImageEditorView::pasteDraftItems() const
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->controller().pasteSelectedNodes();
-}
-
-void ImageEditorView::cutDraftItems() const
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->controller().cutSelectedNodes();
-}
-
-void ImageEditorView::convertDraftItems() const
-{
-	if (_editorScene)
-		_editorScene->imageEditor()->controller().convertSelectedNodesToPixels();
-}
+/******************************************************************************
+ * File: ImageEditorView.cpp
+ * Date: 15.3.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "ImageEditorView.h"
+#include "ImageEditorScene.h"
+#include "ImageEditor.h"
+#include "DraftItemNode.h"
+#include "core/GrinderApplication.h"
+#include "controller/ImageEditorController.h"
+#include "ui/UIUtils.h"
+#include "res/Resources.h"
+
+ImageEditorView::ImageEditorView(QWidget* parent) : VisualSceneView(parent)
+{
+	// Set the background of the view to a checkerboard pattern
+	setBackgroundBrush(QPixmap{FILE_ICON_EDITOR_BACKGROUND});
+
+	// Set widget border
+	setStyleSheet(QString{"QGraphicsView { border: 1px solid %1; }"}.arg(QPalette{}.color(QPalette::Dark).name()));
+
+	// Create the sampling mode menu
+	QMenu* samplingModeMenu = new QMenu{this};
+	_samplingModeLayerAction = samplingModeMenu->addAction(QIcon{FILE_ICON_LAYER}, "Layer sampling", this, SLOT(selectLayerSamplingMode()));
+	_samplingModeLayerAction->setCheckable(true);
+	_samplingModeImageAction = samplingModeMenu->addAction(QIcon{FILE_ICON_EDITOR_SAMPLING_IMAGE}, "Image sampling", this, SLOT(selectImageSamplingMode()));
+	_samplingModeImageAction->setCheckable(true);
+
+	// Create view actions
+	_showDirectionsAction = UIUtils::createAction(this, "&Show direction arrows", FILE_ICON_EDITOR_SHOWDIRECTIONS, SLOT(showDirectionArrows()), "Show direction arrows on items");
+	_showDirectionsAction->setCheckable(true);
+	_showDirectionsAction->setChecked(true);
+	_showTagsAction = UIUtils::createAction(this, "&Show tags", FILE_ICON_EDITOR_SHOWTAGS, SLOT(showTags()), "Show tags on items");
+	_showTagsAction->setCheckable(true);
+	_showTagsAction->setChecked(true);
+	_snapToEdgesAction = UIUtils::createAction(this, "Sna&p to edges", FILE_ICON_EDITOR_SNAPTOEDGES, SLOT(snapToEdges()), "Snap items to the image edges");
+	_snapToEdgesAction->setCheckable(true);
+	_snapToEdgesAction->setChecked(true);
+
+	_zoomFitAction = UIUtils::createAction(this, "Zoom to &window", FILE_ICON_ZOOMFIT, SLOT(fitImageToWindow()), "Zoom the view to fit the image to its window", "Ctrl+Alt+A");	
+
+	_samplingModeAction = UIUtils::createAction(this, "Sampling mode", "", SLOT(toggleSamplingMode()), "Select the sampling mode", "Ctrl+M");
+	_samplingModeAction->setMenu(samplingModeMenu);
+
+	_copyDraftItems = UIUtils::createAction(this, "&Copy item(s)", FILE_ICON_COPY, SLOT(copyDraftItems()), "Copy the selected items to the clipboard");
+	_copyDraftItems->setShortcut(QKeySequence{QKeySequence::Copy});
+	_pasteDraftItems = UIUtils::createAction(this, "&Paste item(s)", FILE_ICON_PASTE, SLOT(pasteDraftItems()), "Paste items from the clipboard");
+	_pasteDraftItems->setShortcut(QKeySequence{QKeySequence::Paste});
+	_cutDraftItems = UIUtils::createAction(this, "Cu&t item(s)", FILE_ICON_CUT, SLOT(cutDraftItems()), "Copy the selected items to the clipboard and remove them afterwards");
+	_cutDraftItems->setShortcut(QKeySequence{QKeySequence::Cut});
+	_convertDraftItemsAction = UIUtils::createAction(this, "&Convert to pixels", FILE_ICON_EDITOR_CONVERTTOPIXELS, SLOT(convertDraftItems()), "Converts the selected items to pixels", "Return");
+
+	// Listen for clipboard changes to update our actions
+	connect(&grinder()->clipboardManager(), &ClipboardManager::dataChanged, this, &ImageEditorView::updateActions);
+
+	updateActions();	
+}
+
+void ImageEditorView::setEditorScene(ImageEditorScene* scene)
+{
+	if (_editorScene)
+	{
+		disconnect(_editorScene, nullptr, this, nullptr);
+		disconnect(&_editorScene->imageEditor()->editorTools(), nullptr, this, nullptr);
+		disconnect(&_editorScene->imageEditor()->environment(), nullptr, this, nullptr);
+	}
+
+	_editorScene = scene;
+	VisualSceneView::setScene(scene);
+
+	if (_editorScene)
+	{				
+		// Update the view's cursor when the active draft item in-place editor has changed
+		connect(_editorScene, &ImageEditorScene::draftItemInPlaceEditorActivated, this, &ImageEditorView::draftItemInPlaceEditorActivated);
+		connect(_editorScene, &ImageEditorScene::draftItemInPlaceEditorDeactivated, this, &ImageEditorView::draftItemInPlaceEditorDeactivated);
+
+		// Update the view's cursor when the active image editor tool has changed
+		connect(&_editorScene->imageEditor()->editorTools(), &ImageEditorToolList::activeToolChanging, this, &ImageEditorView::imageEditorToolChanging);
+		connect(&_editorScene->imageEditor()->editorTools(), &ImageEditorToolList::activeToolChanged, this, &ImageEditorView::imageEditorToolChanged);
+
+		// Update the view's actions when the image editor environment has changed
+		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::showDirectionArrowsChanged, this, &ImageEditorView::showDirectionArrowsChanged);
+		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::showTagsChanged, this, &ImageEditorView::showTagsChanged);
+		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::snapToEdgesChanged, this, &ImageEditorView::snapToEdgesChanged);
+		connect(&_editorScene->imageEditor()->environment(), &ImageEditorEnvironment::samplingModeChanged, this, &ImageEditorView::samplingModeChanged);
+	}	
+}
+
+void ImageEditorView::removeSelectedItems() const
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->controller().removeSelectedNodes();
+}
+
+void ImageEditorView::resizeSelectedItems(QSize delta)
+{
+	if (_editorScene)
+	{
+		for (auto item : _editorScene->getNodes<DraftItemNode>(true))
+		{
+			if (auto draftItem = item->draftItem().lock())	// Make sure the underlying draft item still exists
+			{
+				if (auto sizeProperty = draftItem->properties().property<SizeProperty>(PropertyID::Size))
+					sizeProperty->setValue(*sizeProperty + delta);
+			}
+		}
+	}
+}
+
+void ImageEditorView::prepareNodeContextMenu(QMenu& menu) const
+{
+	QAction* firstAction = !menu.actions().isEmpty() ? menu.actions().first() : nullptr;
+
+	menu.insertAction(firstAction, _cutDraftItems);
+	menu.insertAction(firstAction, _copyDraftItems);
+	menu.insertAction(firstAction, _pasteDraftItems);
+	menu.insertSeparator(firstAction);
+	menu.insertAction(firstAction, _convertDraftItemsAction);
+}
+
+void ImageEditorView::prepareNodesContextMenu(QMenu& menu) const
+{
+	prepareNodeContextMenu(menu);
+}
+
+std::vector<QAction*> ImageEditorView::getActions(AddActionsMode mode) const
+{
+	std::vector<QAction*> actions;
+
+	if (mode != AddActionsMode::Toolbar)
+	{
+		actions.push_back(_cutDraftItems);
+		actions.push_back(_copyDraftItems);
+		actions.push_back(_pasteDraftItems);
+		actions.push_back(nullptr);
+
+		actions.push_back(_selectAllAction);
+		actions.push_back(_deleteSelectedAction);
+		actions.push_back(nullptr);
+	}
+
+	actions.push_back(_samplingModeAction);
+	actions.push_back(nullptr);
+	actions.push_back(_snapToEdgesAction);
+	actions.push_back(nullptr);
+	actions.push_back(_showDirectionsAction);
+	actions.push_back(_showTagsAction);
+	actions.push_back(nullptr);
+	actions.push_back(_zoomInAction);
+	actions.push_back(_zoomOutAction);
+	actions.push_back(_zoomFullAction);
+	actions.push_back(_zoomFitAction);
+
+	return actions;
+}
+
+void ImageEditorView::drawBackground(QPainter* painter, const QRectF& rect)
+{
+	// Draw scale-invariant background
+	auto scaleFactor = painter->transform().m11();
+	auto bgRect = rect;
+
+	bgRect.setTopLeft(bgRect.topLeft() * scaleFactor);
+	bgRect.setBottomRight(bgRect.bottomRight() * scaleFactor);
+
+	painter->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
+	painter->fillRect(bgRect, backgroundBrush());
+	painter->scale(scaleFactor, scaleFactor);
+}
+
+void ImageEditorView::keyPressEvent(QKeyEvent* event)
+{
+	if (dynamic_cast<QGraphicsProxyWidget*>(_scene ? _scene->focusItem() : nullptr) == nullptr)	// If a widget inside the scene has the input focus, do not process key events here
+	{
+		if ((event->key() == Qt::Key_Up || event->key() == Qt::Key_Down || event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) && (event->modifiers() == Qt::ShiftModifier))	// Enable item resizing via cursor keys
+		{
+			QSize delta{0, 0};
+			int offset = 1;
+
+			switch (event->key())
+			{
+			case Qt::Key_Left:
+				delta.setWidth(-offset);
+				break;
+
+			case Qt::Key_Right:
+				delta.setWidth(offset);
+				break;
+
+			case Qt::Key_Up:
+				delta.setHeight(-offset);
+				break;
+
+			case Qt::Key_Down:
+				delta.setHeight(offset);
+				break;
+
+			default:
+				break;
+			}
+
+			if (!delta.isNull())
+			{
+				resizeSelectedItems(delta);
+				return;
+			}
+		}
+	}
+
+	VisualSceneView::keyPressEvent(event);
+}
+
+void ImageEditorView::updateActions()
+{
+	VisualSceneView::updateActions();
+
+	bool draftItemSelected = false;
+	bool editableItemSelected = false;
+	bool activeLayerEditable = false;
+
+	if (_editorScene)
+	{
+		auto selectedNodes = _editorScene->getNodes<DraftItemNode>(true);
+		draftItemSelected = !selectedNodes.empty();
+
+		for (const auto& selectedNode : selectedNodes)
+		{
+			if (!selectedNode->isLocked())
+			{
+				editableItemSelected = true;
+				break;
+			}
+		}
+
+		auto activeLayer = _editorScene->imageEditor()->controller().activeLayer();
+		activeLayerEditable = activeLayer ? !activeLayer->hasFlag(Layer::Flag::Locked) : false;
+	}
+
+	_zoomFitAction->setEnabled(_scene);		
+
+	_copyDraftItems->setEnabled(_scene && draftItemSelected);
+	_pasteDraftItems->setEnabled(_scene && grinder()->clipboardManager().hasData(DraftItemVector::Serialization_Element) && activeLayerEditable);
+	_cutDraftItems->setEnabled(_scene && draftItemSelected && editableItemSelected);
+	_convertDraftItemsAction->setEnabled(_scene && draftItemSelected && editableItemSelected);
+	_deleteSelectedAction->setEnabled(_deleteSelectedAction->isEnabled() && draftItemSelected && editableItemSelected);
+
+	updateSamplingMode();
+}
+
+void ImageEditorView::updateSamplingMode()
+{
+	if (_editorScene)
+	{
+		auto modifyActions = [this](QString text, QString icon, bool layerChecked, bool imageChecked) {
+			_samplingModeAction->setText(text);
+			_samplingModeAction->setToolTip(text);
+			_samplingModeAction->setIcon(QIcon{icon});
+
+			_samplingModeLayerAction->setChecked(layerChecked);
+			_samplingModeImageAction->setChecked(imageChecked);
+		};
+
+		switch (_editorScene->imageEditor()->environment().getSamplingMode())
+		{
+		case ImageEditorEnvironment::SamplingMode::Layer:
+			modifyActions("Sampling mode: Layer", FILE_ICON_LAYER, true, false);
+			break;
+
+		case ImageEditorEnvironment::SamplingMode::Image:
+			modifyActions("Sampling mode: Image", FILE_ICON_EDITOR_SAMPLING_IMAGE, false, true);
+			break;
+		}
+	}
+}
+
+void ImageEditorView::updateCursor(const QCursor& cursor)
+{
+	setCursor(cursor);
+	viewport()->setCursor(cursor);
+}
+
+void ImageEditorView::showDirectionArrows()
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->environment().setShowDirectionArrows(_showDirectionsAction->isChecked());
+}
+
+void ImageEditorView::showTags()
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->environment().setShowTags(_showTagsAction->isChecked());
+}
+
+void ImageEditorView::snapToEdges()
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->environment().setSnapToEdges(_snapToEdgesAction->isChecked());
+}
+
+void ImageEditorView::fitImageToWindow()
+{
+	if (_editorScene)
+		_editorScene->fitViewToImage();
+}
+
+void ImageEditorView::toggleSamplingMode()
+{
+	if (_editorScene)
+	{
+		switch (_editorScene->imageEditor()->environment().getSamplingMode())
+		{
+		case ImageEditorEnvironment::SamplingMode::Layer:
+			selectImageSamplingMode();
+			break;
+
+		case ImageEditorEnvironment::SamplingMode::Image:
+			selectLayerSamplingMode();
+			break;
+		}
+	}
+}
+
+void ImageEditorView::selectLayerSamplingMode()
+{
+	if (_editorScene)
+	{
+		_editorScene->imageEditor()->environment().setSamplingMode(ImageEditorEnvironment::SamplingMode::Layer);
+		updateSamplingMode();
+	}
+}
+
+void ImageEditorView::selectImageSamplingMode()
+{
+	if (_editorScene)
+	{
+		_editorScene->imageEditor()->environment().setSamplingMode(ImageEditorEnvironment::SamplingMode::Image);
+		updateSamplingMode();
+	}
+}
+
+void ImageEditorView::imageEditorToolChanging(ImageEditorTool* oldTool, ImageEditorTool* newTool)
+{
+	if (oldTool)
+		disconnect(oldTool, &ImageEditorTool::changeCursor, this, &ImageEditorView::updateCursor);
+
+	if (newTool)
+		connect(newTool, &ImageEditorTool::changeCursor, this, &ImageEditorView::updateCursor);
+}
+
+void ImageEditorView::imageEditorToolChanged(ImageEditorTool* tool)
+{
+	updateCursor(tool->getCursor());
+
+	if (_editorScene)
+		_editorScene->clearSelection();
+}
+
+void ImageEditorView::draftItemInPlaceEditorActivated(InPlaceEditorBase* editor)
+{
+	connect(editor, &InPlaceEditorBase::changeCursor, this, &ImageEditorView::updateCursor);
+}
+
+void ImageEditorView::draftItemInPlaceEditorDeactivated(InPlaceEditorBase* editor)
+{
+	disconnect(editor, &InPlaceEditorBase::changeCursor, this, &ImageEditorView::updateCursor);
+}
+
+void ImageEditorView::showDirectionArrowsChanged(bool show)
+{
+	_showDirectionsAction->setChecked(show);
+	update();
+}
+
+void ImageEditorView::showTagsChanged(bool show)
+{
+	_showTagsAction->setChecked(show);
+	update();
+}
+
+void ImageEditorView::snapToEdgesChanged(bool snap)
+{
+	_snapToEdgesAction->setChecked(snap);
+	update();
+}
+
+void ImageEditorView::samplingModeChanged(ImageEditorEnvironment::SamplingMode mode)
+{
+	Q_UNUSED(mode);
+
+	updateSamplingMode();
+	update();
+}
+
+void ImageEditorView::copyDraftItems() const
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->controller().copySelectedNodes();
+}
+
+void ImageEditorView::pasteDraftItems() const
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->controller().pasteSelectedNodes();
+}
+
+void ImageEditorView::cutDraftItems() const
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->controller().cutSelectedNodes();
+}
+
+void ImageEditorView::convertDraftItems() const
+{
+	if (_editorScene)
+		_editorScene->imageEditor()->controller().convertSelectedNodesToPixels();
+}
diff --git a/Grinder/ui/image/ImageEditorView.h b/Grinder/ui/image/ImageEditorView.h
index 62b9163b2e439b8935cd84c0f02df8115374d091..f77e39d1dc1b44ac9aaf5c6881c243a6caeceed1 100644
--- a/Grinder/ui/image/ImageEditorView.h
+++ b/Grinder/ui/image/ImageEditorView.h
@@ -1,93 +1,104 @@
-/******************************************************************************
- * File: ImageEditorView.h
- * Date: 15.3.2018
- *****************************************************************************/
-
-#ifndef IMAGEEDITORVIEW_H
-#define IMAGEEDITORVIEW_H
-
-#include "ui/visscene/VisualSceneView.h"
-#include "ImageEditorStyle.h"
-
-namespace grndr
-{
-	class ImageEditorScene;
-	class ImageEditorTool;
-	class InPlaceEditorBase;
-
-	class ImageEditorView : public VisualSceneView
-	{
-		Q_OBJECT
-
-	public:
-		ImageEditorView(QWidget *parent = nullptr);
-
-	public:
-		ImageEditorScene* editorScene() { return _editorScene; }
-		const ImageEditorScene* editorScene() const { return _editorScene; }
-		void setEditorScene(ImageEditorScene* scene);
-
-	public slots:
-		virtual void removeSelectedItems() const override;
-		virtual void resizeSelectedItems(QSize delta);
-
-	public:
-		virtual const ImageEditorStyle& sceneStyle() const override { return ImageEditorStyle::style(); }
-
-		virtual void prepareNodeContextMenu(QMenu& menu) const override;
-		virtual void prepareNodesContextMenu(QMenu& menu) const override;
-
-	protected:
-		virtual std::vector<QAction*> getActions(AddActionsMode mode) const override;
-
-	protected:		
-		virtual void drawBackground(QPainter* painter, const QRectF& rect) override;
-
-		virtual void keyPressEvent(QKeyEvent* event) override;
-
-	protected slots:
-		virtual void updateActions() override;
-
-	private:
-		void updateCursor(const QCursor& cursor);
-
-	private slots:
-		void showDirectionArrows();
-		void showTags();
-		void snapToEdges();
-
-		void fitImageToWindow();
-
-		void imageEditorToolChanging(ImageEditorTool* oldTool, ImageEditorTool* newTool);
-		void imageEditorToolChanged(ImageEditorTool* tool);
-
-		void draftItemInPlaceEditorActivated(InPlaceEditorBase* editor);
-		void draftItemInPlaceEditorDeactivated(InPlaceEditorBase* editor);
-
-		void showDirectionArrowsChanged(bool show);
-		void showTagsChanged(bool show);
-		void snapToEdgesChanged(bool snap);
-
-		void copyDraftItems() const;
-		void pasteDraftItems() const;
-		void cutDraftItems() const;
-		void convertDraftItems() const;	
-
-	private:
-		ImageEditorScene* _editorScene{nullptr};
-
-	private:
-		QAction* _showDirectionsAction{nullptr};
-		QAction* _showTagsAction{nullptr};
-		QAction* _snapToEdgesAction{nullptr};
-
-		QAction* _zoomFitAction{nullptr};
-
-		QAction* _copyDraftItems{nullptr};
-		QAction* _pasteDraftItems{nullptr};
-		QAction* _cutDraftItems{nullptr};
-		QAction* _convertDraftItemsAction{nullptr};				
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: ImageEditorView.h
+ * Date: 15.3.2018
+ *****************************************************************************/
+
+#ifndef IMAGEEDITORVIEW_H
+#define IMAGEEDITORVIEW_H
+
+#include "ui/visscene/VisualSceneView.h"
+#include "ImageEditorEnvironment.h"
+#include "ImageEditorStyle.h"
+
+namespace grndr
+{
+	class ImageEditorScene;
+	class ImageEditorTool;
+	class InPlaceEditorBase;
+
+	class ImageEditorView : public VisualSceneView
+	{
+		Q_OBJECT
+
+	public:
+		ImageEditorView(QWidget *parent = nullptr);
+
+	public:
+		ImageEditorScene* editorScene() { return _editorScene; }
+		const ImageEditorScene* editorScene() const { return _editorScene; }
+		void setEditorScene(ImageEditorScene* scene);
+
+	public slots:
+		virtual void removeSelectedItems() const override;
+		virtual void resizeSelectedItems(QSize delta);
+
+	public:
+		virtual const ImageEditorStyle& sceneStyle() const override { return ImageEditorStyle::style(); }
+
+		virtual void prepareNodeContextMenu(QMenu& menu) const override;
+		virtual void prepareNodesContextMenu(QMenu& menu) const override;
+
+	protected:
+		virtual std::vector<QAction*> getActions(AddActionsMode mode) const override;
+
+	protected:		
+		virtual void drawBackground(QPainter* painter, const QRectF& rect) override;
+
+		virtual void keyPressEvent(QKeyEvent* event) override;
+
+	protected slots:
+		virtual void updateActions() override;
+
+	private:
+		void updateSamplingMode();
+		void updateCursor(const QCursor& cursor);
+
+	private slots:
+		void showDirectionArrows();
+		void showTags();
+		void snapToEdges();
+
+		void fitImageToWindow();
+
+		void toggleSamplingMode();
+		void selectLayerSamplingMode();
+		void selectImageSamplingMode();
+
+		void imageEditorToolChanging(ImageEditorTool* oldTool, ImageEditorTool* newTool);
+		void imageEditorToolChanged(ImageEditorTool* tool);
+
+		void draftItemInPlaceEditorActivated(InPlaceEditorBase* editor);
+		void draftItemInPlaceEditorDeactivated(InPlaceEditorBase* editor);
+
+		void showDirectionArrowsChanged(bool show);
+		void showTagsChanged(bool show);
+		void snapToEdgesChanged(bool snap);
+		void samplingModeChanged(ImageEditorEnvironment::SamplingMode);
+
+		void copyDraftItems() const;
+		void pasteDraftItems() const;
+		void cutDraftItems() const;
+		void convertDraftItems() const;	
+
+	private:
+		ImageEditorScene* _editorScene{nullptr};
+
+	private:
+		QAction* _showDirectionsAction{nullptr};
+		QAction* _showTagsAction{nullptr};
+		QAction* _snapToEdgesAction{nullptr};
+
+		QAction* _zoomFitAction{nullptr};
+
+		QAction* _samplingModeAction{nullptr};
+		QAction* _samplingModeLayerAction{nullptr};
+		QAction* _samplingModeImageAction{nullptr};
+
+		QAction* _copyDraftItems{nullptr};
+		QAction* _pasteDraftItems{nullptr};
+		QAction* _cutDraftItems{nullptr};
+		QAction* _convertDraftItemsAction{nullptr};
+	};
+}
+
+#endif
diff --git a/Grinder/ui/image/tools/ColorPickerTool.cpp b/Grinder/ui/image/tools/ColorPickerTool.cpp
index 19e78a0b72c03fd7ba0cd500931699754f8acc99..83f7cf86f350a4dfe9f727f45e4900b29188dace 100644
--- a/Grinder/ui/image/tools/ColorPickerTool.cpp
+++ b/Grinder/ui/image/tools/ColorPickerTool.cpp
@@ -1,62 +1,62 @@
-/******************************************************************************
- * File: ColorPickerTool.cpp
- * Date: 22.3.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "ColorPickerTool.h"
-#include "ui/image/ImageEditor.h"
-#include "res/Resources.h"
-
-const char* ColorPickerTool::tool_type = "ColorPickerTool";
-
-ColorPickerTool::ColorPickerTool(ImageEditor* imageEditor) : ImageEditorTool(imageEditor, "Color picker", FILE_ICON_EDITOR_COLORPICKER, "K", QCursor{QPixmap{FILE_CURSOR_EDITOR_COLORPICKER}, 0, 23})
-{
-
-}
-
-void ColorPickerTool::toolActivated(ImageEditorTool* prevTool)
-{
-	ImageEditorTool::toolActivated(prevTool);
-
-	_previousTool = prevTool;
-	_switchToPreviousTool = false;
-}
-
-ImageEditorTool::InputEventResult ColorPickerTool::mousePressed(const QGraphicsSceneMouseEvent* event)
-{
-	if (event->widget())
-	{
-		// Grab the current scene display and get the pixel color under the cursor		
-		auto pixmap = event->widget()->grab();
-		auto image = pixmap.toImage();
-		auto pos = event->widget()->mapFromGlobal(event->screenPos());
-
-		// Set the grabbed color as the primary one and switch back to the previous tool
-		_imageEditor->environment().setPrimaryColor(image.pixelColor(pos));
-		_switchToPreviousTool = true;
-	}
-
-	return InputEventResult::Process;
-}
-
-ImageEditorTool::InputEventResult ColorPickerTool::mouseMoved(const QGraphicsSceneMouseEvent* event)
-{
-	Q_UNUSED(event);
-	return InputEventResult::Process;
-}
-
-ImageEditorTool::InputEventResult ColorPickerTool::mouseReleased(const QGraphicsSceneMouseEvent* event)
-{
-	Q_UNUSED(event);
-
-	if (_switchToPreviousTool)
-	{
-		if (_previousTool)
-			_imageEditor->editorTools().activateTool(_previousTool->getToolType());
-
-		_switchToPreviousTool = false;
-	}
-
-	return InputEventResult::Process;
-}
+/******************************************************************************
+ * File: ColorPickerTool.cpp
+ * Date: 22.3.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "ColorPickerTool.h"
+#include "ui/image/ImageEditor.h"
+#include "res/Resources.h"
+
+const char* ColorPickerTool::tool_type = "ColorPickerTool";
+
+ColorPickerTool::ColorPickerTool(ImageEditor* imageEditor) : ImageEditorTool(imageEditor, "Color picker", FILE_ICON_EDITOR_COLORPICKER, "K", QCursor{QPixmap{FILE_CURSOR_EDITOR_COLORPICKER}, 0, 23})
+{
+
+}
+
+void ColorPickerTool::toolActivated(ImageEditorTool* prevTool)
+{
+	ImageEditorTool::toolActivated(prevTool);
+
+	_previousTool = prevTool;
+	_switchToPreviousTool = false;
+}
+
+ImageEditorTool::InputEventResult ColorPickerTool::mousePressed(const QGraphicsSceneMouseEvent* event)
+{
+	if (event->widget())
+	{
+		// Grab the current scene display and get the pixel color under the cursor
+		auto pixmap = event->widget()->grab();
+		auto image = pixmap.toImage();
+		auto pos = event->widget()->mapFromGlobal(event->screenPos());
+
+		// Set the grabbed color as the primary one and switch back to the previous tool
+		_imageEditor->environment().setPrimaryColor(image.pixelColor(pos));
+		_switchToPreviousTool = true;
+	}
+
+	return InputEventResult::Process;
+}
+
+ImageEditorTool::InputEventResult ColorPickerTool::mouseMoved(const QGraphicsSceneMouseEvent* event)
+{
+	Q_UNUSED(event);
+	return InputEventResult::Process;
+}
+
+ImageEditorTool::InputEventResult ColorPickerTool::mouseReleased(const QGraphicsSceneMouseEvent* event)
+{
+	Q_UNUSED(event);
+
+	if (_switchToPreviousTool)
+	{
+		if (_previousTool)
+			_imageEditor->editorTools().activateTool(_previousTool->getToolType());
+
+		_switchToPreviousTool = false;
+	}
+
+	return InputEventResult::Process;
+}
diff --git a/Grinder/ui/image/tools/EraserTool.cpp b/Grinder/ui/image/tools/EraserTool.cpp
index b3fc73f7a039f2c82481505685eebe767a5b32a5..149ef2d248f9ce505a338ec179dee202e6d354a2 100644
--- a/Grinder/ui/image/tools/EraserTool.cpp
+++ b/Grinder/ui/image/tools/EraserTool.cpp
@@ -1,72 +1,72 @@
-/******************************************************************************
- * File: EraserTool.cpp
- * Date: 21.5.2018
- *****************************************************************************/
-
-#include "Grinder.h"
-#include "EraserTool.h"
-#include "ui/image/ImageEditor.h"
-#include "ui/visscene/RubberBandNode.h"
-#include "image/ImageUtils.h"
-#include "res/Resources.h"
-
-const char* EraserTool::tool_type = "EraserTool";
-
-EraserTool::EraserTool(ImageEditor* imageEditor) : PaintbrushTool(imageEditor, "Eraser", FILE_ICON_EDITOR_ERASER, "E", QCursor{QPixmap{FILE_CURSOR_EDITOR_ERASER}, 12, 12})
-{
-	_eraseByDefault = true;
-}
-
-void EraserTool::createProperties()
-{
-	PaintbrushTool::createProperties();
-
-	// The eraser should have a default width equal to the cursor size
-	setPropertyGroup("General");
-
-	penWidth()->setValue(_cursor.pixmap().width());
-	penWidth()->setName("Eraser width");
-	penWidth()->setDescription("The width of the eraser in (screen) pixels.");
-}
-
-VisualSceneInputHandler::InputEventResult EraserTool::rightMousePressed(const QGraphicsSceneMouseEvent* event)
-{
-	createRubberBand(event->scenePos());
-	return InputEventResult::Process;
-}
-
-VisualSceneInputHandler::InputEventResult EraserTool::rightMouseMoved(const QGraphicsSceneMouseEvent* event)
-{
-	if (_rubberBandNode)
-	{
-		_rubberBandNode->move(event->scenePos());
-		return InputEventResult::Process;
-	}
-	else
-		return InputEventResult::Ignore;
-}
-
-VisualSceneInputHandler::InputEventResult EraserTool::rightMouseReleased(const QGraphicsSceneMouseEvent* event)
-{
-	Q_UNUSED(event);
-
-	if (_rubberBandNode)
-	{
-		// Erase all pixels within the rubber band rectangle
-		auto eraseRect = _rubberBandNode->getRect();
-		std::list<QPoint> points;
-
-		for (int r = eraseRect.top(); r <= eraseRect.bottom(); ++r)
-		{
-			for (int c = eraseRect.left(); c <= eraseRect.right(); ++c)
-				points.emplace_back(c, r);
-		}
-
-		_imageEditor->controller().paintPixels(nullptr, points, QColor{});
-
-		removeRubberBand();
-		return InputEventResult::Process;
-	}
-	else
-		return InputEventResult::Ignore;
-}
+/******************************************************************************
+ * File: EraserTool.cpp
+ * Date: 21.5.2018
+ *****************************************************************************/
+
+#include "Grinder.h"
+#include "EraserTool.h"
+#include "ui/image/ImageEditor.h"
+#include "ui/visscene/RubberBandNode.h"
+#include "image/ImageUtils.h"
+#include "res/Resources.h"
+
+const char* EraserTool::tool_type = "EraserTool";
+
+EraserTool::EraserTool(ImageEditor* imageEditor) : PaintbrushTool(imageEditor, "Eraser", FILE_ICON_EDITOR_ERASER, "E", QCursor{QPixmap{FILE_CURSOR_EDITOR_ERASER}, 12, 12})
+{
+	_eraseByDefault = true;
+}
+
+void EraserTool::createProperties()
+{
+	PaintbrushTool::createProperties();
+
+	// The eraser should have a default width equal to the cursor size
+	setPropertyGroup("General");
+
+	penWidth()->setValue(_cursor.pixmap().width());
+	penWidth()->setName("Eraser width");
+	penWidth()->setDescription("The width of the eraser in (screen) pixels.");
+}
+
+VisualSceneInputHandler::InputEventResult EraserTool::rightMousePressed(const QGraphicsSceneMouseEvent* event)
+{
+	createRubberBand(event->scenePos());
+	return InputEventResult::Process;
+}
+
+VisualSceneInputHandler::InputEventResult EraserTool::rightMouseMoved(const QGraphicsSceneMouseEvent* event)
+{
+	if (_rubberBandNode)
+	{
+		_rubberBandNode->move(event->scenePos());
+		return InputEventResult::Process;
+	}
+	else
+		return InputEventResult::Ignore;
+}
+
+VisualSceneInputHandler::InputEventResult EraserTool::rightMouseReleased(const QGraphicsSceneMouseEvent* event)
+{
+	Q_UNUSED(event);
+
+	if (_rubberBandNode)
+	{
+		// Erase all pixels within the rubber band rectangle
+		auto eraseRect = _rubberBandNode->getRect();
+		std::list<QPoint> points;
+
+		for (int r = eraseRect.top(); r <= eraseRect.bottom(); ++r)
+		{
+			for (int c = eraseRect.left(); c <= eraseRect.right(); ++c)
+				points.emplace_back(c, r);
+		}
+
+		_imageEditor->controller().paintPixels(nullptr, points, QColor{});
+
+		removeRubberBand();
+		return InputEventResult::Process;
+	}
+	else
+		return InputEventResult::Ignore;
+}
diff --git a/Grinder/ui/image/tools/EraserTool.h b/Grinder/ui/image/tools/EraserTool.h
index 2946b0a74867d6a4228619298e3f95e8f5984c6a..500de2f2c52fbc2fc7ee26196e406214eb01616e 100644
--- a/Grinder/ui/image/tools/EraserTool.h
+++ b/Grinder/ui/image/tools/EraserTool.h
@@ -1,36 +1,36 @@
-/******************************************************************************
- * File: EraserTool.h
- * Date: 21.5.2018
- *****************************************************************************/
-
-#ifndef ERASERTOOL_H
-#define ERASERTOOL_H
-
-#include "PaintbrushTool.h"
-
-namespace grndr
-{
-	class EraserTool : public PaintbrushTool
-	{
-		Q_OBJECT
-
-	public:
-		static const char* tool_type;
-
-	public:
-		EraserTool(ImageEditor* imageEditor);
-
-	public:
-		virtual QString getToolType() const override { return tool_type; }
-
-	protected:
-		virtual void createProperties() override;
-
-	protected:
-		virtual InputEventResult rightMousePressed(const QGraphicsSceneMouseEvent* event) override;
-		virtual InputEventResult rightMouseMoved(const QGraphicsSceneMouseEvent* event) override;
-		virtual InputEventResult rightMouseReleased(const QGraphicsSceneMouseEvent* event) override;
-	};
-}
-
-#endif
+/******************************************************************************
+ * File: EraserTool.h
+ * Date: 21.5.2018
+ *****************************************************************************/
+
+#ifndef ERASERTOOL_H
+#define ERASERTOOL_H
+
+#include "PaintbrushTool.h"
+
+namespace grndr
+{
+	class EraserTool : public PaintbrushTool
+	{
+		Q_OBJECT
+
+	public:
+		static const char* tool_type;
+
+	public:
+		EraserTool(ImageEditor* imageEditor);
+
+	public:
+		virtual QString getToolType() const override { return tool_type; }
+
+	protected:
+		virtual void createProperties() override;
+
+	protected:
+		virtual InputEventResult rightMousePressed(const QGraphicsSceneMouseEvent* event) override;
+		virtual InputEventResult rightMouseMoved(const QGraphicsSceneMouseEvent* event) override;
+		virtual InputEventResult rightMouseReleased(const QGraphicsSceneMouseEvent* event) override;
+	};
+}
+
+#endif
diff --git a/Grinder/ui/image/tools/SelectionTool.cpp b/Grinder/ui/image/tools/SelectionTool.cpp
index aaebe1916b5524bcfd595d05a9d14cb46f4f5fad..114697f8c3a33d30b06fb6efaa104125ae7e12ce 100644
--- a/Grinder/ui/image/tools/SelectionTool.cpp
+++ b/Grinder/ui/image/tools/SelectionTool.cpp
@@ -33,6 +33,9 @@ void SelectionTool::toolActivated(ImageEditorTool* prevTool)
 	// Listen to layer switching in order to hide any active selection
 	connect(&_imageEditor->controller(), &ImageEditorController::layerSwitching, this, &SelectionTool::layerSwitching);
 
+	// Reset the current selection when changing the sampling mode
+	connect(&_imageEditor->environment(), &ImageEditorEnvironment::samplingModeChanged, this, &SelectionTool::resetSelection);
+
 	// Install an event filter to catch all key events in the application to properly handle control and shift states
 	grinder()->installEventFilter(this);
 }
@@ -287,7 +290,9 @@ void SelectionTool::processSelection()
 {
 	if (auto layer = _imageEditor->controller().activeLayer())
 	{
-		_selection.trimSelection(layer);
+		if (_imageEditor->environment().getSamplingMode() == ImageEditorEnvironment::SamplingMode::Layer)
+			_selection.trimSelection(layer);
+
 		_selection.createSelectionNode(layer);
 	}
 }
diff --git a/Grinder/ui/image/tools/WandSelectionTool.cpp b/Grinder/ui/image/tools/WandSelectionTool.cpp
index 005a26aa0174341d36bfc9b134c209c7dc261554..ccfd2a3cceb806360636d033eaa252f04d3530ff 100644
--- a/Grinder/ui/image/tools/WandSelectionTool.cpp
+++ b/Grinder/ui/image/tools/WandSelectionTool.cpp
@@ -134,12 +134,17 @@ void WandSelectionTool::createSelectionFromSeeds(bool handleReplace)
 	{
 		if (auto layer = _imageEditor->controller().activeLayer())
 		{
+			cv::Mat sourceImage;
+
+			if (_imageEditor->environment().getSamplingMode() == ImageEditorEnvironment::SamplingMode::Image)
+				sourceImage = _imageEditor->getDisplayedImage();
+
 			LayerPixelsData::Selection selection;
 			bool initialized = false;
 
 			for (const auto& seed : _seeds)
 			{
-				auto seedSelection = _wandAlgorithm->execute(seed, *layer);
+				auto seedSelection = _wandAlgorithm->execute(seed, *layer, sourceImage);
 
 				if (!initialized)
 				{