diff --git a/config/Sources.cmake b/config/Sources.cmake
index db4b200fa99597af4f96432e35e80af387ae881a..6cf9c6f4663c4307ee6c9350941cbe6e2f2b5a2c 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -41,6 +41,9 @@ set(vkcv_sources
 		
 		${vkcv_source}/vkcv/BufferManager.hpp
 		${vkcv_source}/vkcv/BufferManager.cpp
+		
+		${vkcv_include}/vkcv/ImageConfig.hpp
+		${vkcv_source}/vkcv/ImageConfig.cpp
 
 		${vkcv_include}/vkcv/Image.hpp
 		${vkcv_source}/vkcv/Image.cpp
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 1a4ce7c8ca203661d6bb21fdfbde0beb8ac02b12..fc80436ec85967619dab6aa5a518f0986e2b4f62 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -21,6 +21,7 @@
 #include "EventFunctionTypes.hpp"
 #include "GraphicsPipelineConfig.hpp"
 #include "Handles.hpp"
+#include "ImageConfig.hpp"
 #include "PassConfig.hpp"
 #include "PushConstants.hpp"
 #include "Result.hpp"
@@ -318,24 +319,17 @@ namespace vkcv {
 					  SamplerBorderColor borderColor = SamplerBorderColor::INT_ZERO_OPAQUE);
 
 		/**
-		 * Creates an #Image with a given format, width, height, depth
-		 * and a lot more optional parameters.
+		 * Creates an #Image with a given format, configuration
+		 * and whether a mipchain should be created.
 		 *
 		 * @param[in] format Image format
-		 * @param[in] width Image width
-		 * @param[in] height Image height
-		 * @param[in] depth Image depth
+		 * @param[in] config Image configuration
 		 * @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]] 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);
+		[[nodiscard]] ImageHandle createImage(vk::Format format,
+											  const ImageConfig& config,
+											  bool createMipChain = false);
 
 		/**
 		 * @brief Fills the image with given data of a specified size
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 69d4bc07e7f40af3d5d2802dd06576f166329427..511ac67102ec26e9bd92c1b9e62b42d34c784e4d 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -10,6 +10,7 @@
 #include "BufferTypes.hpp"
 #include "Core.hpp"
 #include "Handles.hpp"
+#include "ImageConfig.hpp"
 #include "Multisampling.hpp"
 
 namespace vkcv {
@@ -131,5 +132,10 @@ namespace vkcv {
 				bool createMipChain = false, bool supportStorage = false,
 				bool supportColorAttachment = false,
 				Multisampling multisampling = Multisampling::None);
+	
+	Image image(Core &core,
+				vk::Format format,
+				const ImageConfig &config,
+				bool createMipChain = false);
 
 } // namespace vkcv
diff --git a/include/vkcv/ImageConfig.hpp b/include/vkcv/ImageConfig.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..21e9f6d05ac254e90e29d670304df961099cecef
--- /dev/null
+++ b/include/vkcv/ImageConfig.hpp
@@ -0,0 +1,160 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/ImageConfig.hpp
+ * @brief Structure for image configuration.
+ */
+
+#include "Multisampling.hpp"
+
+namespace vkcv {
+	
+	struct ImageConfig {
+	private:
+		uint32_t m_width;
+		uint32_t m_height;
+		uint32_t m_depth;
+		
+		bool m_supportStorage;
+		bool m_supportColorAttachment;
+		bool m_cubeMapImage;
+		
+		Multisampling m_msaa;
+		
+	public:
+		/**
+		 * Constructor of the image configuration by
+		 * a given resolution.
+		 *
+		 * @param[in] width Image width
+		 * @param[in] height Image height
+		 * @param[in] depth Image depth
+		 */
+		ImageConfig(uint32_t width,
+					uint32_t height,
+					uint32_t depth = 1);
+	
+		ImageConfig(const ImageConfig &other) = default;
+		ImageConfig(ImageConfig&& other) = default;
+
+		~ImageConfig() = default;
+
+		ImageConfig& operator=(const ImageConfig &other) = default;
+		ImageConfig& operator=(ImageConfig&& other) = default;
+		
+		/**
+		 * Return the configured width of the image.
+		 *
+		 * @return Image width
+		 */
+		[[nodiscard]]
+		uint32_t getWidth() const;
+		
+		/**
+		 * Set configured width of the image.
+		 *
+		 * @param[in] width Image width
+		 */
+		void setWidth(uint32_t width);
+		
+		/**
+		 * Return the configured height of the image.
+		 *
+		 * @return Image height
+		 */
+		[[nodiscard]]
+		uint32_t getHeight() const;
+		
+		/**
+		 * Set configured height of the image.
+		 *
+		 * @param[in] height Image height
+		 */
+		void setHeight(uint32_t height);
+		
+		/**
+		 * Return the configured depth of the image.
+		 *
+		 * @return Image depth
+		 */
+		[[nodiscard]]
+		uint32_t getDepth() const;
+		
+		/**
+		 * Set configured depth of the image.
+		 *
+		 * @param[in] depth Image depth
+		 */
+		void setDepth(uint32_t depth);
+		
+		/**
+		 * Return whether the image is configured to
+		 * support storage operations.
+		 *
+		 * @return True, if it supports storage, otherwise false
+		 */
+		[[nodiscard]]
+		bool isSupportingStorage() const;
+		
+		/**
+		 * Set whether the image is configured to
+		 * support storage operations.
+		 *
+		 * @param[in] supportStorage Support storage
+		 */
+		void setSupportingStorage(bool supportStorage);
+		
+		/**
+		 * Return whether the image is configured to
+		 * support being used as color attachment.
+		 *
+		 * @return True, if it supports color attachment, otherwise false
+		 */
+		[[nodiscard]]
+		bool isSupportingColorAttachment() const;
+		
+		/**
+		 * Set whether the image is configured to
+		 * support being used as color attachment.
+		 *
+		 * @param[in] supportColorAttachment Support color attachment
+		 */
+		void setSupportingColorAttachment(bool supportColorAttachment);
+		
+		/**
+		 * Return whether the image is configured to
+		 * be a cube map.
+		 *
+		 * @return True, if the image is a cube map, otherwise false
+		 */
+		[[nodiscard]]
+		bool isCubeMapImage() const;
+		
+		/**
+		 * Set whether the image is configured to
+		 * be a cube map.
+		 *
+		 * @param[in] cubeMapImage Is cube map image
+		 */
+		void setCubeMapImage(bool cubeMapImage);
+		
+		/**
+		 * Return type of multisampling the image
+		 * is configured to use.
+		 *
+		 * @return Multisampling
+		 */
+		[[nodiscard]]
+		Multisampling getMultisampling() const;
+		
+		/**
+		 * Set the multisampling of the image
+		 * configuration.
+		 *
+		 * @param[in] msaa Multisampling
+		 */
+		void setMultisampling(Multisampling msaa);
+		
+	};
+	
+}
diff --git a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
index f31596ae80c86a432f62a50621de949961e83d56..133b380095abc6c729ef94da675cc9f394475ab4 100644
--- a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
+++ b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
@@ -294,7 +294,7 @@ namespace vkcv::effects {
 					cmdStream,
 					m_downsamplePipeline,
 					dispatch,
-					{ DescriptorSetUsage(0, mipDescriptorSets[mipLevel]) },
+					{ useDescriptorSet(0, mipDescriptorSets[mipLevel]) },
 					PushConstants(0)
 			);
 			
@@ -342,7 +342,7 @@ namespace vkcv::effects {
 					cmdStream,
 					m_upsamplePipeline,
 					dispatch,
-					{ DescriptorSetUsage(0, mipDescriptorSets[mipLevel - 1]) },
+					{ useDescriptorSet(0, mipDescriptorSets[mipLevel - 1]) },
 					PushConstants(0)
 			);
 			
@@ -388,7 +388,7 @@ namespace vkcv::effects {
 				cmdStream,
 				m_lensFlaresPipeline,
 				dispatch,
-				{ DescriptorSetUsage(0, m_lensFlaresDescriptorSet) },
+				{ useDescriptorSet(0, m_lensFlaresDescriptorSet) },
 				PushConstants(0)
 		);
 	}
