diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
index 2e2d675284079262654497e9d3f95a02e95d89b1..352d7e89c99ced73bd223007d80e9c9664d8254f 100644
--- a/include/vkcv/Buffer.hpp
+++ b/include/vkcv/Buffer.hpp
@@ -21,7 +21,7 @@ namespace vkcv {
 	template<typename T>
 	class Buffer {
 	public:
-		Buffer() : m_core(nullptr), m_handle() {};
+		Buffer() : m_core(nullptr), m_handle() {}
 		
 		Buffer(Core* core, const BufferHandle& handle) : m_core(core), m_handle(handle) {}
 		
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 593c28de98ea265af80871759c01e15244de2c85..a77d8b2851e0e1e37a1da2aaf5da9b822759da97 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -14,7 +14,6 @@
 #include "Window.hpp"
 #include "PassConfig.hpp"
 #include "Handles.hpp"
-#include "Image.hpp"
 #include "BlitDownsampler.hpp"
 #include "GraphicsPipelineConfig.hpp"
 #include "ComputePipelineConfig.hpp"
@@ -333,24 +332,49 @@ namespace vkcv
 									float mipLodBias = 0.0f, SamplerBorderColor borderColor = SamplerBorderColor::INT_ZERO_OPAQUE);
 
         /**
-         * Creates an #Image with a given format, width, height and depth.
+         * Creates an #Image with a given format, width, height, depth
+         * and a lot more optional parameters.
          *
-         * @param format Image format
-         * @param width Image width
-         * @param height Image height
-         * @param depth Image depth
-         * @return Image-Object
+         * @param[in] format Image format
+         * @param[in] width Image width
+         * @param[in] height Image height
+         * @param[in] depth Image depth
+         * @param[in] createMipChain Flag to create a mip chain
+         * @param[in] supportStorage Flag whether support storage
+         * @param[in] supportColorAttachment Flag whether attachment is supported
+         * @param[in] multisampling Multisampling
+         * @return Image handle
          */
         [[nodiscard]]
-        Image createImage(
-			vk::Format      format,
-			uint32_t        width,
-			uint32_t        height,
-			uint32_t        depth = 1,
-			bool            createMipChain = false,
-			bool            supportStorage = false,
-			bool            supportColorAttachment = false,
-			Multisampling   multisampling = Multisampling::None);
+        ImageHandle createImage(vk::Format format,
+								uint32_t width,
+								uint32_t height,
+								uint32_t depth=1,
+								bool createMipChain=false,
+								bool supportStorage=false,
+								bool supportColorAttachment=false,
+								Multisampling multisampling=Multisampling::None);
+		
+		/**
+		 * Fills the image with given data of a specified size
+		 * in bytes.
+		 *
+		 * @param image Image handle
+		 * @param data Image data pointer
+		 * @param size Size of data
+		 */
+		void fillImage(const ImageHandle& image,
+					   const void *data,
+					   size_t size);
+		
+		/**
+		 * Switches the images layout synchronously if possible.
+		 *
+		 * @param image Image handle
+		 * @param layout New image layout
+		 */
+		void switchImageLayout(const ImageHandle &image,
+							   vk::ImageLayout layout);
 		
 		/**
 		 * @brief Returns the default blit-downsampler.
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 5e5e76454556a6c020d38d72894705ee1d4a3317..8b738b07c6302629d42978dc1f585383366ea52a 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -7,6 +7,8 @@
  
 #include <vulkan/vulkan.hpp>
 
+#include "BufferTypes.hpp"
+#include "Core.hpp"
 #include "Handles.hpp"
 #include "Multisampling.hpp"
 
@@ -39,6 +41,17 @@ namespace vkcv {
 	class Image {
 		friend class Core;
 	public:
+		Image() : m_core(nullptr), m_handle() {};
+		
+		Image(Core* core, const ImageHandle& handle) : m_core(core), m_handle(handle) {}
+		
+		Image(const Image& other) = default;
+		Image(Image&& other) = default;
+		
+		~Image() = default;
+		
+		Image& operator=(const Image& other) = default;
+		Image& operator=(Image&& other) = default;
 		
 		/**
 		 * @brief Returns the format of the image.
@@ -86,7 +99,7 @@ namespace vkcv {
 		 * @return Number of mip levels
 		 */
 		[[nodiscard]]
-		uint32_t getMipCount() const;
+		uint32_t getMipLevels() const;
 
 		/**
 		 * @brief Switches the image layout,
@@ -116,39 +129,19 @@ namespace vkcv {
 									  Downsampler &downsampler);
 		
 	private:
-	    // TODO: const qualifier removed, very hacky!!!
-	    //  Else you cannot recreate an image. Pls fix.
-		ImageManager* m_manager;
+		Core* m_core;
 		ImageHandle m_handle;
 
-		Image(ImageManager* manager, const ImageHandle& handle);
-		
-		/**
-		 * @brief Creates an image with given parameters like width, height,
-		 * depth, amount of mip levels and others.
-		 *
-		 * @param[in,out] manager Image manager
-		 * @param[in] format Vulkan image format
-		 * @param[in] width Width of the image
-		 * @param[in] height Height of the image
-		 * @param[in] depth Depth of the image
-		 * @param[in] mipCount Amount of mip levels
-		 * @param[in] supportStorage Support of storage
-		 * @param[in] supportColorAttachment Support of color attachment
-		 * @param[in] msaa MSAA mode
-		 * @return New created image
-		 */
-		static Image create(
-			ImageManager*   manager,
-			vk::Format      format,
-			uint32_t        width,
-			uint32_t        height,
-			uint32_t        depth,
-			uint32_t        mipCount,
-			bool            supportStorage,
-			bool            supportColorAttachment,
-			Multisampling   msaa);
-
 	};
 	
