From 8fc7ef12dc90906c1962eff79acda6f734073351 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20M=C3=BCller?= <d_muel20@uni-muenster.de>
Date: Mon, 28 Oct 2019 15:18:30 +0100
Subject: [PATCH] * Image editor tools can now work on the entire image pixels

---
 Grinder/Version.h                             |   4 +-
 Grinder/controller/ImageEditorController.cpp  |  78 +-
 Grinder/controller/ImageEditorController.h    |   2 +
 Grinder/cv/Pixel.h                            | 468 +++++------
 Grinder/cv/algorithms/FloodFill.cpp           |  66 +-
 Grinder/cv/algorithms/FloodFill.h             |  60 +-
 Grinder/cv/algorithms/SeedFill.cpp            | 228 +++---
 Grinder/cv/algorithms/SeedFill.h              |  97 +--
 .../wand/ColorDistanceWandAlgorithm.cpp       |  12 +-
 .../wand/ColorDistanceWandAlgorithm.h         |   2 +-
 .../cv/algorithms/wand/EdgesWandAlgorithm.cpp |  11 +-
 .../cv/algorithms/wand/EdgesWandAlgorithm.h   |  76 +-
 Grinder/cv/algorithms/wand/WandAlgorithm.h    |  68 +-
 .../wand/WatershedWandAlgorithm.cpp           |  12 +-
 .../algorithms/wand/WatershedWandAlgorithm.h  |  56 +-
 Grinder/image/ImageBuild.cpp                  |   4 +-
 Grinder/image/ImageBuild.h                    |   2 +-
 Grinder/image/Layer.cpp                       |   4 +-
 Grinder/image/Layer.h                         |   2 +-
 Grinder/image/LayerPixelsData.cpp             |  28 +-
 Grinder/image/LayerPixelsData.h               |   5 +-
 Grinder/res/Grinder.qrc                       |   1 +
 Grinder/res/Resources.h                       |   1 +
 Grinder/res/icons/sampling-image.png          | Bin 0 -> 57530 bytes
 Grinder/ui/image/ImageEditor.cpp              | 152 ++--
 Grinder/ui/image/ImageEditor.h                | 121 +--
 Grinder/ui/image/ImageEditorEnvironment.cpp   | 164 ++--
 Grinder/ui/image/ImageEditorEnvironment.h     | 158 ++--
 Grinder/ui/image/ImageEditorSelection.cpp     |  10 +-
 Grinder/ui/image/ImageEditorTool.cpp          | 174 ++--
 Grinder/ui/image/ImageEditorTool.h            | 168 ++--
 Grinder/ui/image/ImageEditorToolList.cpp      |   1 +
 Grinder/ui/image/ImageEditorView.cpp          | 752 ++++++++++--------
 Grinder/ui/image/ImageEditorView.h            | 197 ++---
 Grinder/ui/image/tools/ColorPickerTool.cpp    | 124 +--
 Grinder/ui/image/tools/EraserTool.cpp         | 144 ++--
 Grinder/ui/image/tools/EraserTool.h           |  72 +-
 Grinder/ui/image/tools/SelectionTool.cpp      |   7 +-
 Grinder/ui/image/tools/WandSelectionTool.cpp  |   7 +-
 39 files changed, 1908 insertions(+), 1630 deletions(-)
 create mode 100644 Grinder/res/icons/sampling-image.png

