Add to_file function for image

This commit is contained in:
hodasemi 2023-01-20 13:30:36 +01:00
parent 530f0d4e03
commit 69ec318579

View file

@ -5,6 +5,7 @@ use crate::prelude::*;
use anyhow::Result; use anyhow::Result;
use std::cmp; use std::cmp;
use std::path::Path;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
@ -776,6 +777,88 @@ impl Image {
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL => VK_ACCESS_SHADER_READ_BIT.into(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL => VK_ACCESS_SHADER_READ_BIT.into(),
} }
} }
pub fn to_file(self: &Arc<Image>, path: impl AsRef<Path>) -> Result<()> {
let buffer = self.copy_image_to_buffer()?;
let memory = buffer.map_complete()?;
let image = image::RgbaImage::from_raw(
self.width,
self.height,
memory.iter().map(|&v| v).collect(),
)
.ok_or(anyhow::anyhow!(
"failed to create image from raw while saving to file: {:?}",
path.as_ref()
))?;
image.save(path)?;
Ok(())
}
fn copy_image_to_buffer(self: &Arc<Image>) -> Result<Arc<Buffer<u8>>> {
let buffer = Buffer::builder()
.set_usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.set_memory_usage(MemoryUsage::GpuToCpu)
.set_size((self.width * self.height * 4) as VkDeviceSize)
.build(self.device.clone())?;
let command_buffer =
CommandBuffer::new_primary().build(self.device.clone(), self.queue.clone())?;
SingleSubmit::builder(&command_buffer, &self.queue, |recorder| {
// copy info for copying the content of the buffer into the image
let buffer_image_copy = VkBufferImageCopy {
bufferOffset: 0,
bufferRowLength: 0,
bufferImageHeight: 0,
imageSubresource: VkImageSubresourceLayers {
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
mipLevel: 0,
baseArrayLayer: 0,
layerCount: 1,
},
imageOffset: VkOffset3D { x: 0, y: 0, z: 0 },
imageExtent: VkExtent3D {
width: self.width(),
height: self.height(),
depth: 1,
},
};
// subresource information
let subresource_range = VkImageSubresourceRange {
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
baseMipLevel: 0,
levelCount: 1,
baseArrayLayer: 0,
layerCount: 1,
};
let current_layout = self.image_layout();
recorder.set_image_layout(
self,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
subresource_range.clone(),
);
recorder.copy_image_to_buffer(
self,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
&buffer,
&[buffer_image_copy],
);
recorder.set_image_layout(self, current_layout, subresource_range);
Ok(())
})
.submit()?;
Ok(buffer)
}
} }
impl VulkanDevice for Image { impl VulkanDevice for Image {