+	Image image(Core &core,
+				vk::Format format,
+				uint32_t width,
+				uint32_t height,
+				uint32_t depth=1,
+				bool createMipChain=false,
+				bool supportStorage=false,
+				bool supportColorAttachment=false,
+				Multisampling multisampling=Multisampling::None);
+	
 }
diff --git a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
index e68fd54b342e427c2e88a2d932141c129b97e712..fbfa20fb743fee689586b1e24034dbc4334c51a7 100644
--- a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
+++ b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
@@ -3,6 +3,7 @@
 
 #include <vkcv/DrawcallRecording.hpp>
 #include <vkcv/PushConstants.hpp>
+#include <vkcv/Image.hpp>
 
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <vkcv/asset/asset_loader.hpp>
@@ -125,7 +126,8 @@ namespace vkcv::effects {
 								   const std::string &texturePath) {
 		const auto texture = vkcv::asset::loadTexture(texturePath);
 		
-		Image image = core.createImage(
+		auto image = vkcv::image(
+				core,
 				vk::Format::eR8G8B8A8Unorm,
 				texture.width,
 				texture.height
@@ -494,7 +496,7 @@ namespace vkcv::effects {
 					1,
 					true,
 					true
-			).getHandle();
+			);
 			
 			m_downsampleDescriptorSets.clear();
 			m_upsampleDescriptorSets.clear();
@@ -524,7 +526,7 @@ namespace vkcv::effects {
 					1,
 					true,
 					true
-			).getHandle();
+			);
 			
 			m_flaresDescriptorSets.clear();
 			
diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp
index 8c3f3099cee731d24854d314fd7e3df4506a9aec..6ee280a0796de1c9a83c19a84272fccc54181f63 100644
--- a/modules/material/src/vkcv/material/Material.cpp
+++ b/modules/material/src/vkcv/material/Material.cpp
@@ -1,6 +1,8 @@
 
 #include "vkcv/material/Material.hpp"
 
+#include "vkcv/Image.hpp"
+
 namespace vkcv::material {
 	
 	Material::Material() {
@@ -112,35 +114,35 @@ namespace vkcv::material {
 		};
 		
 		if (!colorImg) {
-			vkcv::Image defaultColor = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
+			vkcv::Image defaultColor = image(core, vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float colorData [4] = { 228, 51, 255, 1 };
 			fillImage(defaultColor, colorData);
 			images[0] = defaultColor.getHandle();
 		}
 		
 		if (!normalImg) {
-			vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Unorm, 2, 2);
+			vkcv::Image defaultNormal = image(core, vk::Format::eR8G8B8A8Unorm, 2, 2);
 			float normalData [4] = { 0, 0, 1, 0 };
 			fillImage(defaultNormal, normalData);
 			images[1] = defaultNormal.getHandle();
 		}
 		
 		if (!metRoughImg) {
-			vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Unorm, 2, 2);
+			vkcv::Image defaultRough = image(core, vk::Format::eR8G8B8A8Unorm, 2, 2);
 			float roughData [4] = { 228, 51, 255, 1 };
 			fillImage(defaultRough, roughData);
 			images[2] = defaultRough.getHandle();
 		}
 		
 		if (!occlusionImg) {
-			vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Unorm, 2, 2);
+			vkcv::Image defaultOcclusion = image(core, vk::Format::eR8G8B8A8Unorm, 2, 2);
 			float occlusionData [4] = { 228, 51, 255, 1 };
 			fillImage(defaultOcclusion, occlusionData);
 			images[3] = defaultOcclusion.getHandle();
 		}
 		
 		if (!emissiveImg) {
-			vkcv::Image defaultEmissive = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
+			vkcv::Image defaultEmissive = image(core, vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float emissiveData [4] = { 0, 0, 0, 1 };
 			fillImage(defaultEmissive, emissiveData);
 			images[4] = defaultEmissive.getHandle();
diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp
index a23344742cdd580f793cef6e16791fd5feb23b32..f702aa34d46dd942ac864c812328a79c72d3df65 100644
--- a/modules/scene/src/vkcv/scene/Scene.cpp
+++ b/modules/scene/src/vkcv/scene/Scene.cpp
@@ -1,6 +1,7 @@
 
 #include "vkcv/scene/Scene.hpp"
 
+#include <vkcv/Image.hpp>
 #include <vkcv/Logger.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 
@@ -162,7 +163,7 @@ namespace vkcv::scene {
 			asset_sampler = &(asset_scene.samplers[asset_texture.sampler]);
 		}
 		
-		Image img = core.createImage(format, asset_texture.w, asset_texture.h, 1, true);
+		Image img = vkcv::image(core, format, asset_texture.w, asset_texture.h, 1, true);
 		img.fill(asset_texture.data.data());
 		image = img.getHandle();
 		
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index aaa093252baa05ffb5694ab9a4f6a7c993f1df26..247161e35718cde352da5461b51f30c4fe8570c7 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -279,7 +279,7 @@ namespace vkcv::upscaling {
 					outputWidth, outputHeight,1,
 					false,
 					true
-			).getHandle();
+			);
 			
 			m_core.prepareImageForStorage(cmdStream, m_intermediateImage);
 		}
diff --git a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
index 906b1e3ce0b5a83c2ce490644b381b02da6e77ae..2b25c9132b20368f37568d95608b23b89645016e 100644
--- a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
@@ -7,6 +7,7 @@
 #include "NIS_Scaler.h.hxx"
 
 #include <vkcv/File.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/Logger.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
@@ -77,14 +78,14 @@ namespace vkcv::upscaling {
 		const size_t rowPitch = kFilterSize * 2;
 		const size_t imageSize = rowPitch * kPhaseCount;
 		
-		Image image = core.createImage(
+		Image image = vkcv::image(
+				core,
 				vk::Format::eR16G16B16A16Sfloat,
 				kFilterSize / 4,
 				kPhaseCount
 		);
 		
 		image.fill(data, imageSize);
-		
 		return image.getHandle();
 	}
 	
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index 72e34a42e74a54fd2c978ed498e03044b890b22a..43247f69e4fd379143bd97bf954fa51e12ef55d6 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
@@ -65,9 +66,14 @@ int main(int argc, const char** argv) {
         std::filesystem::path grassPath(grassPaths[i]);
         vkcv::asset::Texture grassTexture = vkcv::asset::loadTexture(grassPath);
 
-        vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, grassTexture.width, grassTexture.height);
+        vkcv::Image texture = vkcv::image(
+				core,
+				vk::Format::eR8G8B8A8Srgb,
+				grassTexture.width,
+				grassTexture.height
+		);
+		
         texture.fill(grassTexture.data.data());
-
         texturesArray.push_back(texture);
     }
 
@@ -161,7 +167,7 @@ int main(int argc, const char** argv) {
 	
 	{
 		vkcv::asset::Texture &tex = mesh.textures[0];
-		vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
+		vkcv::Image texture = vkcv::image(core, vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
 		texture.fill(tex.data.data());
 		texturesArray.push_back(texture);
 	}
@@ -228,7 +234,7 @@ int main(int argc, const char** argv) {
 					vk::Format::eD32Sfloat,
 					swapchainWidth,
 					swapchainHeight
-			).getHandle();
+			);
 		}
 
 		cameraManager.update(dt);
diff --git a/projects/fire_works/src/main.cpp b/projects/fire_works/src/main.cpp
index a657d8bf69b964cd4a6c2a7551a1c65f8c7f134b..91c044e6984f1de5cbd56d47c3cca26dcc7f811c 100644
--- a/projects/fire_works/src/main.cpp
+++ b/projects/fire_works/src/main.cpp
@@ -3,6 +3,7 @@
 
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/Pass.hpp>
 #include <vkcv/DrawcallRecording.hpp>
 
@@ -335,7 +336,7 @@ int main(int argc, const char **argv) {
 				swapchainExtent.width,
 				swapchainExtent.height,
 				1, false, true, true
-		).getHandle();
+		);
 	}
 	
 	vkcv::ShaderProgram particleShaderProgram;