diff --git a/Grinder/Version.h b/Grinder/Version.h
index bca1fcc..b68f9ad 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 1be8674..d837f73 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 5ba2ac7..e21183b 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 9abb995..a72ac3f 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 08c4d74..6d2b717 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 cc0b41c..3fbbbb4 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 873469d..5c8ec45 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 afd0332..52aac4d 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 9dd2855..b4b8edc 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 eb7e560..7b6b48a 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 b4debf2..f4b8bea 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 b8906e5..2f501e0 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 b720ee4..72009df 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 fbc61e0..b68f78c 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 775fba8..eedb076 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 173af86..401f635 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 b7e41dc..7f28e94 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 d22f0fc..80d2af0 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 4db5c89..892bd26 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 8cd690b..efdc5ce 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 6eac07c..625ca62 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 2be16db..e5b1be0 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 c1f1539..d6e7f6d 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
GIT binary patch
literal 57530
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%0AAr@X4!=3v@|^~-sk%UMFJtMv3$68
zX_JfY=&+WO;*yea_Dm?R=QINvArVmpkgoUqdJg7aeAz~h9+g0hR2L@`LWb>^0f$kU
zO?B~7G@2+I48dA%$m<{+P!JYHiJyA(Yq7UPo?`b)%<$yA(hZ2>w6Bw4PYq&-2Wv@E
zL)*G&;)h|m-(4?4{=X{;DSB{h$U)G}H-o{0TJ%Tr1G<gK^5e+;z#l)H8>^;2AYVi$
zHdO9hfg8^{Xmv=vss|=E2f$H4>v=r~JH5(w8{B)I#LVjMaeXTzI%^+fsHt{0#VI8X
z4GmQ<G(m=E-zyt<Cq7bR_CK_}Wk6Ni-uAs{P*Rj`q$H&qBvo2UIwS;1>28n)k?t<(
zmKLPDJEglDp0V6}pL6f?et!LkYt1><oFo4EyA~_>V}Q)bc-QE2*fXSloY_>eQw#A!
z?Gto!tW#|Of5-&;L`6Si(XJBL&mLX7_HFMy<-zSDSi39EigBiEJHqV;xKb&eq5VOi
zL#Xho5591cv=(I5icN7F`n`cKx4Z^|utyB@yp)NCi4=j(ex1<JH19tzjatM_^aB%Y
zy8~vWSkWhAuh3)!^wIwE6fM;9r6u)B=QiA-UZ=poq}m%pjnsV+7D0?gR|NqQ01|a+
ze^^n^pg}tB8u70PB}vHOic1kbtc4foiUQ%kgK<I`3vN<k_uTgeWOx&JGB~-w(kuoR
zSrpmWz~slXaB|X;&f<#glzR$256p{7jiO<#<ftfYT6$*VSLTJ@Rd=q{@uBluOp3JQ
zRd8@V=78@32k<(pz|lo)eb>MJQJwW9B|Uw4a3!7xt@V~@td|idQEQCBro-RA0~`0N
zG~<sS_03@|wcji&vuB4%zLk}*Jp#VUM#tnU3a}yEfC9?toYxt*<bN^-&{ozKOCtR^
z<c|%0>4$Tc+$Ns`ksipLGu`8IOh;y%DKTKoMR@6jh#OZoVirpP9V@S-In~^y4;>#X
zm?-L(5lcK{v-jvzem-5cp?#})q?bp@fKPQaC162Ss`|1D!OySpUiW>*@Kz|WAFxhu
z1>v#I4MDe$D01avKviMH)WHz-Eix7PNHH-sc56!hIR6*m9(Q6M>S*`jimeG46^0V4
zCegX;qJZeqVpxffSmg|n-0AswBe7A2gcuYI@u#U0;=YR6Cg$mrZ|&lm0q6y=5OfQm
zpggUhUp++u%C%!boRey!`ZcK7!fr>OeQzLBkqlhXnGmC17r;hT-oy$LG<lia<y?sQ
z3Ks({oG4I3pYXduQkxEpnQvxda<?U`h7j_R4Xg9H$Cp0KW<-jmMYH07-c>hrFZr>Y
zm!AN6cJ0~Y={JmrAw+>Lq5FtkU(RoV5>L=lVTjAKsp09X<xAezVwFCsWVeEX-0Tdd
zvj1%-{_7o3WoHvx9Zy<~{C*;kw82~dgY)ipDhTi#gUUWQD+324k!32H0srnJ`Q{w?
zd}iNKw%==OWezo;B!CopnGz=-fZo`B?O%5NZ56P>6$DfPNqr&C`k*jl2lVoa)<#Q{
z9uMws?a>2tbbMYxv3oP9Q%0F-6#_|et=2=LS<~~iUk*!zZ$KT4BZCK>pNeH^#vT)6
z_{o(Is7sWoFt-|YR_(3QH8cB3tb-KTr5)Pp;fk_GxqbETy#zZQwDXG@voM+;ledEw
zDUUWYHs%LCfvIXBD#r|TwgRTVNZj6~J6vQKNSvSa6udxjuhFI_exINWtepvfPfr!K
zD!VxTl=3`Ix}1bD=_V88@KtwfC)Z;pq!$jn#w~r+GnK=_LP>p6?z54PFKQd_jSp4F
zlHwf8d8_!eO4RoTHVz$f!Rwh?Jy~4E@V$q_vc~rQRfYM4>l!vaw>`x*;Jl8|NxJUx
zrwzHNc8XdbZqH_2`Z88EnneeSXyQB%z7CRzm_Wr9afUtIpQ07Cf3`|&a-nA79MDU%
zk=0EFOT%YINnA~%^|;)S_3HWlg;{-D)h8!8BH3%Y(_1+Z_BSAOdH&(+2hL(GMFoZB
zvCY$5O49K5+*DH#2iF3*&s^l&fr)C)>T01VYUd8h+=2qr&noGcA*}|2gF6`e!iNiO
z&NdC7)dEXr>7(dLK%np*XmSmR3<<$_Eo}mllQ|Ft+}}<h0GWa|Y0xnUI#jI)M+!PF
ze0Es~b;xK<y=iAQd%G-qxYPh^iikta45Wwn<`?EcTuP@^HGo4TCd?CW7hpy+V#L{2
zYMR9Z(ix3X{tIJ(G+TesqY&<%1<h5%2QNXop!qS|u!~ME))eMJWw(AKQP_RN0x>r1
zX1oBXwG-6T&~WIwzJH!knv-L1WvYJ60Yu#Kj!y}WBTpyccCUlQ5|A)2&wHNrASEUw
z$azwJAWSH|8LYjyMgBR>QDwL0xwv+ug;Z99Z8sob#Mu<m;zLVmZ*-R;OndCAY<G4A
zw#3fNiyf5$_BQ0>-6cxum?<w7eR##T5T$diYM7_Yduw7pN`6ukug}?1E^@W6?W8ed
zUcc;N)v7Mnma7EKfs0r=7=d~61<cHJbcQ9}@PA4y2>x?Gc(<*ktY+0vM4O@!p3h1b
z2t96`>B(8gnGG>JFJ8N7BjR(m*d2<7#1){(pmA_;98^vbZTw8XM|!oP_WP46E$an=
z_qR>0)hAe!e4d~7Ua`#jEuC=tg7$yLJGc>}1M5jwXY~ZiLQtSxSy54l+xqDS1R9hX
z@=kh;BWW`y<t3Pfzd;L}EbV^q<BC3Ye>TbLy<^Sk5iOE`P0;R}M?$^5$1zn}9dBAm
zHl#(A%JprO8Sv1Jc2SYjRRBuM<+hPJ14PFP%L~-M{be-%cmBel-Hj%lf^N#y5A|c_
zG3m?S!MY>~7`;Q_p5L_2Ir6n}1Ja_m1kF)QxBP3mjg}}xJHsH-5C8jW!#VTn^QnsE
z#kCIx@BBh;#G-N$wQk#(m+mFWly(@&jv7wk9{kwVYy>)=2U*nMZplZWAN-TYLo<6q
z)AzIED1EAUxpvbeuH&QD2TmYI3iOuU8QK+)C-LAW>jN|j*zm&rYO$*b$!30PPq|vP
zvS;Uk!^6091I_S!qv;+-L3A+@)sP_he)8xd;mf9QgD+<XCo(oX^gJ{9?|BB|pNkt=
zom9@EB_Hh&CHvUtBbC+FUwDmPqY&LBPF&0;?-OrYd$^f8Q)|g_80e?ffq=r(i?r0F
zgh!%%uDZHbn_|%PmL&{l11Pk(v**s!(=4I0pO@C|>D-s`cDa9)bgA4Vycr)Yp)mB=
z1FiKQ5G)Ti%*4NR>nj5p=*pjh@z}GE%s@&SbIRfPxH1U@xZFzhC^7RT0>}6H1q3ba
z19nKkOr|V5U_-e=-p;sy)%EQ%lA=IJrH8ss#Zc_eUrUdyMYH8ixKy<Ijg^Z_0IyL(
zwPzlk#KE9f%Kk5_<C6A^+rtAlE6th;U3Gwn3s~&<K0?q}R;my?my|?g`^mT@xFl9A
zDY9Q%SzB8Wuko!BB~s&E4hUIc#1&QVfOuvv)<Blv7cVzV1UV5h&9sq^LgTYSX*-*{
z1)n~e&E>6`O@m%p^N#`HjDv*XyW^oE`MfkniEn>r%r)Vpaz#x$+sMciQJlL`lY>Ha
zVx&lF=XZHv|01yWM#}mxFAM6iV5c``uG#}ga|VsG6o?G)CdpP)06uFkyZT-Iuv8OI
zt=T+h(*919@ZqEGkiNv|=qfcDW)8rVSRnM!2}B+~&joUj(n19_m4)@Q+qN$5NS$|2
zONj8y(Kq10v@k}#*PAL$CRSvP6)zh0o1#y4)cf(|DA5NKCborPtz>>ECd?~Mn?PoG
z8|^|_N$Cs0^#bU6H+8RR+rqi~ftGRG%YuDM2Mt30A))<kSOnp65XKJ!mOUps|JUlq
zZhi>tTIQx++1Xw1;DM0m!hKz>jtRhT=Lqz?&mXa!CSn>6>ozD$8J-(a$7LH7s{~?a
zI{r)bgpD_i4QY=g?`vB>3RcyWEDnv1_M)?>m)sFg_<DQ8Rty{HNwPdXXNiZjxRuRA
z6y3M=-Q8R3K`+)wx*nh#=9ibVa-Jqzd(t1R@L;=%U2k5thwD*0GH^myz#nW9G<3iM
z1N4K6UWZRU@YRV#S4X)6@w}b{4fT8MRAU^>I6R<S%ZDcPCVy2219WMoU*2F-I49_U
z_U@kAY;`|BziF!xC<dMIeMCs}#{1-EXa_cdbG}E{zyLneix+Qm0}CrKjkusppUTNr
z|9+X*91WQ2QuQ$9tQ`WbwC7q9FcdP~oR5M_g2jmN@ERaS-i0R6v}f%fz!KEoMro0a
zT+P0qUU}s~iHZ8qwQrkkZu!obg|lNLo`?1{g(SNB8R@UdM8Qk8kdUzH6@cwm^F;CA
z5ZpVu;@bPt`6$n`O#oCt%vIc`fQ}*lrj4Q1=E{Z)iZ6>ftBn}5y92$Es;yKhyY6$^
z4~(U60=n%@E3-wZnGr?wsu{Rf2jGBQ9loa{PNV2H5XP30lS^Gf&;R#}hj&DxVPq0$
zYWegidpiq2AS<;lW@lzN2~&+H;KsJlbj%MnX~Ti;PiAA|s@u^;+!xtc;~Hsdp&y0y
zG>Ye+1|<eTIo*B9EYSc>%p$Y*C<!QE-2n&m%S&_8xZ*<M8PE*qr;h+}cR?~6(JP-X
z1@Ve3)jpMxrIQdsJrJZSK?7O6pyo+2-zj&zWXkFhYV!Yij8+t2h|9j(!Uresr?U3i
zfEd$N@g@Ii`dqer{<PXW{-|ia<;P3sTLJ2fU#1=nB_$q&eVlijlG@tZ1C<66-jGw5
z!-!RTtmhbrB9SyXR3oIava%IuY9nr$1us&CE|Gp~SRu($LqJ#OU1=F}T+Y)_Ku93R
zmIvJw;fGfVvc1yAwBre|wq(U&V4&@mq^T*9<<H)sh|~OQPFhg`Cq8-bO|TR&2im`h
z9lOV67ukR)(v^y93aB4cl!y{1x#6Xh*8=?cOBZRe)7SfiB=~l1W)+XqfPyPbRR8|%
zW3l;>=j<H-if9M6onSMSqv7G<qyF+tJ;CEUDR_rgxPUkasN~|4KalRqCP1Kl5LH3z
zHd^y&-$=Z&VqpS-=Fi3k70t$Lq#n)mSg@z@;83alK#Ah{I|9B%y$-f~SN7sAsj?Pm
zP-6%`W25<2eGmo6u}mR@C!pn7O3SS=Pv8gF;~Zlni{R!?F<Te62Z<6fjEeqp8%hj6
z0XH{oARYe9B^%qr<MKfObdKDHg~`&m#~!O47kVjCKak9Rp}lu^G=M?YU&b%&Z=HzG
zB?3al(MMN_2{EP59>v!Vipc`Gk2kcSD<9_4Cmk20&fX)@Em!<e*F1w3MnXfMnlNi0
z=Q8XmKloz*Xftvs)$6iFqc#L5(!?dd9Dr;syy5Lj(dJ4ci80c9jFquRP&B{-S7Gah
z%jCOTyiZaD%r=}>_p2228?d)b1G{^-aVIBn6+|W;0Kf6#-7OIO1HcJEj|iD+sjI>y
z&<~aRYr`DW!`Zv?R~?#5kk^9*G^IX*CpgTj%JR2PN~O4G{&$RSkym>elXWYvYM(XB
zZD>J|$RPK)sm4HxgjH}btL<&vN9<?pcnUhPBJgH23u>Yt6m!)Jo1a_|X-(8P>eS|{
z0_2P=GXn!dQQ=}`Nox3Km%EGsIAMW(APh>=Vw5Rcpozu9!xI2cIo8XT#(8c>O%C#>
z3}0NZlk&Q|W@xsz7;a@~NB+HJ=!Ge(xdQ#&T0oBz2W7HhW4Eo}@Y)f{=Oqm1_hwf*
zIenhScoJG)W@_p1QuuVMX9kl~BJDfPxUkD-XZbonfPkE)e0c!_$OB7)G_p|0qS<+1
zsCJ3arQ_{gQ9Fq1#sZuoz%!_`$Pj~4*jTwrw}Iv3(#Y0+-kwSdcHYK!-yyobLU;XB
zmj*w1-u>Bg5&@a#&tdZn^Hs#uuQxj~Vr}kPK!^*4)67I!Jp;&fCnH}<wPH24PlC3B
zNZ{Ec;Be20Qnwa~>5$bL1Nn8usnU~eFi6nFLIoJ9<(D^lt&93L{9{5am&+hO(Qiw1
z_BIX;zAb|@q4ngV;BAorHYZ)`@3_=d%aB3B?KSaeiQbe7=_fM^p!qp{JgEug!3K*@
z=eg0qU$TbOe+Q-`0)GDd84hp?3XN|#r{7w#CnHpV**6Vl-(xEYskU~2aB1@Qm$3JD
zp<dSNrTJMThMYDJ>IIdi%nHmsfdjz@j1HbnC&vB=<JLt}2mXcGNe_Nld70hZL}D%E
z-HZWSPx(dqMCDRAuXlp8O#n>9ENEF9Fb_(as|j_Ne=@To)j2s41Cc?8_C-qyP#m=L
zR;qUjADjL!Nen1e73x)Yy@~;9xC&-0UU2Rp$xyEQ^_aZtnS2Pux=SG&gslreCa-(y
zBHnwjVmR*dMl%qZfH`flYk|-*hX*qotV?67aAt-Dq?yfE6~C%8Yf8e2t4A6RD?)_n
zQs@<05!T8`z0dV4H}2!idxoaRwSYBLS)m#r+0o=#@=j2Q9OdKg&Vi7Dp#sG=T1S0w
zP|y<+=KpeXq3if}8VhDnl9%>`wye4(h5N-5=P8D`teqz<ywMUa+O8?X!MArnUVSD-
zqZCRtd4PQ-I>z?~J~TJfXop5mr9n6OylWI+dRD>mqJ5DPn|1Rp1-Uapp^(RufnPNs
zNu%t^5nnahg&lgVG0+iYEj>E|sEPPr4Xxq3K;KX|*(YS$oDE$W)M5yQfWz8%$-O)+
zjchqA^k1`56x|e@RF*3NYS>uKvk2u{kkMz!AVt!D<RpQ~1K0XIN(Ev-j#s|-L7Y+Q
z=bez(jR(dqXRkpW9T11cm|J{zXuLPNcXXEyH1Mz&jpv@To#s3|!E##X-#)>K?W75g
z&w*xLc#4YlxER&}a_Hb-d;bcd=?OoIC3eR9VtEom;IIMY&Usr2FOa*1hVHG+|MAFq
zHi4!VZc9G0g?P_L8*T>>7ik0qXZFI(29GYvEBV9ryr30Fesc{C{UbNee2(P}!Vq37
zz`!-Tpc<A77$r^sJb9sF0mq`4K$EX4bN?y}UOxs7&a-@dp<Zq%t4oN#MrMo+`N$za
zJ(I1KAzLJ`wwAlTs%Y;b_)7oG&!v_H6V-UmzC}2!ZH<SuiNqJ=6&G+S{tqJj&unas
zTljcO1M8c&Y`_oy;1g=z%6^wNyxnglCRJfKd@|1?DA;Ph_Tv4exI`Kt=xftRKv;5j
zL9GbrNjz&e8^r;wCHzsp$_1XrFJgIMAir=qv=cG@F%8xG<xhE~kZENW9&FMbLTW@e
z|E2KzcLqS^z4(3E@G40Y9i~&lgcbc`tVN~xuoMh915<<JKmSp_wENGQg3b-BF8w>M
zr0~3jtj?VWjJ_P)@1q!-d(9XZ<;E|YffwNMC_9K4p?(XaHL#7_x4-B};CFP_Hel^7
zpe9xx2xM|i1I$P<C;}jRy5OUGf##b0=InyH(!sWY(2mOV9nJQA89=Ypv@v9F@G4D?
z8H9#~dOR1j1b9QlFa5()a;%R)MY(#>0-0$uVn=$ULbayNU(nk>?TSzrA{MS-!cX`Z
zlZKcHOTHvP?Z(^g8h8~aiSk<tl0C4`k8dn9r+?bh^k!XjsDm<~SUecdMIun@r23P3
zIpjCHFbUD_QSWgRDf-1%uq%cnv~<Jy7Q$W7n^J{=Dwlx%ELXU!f#MX(F@j_vK}$dj
z2?IeaTkc}Vc|hf$8s0q37+l=k+G=Ds>iKJ5gm$b!t!^v)@}ri4^o=7t=-4!w1GHwE
z<bY7>^~nm07B{O$i!Q6q@c4Z4G5+WdYRUM%qdY(|{b<B(qn-~iGz6}7<Yfcp;sq!X
zTbjBQ>mXWgcmgVM*|$wie!sv1VM=<o@@ZxuGo58i752+i2o_d@IF+lg|480Os*vM6
zD&!}KokjpyD*wGZHUO%gK<+!fFQWc&CZR=FP-k+P_4lXB>rBzeE79tHtw2!S*s?h_
zMXDQH+_<F=$f2Y9y6tXz$_4Drog0bPkLR8N4UNXp9SlLbcaYr+1n*t4EZdZLEkVj;
z0XUJ<h&NWejYq$)ul=Q`cWKCBTdhd9-;NE0Vb&tuwGQQf+@VXJWEFhbEeoH-sbS8{
zv<~_b`Lz~@TD0p7i4N!NYUdV&Iwr*_Kum5DXyB<3W&e?n{P9m9hDr3L^OIC@U0geK
zi1$EBMh1m_p6m~O7Q7&ay*xz8s{#NAAs1X!;#)%T+_Sw@fbZQ9d*tc1+;z*W7h64B
z5%cXE9yp4_E^mgnQENCjYD(d9SuMIrF_06A071#;$S(E^W{nWwfn~ou`9{Xam)Q83
zP(m;!rB2r|jM2k|ber|Ou+M9BEnl+kfg3FAFRbcEXV3nawa{Mjzh3$aP{<@JAw1px
zW<v&;jrGSTj|BlzRnl>oUOnMe7}?cVP?GydaM1T|1y=!p>xBYbG`8)iD2R@=fpCp;
zALkwm2O}LQ&S-AGV~`O+^Zi*50Ig+KDfl(nX0YsOl5Sn_U1DPO_c8zj*)s^YxxK%o
zU{V?IoAA}~hfSq+_edU~9;6If4Q6Y(6bd=;fYH?V@`URTvgwZ|A$0S>3vXz+g<_9V
zo$p{2>LC<y{2H2?yP@&9!~iTIwD#F0Q=_wd;rS)(ao>RK;BzGcX(P^Ig>N5ioEqwN
zZRWg9u3?Va!aU1tUN(PU7$PZ&d~Ik_Kl1!d9-uQae<`U4p?P8tAUC-MYJ^ZlMcd4Q
z@tbkk0HoWQRaGYqR=Q-Sfh3GEF;h70Q9m-FJtyp65)jZj=0BE?V_MA|{DzDB?a(I*
zicNk6HMRI+m+gxABX>WSKv{^v1*kM4?d|Oa%!a|I?0G;IK7B!~ky(OR2rkiqDK3Zj
zk-RZ(T5(3Bhl+8l)o&*NKlB5Jiu9Z;CsxnXx8sAclZ$W12xU}bV`JrhnJN0?=YMbA
zx4q*Pv@|W+5ApW)mQJcw<A2F>2UA`1`u2{R!mO!T_xev8&tLj;(Cudxbm5#Mh(?MI
zsL8e0na`5$?d?fTYBlu$+-u!YYy0ZiqR$|k`I~q3z&X+2tZZ&@cLcRIe7aFFgj|3N
zRRE-*M##Cp@5=|&Y@SM-?|T%c4}D}MEzg&wDBzfx1-LYJP+HciU!{8GvwYCGA@d?p
zfD8Q78hpe<^t<<259N_`U`nBan)2DjzeJOu=0u1jfC)V{J(mCq<)C2u0jOYXT?;nO
zt{s){S!ZVA?=pLL7hUqNb><Y)fF3cVQ^ZlK^sa_l^ADntNP3)Qy2&cEBb%qGqW3Fu
zH!d>y?;aqF(TukSQslFHXMqc!+*Q(DD@*gb@GE5SznRL!L&1DxPqj_ML4Icvil$$=
z4F!pz?MLG4`$52-0FQh3YPA?1nju(8_-9>rWEM3Nznr(@qCsN<eY#8xOiXW74TV0H
z@mPf6LXc@ES587ci;<*y5H)&Kqm@oga+*EO(re`{8hQ+KNb}p$MC6%R|B13P=)t(q
zK##mKCk+Gh4;0I~fI6+7;65&7Dk`d9ARpQ}mAs$LLkB417e>a$#v{{&Qo^|+!Nvy@
zmp@*&gSxO>-40@oKaBbRGr06JYm%Vz2)9XWER5@L-Iy4Sa!@kslxB2agNLVvQI}sA
z&*;%hyF~H~IU$1>vuD*lE?Xmc4Ls{FdiQ**eyGkZW{F!xQ#aum`E`bg^IPh?og!a8
zuI`2eE6G*UL-~@;ZCl#BICy8*3BzXHUCsd8lrpi6rkb`Zo{ZvYe5Mv>%|!vt_5Yt|
z_5t*0ed%4r-m?Pr+|9@pwn=kQp*N0PB-P2*uuB}S_gj7?Y=~-kZ1qBTI2@)v3!Q`@
zY7rD?J_B(osN~V4fp4>s%H?FOuC8w6I*%%Pln79jFPfyE3@;xO!6hn@evTI6<!mBe
z*#i>2%N6UuEcOS=T6e~mxC$GbOAgFG{rQjrpnVblXHNkOK&Z3sJ_uAZNVYN%$6kDk
zD>@$(hVa+Ksovfgx~3fR@5_8iDhur931=qT-bMV@>Xk4vliFc6iiimjun0eBxNHCo
z#Qf??nwo?+-70=_`?i6Cv7(kN<)UBTHL6oMNW8ECY9%)-Cn|~>xgl<;CLc$)LWMdj
zsJ7=2zs${-I(2$)rT@?TN`Kn8ZfR3INHv>>&@4B3Q2|5|uMN&if33yR9fTx6kbk42
zqBl)$od>D=`?5|g4h?m2io7NKjr-I9XaT$cXNG|FmFoupB`0W-ot=Ngh3w<lAtuKH
zz)-u<ngtGZeG<ZBE7Lb}t_#5LU_HBBCjh;-1T)|BA{D>&7TTeqb#|Iz{8y;$PfQM7
z1~KX?HfhJkq>4{RggG?1Al5#wu+X@(>z);yXpEtv%vaW~(I%fFPe4ReFjPAuFZA_N
zmbT@m1KoqbQAEIu+k81-;ZVyjb%Q57v`a#q*wuBnsv1ZQxO+CP#MCR5Vm$+Eudm*K
z4k;@F^F5s-Cwc~k+t0f@(xO<dy+GW9n9h`v>DI#1(SmUH@sdo_mw&&`0GQJR=4H)P
zsqD9HF%?;B)WX!kc2heTny56DmC3t@n^QqMmR$7LH%P}oj<>`K0P9^KEE{Yr+}~9A
zxIn>zs<e!hZ17<2FVkjvuw~7M(=Q-D4WKwt{S_-iArkQb$4R${CZDc^A^J@l>){q?
zCMFTz@Qz0KdAc*C6lopV0e7W-l03p4v7SpN2%2~MKMUX$FJ<)n&pN?akPW1sI%SB<
zc~%ZePs~8e5tCpu5KPW(ZyLmVZM;TRJ2<+mB*qBSexMDkdbXD*mBK*7c6MoLXe54n
zR~t|k#j~>wpOvMW85)31w)xkj9tBXWt2chu^X=d$A~toAF+TDhWyR2h*|Yrk^Exx@
z6R?FG99_a@$jXb~EFf98%dWbPX1)GnTS5D&{@7L&Gqbb(rbV)+PlUM>rSxLLcDikb
zGl4*I6W{7d@B&t1X`BL(`27ShoXtVagJQNn1egohe|)>ZTz$#S{$0E&MuG)&ZA}73
zjw}c)420boNM#n*Z{QvYY>A0kO?#!$14rozBk-gdPD5giIso=uRe#ZtA_;Km?=OG6
z56tVm1MMl6rTFhz?u7n0NizR9Nw~{L*P>P=8L<!mMzPUVDF<797bzZ*Gd+CI>d{rz
zO!D>A1wI^nw>I}ga|aLy4U?0dS5;CPBVdyQYKYY&xT%trt+4<q$-39z&jBZ}fsMs3
zR`jy-z+T-99j@<PBWtco_Hfb<S0jGG!7%}11F*QyFI}_(rTa|I{CD(Daw56^^}O^@
zosi=s`^{&WOz9p|5**{doV69z15xx&RO;TZalpQiTVGp41E)RSx9Dh@ozsp_t2<O!
zK&x^}_RE&7y{HN({wME!7z%cq*?D~0*|d0^_r2gc?>&sC=S|;t5qwXz0-E|5&?dr6
zu^2!k?>BgZ(=@<s3pC9MR}So`%2hRKV*|hg=Q5w|0~I2FiHQC=MbpLdCx`<4=}cMi
ziTZ((v+KJ)&LU6G_xl+B%_ONhbt3WB#t;@za=a7$B6QPG9~hH5x++z=$<9zUfJ~tL
zc;7ZPKiW%O&cS%=Ew8F06p%)~pA>L7cd{C#xSQ3fWI338aO@})hW@Mf=&Ef4pX(8>
zs1q%#hd9XGQEZ=JUDE3G+5f?TXhK1#e+(qNf*dNgMSsZqnE(MSH!m`m)Yurwp7Yal
z4*dQYAQ}xEhm#}aGiY>#v8YHeRF>H}m%B>Bfx2&Gy-EfU9dwr-Y8<E!Bb5zjQf+^X
zx{M?%@g`?g93;CHDJf6Pyvui!`GJ3@sV32hkFbt?rWo-mK>TS3)-yeMOfh*FwWkWR
zDiPu)&!)|`5aBh_)e_vI;t!lepV0r>8r!q|I+L<-adS~5811sNU^D2pc#-51Bkwry
z))dt8lwS_!)ZBZ&pr;3l-$SRGAk@4;kXY>jUr*)S7|g)kezDrHff_1$Jy6pm%V)>~
zQb4*w9B1RgLpR2t=;z#K;M?4b8zKy%a2N<2#BO=$XJrtmv1(%CaQSt#C_#qjj(GEY
z?Q6M44bEhGM>GAkD~K>5T)x<gp|o>xJ&-7pQ{0m;4doH^ng2>n3TP!nB&iR9n>Ord
z=x)e5RL;D!Sqd61l0FlV7E<I!B}GO0)jjN{L-dqZV6R%rS_S=%TDa!CQ%a-1mD3^1
zvg2&=xszB8oH8GHTkx-OdFKJp{~RD<A!B{dSvH_;k<+coBFfbQY+RI8HjTn>X^1ew
zys{$YBRd$T+KjToXbK^+BhvE?JVFofbBWVU1g-MF&t3*7CP+kCJ8$`Z95Z7C)%7+D
z*`(-z!kGYnJloTgSX$Vy{l=iwm>7>J;l%lc<!BDGv`4JHdew`K=kO4liE?ft;H%3^
zs$Sqvnak$Bj&=(}3hRV;!g&6$`uGYSP7z~6$auZ@%2P2~?d(yGy)0{dQMCeh$0j}`
zwXitfZSiz+E9=atQ0t@(WA!w_8epi8$z9sb1lXR&Cz*2+6OlO878jFiZG`AV1O-*E
zbFp&@JauEnkTm$*nW*it)N+`2b%QwCQin4;)tt6_V;#ptmMj!oVWWG{m1ij1$zA9s
zZS+FAcgdnZfkO{|s^U{P5c3=D?Pp{>F8CztLG-Ty!}PEwApTG&Ol5PpaD7dKvl|<-
zTB&+YD02`bs0t4W-&iv*m-R@MebM4}qkmd85HSDp{&c45)8fPtt=Ej_%zaW5fyC&N
zMRIYe)3wVs;~MY_P4{)F$?}|u8!*G91=nnyNbI?_94H|TYKxY)GYM6n3}0-@vgBSl
zp^WKP@U2Vh``Y|K*^;`eM;Y!2CA_h6OPKiG;&wG#JL+~ebhw#>#q+OO09%=nUDdyR
zf^_jBtSGCt_LOEyZef&K1GBWc%;d&6bC3fs=r+AJODsWbR3;mQF&BfHCa&-Z9qv(X
zo{!F;A&l^_T@y+6O&mmjvnWis7aV=g@j>nOqX5y_din8j6DSM9J~?^Z#EdS$n_B5D
zeCLtjh<(e*T6e->rt_-h!OUFi&MuMDoEN8g+;=fD9vAl{egR}lOTq+6;mPZt-xZaN
zN`Z<cjmVmCF`a|uh#N1mB_yLl^MS7C|MTdJ^NY~x`33tcAV0|(r*gS85p$1G##R=h
zb>wxK=;<w4(NMPz)tuvl$<@xwx<D}A3G@{%1`Dd<{SaWuGvR`T6o4b|K>@rMq>v-H
zDVq3e^KWSleOupoIQM_l7B`VI61P{j*A*8O7pny<8DkS!DeEoctWK<ajR5ZvYqe!b
z6*P-F%n}b6x4#kF=zq6zeyzQ=zvq&ctLl;cVeTxjIAtOE$4?RLeevw3#faR|XFYk|
zlx``L0N)?HaU0g@Kr=G>IV>PW@Qz?^lt)y3qiqLcVP<ZG*O>9ypI`gy@09_g9!Stq
z1_=BnzsgoA==Y~Ph%o9K?{&yoYMoqcdSiD83FQ2jk>d~p465nlomFCJwT{!@0MkH2
zw`Ki%>H<*LF$cQXKV8I`s{su}1Js-vZ48AYp@#MOMI1)2WGMNyn8}^;0C5_d8?+8v
z0$5sEHfDPI!tWLJxy0x{7v@InH7!%`PeA%xeJ*Mi^YpgWl+cBjzf5!#vwRH_?X`h5
z_W;9juCwHH&6$#}s4ziowQ$U@3g_e?V2qq7!pgqSKjk|eDUP1ILy~pTbY?e0ms?)&
z_C()wm1$6*REqV}>UX7c9ujUGI0zzS`)9fzD8yF=6EGL34}o_)fMhy%e1AlRS1C&S
zJDig25+AkG@4W0NO0s_<StBUOza~1G18^^KRg@<gOh3I!ZE9v>t+SCOQ&dp1LvMQ9
zOzx?j+F;|#eyzR%cOh;BBb|`{9<)giST`H_aNv7+@9+S)QjU5l=eTXN{;!~_aSjeA
zv{0Ef+SPeb`Xie-Z_VJnRIwyn@>0Xx#X59wrOpv%lCJ--SEWsez-qv9#Z{-(NhrYh
z@+CZr5Gx*%pk)<bn5Bh<-BaAyN;|s?9P*Y(W3`luX;oxit!0|h!CeDk`_4;I9-hL{
zGNG`KhFWfINjTwG5pS`NEe5_${#mxce;+EasG|w;1}kR2tZ|7!l5zy_=-p^<g=}5!
zaL)*(a{+^x*pdM6xZ1&XOSMRys^6!)CBpV8@5;hY!?iWemrBFUfso(uuFp!UznZG+
zRZlUn3?%Rp2Ufh2QN*!)n;=Md?JkOI`lVvvRYE#ij+bJ!rKRk-tp3-4x-_$oj+Jm6
zYYJmw4(#TZg2TG($-y%xH438-RF3?3VGNt|ZZF8Zn#MWLX#jn-7Z=$L&i;2ub=bfK
zh1@P^!z-uIQ?t-sc=G{$qcz^`&_V8$FeK`0ph@1d+I^4kfy^u6CVoYoMaSLKCdGHt
z8;(owQ6YGcyvG4J+k}KR3W^U2E45NVV+;*VEx|0eNKow>M=}e^{*@n*3cadY76)5a
zR-~GZ&S%^ykGEQC^tMp~GhvhWxyMwr!|szopq8)cZB4o){jx1Z?F3C`$(hw_?O0VM
zP1Z)scgP#r;ewK5w1&0o0Y}Oi#%00L--wAf)oU!YFrDr_u%weYSh!v3yr)vhmu{1p
zG3O3!T~d#);VKFj4GF+GW(cqocqwa(nK=)N-K3c&hXH~fR`#62@EHLSIwmzQHY&?8
zTT(ESX->Q#+i2h76>~0<zxD`r!gcCHS|Gw&+?De0-l=ozR}ZK~P+_&OG~kOA!Oq4m
zm8M{C_|J?9;zca3oD_lWvI%dn3(1qgp&)61lbQKI8ZT{HUDd^SQc)vV>PeH}^%L4$
zfM9df++iDba^!vv>FV!~QiDWEaF<L$mgHs3N8lkN7_F#+y!`r2)KBAUq5Dj5%PAIj
znQ=twV5W4FcTr9}8ykv=`A@c6uI|*s_TTiE4`z#qS<Q2~2M+|t%DkC9UjizhykKkE
zZ1{rI^X+>stHy#dbitzky<ic*DK@4{&>&+y=S$)LJYlN|fmxC|cR~EV?&Hn`sj8An
z^8ECCMcdlZxuLP~B<M}sS+g__8y=c+q#4N`efPt}94rC4JiC51vo$L+x%-$@ox|2G
zw<r<r5-}vm$VFCZc2yAxhl(hauL}iOy;oB^llmQN+v7q4v-K@1mCk3_Fqnwvt4G(M
zYHNkto&TaGJ$-X&X2lNiy>1@ig$QrnTiw+1BD)Xhxd?+<>yv^iH&fzM=JrgGKf7()
zKX!=f`}gy?Tpv^5$nan39!iunJ-~!Bv*bzuWm+e<<(LeA<wBJ}#Yh6lkp?&+0`fdH
z9Yqa?FuB#aRh9-zGTnsHW!hoy)xGlf<`s%_ObQSdj$L%8s+=+t7d<c8$vVBZj-fBp
z$1g!Tdo6u=m~_d3)W2e~Aq7^=_4&gMS`L8ZZ%iTuNDBJ9{AOfg%3n-MWlmPvuw{_`
zY=<8Lm%z6Uf&?C<H(j*(boskB{8mJW5LC#RpXg)RnwoJ8$**A?L}IIhA@%$&Jw5cr
z-;49_lt6=r!I;?|<GhLr9F2Od{oW6b?CjZh#U0Cd4r>7a)hi!0!fq=K>$$y6(001t
zoxwSFZ^ZY7*c>9SsF+w~KmTKVnqGBVrC3uf^n=5ydjP<F%I<CN--V(2i1BzJhdsP8
zkqH_|RWe+Ue+Cw5A#k$DdTs@|$6TyJF(}B~VQ2HPkcRWZq8Wfh-lSFdebA0mnu*Iv
ze{{66@$$XQ)NWYuGkO)X-tO+{h{V_$3gasFrRT}pSS@|{GrXjEm2+Wk1_|r`^Mf6y
zOflha`%DSzky0PvSFJH6R-M$|iydjug-?<?=I7QN?1vTa2LsBmr1Q<SkMcN&s5vol
z5!mjg*ZUI<L*ce;<0=nmJBe1WmIJ#F@`~jULhcFk;-Al=x|kmhS0v+wlR+Y|h<9uN
z`I}hwf|L7t-M=H})y<S+mnrFum9fL1-{k{wCQf0FpV~VFc$bymIsrbeFoT<lwYeT;
zd>sd(o;Nn!cRSaocerGSktXg`Ls5Yx1e|75hx_2&GgDsHVO8zaA0{1Oh*M*%a5MW;
zVAG9zyow={6t;>ovD##BY~@y19AfeOR9sR}5JPQiLigH#qiRZ@@TP40R{8XN>!L`b
z#^QhHFw9r#YD5-bOE~w%wK;tqX20aY+vugl=5yaZLvZ&Y*hrO69IB*HD}ZUcyah(_
ztANp}$LMRv0M0(>6(!LZ^Ff!^u=_)N5q<uGTy<q-bX(qFys?{LM~7B`M88UW2wnVG
z5G!ZB<}N>sr_x!_tCN<YLuA<T*K#_G%_}6y2*&mZL`#eS01Bf+_RW566zEO(x2yvQ
zNHcEL&3ukmdf|0w#|hS^>(f`)H=O1R43wJHaPe^)R{g(OJN;3M_CA@J1_2r8s58Vi
z+(_d^$&|ZCR~NLfU&Q0#4C-2Vgu+jn2lvkAKeD514h>J=4J%X_ZUC8<*Y56KQ><I<
z@n4KNaHI1Il{UV^+Mh*8$8k26j6k<uy}!3!OiHJZ21M1|!7sQU?4Qc-oUeo5>>?+!
zeE$<1uRyH3v6+<Q<)>}Wn73&vcR8IK9w-CK34s@xF?OV;L^bcfpIcHuuDzQUFD<)p
zopiHtD?UH}`8hA6yuf5`>ppv%0ICUmo0BHYWxQ7QT>dev=d=@Q1}p^sgAUwoUaLD9
z=A%?J8prOXp)Q$PB!{*wA>WxL9qUx1SS(rGEdTJ0Z9QOO_9M?Ug{19$1AP<@pwTF-
zZTJir6kRv^*6Z)iagMb$Q!L{@nt;JiNWec8-6Kx!1k980>D{nkh0LaTU3P&&-WmgO
z@8{nhn^esOY@AObW0u%CH9U;xa&=X_X!~N=bhnle!%w(&A~Nn&;OXXs@GSg7zd7IO
z?H_CGKbt#Rk9K5o^61D+HF}s(^Y?}fkz9H+a}#sYZ7#e;4b?>}cN?i43$Zniu-AiI
zUG2Tgfy5?k{BL<_-wYb^e`ik5IsHDm=LFA@>k{F<bA7hMJY8zN+H67hg20cB-sGd%
z*PJdY9VER^*4E6XUI`n-iz+JaX!h8h2@E|w-Q8Q8Tcd-B5SArNGK>qdsp~gncuj<@
z>!Qe?Q@**z-b%VRGxaYGPeunV@h-GiHTmxa*H#-ZL(V~dM-$qaOF?vBYa7Nu$5>=y
zVNSohy^m$g$Y}d6B_>0nUVr|F9Z%QA*;%NJIBjPrcWmo|;2jE3yNNwNKNIrgk0r0O
z@js!W{~X4>I9cYVcKtwx8KKwSygj~CvQVnG+U;l|U8<)6ox)c?o)6Nxua1^tBwWWW
zY3dN-5yS`^nx0Gj>v&nF<v0_x?~Td0Jr65>F(%#5o4gMvG1{W4kXVQHs#OcD8LZsi
zlMyijyo2|*jzhVN-GanG)J8OP8`pd<S%(0>%Jt(%$1$IVNT<Qx)(lz8LV5-w{FfT+
z7o5e#`2wW%jN3d!>FrZJ2E4OCpH1O;$AaI<!y}^JBw?%vT(}hbH3P>n*C9bpcT&^5
zdej`RUQWw_2Qlk6CYS?xCS&^14pUE(-YmsEEs0B02JuNk`oe;@rlvd62)y$`tN2ZQ
zJCAQsy*9Li$75KFn2`|;g0{G_7U5Dxa{;t+0c5D@Wqd?wW_LeWXnrD$a2E>Z7+K=h
zA<Nsc`vy-B#Ab~3QuEK4|24n-sJ=D4jR-Rau#FhxkR`f26U~{SAx8&;&jDk!nEA~d
z9qQIHbQmFbg>97Ucfgh`vJW_UG4}ob!&-szfo8qExr39qA&KeQ6aK(q9{o%mdHE$0
zB9dWtl!zg)2eR60gq>mjRxb|@mQn#aJTaLuLe<V^+t}6z%o66iMisy8!x?y~s&vPl
za#&f`%jfn9-xXUYBUN+N%*}zm$;Y`)M8{$a<Gr6KQM}(7zSj8ud!eVWHRbl!n+0}m
z6a;)M#B@(o>x?u#dIWk$E?~Si@0h|50*I5fHde1(Cx4vnWS4YH(=Uj?vdV!LtWyGn
z!B#?G9Y2J+{jLi8*S=I5@)hZ=w>N*`Jb<gbGX;vPH;$<bR@fn(q~6PclAx{a706h~
zWR{T2BrJ?l2n(mNaYSN8h<{D_#UU^~Re6^S8g^3sGLg^Dw`L<q4XLtcZ2@+4hs$h=
zOdx@(`P;xxT;#^p*GYN9?A%`SIECFdzrcc2J>R}jo#bNwjq}W$(R5}(6D>eD56mWa
zDTQHipup>5#cYT?W0U99Ey7B7aHxP|_=J!yyrdV^p|(lXip=BH-e=O0{Z4_K7euRN
zRd#3dMSFWIw1&^SKf`MUeuXb3#2mwowwN_qh)Z<gCCdMf`~&0S_Ra5csnJ2}xBP7*
z1b!zm8;Y=FaN-&@?g)dMva2n+6~(2c@E07GI}=4bU>+X90)=818AaP(8?W1XK@eQZ
zSLXef4eIwilHIGvamvH@;>H1Qq9i=DzL-nHye5;nk&7t)wxVJ51WB~yMX}HtKB0r)
z;_!H5ZpormUE9{R0e}qFZ*LQ7f_>llwiyP!>ZucDzptWCYUDZjxV2IX-W{5U5W@|l
z@DtD1Loqt?X|qPvGc~K4h|7mQ)h|1dB>HjiUt0ULvLAlgu2GEd`W?olu&(W`==jM0
z`ekSBj^MY>dD+;Fddke0$DEc63<nn3C~CY6vUV#OIl%k2e=>N$gS=i+I@RI6a&&c&
z>h6#6#-`y#b5yi-?1sFH<Ob8+iH*W}c#-8tTTrvb#9uM;gRTVKVC=1}uzbkzaqaf|
z7no%8ey)+?L*JlwIpRN#^z-Pkl!D3cTC*4%D-|;xVF#l?P|lJ?8y@a+)a+{gsHwwl
zKx8D(^k^}U)0mlCtA51+NUhhbUR!vs*5%d6J<tV@-@D`Cl7@_|72GMIhK2~jwNdTV
zeu~5^=a&yi2peW+!NVhY=}}r(f5G-eoXLyrHoa|Y!RLm&gMV*5Fk*t{X6jPg%+ki?
zZjua+i3LxFR1$Kw@83a<bexU-nx#6f;#p4NbH}Gh(**|yq>}MGvLM*SkTOk=HTFPc
z=qThp`t8xC0;hK6OecxR)zlv7z2Dy6x&s~EeCV$ZFB3REtvw6ZJTT?9>xX%na<GVw
ziYB#2BW0Mn>h*yIq6<l5B2s@16R7w#;UK3-BRF{3bDOXJ$IU0xod)9M`OcqoDPd&G
zZ^gEn@g3?$KNrK|^-N|Vz*ptLVe^Gehm#4P$TPyDyGTjZR7tO8sk8FS^U^nAcWj=p
zSUjM8aBBl6xR$n#t`05hkt$yOhO5_U0^TEu>wbmcy?B6JtC#i>jRjrIa^zD^9$J9R
znJc%*$Ih>=sHsVDU=(HeHC}1b6#n!II4nVejp>AgrITC7uE?!>S5|5Dhyju*@8)w2
z#CtGOQ1HpETh`7Om@`#1Nfxt_p9+N<pP7sczOV{u1bYe2@4-iZ4w}}#{TOn;Xl12J
zyI&olb%fA5dtkgzd%d1P?6fnJ`ZPP;;nhm0@Zru4H2=5nVDS3|uw_&8sWDumbqI9P
zn8472ntCSEml`vXLSE&^L5fSinM6tUKD)R!SA>QNg)NCJOujYdB;U#n9fvJGP=@DV
zy_u(EnYfq$vOaJ=H>9-m2d{=cN~Bb-f7jN^7=2dkr}$OZrs<-7jN(o1sG+j*<abTr
zXbYyycU=2-D8TD?t}bZmmQ7oV57q0WXwU^0+$2c%@zZ}UMn=pc^;);FcX10JpBN8_
zq?-N{9P#-(I3hyu*7Or$Vzni+SW!j}z)_agX8nFh<GgqywvMY|_JNB~#s~CvzwVvz
zelMTsF~ZJrYVOl|D#Kl?Lxw?uA}1|~5<pubmo@1;6Z(@S0g*&3bQfo=n8_<si1^|m
zIWHcKtSet^IwIxrjlj4KBE2yP4LgCIeHQdBoPJ)!L{8eUbt)zxB3SrPJ@wA?D+OZ+
zpdv)asuBf%(#bC$JZgD~2VsH8<DxSfe3c*V?N%?#U;(i;5{?faKum3ZoTKWYs_6T!
ztawunf<jf4nvzFs!TY@r%+ab!yZHqLS8wIy4sI}~P*?9c4GfE>%3shJa}+yV?<?lh
z&dq)YFr?7hT;;WA(Gu`wG`cs8W0f2jJ~BqnksW>r<W3W>{uKfK=V`%m(8tqC;=JRb
zW40U}2N5(Eg&W7GRb4boO6aYT4Mg#C@vLnL?}(i`9~r1{;Y(b43*p6V#gn#e2w5;P
zHKAN=J;12FHZ*<m?8WNyWK=#ZBG;#et2I_xH>J^f@q=&T1EqH(%A=kP()FCGk?81F
zLE{}aY=5u9G<5o{TPgt;w@{f`IS@(NP%}HH2aIzjc=(Ifq1RT2-#Ry9^TS6ifGG_t
z`5?ryP~vpgYV5PzwR-tLYHr`TM`^U<0N6ALU>}uRH=n75yAZi%eLkCjsI)@W+QPZC
zIZ7yNU)QKZ05&92!)*sgS<=>XeE!Tge78W(RkO0O&M@=eLt>XwM}7;cTV}u82LPAg
zH12$$*yEFhi2y0a;W$9o-~xjz9JsRx)tK!_uf_=5GS@phi3W5i2Q668QMIQ4kA%+0
zda2Q(#G|3ONn3)ti_ayVQiO;6i8$T!WbW*~v6+qzB+0&*Zg-z8Y}yZt!i+aK@JARw
zzV6}^b7+(>0;fC=I!*5XiG1ZDNKt#J)f@FE%mMFprKg}kR!c9vSC@c$Vc9nIC5TCh
zgNYL+@3>+z_R)~!SoOD?4mASO=b~C8CvyscObj)%4=!hS9faS{%N{EEl4#a(pNavx
zl}z59()ifKn|^JTx~KuC-9S0Um~v43I}wkF_?Unok>GKSne{25%!5G%Uz6t^MrTKI
zxU5iWNqPfy7S-TK5ZlS6pUe68P^ls-alVmrZ;JJQa5We^P5~R9955r?Kg_LN1x}LQ
zCWFIubgGuVC`RcVNz`(xgGjD!ZlN)6c@ZB~ZjOTSxz#nPgpAPC#Dbnk)0o%QL`iO5
zb_{%6BG|DAoSo0sm$6Q6oX_rzK_?9%;BJ<5Chtpvn&0x!CtvG$In8G@Gygpx!^l1q
zX17O=Kpe9tCWh0^N!+iwy7(Rrw88bYrY{#dU!OJ~UBl6Fv6q2H0Z7OOfN;AHgIr0c
zVHcI@NwvFA{`BhOE*CZHbJk=QV!`O|JpiD-=qs$NVeBAhEH0j11Da}dF#ELAxbQqI
zNC_wT%LYYSj#4`hD)T@zrc~&kfY=N2gaj+2`Rg-!dC`I4tw&s7zG`x_aKkUE9sGO{
z(nuTK<HSQsQJg#QW!0}H8heJLU19g>NOI}+3>1-P1D)_I5Tlu>s&Zg*^b-wwOJQg}
zs}iH7pjO8z)SLzx{3xTWEMs-De)||My(<H0>$sqglhXnkMAh~9CnBWuPHG|0!Dsc8
zsVTEWs59V>G<0sA3qC=WG*E8MPY)bvQw#Z$MoVhl`tn{f%xkZ3x$Ac@FkQ*qMg5ic
zUd;?XwgvDkqAc7d2KApPwt3Pq@U@{!zJPmXNkLZIyLNsLnAS<oBu7MyA20Q!G;a8y
zcKuZBKY{D$cV9izpvg3q_+vcTYb7)0-Tl4#?!B{nKtFN>B^-iVX9(IUgUGG<az(ZQ
zx+^Gn#cr!i7xRs7*E{}_{W|6E_ekmKnLUu)jggf+^PeHp1vw`gnCPl8|McAeuE1(B
z8>+<UTKZx8SOdHxj^QKIEloTwGLUc=lz|!mZuo!iz4CO7)&u3RYHKY+@_b3P6~#@<
zsbB{m1bOz)b6X1>`qj5EsXBgb9)@FPPF7&{<^z0lgPbLIMN|4wt$SwoLg7K|6?%_X
zLy6o5$1a^I9hI9_&^(C_AuNmrNNWiJtt$_#hvs2`bOVB@+A32AbV0#VOp4I=q4S^j
zF+(SnORuRQFJG!RUZ5;PUtXaF@;c8!enH>fz8c#kH1Xtw3q;yewgV0)n4XF=dX<Bf
zt6Hp9k%Kyz(r;Gf(Y|$_5}>=}Tq5M?;i%sU1HTSx1p+5~>0cZufqQ+q3qL}NM~3tC
z6Hx$PPvpdTy16YO!Pu5*v@>uXHV_^jlE6H1L0GKt|M@VL*ho5O4G<8`lUrPbZb_Io
zq^lULScs6vei^huZyTWRR{!C{?JMe^5Z!e7r{W5Mv0yV5-Sr3&>Jr0)Fgy*)pnY)!
zor3=!29-AS$S!+$c~6F|2Pu`O4a&%ChZ<<)=RzH%1{A0eoJZmcPoo{7@yz!7&PyL@
zUziq=bnv++%)qD#n0mnThzMkXyr%^>Ra(jZ|7&pFa}YAtvQ@SM@APN?`7L794k_u!
zkMSke5h0*5*;To9=)a@&UhZ;w(Hx;?U;$Zr49~3a47KP#52g*ILuA%)Sws5JAfVgN
zK^Z}m{y*dQyn6`iVK%_Szk9R<sXi<CnU3(EJ95vb@aemWAbzcbX<>g%f+7rFCG;8c
zla}6`f!GRj=cPAzLY@VlAHDv5Gfsl-`<<6w(p0N(o})?#Vvqm1(FwV|PzQ#=i+ExP
zpiNljKl+06&*R^KvwwILEz~8<$_GLAqe0iJPYd(>=X(L7yLXlIs@J}#l&d;0$d9*?
z{uzZUcl$!;)I*3t&T--qj4%sP9oj6V1wz{2Z%c*Tp5**~;^R$fKKLCvuTx49mKeio
zpLza0QZ>J+E4=#DGDp|@!sl{$5YNN*ume38u_DMnw+11(heZ^Bnt^D3J;<R$Sl)lW
z%Y!rJAbZaiOXtxE(FHlNV?;BK8rXjxxFn^$+e{O^xrhHxh_KhX3gn*$`mw#ZbIR!_
zWN8mxWZ9)`eC*LbzlGmt%4X`!C1cMu2OCuqU7v4l0}s+(8iDTRiz)K;aoH-^5UYmI
zlW$iaK)uwC@$nZJ&jf@LEMa8w=SMAJ6<a#5Xjz>Gq)A>v<S`$~HFz>=z<~ckz`8+`
zyl}15qN(URxBCFG!UI8Zol-+g@I5-;Df6iVnv6Z3__jqjh{4#0AR#h{Qw6C8B8)HQ
zSJ*F&Db=%Y6H~UxEYWrOc1G`8Nl~@%ZX|ynkhM)c0T*}^HnpW2$MJA=h~SMYxe;$b
z!1uPD{As)^mPR)XA}qLu*cUCF8=^;YhshqU>wR`@kR@bfx!p^qYE)P-I2245egRtz
zlZx(HM-7NPDZs3E++y*djz%Grad={iJn@~<DQhe3Y{ssaUV#&8#+c=C|FlgiCU4wv
z|1v&x3xygF8B?T-m4Y+Y=7yA~tD@q=$!BWOD*|0F7EChVh-~rQ!l`Lp?qh`F?Hb*6
z_J_w6@x2RCl1Rq~oM!mYuTqeoEA776-6_&H?*1u!-#_p`+P{l*+v-%t7fC7UoZ$>6
z>T(4<94az0xfrEBv$0w3ByKG~UJAGG;9Cu;N^E5D0oAn&@Rdk|AD@lOt+MKRK+7#4
zs+GjNjC=A?9IRNc10z^?5#(;}cJv^Dr}ebwSoX*EoCnPKmY?o%jf9pk3=pZ}PbI3@
z$ibU_hYGJIr(b9mm~xT|W|d7DAGQd1QXF6s3X<+^WX7M6-j=cV(_(<X`bK;coxWx6
zyTZ7a*M{2-oQ}r?f2ETkd)kCF+h#B3p#ggzR|El9eZ6fnHPd`p4ZkZ-iYmuXXaoJA
zZx-^XDD4KZf3Y;GIQ3wl0N$Sgz-^6{93KqRVwbV$z(GHk-`mjt;LVD~*Q5Vf=nK!E
zPkkl2JV-1H<$GMjs?aiEhCl`#dU$P>$E$eSCCCWAm1^HB6mYq(SuK_a9V(*)>^<%H
zR+!bWe=g{gGt-<VodkpQRmC&4ohS+V$2W+#XW?bzN;kOQ0*9A$|GMN?(thYA@zBs|
zDPb*wuCSoPevWcD%B5Racg{?U{UOq4Woc0I;m@F+VBDSrPmx5PfJ?lfh~g6@yvYRP
zLVm*#8AzO}aJA=1i><sQxeXNZnx;spq0dDhXhCCqaA}9$#gY4vau@S8^bQ!3V@J#c
zhAYc07;khS@%r+1PoNi4qh1O(?72r6zeg}!aqS96Xp8h2rg;T@6Kj;fj3Agr;DZhq
z<95?zm<Br5h_w&;oi9^Wt~MzD{GHnv`8l`}AgYyoAGJ|}-Zl^6>PVONGud?(_&jF0
zExbr%v#!h7fQ~%1DFRKa0u1<k*KygB_Cpyhc9l1FJ_cAo7Jc2&XJHWO)qF=%9sCaZ
z)Fi!=q{*IMDWAT10{yQe&(ub^S#g_tZ`PyNkx`HQDLq03)u4kS5(vIp5CT6>q@}w|
z=>LrYWa|%|Th;$FrgU;Msz=Dryi-|u#uJq8QW|}JUv*vom;2O_RwZ@IyPl4fK-Eqh
z7mt;w|5hyo8J#g<GH;uDolLDDSmNB5lxpv1e}Lh0QAz#mM6ly0GXLMnep|H^sJzf{
z!sO$wcjRjWL8>in8UudF<xIcx6KKIvCp{*|1I`!4-9h2Dow@!ed(QNuU>O%ZHu0|o
zUtB@{dh-5&zg^ecO_so*+i~NBt8e_APltd>ZGsQ$ze4+Mr(c2W4pI;o2Nou7@g_j$
zPC9wu=YPT5spTO1S5D|Ya@0<u_9M`K4>ci<*7rxv6hUFFr&_d;gQ-q-E+<%q(SC=H
z^WSIAGk07$;aa>&0ci8g6Gc9s76VN$QV>6%*$lKZMd(BI{exx?!TQA~amF}wfK1&m
zh5NS-3s9ZXOh!N6Hf8@aDMBE3=&{_3Iv+pnjK9=#VA2(COyMzl`E4eTGSI>x*&kbX
zZ}8PRZr^NV80ewasyz9+Te=)bSC`J$qJ8e&MurnT(i(%8&-R%z(+e0vD%v07`x9rE
z`2GVXi^+^9E%-!%DQl9~f&90J%vQ?&=Q(vG#nGq`l=}F9HL7d60mv{PpY2ie*@6y%
zf;Gk2NF?xTf11%OP#zI;ns`z^VYX3UJzHv$k<v_VKj22#-)Tm3L6RaXzMc;H?)iV+
z{{o<8k|$rBcydlVEf1V@=A6jR{ISsZgQY6OQg<WSIZ|Cd_Y8`iK@qu>t?s#7PVlXd
z=NI_+h(1wk2yTAZIsfb(8Bp@t*f@VD>+LDI@4^@Q_?SLvJJFk{0IXM13>)Kb_U1-e
z{*#>2xw7ky!p=Y$L!kJRj2U^a{Jp_}bakS%nmM2O2N@RT^QX>&GSxHYe~%{o;H~k?
z1}m65VK#>!H!ypj;ss^(MUC}8Ot(os{IWPuZJBaW@>4eDL)PNvv%UF+ojll-y)PV=
zuaTQ?d=Bi+@+WDheccrb?6?k24w3+RV~P2O@9an4JuW_G^%s~;X10hhY4TjwW!}^@
zdD8<>2-zlF2bQdFEQII3{E{4?mZlYCv5foVO5nD=Xbp>)Ni%>^%yHxG-+vA-w13#7
zo@Si;FEK!E()I~W#=#xHkl%b)?tbZ|mX`n8+`vem@YMOu#v4yp%==yP!@a?1qKuqo
zOdxCStE-K`J%`&azrA}lwVP8hrBHA;*Y97&8#gEAPc+M}XPo;taDk5sw=-9=&qH8<
j6qQ^!sn7ZUH~)Y6<}Z^D+iVZyWB>wBS3j3^P6<r_14&f*

literal 0
HcmV?d00001

diff --git a/Grinder/ui/image/ImageEditor.cpp b/Grinder/ui/image/ImageEditor.cpp
index 53cbac6..a64801b 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 614d46a..c50a3b4 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 e55b56d..1d8ebb0 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 478f5d7..f89e9d4 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 9add74d..106a18b 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 31ca6a1..6dd889f 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 3c9747c..f9b0b6d 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 7336363..bb459c9 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 2f0b2cd..7fc3b10 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 62b9163..f77e39d 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 19e78a0..83f7cf8 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 b3fc73f..149ef2d 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 2946b0a..500de2f 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 aaebe19..114697f 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 005a26a..ccfd2a3 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)
 				{
-- 
GitLab