@@ -455,7 +455,7 @@ namespace vkcv::effects {
 				cmdStream,
 				m_compositePipeline,
 				dispatch,
-				{ DescriptorSetUsage(0, m_compositeDescriptorSet) },
+				{ useDescriptorSet(0, m_compositeDescriptorSet) },
 				m_advanced? pushConstants : PushConstants(0)
 		);
 	}
@@ -475,15 +475,15 @@ namespace vkcv::effects {
 				static_cast<float>(m_core.getImageHeight(output)) * 0.5f
 		));
 		
+		vkcv::ImageConfig imageConfig (halfWidth, halfHeight);
+		imageConfig.setSupportingStorage(true);
+		
 		if ((!m_blurImage) ||
 			(halfWidth != m_core.getImageWidth(m_blurImage)) ||
 			(halfHeight != m_core.getImageHeight(m_blurImage))) {
 			m_blurImage = m_core.createImage(
 					m_core.getImageFormat(output),
-					halfWidth,
-					halfHeight,
-					1,
-					true,
+					imageConfig,
 					true
 			);
 			
@@ -510,10 +510,7 @@ namespace vkcv::effects {
 			(halfHeight != m_core.getImageHeight(m_flaresImage))) {
 			m_flaresImage = m_core.createImage(
 					m_core.getImageFormat(output),
-					halfWidth,
-					halfHeight,
-					1,
-					true,
+					imageConfig,
 					true
 			);
 			
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 247161e35718cde352da5461b51f30c4fe8570c7..bacb4ce0814ff0caec0c3d4d353ecf5019e0eda4 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -274,11 +274,12 @@ namespace vkcv::upscaling {
 		if ((!m_intermediateImage) ||
 			(outputWidth != m_core.getImageWidth(m_intermediateImage)) ||
 			(outputHeight != m_core.getImageHeight(m_intermediateImage))) {
+			ImageConfig imageConfig (outputWidth, outputHeight);
+			imageConfig.setSupportingStorage(true);
+			
 			m_intermediateImage = m_core.createImage(
 					m_core.getImageFormat(output),
-					outputWidth, outputHeight,1,
-					false,
-					true
+					imageConfig
 			);
 			
 			m_core.prepareImageForStorage(cmdStream, m_intermediateImage);
@@ -333,7 +334,7 @@ namespace vkcv::upscaling {
 					cmdStream,
 					m_easuPipeline,
 					dispatch,
-					{DescriptorSetUsage(0, m_easuDescriptorSet, { 0 })},
+					{ useDescriptorSet(0, m_easuDescriptorSet, { 0 }) },
 					PushConstants(0)
 			);
 			
@@ -353,7 +354,7 @@ namespace vkcv::upscaling {
 					cmdStream,
 					m_rcasPipeline,
 					dispatch,
-					{DescriptorSetUsage(0,m_rcasDescriptorSet, { 0 })},
+					{ useDescriptorSet(0,m_rcasDescriptorSet, { 0 }) },
 					PushConstants(0)
 			);
 			
@@ -371,7 +372,7 @@ namespace vkcv::upscaling {
 					cmdStream,
 					m_easuPipeline,
 					dispatch,
-					{DescriptorSetUsage(0, m_easuDescriptorSet, { 0 })},
+					{ useDescriptorSet(0, m_easuDescriptorSet, { 0 }) },
 					PushConstants(0)
 			);
 		}
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index 42af6910cd0102f01df29d470269882ebd1cb0d0..37d0c68b34eeb45560907fc43d049d61f0285c17 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -185,9 +185,7 @@ int main(int argc, const char** argv) {
 	vkcv::SamplerHandle sampler = vkcv::samplerLinear(core);
 	vkcv::DescriptorWrites setWrites;
 	
-	for(uint32_t i = 0; i < 6; i++)
-	{
-		
+	for(uint32_t i = 0; i < 6; i++) {
 		setWrites.writeSampledImage(
 				1,
 				texturesArray[i].getHandle(),
@@ -225,8 +223,7 @@ int main(int argc, const char** argv) {
 			(swapchainHeight != core.getImageHeight(depthBuffer))) {
 			depthBuffer = core.createImage(
 					vk::Format::eD32Sfloat,
-					swapchainWidth,
-					swapchainHeight
+					vkcv::ImageConfig(swapchainWidth, swapchainHeight)
 			);
 		}
 
diff --git a/projects/fire_works/src/main.cpp b/projects/fire_works/src/main.cpp
index 472b781905fc446c592bef74bc0262792e8c3988..0166da4b5788990a05f85da5a3b41c0e206d956a 100644
--- a/projects/fire_works/src/main.cpp
+++ b/projects/fire_works/src/main.cpp
@@ -331,11 +331,17 @@ int main(int argc, const char **argv) {
 	
 	std::array<vkcv::ImageHandle, 4> colorBuffers;
 	for (size_t i = 0; i < colorBuffers.size(); i++) {
+		vkcv::ImageConfig colorBufferConfig (
+				swapchainExtent.width,
+				swapchainExtent.height
+		);
+		
+		colorBufferConfig.setSupportingStorage(true);
+		colorBufferConfig.setSupportingColorAttachment(true);
+		
 		colorBuffers[i] = core.createImage(
 				colorFormat,
-				swapchainExtent.width,
-				swapchainExtent.height,
-				1, false, true, true
+				colorBufferConfig
 		);
 	}
 	
@@ -700,65 +706,60 @@ int main(int argc, const char **argv) {
 	std::vector<uint32_t> zeroVoxel;
 	zeroVoxel.resize(voxelWidth * voxelHeight * voxelDepth, 0);
 	
+	vkcv::ImageConfig voxelImageConfig (
+			voxelWidth,
+			voxelHeight,
+			voxelDepth
+	);
+	
+	voxelImageConfig.setSupportingStorage(true);
+	
 	vkcv::Image voxelRed = vkcv::image(
 			core,
 			vk::Format::eR32Uint,
-			voxelWidth,
-			voxelHeight,
-			voxelDepth,
-			false, true
+			voxelImageConfig
 	);
 	
 	vkcv::Image voxelGreen = vkcv::image(
 			core,
 			vk::Format::eR32Uint,
-			voxelWidth,
-			voxelHeight,
-			voxelDepth,
-			false, true
+			voxelImageConfig
 	);
 	
 	vkcv::Image voxelBlue = vkcv::image(
 			core,
 			vk::Format::eR32Uint,
-			voxelWidth,
-			voxelHeight,
-			voxelDepth,
-			false, true
+			voxelImageConfig
 	);
 	
 	vkcv::Image voxelDensity = vkcv::image(
 			core,
 			vk::Format::eR32Uint,
-			voxelWidth,
-			voxelHeight,
-			voxelDepth,
-			false, true
+			voxelImageConfig
 	);
 	
 	std::array<vkcv::ImageHandle, 2> voxelData {
 		core.createImage(
 			vk::Format::eR16G16B16A16Sfloat,
-			voxelWidth,
-			voxelHeight,
-			voxelDepth,
-			false, true
+			voxelImageConfig
 		),
 		core.createImage(
 			vk::Format::eR16G16B16A16Sfloat,
-			voxelWidth,
-			voxelHeight,
-			voxelDepth,
-			false, true
+			voxelImageConfig
 		)
 	};
 	
+	vkcv::ImageConfig voxelSamplesConfig (
+			voxelWidth,
+			voxelHeight
+	);
+	
+	voxelImageConfig.setSupportingStorage(true);
+	
 	vkcv::Image voxelSamples = vkcv::image(
 			core,
 			colorFormat,
-			voxelWidth,
-			voxelHeight,
-			1, false, true
+			voxelSamplesConfig
    	);
 	
 	vkcv::SamplerHandle voxelSampler = vkcv::samplerLinear(core, true);
@@ -934,14 +935,20 @@ int main(int argc, const char **argv) {
 			continue;
 		}
 	
-		for (size_t i = 0; i < colorBuffers.size(); i++) {
-			if ((core.getImageWidth(colorBuffers[i]) != swapchainWidth) ||
-				(core.getImageHeight(colorBuffers[i]) != swapchainHeight)) {
-				colorBuffers[i] = core.createImage(
+		for (auto& colorBuffer : colorBuffers) {
+			if ((core.getImageWidth(colorBuffer) != swapchainWidth) ||
+				(core.getImageHeight(colorBuffer) != swapchainHeight)) {
+				vkcv::ImageConfig colorBufferConfig (
+						swapchainWidth,
+						swapchainHeight
+				);
+				
+				colorBufferConfig.setSupportingStorage(true);
+				colorBufferConfig.setSupportingColorAttachment(true);
+				
+				colorBuffer = core.createImage(
 					colorFormat,
-					swapchainWidth,
-					swapchainHeight,
-					1, false, true, true
+					colorBufferConfig
 				);
 			}
 		}
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 1350156140e4946599982a5057b2bab0bab276aa..ecb1d9791e764b8bc36515fa7a76def7ee25ca6c 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -117,8 +117,10 @@ int main(int argc, const char** argv) {
 			(swapchainHeight != core.getImageHeight(depthBuffer))) {
 			depthBuffer = core.createImage(
 					vk::Format::eD32Sfloat,
-					swapchainWidth,
-					swapchainHeight
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
 			);
 		}
 		
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index 9fb7247ec6da805acd2312c3889c45e4a95a3d48..1d0fd0e989c4b41d0f08feaa7f4c8ae0b8fa3d3c 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -103,8 +103,10 @@ int main(int argc, const char** argv) {
 			(swapchainHeight != core.getImageHeight(depthBuffer))) {
 			depthBuffer = core.createImage(
 					vk::Format::eD32Sfloat,
-					swapchainWidth,
-					swapchainHeight
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
 			);
 		}
 		
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 1b6533cfdd3726ad8b1901ae5bbb800d5c65b81d..e96f22eb665e681e9d4e1b100ad47fa60df267f3 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -150,15 +150,23 @@ int main(int argc, const char** argv) {
 	
 	vkcv::ImageHandle depthBuffer = core.createImage(
 			vk::Format::eD32Sfloat,
+			vkcv::ImageConfig(
+					swapchainExtent.width,
+					swapchainExtent.height
+			)
+	);
+	
+	vkcv::ImageConfig colorBufferConfig (
 			swapchainExtent.width,
 			swapchainExtent.height
 	);
 	
+	colorBufferConfig.setSupportingStorage(true);
+	colorBufferConfig.setSupportingColorAttachment(true);
+	
 	vkcv::ImageHandle colorBuffer = core.createImage(
 			colorFormat,
-			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, true, true
+			colorBufferConfig
 	);
 	
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
@@ -168,14 +176,22 @@ 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);
+		if ((swapchainWidth != swapchainExtent.width) ||
+			((swapchainHeight != swapchainExtent.height))) {
+			depthBuffer = core.createImage(
+					vk::Format::eD32Sfloat,
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
+			);
+			
+			colorBufferConfig.setWidth(swapchainWidth);
+			colorBufferConfig.setHeight(swapchainHeight);
 			
 			colorBuffer = core.createImage(
 					colorFormat,
-					swapchainExtent.width,
-					swapchainExtent.height,
-					1, false, true, true
+					colorBufferConfig
 			);
 			
 			swapchainExtent.width = swapchainWidth;
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index 26cfbbc38e2a190326b8a17adde5b8e4f44ec1cc..0a334932defb8ea3632d4047a4ca8e66e91faa20 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -301,33 +301,24 @@ 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;
+	vkcv::ImageConfig depthBufferConfig (width, height);
 
 	targets.depthBuffer = core.createImage(
 		AppConfig::depthBufferFormat,
-		width,
-		height,
-		1,
-		false
+		depthBufferConfig
 	);
+	
+	vkcv::ImageConfig bufferConfig (width, height);
+	bufferConfig.setSupportingColorAttachment(true);
 
 	targets.colorBuffer = core.createImage(
 		AppConfig::colorBufferFormat,
-		width,
-		height,
-		1,
-		false,
-		false,
-		true
+		bufferConfig
 	);
 
 	targets.motionBuffer = core.createImage(
 		AppConfig::motionBufferFormat,
-		width,
-		height,
-		1,
-		false,
-		false,
-		true
+		bufferConfig
 	);
 
 	return targets;
diff --git a/projects/indirect_dispatch/src/MotionBlurSetup.cpp b/projects/indirect_dispatch/src/MotionBlurSetup.cpp
index 0244c4ae9519ea6c6f818e024930e70c15e7a289..7589f77b80398e0bc1d7f1aec9b9570cc20acf3f 100644
--- a/projects/indirect_dispatch/src/MotionBlurSetup.cpp
+++ b/projects/indirect_dispatch/src/MotionBlurSetup.cpp
@@ -9,51 +9,37 @@ MotionBlurRenderTargets createRenderTargets(const uint32_t width, const uint32_t
 
 	// divide and ceil to int
 	const uint32_t motionMaxWidth  = (width  + (MotionBlurConfig::maxMotionTileSize - 1)) / MotionBlurConfig::maxMotionTileSize;
-	const uint32_t motionMaxheight = (height + (MotionBlurConfig::maxMotionTileSize - 1)) / MotionBlurConfig::maxMotionTileSize;
+	const uint32_t motionMaxHeight = (height + (MotionBlurConfig::maxMotionTileSize - 1)) / MotionBlurConfig::maxMotionTileSize;
 
+	vkcv::ImageConfig targetConfig (motionMaxWidth, motionMaxHeight);
+	targetConfig.setSupportingStorage(true);
+	
 	targets.motionMax = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
-		motionMaxWidth,
-		motionMaxheight,
-		1,
-		false,
-		true
+		targetConfig
 	);
 
 	targets.motionMaxNeighbourhood = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
-		motionMaxWidth,
-		motionMaxheight,
-		1,
-		false,
-		true
+		targetConfig
 	);
 
 	targets.motionMin = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
-		motionMaxWidth,
-		motionMaxheight,
-		1,
-		false,
-		true
+		targetConfig
 	);
 
 	targets.motionMinNeighbourhood = core.createImage(
 		MotionBlurConfig::motionVectorTileFormat,
-		motionMaxWidth,
-		motionMaxheight,
-		1,
-		false,
-		true
+		targetConfig
 	);
+	
+	vkcv::ImageConfig outputConfig (width, height);
+	outputConfig.setSupportingStorage(true);
 
 	targets.outputColor = core.createImage(
 		MotionBlurConfig::outputColorFormat,
-		width,
-		height,
-		1,
-		false,
-		true
+		outputConfig
 	);
 
 	return targets;
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index 5951c8c0653011810902a6e8499d02c96d07fd1c..f90fa0892982f68fa959671b5eb6f207aac72b65 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -528,7 +528,13 @@ 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);
+			depthBuffer = core.createImage(
+					vk::Format::eD32Sfloat,
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
+			);
 		}
   
 		cameraManager.update(dt);
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 512e1e6d1e6ea694289cb862ecae425b6bf8ee66..ceaeb43c891a09a7e730724bd22cdbea1b0b3f00 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -324,8 +324,10 @@ int main(int argc, const char** argv) {
 			(swapchainHeight != core.getImageHeight(depthBuffer))) {
 			depthBuffer = core.createImage(
 					vk::Format::eD32Sfloat,
-					swapchainWidth,
-					swapchainHeight
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
 			);
 		}
 		
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index 00bb497b9798064c4b5ac449d6bac8495a1783e8..7f9e9fb7e12dd9c5e2437f2367d0f95eea67a0de 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -208,11 +208,17 @@ int main(int argc, const char **argv) {
 
 	const auto swapchainExtent = core.getSwapchainExtent(window.getSwapchain());
 	
+	vkcv::ImageConfig colorBufferConfig (
+			swapchainExtent.width,
+			swapchainExtent.height
+	);
+	
+	colorBufferConfig.setSupportingStorage(true);
+	colorBufferConfig.setSupportingColorAttachment(true);
+	
     vkcv::ImageHandle colorBuffer = core.createImage(
 			colorFormat,
-			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, true, true
+			colorBufferConfig
 	);
 	
 	vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core);
@@ -237,11 +243,12 @@ int main(int argc, const char **argv) {
 				 uint32_t swapchainWidth, uint32_t swapchainHeight) {
 		if ((core.getImageWidth(colorBuffer) != swapchainWidth) ||
 			(core.getImageHeight(colorBuffer) != swapchainHeight)) {
+			colorBufferConfig.setWidth(swapchainWidth);
+			colorBufferConfig.setHeight(swapchainHeight);
+			
 			colorBuffer = core.createImage(
 					colorFormat,
-					swapchainWidth,
-					swapchainHeight,
-					1, false, true, true
+					colorBufferConfig
 			);
 		}
 
diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp
index 53f52c3d724b8db14641108d9b8a0e33e1844600..75ee36b2ac232e20d7baf29db34909dee67cca00 100644
--- a/projects/path_tracer/src/main.cpp
+++ b/projects/path_tracer/src/main.cpp
@@ -63,24 +63,23 @@ int main(int argc, const char** argv) {
 			initialHeight,
 			true
 	);
+	
+	vkcv::ImageConfig imageConfig (
+			initialWidth,
+			initialHeight
+	);
+	
+	imageConfig.setSupportingStorage(true);
 
 	// images
 	vkcv::ImageHandle outputImage = core.createImage(
 		vk::Format::eR32G32B32A32Sfloat,
-		initialWidth,
-		initialHeight,
-		1,
-		false,
-		true
+		imageConfig
 	);
 
 	vkcv::ImageHandle meanImage = core.createImage(
 		vk::Format::eR32G32B32A32Sfloat,
-		initialWidth,
-		initialHeight,
-		1,
-		false,
-		true
+		imageConfig
 	);
 
 	vkcv::shader::GLSLCompiler compiler;
@@ -248,25 +247,19 @@ 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 != widthPrevious || swapchainHeight != heightPrevious) {
+		if ((swapchainWidth != widthPrevious) || (swapchainHeight != heightPrevious)) {
+			imageConfig.setWidth(swapchainWidth);
+			imageConfig.setHeight(swapchainHeight);
 
 			// resize images
 			outputImage = core.createImage(
 				vk::Format::eR32G32B32A32Sfloat,
-				swapchainWidth,
-				swapchainHeight,
-				1,
-				false,
-				true
+				imageConfig
 			);
 
 			meanImage = core.createImage(
 				vk::Format::eR32G32B32A32Sfloat,
-				swapchainWidth,
-				swapchainHeight,
-				1,
-				false,
-				true
+				imageConfig
 			);
 
 			// update descriptor sets
diff --git a/projects/rtx_ambient_occlusion/src/main.cpp b/projects/rtx_ambient_occlusion/src/main.cpp
index f5d8a46feefd070967d0f68742ad0c3b2749f160..2e999baee212aa6d9da8ca03d2649bafe69eccb8 100644
--- a/projects/rtx_ambient_occlusion/src/main.cpp
+++ b/projects/rtx_ambient_occlusion/src/main.cpp
@@ -101,8 +101,10 @@ int main(int argc, const char** argv) {
 			((swapchainHeight != core.getImageHeight(depthBuffer)))) {
 			depthBuffer = core.createImage(
 					vk::Format::eD32Sfloat,
-					swapchainWidth,
-					swapchainHeight
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
 			);
 		}
 		
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index 043d135257ce63398ec34e5f6d47e4f4ffd6c61d..72cc9995dffd4ef8c938820f2678fac29c54e5ee 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -222,11 +222,17 @@ int main(int argc, const char **argv) {
 
 	const auto swapchainExtent = core.getSwapchainExtent(window.getSwapchain());
 	
+	vkcv::ImageConfig colorBufferConfig (
+			swapchainExtent.width,
+			swapchainExtent.height
+	);
+	
+	colorBufferConfig.setSupportingStorage(true);
+	colorBufferConfig.setSupportingColorAttachment(true);
+	
     vkcv::ImageHandle colorBuffer = core.createImage(
 			colorFormat,
-			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, true, true
+			colorBufferConfig
 	);
 	
 	vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core);
@@ -245,11 +251,12 @@ int main(int argc, const char **argv) {
 				 uint32_t swapchainWidth, uint32_t swapchainHeight) {
 		if ((core.getImageWidth(colorBuffer) != swapchainWidth) ||
 			(core.getImageHeight(colorBuffer) != swapchainHeight)) {
+			colorBufferConfig.setWidth(swapchainWidth);
+			colorBufferConfig.setHeight(swapchainHeight);
+			
 			colorBuffer = core.createImage(
 					colorFormat,
-					swapchainWidth,
-					swapchainHeight,
-					1, false, true, true
+					colorBufferConfig
 			);
 		}
 
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index ac2b2b6a19c23e039178da43705a4f1033fa6682..fecdaf98b8429dcb18c8aec811ce40c24eb5d0f4 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -387,48 +387,69 @@ int main(int argc, const char** argv) {
 	skyPipeConfig.setWritingDepth(false);
 
 	vkcv::GraphicsPipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
+	
+	vkcv::ImageConfig depthBufferConfig (
+			swapchainExtent.width,
+			swapchainExtent.height
+	);
+	
+	depthBufferConfig.setMultisampling(msaa);
 
 	// render targets
 	vkcv::ImageHandle depthBuffer = core.createImage(
 			depthBufferFormat,
+			depthBufferConfig
+	);
+	
+	const bool colorBufferRequiresStorage = !usingMsaa;
+	
+	vkcv::ImageConfig colorBufferConfig (
 			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, false, false, msaa
+			swapchainExtent.height
 	);
+	
+	colorBufferConfig.setSupportingStorage(colorBufferRequiresStorage);
+	colorBufferConfig.setSupportingColorAttachment(true);
+	colorBufferConfig.setMultisampling(msaa);
 
-    const bool colorBufferRequiresStorage = !usingMsaa;
 	vkcv::ImageHandle colorBuffer = core.createImage(
 			colorBufferFormat,
+			colorBufferConfig
+	);
+	
+	vkcv::ImageConfig resolveBufferConfig (
 			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, colorBufferRequiresStorage, true, msaa
+			swapchainExtent.height
 	);
+	
+	resolveBufferConfig.setSupportingStorage(true);
+	resolveBufferConfig.setSupportingColorAttachment(true);
 
 	vkcv::ImageHandle resolvedColorBuffer;
 	if (usingMsaa) {
 		resolvedColorBuffer = core.createImage(
 				colorBufferFormat,
-				swapchainExtent.width,
-				swapchainExtent.height,
-				1, false, true, true
+				resolveBufferConfig
 		);
-	}
-	else {
+	} else {
 		resolvedColorBuffer = colorBuffer;
 	}
 	
+	vkcv::ImageConfig swapBufferConfig (
+			swapchainExtent.width,
+			swapchainExtent.height
+	);
+	
+	swapBufferConfig.setSupportingStorage(true);
+	
 	vkcv::ImageHandle swapBuffer = core.createImage(
 			colorBufferFormat,
-			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, true
+			swapBufferConfig
 	);
 	
 	vkcv::ImageHandle swapBuffer2 = core.createImage(
 			colorBufferFormat,
-			swapchainExtent.width,
-			swapchainExtent.height,
-			1, false, true
+			swapBufferConfig
 	);
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
@@ -656,40 +677,48 @@ int main(int argc, const char** argv) {
 				core.writeDescriptorSet(materialDescriptorSets[i], setWrites);
 			}
 			
+			depthBufferConfig.setWidth(fsrWidth);
+			depthBufferConfig.setHeight(fsrHeight);
+			
 			depthBuffer = core.createImage(
 					depthBufferFormat,
-					fsrWidth, fsrHeight, 1,
-					false, false, false,
-					msaa
+					depthBufferConfig
 			);
 			
+			colorBufferConfig.setWidth(fsrWidth);
+			colorBufferConfig.setHeight(fsrHeight);
+			
 			colorBuffer = core.createImage(
 					colorBufferFormat,
-					fsrWidth, fsrHeight, 1,
-					false, colorBufferRequiresStorage, true,
-					msaa
+					colorBufferConfig
 			);
 
 			if (usingMsaa) {
+				resolveBufferConfig.setWidth(fsrWidth);
+				resolveBufferConfig.setHeight(fsrHeight);
+				
 				resolvedColorBuffer = core.createImage(
 						colorBufferFormat,
-						fsrWidth, fsrHeight, 1,
-						false, true, true
+						resolveBufferConfig
 				);
 			} else {
 				resolvedColorBuffer = colorBuffer;
 			}
 			
+			swapBufferConfig.setWidth(fsrWidth);
+			swapBufferConfig.setHeight(fsrHeight);
+			
 			swapBuffer = core.createImage(
 					colorBufferFormat,
-					fsrWidth, fsrHeight, 1,
-					false, true
+					swapBufferConfig
 			);
 			
+			swapBufferConfig.setWidth(swapchainWidth);
+			swapBufferConfig.setHeight(swapchainHeight);
+			
 			swapBuffer2 = core.createImage(
 					colorBufferFormat,
-					swapchainWidth, swapchainHeight, 1,
-					false, true
+					swapBufferConfig
 			);
 		}
 
@@ -955,8 +984,8 @@ int main(int argc, const char** argv) {
 			upscaling2.setSharpness(sharpness);
 
 			if (ImGui::Button("Reload forward pass")) {
-
 				vkcv::ShaderProgram newForwardProgram;
+				
 				compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"),
 					[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
 					newForwardProgram.addShader(shaderStage, path);
@@ -973,8 +1002,8 @@ int main(int argc, const char** argv) {
 					forwardPipeline = newPipeline;
 				}
 			}
+			
 			if (ImGui::Button("Reload tonemapping")) {
-
 				vkcv::ShaderProgram newProgram;
 				compiler.compile(vkcv::ShaderStage::COMPUTE, std::filesystem::path("assets/shaders/tonemapping.comp"),
 					[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
@@ -990,6 +1019,7 @@ int main(int argc, const char** argv) {
 					tonemappingPipeline = newPipeline;
 				}
 			}
+			
 			ImGui::End();
 		}
 
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 1c3eb776b43d29ffe53aa62a03e3bc06fe145767..9a5548b7189030e3a3296edb0486cef5c9225dd1 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -309,8 +309,10 @@ int main(int argc, const char **argv) {
 	
 	vkcv::ImageHandle depthBuffer = core.createImage(
 			vk::Format::eD32Sfloat,
-			swapchainExtent.width,
-			swapchainExtent.height
+			vkcv::ImageConfig(
+					swapchainExtent.width,
+					swapchainExtent.height
+			)
 	);
 	
 	vkcv::Image grid = vkcv::image(
@@ -605,8 +607,10 @@ int main(int argc, const char **argv) {
 		if ((swapchainWidth != swapchainExtent.width) || ((swapchainHeight != swapchainExtent.height))) {
 			depthBuffer = core.createImage(
 					vk::Format::eD32Sfloat,
-					swapchainWidth,
-					swapchainHeight
+					vkcv::ImageConfig(
+							swapchainWidth,
+							swapchainHeight
+					)
 			);
 			
 			swapchainExtent.width = swapchainWidth;
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 6ccf1de841996c85905689f0ef45e3dbdcf7c285..99a516ad96e6feaf90990f1be8747ff967ada9ab 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -859,17 +859,24 @@ namespace vkcv {
 											   mipLodBias, borderColor);
 	}
 
-	ImageHandle 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,
+								  const ImageConfig& config,
+								  bool createMipChain) {
 		uint32_t mipCount = 1;
 		if (createMipChain) {
-			mipCount =
-				1 + (uint32_t)std::floor(std::log2(std::max(width, std::max(height, depth))));
+			mipCount = 1 + (uint32_t) std::floor(
+					std::log2(std::max(
+							config.getWidth(),
+							std::max(config.getHeight(), config.getDepth()))
+					)
+			);
 		}
 
-		return m_ImageManager->createImage(width, height, depth, format, mipCount, supportStorage,
-										   supportColorAttachment, multisampling);
+		return m_ImageManager->createImage(
+				format,
+				mipCount,
+				config
+		);
 	}
 
 	void Core::fillImage(const ImageHandle &image, const void* data, size_t size) {
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index 6e5b5fc1b3efbbcf4203e9825230eca20cbf55e5..63a395e7f8f0e590d6b2dbdde3f8d527c4d8c87b 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -75,9 +75,22 @@ namespace vkcv {
 	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));
+		ImageConfig config (width, height, depth);
+		config.setSupportingStorage(supportStorage);
+		config.setSupportingColorAttachment(supportColorAttachment);
+		config.setMultisampling(multisampling);
+		return image(core, format, config, createMipChain);
+	}
+	
+	Image image(Core &core, vk::Format format, const ImageConfig &config, bool createMipChain) {
+		return Image(
+				&core,
+				core.createImage(
+						format,
+						config,
+						createMipChain
+				)
+		);
 	}
 
 } // namespace vkcv
diff --git a/src/vkcv/ImageConfig.cpp b/src/vkcv/ImageConfig.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d95a7ff6bb843b4405f119d6bec0e50a06658e0e
--- /dev/null
+++ b/src/vkcv/ImageConfig.cpp
@@ -0,0 +1,80 @@
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Image.cpp
+ * @brief Structure for image configuration
+ */
+#include "vkcv/ImageConfig.hpp"
+
+namespace vkcv {
+	
+	ImageConfig::ImageConfig(uint32_t width,
+							 uint32_t height,
+							 uint32_t depth)
+	: m_width(width),
+	  m_height(height),
+	  m_depth(depth),
+	  
+	  m_supportStorage(false),
+	  m_supportColorAttachment(false),
+	  m_cubeMapImage(false),
+	  
+	  m_msaa(Multisampling::None)
+	{}
+	
+	uint32_t ImageConfig::getWidth() const {
+		return m_width;
+	}
+	
+	void ImageConfig::setWidth(uint32_t width) {
+		m_width = width;
+	}
+	
+	uint32_t ImageConfig::getHeight() const {
+		return m_height;
+	}
+	
+	void ImageConfig::setHeight(uint32_t height) {
+		m_height = height;
+	}
+	
+	uint32_t ImageConfig::getDepth() const {
+		return m_depth;
+	}
+	
+	void ImageConfig::setDepth(uint32_t depth) {
+		m_depth = depth;
+	}
+	
+	bool ImageConfig::isSupportingStorage() const {
+		return m_supportStorage;
+	}
+	
+	void ImageConfig::setSupportingStorage(bool supportStorage) {
+		m_supportStorage = supportStorage;
+	}
+	
+	bool ImageConfig::isSupportingColorAttachment() const {
+		return m_supportColorAttachment;
+	}
+	
+	void ImageConfig::setSupportingColorAttachment(bool supportColorAttachment) {
+		m_supportColorAttachment = supportColorAttachment;
+	}
+	
+	bool ImageConfig::isCubeMapImage() const {
+		return m_cubeMapImage;
+	}
+	
+	void ImageConfig::setCubeMapImage(bool cubeMapImage) {
+		m_cubeMapImage = cubeMapImage;
+	}
+	
+	Multisampling ImageConfig::getMultisampling() const {
+		return m_msaa;
+	}
+	
+	void ImageConfig::setMultisampling(Multisampling msaa) {
+		m_msaa = msaa;
+	}
+	
+}
\ No newline at end of file
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 993243cb5644dd3a1527f3c50efadc9fdc9aa299..56e2bc91e404c6205e44a69affce081a994fee0e 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -153,21 +153,22 @@ namespace vkcv {
 		}
 	}
 
-	ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth,
-										  vk::Format format, uint32_t mipCount, bool supportStorage,
-										  bool supportColorAttachment, Multisampling msaa) {
+	ImageHandle ImageManager::createImage(vk::Format format,
+										  uint32_t mipCount,
+										  const ImageConfig& config) {
 		const vk::PhysicalDevice &physicalDevice = getCore().getContext().getPhysicalDevice();
-
 		const vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format);
 
 		vk::ImageCreateFlags createFlags;
-		vk::ImageUsageFlags imageUsageFlags =
-			(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst
-			 | vk::ImageUsageFlagBits::eTransferSrc);
+		vk::ImageUsageFlags imageUsageFlags = (
+				vk::ImageUsageFlagBits::eSampled |
+				vk::ImageUsageFlagBits::eTransferDst |
+				vk::ImageUsageFlagBits::eTransferSrc
+		);
 
 		vk::ImageTiling imageTiling = vk::ImageTiling::eOptimal;
 
-		if (supportStorage) {
+		if (config.isSupportingStorage()) {
 			imageUsageFlags |= vk::ImageUsageFlagBits::eStorage;
 
 			if (!(formatProperties.optimalTilingFeatures
@@ -180,7 +181,7 @@ namespace vkcv {
 			}
 		}
 
-		if (supportColorAttachment) {
+		if (config.isSupportingColorAttachment()) {
 			imageUsageFlags |= vk::ImageUsageFlagBits::eColorAttachment;
 		}
 
@@ -195,8 +196,8 @@ namespace vkcv {
 		vk::ImageType imageType = vk::ImageType::e3D;
 		vk::ImageViewType imageViewType = vk::ImageViewType::e3D;
 
-		if (depth <= 1) {
-			if (height <= 1) {
+		if (config.getDepth() <= 1) {
+			if (config.getHeight() <= 1) {
 				imageType = vk::ImageType::e1D;
 				imageViewType = vk::ImageViewType::e1D;
 			} else {
@@ -209,7 +210,11 @@ namespace vkcv {
 			imageType = vk::ImageType::e2D;
 			imageViewType = vk::ImageViewType::e2D;
 		}
-
+		
+		if (config.isCubeMapImage()) {
+			imageViewType = vk::ImageViewType::eCube;
+			createFlags |= vk::ImageCreateFlagBits::eCubeCompatible;
+		} else
 		if (vk::ImageType::e3D == imageType) {
 			createFlags |= vk::ImageCreateFlagBits::e2DArrayCompatible;
 		}
@@ -221,27 +226,53 @@ namespace vkcv {
 			imageTiling = vk::ImageTiling::eLinear;
 		}
 
-		const vk::ImageFormatProperties imageFormatProperties =
-			physicalDevice.getImageFormatProperties(format, imageType, imageTiling,
-													imageUsageFlags);
+		const vk::ImageFormatProperties imageFormatProperties = (
+			physicalDevice.getImageFormatProperties(
+					format,
+					imageType,
+					imageTiling,
+					imageUsageFlags
+			)
+		);
 
 		const uint32_t arrayLayers = std::min<uint32_t>(1, imageFormatProperties.maxArrayLayers);
 
 		const vk::ImageCreateInfo imageCreateInfo(
-			createFlags, imageType, format, vk::Extent3D(width, height, depth), mipCount,
-			arrayLayers, msaaToSampleCountFlagBits(msaa), imageTiling, imageUsageFlags,
-			vk::SharingMode::eExclusive, {}, vk::ImageLayout::eUndefined);
+			createFlags,
+			imageType,
+			format,
+			vk::Extent3D(
+					config.getWidth(),
+					config.getHeight(),
+					config.getDepth()
+			),
+			mipCount,
+			arrayLayers,
+			msaaToSampleCountFlagBits(
+					config.getMultisampling()
+			),
+			imageTiling,
+			imageUsageFlags,
+			vk::SharingMode::eExclusive,
+			{},
+			vk::ImageLayout::eUndefined
+		);
 
 		auto imageAllocation = allocator.createImage(
 			imageCreateInfo,
-			vma::AllocationCreateInfo(vma::AllocationCreateFlags(), vma::MemoryUsage::eGpuOnly,
-									  vk::MemoryPropertyFlagBits::eDeviceLocal,
-									  vk::MemoryPropertyFlagBits::eDeviceLocal, 0, vma::Pool(),
-									  nullptr));
+			vma::AllocationCreateInfo(
+					vma::AllocationCreateFlags(),
+					vma::MemoryUsage::eGpuOnly,
+					vk::MemoryPropertyFlagBits::eDeviceLocal,
+					vk::MemoryPropertyFlagBits::eDeviceLocal,
+					0,
+					vma::Pool(),
+					nullptr
+			)
+		);
 
 		vk::Image image = imageAllocation.first;
 		vma::Allocation allocation = imageAllocation.second;
-
 		vk::ImageAspectFlags aspectFlags;
 
 		if (isDepthFormat) {
@@ -257,37 +288,65 @@ namespace vkcv {
 
 		for (uint32_t mip = 0; mip < mipCount; mip++) {
 			const vk::ImageViewCreateInfo imageViewCreateInfo(
-				{}, image, imageViewType, format,
+				{},
+				image,
+				imageViewType,
+				format,
 				vk::ComponentMapping(
-					vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
-					vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity),
-				vk::ImageSubresourceRange(aspectFlags, mip, mipCount - mip, 0, arrayLayers));
+					vk::ComponentSwizzle::eIdentity,
+					vk::ComponentSwizzle::eIdentity,
+					vk::ComponentSwizzle::eIdentity,
+					vk::ComponentSwizzle::eIdentity
+				),
+				vk::ImageSubresourceRange(
+						aspectFlags,
+						mip,
+						mipCount - mip,
+						0,
+						arrayLayers
+				)
+			);
 
 			views.push_back(device.createImageView(imageViewCreateInfo));
 		}
 
 		for (uint32_t mip = 0; mip < mipCount; mip++) {
 			const vk::ImageViewCreateInfo imageViewCreateInfo(
-				{}, image, vk::ImageViewType::e2DArray, format,
+				{},
+				image,
+				vk::ImageViewType::e2DArray,
+				format,
 				vk::ComponentMapping(
-					vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
-					vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity),
-				vk::ImageSubresourceRange(aspectFlags, mip, 1, 0, arrayLayers));
+					vk::ComponentSwizzle::eIdentity,
+					vk::ComponentSwizzle::eIdentity,
+					vk::ComponentSwizzle::eIdentity,
+					vk::ComponentSwizzle::eIdentity
+				),
+				vk::ImageSubresourceRange(
+						aspectFlags,
+						mip,
+						1,
+						0,
+						arrayLayers
+				)
+			);
 
 			arrayViews.push_back(device.createImageView(imageViewCreateInfo));
 		}
 
-		return add({ image, allocation,
-
-					 views, arrayViews,
-
-					 width, height, depth,
-
-					 format, arrayLayers, vk::ImageLayout::eUndefined, supportStorage });
-	}
-
-	ImageHandle ImageManager::createSwapchainImage() const {
-		return ImageHandle::createSwapchainImageHandle();
+		return add({
+			image,
+			allocation,
+			views,
+			arrayViews,
+			config.getWidth(),
+			config.getHeight(),
+			config.getDepth(),
+			format,
+			arrayLayers,
+			vk::ImageLayout::eUndefined,
+			config.isSupportingStorage()
+		});
 	}
 
 	vk::Image ImageManager::getVulkanImage(const ImageHandle &handle) const {
@@ -562,17 +621,19 @@ namespace vkcv {
 		assert(images.size() == views.size());
 		m_swapchainImages.clear();
 		for (size_t i = 0; i < images.size(); i++) {
-			m_swapchainImages.push_back({ images [i],
-										  nullptr,
-										  { views [i] },
-										  {},
-										  width,
-										  height,
-										  1,
-										  format,
-										  1,
-										  vk::ImageLayout::eUndefined,
-										  false });
+			m_swapchainImages.push_back({
+				images [i],
+				nullptr,
+				{ views [i] },
+				{},
+				width,
+				height,
+				1,
+				format,
+				1,
+				vk::ImageLayout::eUndefined,
+				false
+			});
 		}
 	}
 
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index ddc44f9b519061a7881eb0904034da2276b82a12..5a91d962370071ac9c557ad877fd26268e1e2b2a 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -10,7 +10,7 @@
 
 #include "BufferManager.hpp"
 #include "HandleManager.hpp"
-#include "vkcv/Multisampling.hpp"
+#include "vkcv/ImageConfig.hpp"
 
 namespace vkcv {
 
@@ -86,12 +86,9 @@ namespace vkcv {
 
 		~ImageManager() noexcept override;
 
-		[[nodiscard]] ImageHandle createImage(uint32_t width, uint32_t height, uint32_t depth,
-											  vk::Format format, uint32_t mipCount,
-											  bool supportStorage, bool supportColorAttachment,
-											  Multisampling msaa);
-
-		[[nodiscard]] ImageHandle createSwapchainImage() const;
+		[[nodiscard]] ImageHandle createImage(vk::Format format,
+											  uint32_t mipCount,
+											  const ImageConfig& config);
 
 		[[nodiscard]] vk::Image getVulkanImage(const ImageHandle &handle) const;