@@ -724,36 +725,40 @@ int main(int argc, const char **argv) {
 	std::vector<uint32_t> zeroVoxel;
 	zeroVoxel.resize(voxelWidth * voxelHeight * voxelDepth, 0);
 	
-	vkcv::Image voxelRed = core.createImage(
-		vk::Format::eR32Uint,
-		voxelWidth,
-		voxelHeight,
-		voxelDepth,
-		false, true
+	vkcv::Image voxelRed = vkcv::image(
+			core,
+			vk::Format::eR32Uint,
+			voxelWidth,
+			voxelHeight,
+			voxelDepth,
+			false, true
 	);
 	
-	vkcv::Image voxelGreen = core.createImage(
-		vk::Format::eR32Uint,
-		voxelWidth,
-		voxelHeight,
-		voxelDepth,
-		false, true
+	vkcv::Image voxelGreen = vkcv::image(
+			core,
+			vk::Format::eR32Uint,
+			voxelWidth,
+			voxelHeight,
+			voxelDepth,
+			false, true
 	);
 	
-	vkcv::Image voxelBlue = core.createImage(
-		vk::Format::eR32Uint,
-		voxelWidth,
-		voxelHeight,
-		voxelDepth,
-		false, true
+	vkcv::Image voxelBlue = vkcv::image(
+			core,
+			vk::Format::eR32Uint,
+			voxelWidth,
+			voxelHeight,
+			voxelDepth,
+			false, true
 	);
 	
-	vkcv::Image voxelDensity = core.createImage(
-		vk::Format::eR32Uint,
-		voxelWidth,
-		voxelHeight,
-		voxelDepth,
-		false, true
+	vkcv::Image voxelDensity = vkcv::image(
+			core,
+			vk::Format::eR32Uint,
+			voxelWidth,
+			voxelHeight,
+			voxelDepth,
+			false, true
 	);
 	
 	std::array<vkcv::ImageHandle, 2> voxelData {
@@ -763,21 +768,22 @@ int main(int argc, const char **argv) {
 			voxelHeight,
 			voxelDepth,
 			false, true
-		).getHandle(),
+		),
 		core.createImage(
 			vk::Format::eR16G16B16A16Sfloat,
 			voxelWidth,
 			voxelHeight,
 			voxelDepth,
 			false, true
-		).getHandle()
+		)
 	};
 	
-	vkcv::Image voxelSamples = core.createImage(
-		colorFormat,
-		voxelWidth,
-		voxelHeight,
-		1, false, true
+	vkcv::Image voxelSamples = vkcv::image(
+			core,
+			colorFormat,
+			voxelWidth,
+			voxelHeight,
+			1, false, true
    	);
 	
 	vkcv::SamplerHandle voxelSampler = core.createSampler(
@@ -966,7 +972,7 @@ int main(int argc, const char **argv) {
 					swapchainWidth,
 					swapchainHeight,
 					1, false, true, true
-				).getHandle();
+				);
 			}
 		}
 		
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 73ef3bc1eeaac65fbc0abdff7c2725d2d8dce722..db985425b3f12b6225ce85c7905be73f9493765f 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -1,9 +1,9 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/Pass.hpp>
 #include <vkcv/camera/CameraManager.hpp>
-#include <chrono>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
@@ -114,7 +114,7 @@ int main(int argc, const char** argv) {
 	}
 	
 	vkcv::asset::Texture &tex = mesh.textures[0];
-	vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
+	vkcv::Image texture = vkcv::image(core, vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
 	texture.fill(tex.data.data());
 	
 	{
@@ -164,7 +164,7 @@ int main(int argc, const char** argv) {
 					vk::Format::eD32Sfloat,
 					swapchainWidth,
 					swapchainHeight
-			).getHandle();
+			);
 		}
 		
 		cameraManager.update(dt);
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index 2dbafc78a2e89dc93c8ef114d1d5f7c4ca5c1c17..6544c7ad696ab606fd482f3f63049f80b33ccc84 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -105,7 +105,7 @@ int main(int argc, const char** argv) {
 					vk::Format::eD32Sfloat,
 					swapchainWidth,
 					swapchainHeight
-			).getHandle();
+			);
 		}
 		
 		cameraManager.update(dt);
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index e7801286e4c73762dc1001a25e2b85d71e1b7380..e3773cb72f6f46cc1fad146f0346ee259fae3550 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -147,14 +147,14 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat,
 			swapchainExtent.width,
 			swapchainExtent.height
-	).getHandle();
+	);
 	
 	vkcv::ImageHandle colorBuffer = core.createImage(
 			colorFormat,
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, true, true
-	).getHandle();
+	);
 	
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 	
@@ -164,14 +164,14 @@ int main(int argc, const char** argv) {
 	core.run([&](const vkcv::WindowHandle &windowHandle, double t, double dt,
 				 uint32_t swapchainWidth, uint32_t swapchainHeight) {
 		if ((swapchainWidth != swapchainExtent.width) || ((swapchainHeight != swapchainExtent.height))) {
-			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle();
+			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight);
 			
 			colorBuffer = core.createImage(
 					colorFormat,
 					swapchainExtent.width,
 					swapchainExtent.height,
 					1, false, true, true
-			).getHandle();
+			);
 			
 			swapchainExtent.width = swapchainWidth;
 			swapchainExtent.height = swapchainHeight;
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index 4f00858608c2976801bf0ffa8338bbff4896f547..e91b969116d3172c301e68d394930723ede72c63 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -1,6 +1,8 @@
 #include "AppSetup.hpp"
 #include "AppConfig.hpp"
+
 #include <vkcv/Buffer.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
@@ -70,12 +72,14 @@ bool loadImage(vkcv::Core& core, const std::filesystem::path& path, vkcv::ImageH
 		return false;
 	}
 
-	vkcv::Image image = core.createImage(
-		vk::Format::eR8G8B8A8Srgb, 
-		textureData.width, 
-		textureData.height, 
-		1, 
-		true);
+	vkcv::Image image = vkcv::image(
+			core,
+			vk::Format::eR8G8B8A8Srgb,
+			textureData.width,
+			textureData.height,
+			1,
+			true
+	);
 
 	image.fill(textureData.data.data(), textureData.data.size());
 	
@@ -296,7 +300,6 @@ bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, Comput
 }
 
 AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height) {
-
 	AppRenderTargets targets;
 
 	targets.depthBuffer = core.createImage(
@@ -304,7 +307,8 @@ AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, con
 		width,
 		height,
 		1,
-		false).getHandle();
+		false
+	);
 
 	targets.colorBuffer = core.createImage(
 		AppConfig::colorBufferFormat,
@@ -313,7 +317,8 @@ AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, con
 		1,
 		false,
 		false,
-		true).getHandle();
+		true
+	);
 
 	targets.motionBuffer = core.createImage(
 		AppConfig::motionBufferFormat,
@@ -322,7 +327,8 @@ AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, con
 		1,
 		false,
 		false,
-		true).getHandle();
+		true
+	);
 
 	return targets;
 }
\ No newline at end of file
diff --git a/projects/indirect_dispatch/src/MotionBlurSetup.cpp b/projects/indirect_dispatch/src/MotionBlurSetup.cpp
index 82d2593a5b976f9389b58dddac43e3a45d1db303..0244c4ae9519ea6c6f818e024930e70c15e7a289 100644
--- a/projects/indirect_dispatch/src/MotionBlurSetup.cpp
+++ b/projects/indirect_dispatch/src/MotionBlurSetup.cpp
@@ -17,7 +17,8 @@ MotionBlurRenderTargets createRenderTargets(const uint32_t width, const uint32_t
 		motionMaxheight,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	targets.motionMaxNeighbourhood = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
@@ -25,7 +26,8 @@ MotionBlurRenderTargets createRenderTargets(const uint32_t width, const uint32_t
 		motionMaxheight,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	targets.motionMin = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
@@ -33,7 +35,8 @@ MotionBlurRenderTargets createRenderTargets(const uint32_t width, const uint32_t
 		motionMaxheight,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	targets.motionMinNeighbourhood = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
@@ -41,7 +44,8 @@ MotionBlurRenderTargets createRenderTargets(const uint32_t width, const uint32_t
 		motionMaxheight,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	targets.outputColor = core.createImage(
 		MotionBlurConfig::outputColorFormat,
@@ -49,7 +53,8 @@ MotionBlurRenderTargets createRenderTargets(const uint32_t width, const uint32_t
 		height,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	return targets;
 }
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index 5631d3c1ec12ae87ae164378d1b2c61ac5b00607..d975d0c1042b5d8fd4714dbc18ded049703f3d59 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -2,6 +2,7 @@
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
 #include <vkcv/gui/GUI.hpp>
@@ -171,7 +172,7 @@ void compileMeshForIndirectDraw(vkcv::Core &core,
                                 CompiledMaterial &compiledMat,
                                 std::vector<vk::DrawIndexedIndirectCommand> &indexedIndirectCommands)
 {
-    vkcv::Image pseudoImg = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
+    vkcv::Image pseudoImg = vkcv::image(core, vk::Format::eR8G8B8A8Srgb, 2, 2);
     std::vector<uint8_t> pseudoData = {0, 0, 0, 0};
     pseudoImg.fill(pseudoData.data());
 	
@@ -196,7 +197,7 @@ void compileMeshForIndirectDraw(vkcv::Core &core,
             {
                 auto &baseColor     = scene.textures[material.baseColor];
 
-                vkcv::Image baseColorImg = core.createImage(vk::Format::eR8G8B8A8Srgb, baseColor.w, baseColor.h);
+                vkcv::Image baseColorImg = vkcv::image(core, vk::Format::eR8G8B8A8Srgb, baseColor.w, baseColor.h);
                 baseColorImg.fill(baseColor.data.data());
 				baseColorImg.recordMipChainGeneration(mipStream, core.getDownsampler());
 
@@ -526,7 +527,7 @@ int main(int argc, const char** argv) {
 		if ((!depthBuffer) ||
 			(swapchainWidth != core.getImageWidth(depthBuffer)) ||
 			(swapchainHeight != core.getImageHeight(depthBuffer))) {
-			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle();
+			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight);
 		}
   
 		cameraManager.update(dt);
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 07f9b5fc7a1abf9f9425807891ec6e24cba15741..786674d0f7e945ed70b422976f8b756d001eab05 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -303,7 +303,7 @@ int main(int argc, const char** argv) {
 					vk::Format::eD32Sfloat,
 					swapchainWidth,
 					swapchainHeight
-			).getHandle();
+			);
 		}
 		
 		cameraManager.update(dt);
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index ba62b1266aa29147b448fe204bbc737932f9d0b6..147a61099a9db8fcdcf483a629fd1186fb80ad88 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -209,7 +209,7 @@ int main(int argc, const char **argv) {
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, true, true
-	).getHandle();
+	);
 	
 	vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core);
 	bloomAndFlares.setUpsamplingLimit(3);
@@ -238,7 +238,7 @@ int main(int argc, const char **argv) {
 					swapchainWidth,
 					swapchainHeight,
 					1, false, true, true
-			).getHandle();
+			);
 		}
 
         color.fill(&colorData);
diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp
index 6b0133b7da0895142cd16d488806f909271fc7e3..808490f7c9b31e1ae5c8895de409e76c81ed5d93 100644
--- a/projects/path_tracer/src/main.cpp
+++ b/projects/path_tracer/src/main.cpp
@@ -71,7 +71,8 @@ int main(int argc, const char** argv) {
 		initialHeight,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	vkcv::ImageHandle meanImage = core.createImage(
 		vk::Format::eR32G32B32A32Sfloat,
@@ -79,7 +80,8 @@ int main(int argc, const char** argv) {
 		initialHeight,
 		1,
 		false,
-		true).getHandle();
+		true
+	);
 
 	vkcv::shader::GLSLCompiler compiler;
 
@@ -255,7 +257,8 @@ int main(int argc, const char** argv) {
 				swapchainHeight,
 				1,
 				false,
-				true).getHandle();
+				true
+			);
 
 			meanImage = core.createImage(
 				vk::Format::eR32G32B32A32Sfloat,
@@ -263,7 +266,8 @@ int main(int argc, const char** argv) {
 				swapchainHeight,
 				1,
 				false,
-				true).getHandle();
+				true
+			);
 
 			// update descriptor sets
 			traceDescriptorWrites.writeStorageImage(3, outputImage);
diff --git a/projects/rtx_ambient_occlusion/src/main.cpp b/projects/rtx_ambient_occlusion/src/main.cpp
index 0f4f98f7e9acf9ce93370b594fb58a71b41fed75..eb1a92531e541089320dee9f06cae4064604744b 100644
--- a/projects/rtx_ambient_occlusion/src/main.cpp
+++ b/projects/rtx_ambient_occlusion/src/main.cpp
@@ -103,7 +103,7 @@ int main(int argc, const char** argv) {
 					vk::Format::eD32Sfloat,
 					swapchainWidth,
 					swapchainHeight
-			).getHandle();
+			);
 		}
 		
 		cameraManager.update(dt);
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index ec04f36444ce499643f17970960f35b712765300..8d41b3bcf5dabc7059924d20160ba53769b1a401 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -226,7 +226,7 @@ int main(int argc, const char **argv) {
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, true, true
-	).getHandle();
+	);
 	
 	vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core);
 	bloomAndFlares.setUpsamplingLimit(3);
@@ -249,7 +249,7 @@ int main(int argc, const char **argv) {
 					swapchainWidth,
 					swapchainHeight,
 					1, false, true, true
-			).getHandle();
+			);
 		}
 
         color.fill(&colorData);
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index c0f7ed2ad614d0b717a322430b07b776e57971f2..01b2a3c3fa6df54a9a64844e515b4ea80465e9f3 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -153,9 +153,9 @@ glm::mat4 computeShadowViewProjectionMatrix(
 
 ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vertexLayout) : 
 	m_corePtr(corePtr),
-	m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, true, true)),
-	m_shadowMapIntermediate(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, true)),
-	m_shadowMapDepth(corePtr->createImage(shadowMapDepthFormat, shadowMapResolution, shadowMapResolution, 1, false, false, false, msaa)),
+	m_shadowMap(vkcv::image(*corePtr, shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, true, true)),
+	m_shadowMapIntermediate(vkcv::image(*corePtr, shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, true)),
+	m_shadowMapDepth(vkcv::image(*corePtr, shadowMapDepthFormat, shadowMapResolution, shadowMapResolution, 1, false, false, false, msaa)),
 	m_lightInfoBuffer(buffer<LightInfo>(*corePtr, vkcv::BufferType::UNIFORM, 1)){
 
 	vkcv::ShaderProgram shadowShader = loadShadowShader();
diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp
index 4901d6ec470893d83ec978d00a78b9fba90a9fbc..ed1eaed52a482c8403d1c4e7fac8a0799239f399 100644
--- a/projects/voxelization/src/ShadowMapping.hpp
+++ b/projects/voxelization/src/ShadowMapping.hpp
@@ -4,6 +4,7 @@
 #include <vkcv/Core.hpp>
 #include <vkcv/camera/Camera.hpp>
 #include <vkcv/Downsampler.hpp>
+#include <vkcv/Image.hpp>
 
 #include <glm/glm.hpp>
 #define GLM_ENABLE_EXPERIMENTAL // use this before inclusion, else error!
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index f8d7fa4f75ca4d36c9e4bd52058bf9702e0e4663..9fd418277cb4457b91e1a62e589bde7b09e9ae33 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -86,10 +86,10 @@ Voxelization::Voxelization(
 	vkcv::Multisampling msaa)
 	:
 	m_corePtr(corePtr),
-	m_voxelImageIntermediate(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
-	m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
+	m_voxelImageIntermediate(vkcv::image(*m_corePtr, vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
+	m_voxelImage(vkcv::image(*m_corePtr, vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
 	m_voxelBuffer(buffer<VoxelBufferContent>(*m_corePtr, vkcv::BufferType::STORAGE, voxelCount)),
-	m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)),
+	m_dummyRenderTarget(vkcv::image(*m_corePtr, voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)),
 	m_voxelInfoBuffer(buffer<VoxelizationInfo>(*m_corePtr, vkcv::BufferType::UNIFORM, 1)) {
 
 	const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader();
@@ -329,7 +329,7 @@ void Voxelization::renderVoxelVisualisation(
 	vkcv::PushConstants voxelVisualisationPushConstants = vkcv::pushConstants<glm::mat4>();
 	voxelVisualisationPushConstants.appendDrawcall(viewProjectin);
 
-	mipLevel = std::clamp(mipLevel, (uint32_t)0, m_voxelImage.getMipCount()-1);
+	mipLevel = std::clamp(mipLevel, (uint32_t) 0, m_voxelImage.getMipLevels() - 1);
 
 	// write descriptor set
 	vkcv::DescriptorWrites voxelVisualisationDescriptorWrite;
diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp
index de710b64502fe240e455b8d588cccd18872003da..2e71b1fcf124a30d0e366a7bb829702221d51a30 100644
--- a/projects/voxelization/src/Voxelization.hpp
+++ b/projects/voxelization/src/Voxelization.hpp
@@ -2,6 +2,7 @@
 
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Image.hpp>
 #include <glm/glm.hpp>
 #include <vkcv/camera/Camera.hpp>
 #include <vkcv/Downsampler.hpp>
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 61e7d35b379edd9bd3e09be2b38c5c422689755c..139f22fe1a77018a7e09fce54ac90ae2a18bb36b 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -285,19 +285,19 @@ int main(int argc, const char** argv) {
 		vkcv::asset::Texture& specularTexture   = scene.textures[specularIndex];
 
 		// albedo texture
-		sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, albedoTexture.w, albedoTexture.h, 1, true));
+		sceneImages.push_back(vkcv::image(core, vk::Format::eR8G8B8A8Srgb, albedoTexture.w, albedoTexture.h, 1, true));
 		sceneImages.back().fill(albedoTexture.data.data());
 		sceneImages.back().recordMipChainGeneration(mipStream, spdDownsampler);
 		const vkcv::ImageHandle albedoHandle = sceneImages.back().getHandle();
 
 		// normal texture
-		sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Unorm, normalTexture.w, normalTexture.h, 1, true, true));
+		sceneImages.push_back(vkcv::image(core, vk::Format::eR8G8B8A8Unorm, normalTexture.w, normalTexture.h, 1, true, true));
 		sceneImages.back().fill(normalTexture.data.data());
 		sceneImages.back().recordMipChainGeneration(mipStream, spdDownsampler);
 		const vkcv::ImageHandle normalHandle = sceneImages.back().getHandle();
 
 		// specular texture
-		sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Unorm, specularTexture.w, specularTexture.h, 1, true, true));
+		sceneImages.push_back(vkcv::image(core, vk::Format::eR8G8B8A8Unorm, specularTexture.w, specularTexture.h, 1, true, true));
 		sceneImages.back().fill(specularTexture.data.data());
 		sceneImages.back().recordMipChainGeneration(mipStream, spdDownsampler);
 		const vkcv::ImageHandle specularHandle = sceneImages.back().getHandle();
@@ -400,20 +400,20 @@ int main(int argc, const char** argv) {
 	vkcv::GraphicsPipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
 
 	// render targets
-	vkcv::ImageHandle depthBuffer           = core.createImage(
+	vkcv::ImageHandle depthBuffer = core.createImage(
 			depthBufferFormat,
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, false, false, msaa
-	).getHandle();
+	);
 
-    const bool colorBufferRequiresStorage   = !usingMsaa;
-	vkcv::ImageHandle colorBuffer           = core.createImage(
+    const bool colorBufferRequiresStorage = !usingMsaa;
+	vkcv::ImageHandle colorBuffer = core.createImage(
 			colorBufferFormat,
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, colorBufferRequiresStorage, true, msaa
-	).getHandle();
+	);
 
 	vkcv::ImageHandle resolvedColorBuffer;
 	if (usingMsaa) {
@@ -422,7 +422,7 @@ int main(int argc, const char** argv) {
 				swapchainExtent.width,
 				swapchainExtent.height,
 				1, false, true, true
-		).getHandle();
+		);
 	}
 	else {
 		resolvedColorBuffer = colorBuffer;
@@ -433,14 +433,14 @@ int main(int argc, const char** argv) {
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, true
-	).getHandle();
+	);
 	
 	vkcv::ImageHandle swapBuffer2 = core.createImage(
 			colorBufferFormat,
 			swapchainExtent.width,
 			swapchainExtent.height,
 			1, false, true
-	).getHandle();
+	);
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
@@ -677,21 +677,21 @@ int main(int argc, const char** argv) {
 					fsrWidth, fsrHeight, 1,
 					false, false, false,
 					msaa
-			).getHandle();
+			);
 			
 			colorBuffer = core.createImage(
 					colorBufferFormat,
 					fsrWidth, fsrHeight, 1,
 					false, colorBufferRequiresStorage, true,
 					msaa
-			).getHandle();
+			);
 
 			if (usingMsaa) {
 				resolvedColorBuffer = core.createImage(
 						colorBufferFormat,
 						fsrWidth, fsrHeight, 1,
 						false, true, true
-				).getHandle();
+				);
 			} else {
 				resolvedColorBuffer = colorBuffer;
 			}
@@ -700,13 +700,13 @@ int main(int argc, const char** argv) {
 					colorBufferFormat,
 					fsrWidth, fsrHeight, 1,
 					false, true
-			).getHandle();
+			);
 			
 			swapBuffer2 = core.createImage(
 					colorBufferFormat,
 					swapchainWidth, swapchainHeight, 1,
 					false, true
-			).getHandle();
+			);
 		}
 
 		// update descriptor sets which use swapchain image
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 683b99b1138d8c67ef8a3ddbbf10e59296265098..58a07debd5e47b966f47372b73da0befafe31e48 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -2,6 +2,7 @@
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Image.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/gui/GUI.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
@@ -310,9 +311,10 @@ int main(int argc, const char **argv) {
 			vk::Format::eD32Sfloat,
 			swapchainExtent.width,
 			swapchainExtent.height
-	).getHandle();
+	);
 	
-	vkcv::Image grid = core.createImage(
+	vkcv::Image grid = vkcv::image(
+			core,
 			vk::Format::eR16G16B16A16Sfloat,
 			32,
 			32,
@@ -628,7 +630,7 @@ int main(int argc, const char **argv) {
 					vk::Format::eD32Sfloat,
 					swapchainWidth,
 					swapchainHeight
-			).getHandle();
+			);
 			
 			swapchainExtent.width = swapchainWidth;
 			swapchainExtent.height = swapchainHeight;
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 2cc1ac1b9e0cf491087dbca4670c5589a9e1a488..53730e97528a7d4a58c62692f101f597a1c37882 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -5,6 +5,7 @@
  */
 
 #include <GLFW/glfw3.h>
+#include <cmath>
 
 #include "vkcv/Core.hpp"
 #include "PassManager.hpp"
@@ -17,7 +18,7 @@
 #include "DescriptorSetManager.hpp"
 #include "WindowManager.hpp"
 #include "CommandStreamManager.hpp"
-#include <cmath>
+#include "vkcv/Image.hpp"
 #include "vkcv/Logger.hpp"
 #include "vkcv/BlitDownsampler.hpp"
 
@@ -1002,29 +1003,40 @@ namespace vkcv
 		return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, mipLodBias, borderColor);
 	}
 
-	Image Core::createImage(vk::Format      format,
-							uint32_t        width,
-							uint32_t        height,
-							uint32_t        depth,
-							bool            createMipChain,
-							bool            supportStorage,
-							bool            supportColorAttachment,
-							Multisampling   multisampling) {
+	ImageHandle Core::createImage(vk::Format format,
+								  uint32_t width,
+								  uint32_t height,
+								  uint32_t depth,
+								  bool createMipChain,
+								  bool supportStorage,
+								  bool supportColorAttachment,
+								  Multisampling multisampling) {
 		uint32_t mipCount = 1;
 		if (createMipChain) {
 			mipCount = 1 + (uint32_t)std::floor(std::log2(std::max(width, std::max(height, depth))));
 		}
-
-		return Image::create(
-			m_ImageManager.get(), 
-			format,
-			width,
-			height,
-			depth,
-			mipCount,
-			supportStorage,
-			supportColorAttachment,
-			multisampling);
+		
+		return m_ImageManager->createImage(
+				width,
+				height,
+				depth,
+				format,
+				mipCount,
+				supportStorage,
+				supportColorAttachment,
+				multisampling
+		);
+	}
+	
+	void Core::fillImage(const ImageHandle &image,
+						 const void *data,
+						 size_t size) {
+		m_ImageManager->fillImage(image, data, size);
+	}
+	
+	void Core::switchImageLayout(const ImageHandle &image,
+								 vk::ImageLayout layout) {
+		m_ImageManager->switchImageLayoutImmediate(image, layout);
 	}
 	
 	Downsampler &Core::getDownsampler() {
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index 8b40604551ab9bedc42dae9f96eb4e9bd5c44867..e17b95fe719805faa5b200686e529fc700400dd4 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -34,54 +34,37 @@ namespace vkcv{
 				return false;
 		}
 	}
-
-	Image Image::create(
-		ImageManager*   manager,
-		vk::Format      format,
-		uint32_t        width,
-		uint32_t        height,
-		uint32_t        depth,
-		uint32_t        mipCount,
-		bool            supportStorage,
-		bool            supportColorAttachment,
-		Multisampling   msaa)
-	{
-		return Image(
-			manager, 
-			manager->createImage(width, height, depth, format, mipCount, supportStorage, supportColorAttachment, msaa));
-	}
 	
 	vk::Format Image::getFormat() const {
-		return m_manager->getImageFormat(m_handle);
+		return m_core->getImageFormat(m_handle);
 	}
 	
 	uint32_t Image::getWidth() const {
-		return m_manager->getImageWidth(m_handle);
+		return m_core->getImageWidth(m_handle);
 	}
 	
 	uint32_t Image::getHeight() const {
-		return m_manager->getImageHeight(m_handle);
+		return m_core->getImageHeight(m_handle);
 	}
 	
 	uint32_t Image::getDepth() const {
-		return m_manager->getImageDepth(m_handle);
+		return m_core->getImageDepth(m_handle);
 	}
 
-	void Image::switchLayout(vk::ImageLayout newLayout)
-	{
-		m_manager->switchImageLayoutImmediate(m_handle, newLayout);
+	void Image::switchLayout(vk::ImageLayout newLayout) {
+		m_core->switchImageLayout(m_handle, newLayout);
 	}
 
 	const vkcv::ImageHandle& Image::getHandle() const {
 		return m_handle;
 	}
 
-	uint32_t Image::getMipCount() const {
-		return m_manager->getImageMipCount(m_handle);
+	uint32_t Image::getMipLevels() const {
+		return m_core->getImageMipLevels(m_handle);
 	}
 
 	void Image::fill(const void *data, size_t size) {
-		m_manager->fillImage(m_handle, data, size);
+		m_core->fillImage(m_handle, data, size);
 	}
 
 	void Image::recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream,
@@ -89,9 +72,25 @@ namespace vkcv{
 		downsampler.recordDownsampling(cmdStream, m_handle);
 	}
 	
-	Image::Image(ImageManager* manager, const ImageHandle& handle) :
-		m_manager(manager),
-		m_handle(handle)
-	{}
+	Image image(Core &core,
+				vk::Format format,
+				uint32_t width,
+				uint32_t height,
+				uint32_t depth,
+				bool createMipChain,
+				bool supportStorage,
+				bool supportColorAttachment,
+				Multisampling multisampling) {
+		return Image(&core, core.createImage(
+				format,
+				width,
+				height,
+				depth,
+				createMipChain,
+				supportStorage,
+				supportColorAttachment,
+				multisampling
+		));
+	}
 
 }
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 17ed1b8338e219ec12e094b836a3ec2208bf1bb1..fbe109da5ee10d43d011c0120abcdff78934a7d7 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -5,6 +5,7 @@
  */
 #include "ImageManager.hpp"
 #include "vkcv/Core.hpp"
+#include "vkcv/Image.hpp"
 #include "vkcv/Logger.hpp"
 #include "vkcv/Multisampling.hpp"
 #include "vkcv/TypeGuard.hpp"
@@ -529,9 +530,7 @@ namespace vkcv {
 		}
 		
 		auto& image = (*this)[handle];
-		switchImageLayoutImmediate(
-				handle,
-				vk::ImageLayout::eTransferDstOptimal);
+		switchImageLayoutImmediate(handle, vk::ImageLayout::eTransferDstOptimal);
 		
 		const size_t image_size = (
 				image.m_width * image.m_height * image.m_depth *
@@ -589,10 +588,7 @@ namespace vkcv {
 					);
 				},
 				[&]() {
-					switchImageLayoutImmediate(
-							handle,
-							vk::ImageLayout::eShaderReadOnlyOptimal
-					);
+					switchImageLayoutImmediate(handle,vk::ImageLayout::eShaderReadOnlyOptimal);
 				}
 		);