Common/Image: Add resize methods

This commit is contained in:
Connor McLaughlin 2022-09-26 21:35:29 +10:00
parent e3a327f7a2
commit 84917ec6aa
7 changed files with 50 additions and 10 deletions

View file

@ -5,6 +5,7 @@
#include "path.h" #include "path.h"
#include "scoped_guard.h" #include "scoped_guard.h"
#include "stb_image.h" #include "stb_image.h"
#include "stb_image_resize.h"
#include "stb_image_write.h" #include "stb_image_write.h"
#include "string_util.h" #include "string_util.h"
Log_SetChannel(Image); Log_SetChannel(Image);
@ -167,6 +168,42 @@ std::optional<std::vector<u8>> RGBA8Image::SaveToBuffer(const char* filename, in
return ret; return ret;
} }
void RGBA8Image::Resize(u32 new_width, u32 new_height)
{
if (m_width == new_width && m_height == new_height)
return;
std::vector<u32> resized_texture_data(new_width * new_height);
u32 resized_texture_stride = sizeof(u32) * new_width;
if (!stbir_resize_uint8(reinterpret_cast<u8*>(m_pixels.data()), m_width, m_height, GetPitch(),
reinterpret_cast<u8*>(resized_texture_data.data()), new_width, new_height,
resized_texture_stride, 4))
{
Panic("stbir_resize_uint8 failed");
return;
}
SetPixels(new_width, new_height, std::move(resized_texture_data));
}
void RGBA8Image::Resize(const RGBA8Image* src_image, u32 new_width, u32 new_height)
{
if (src_image->m_width == new_width && src_image->m_height == new_height)
{
SetPixels(src_image->m_width, src_image->m_height, src_image->m_pixels.data());
return;
}
SetSize(new_width, new_height);
if (!stbir_resize_uint8(reinterpret_cast<const u8*>(src_image->m_pixels.data()), src_image->m_width,
src_image->m_height, src_image->GetPitch(), reinterpret_cast<u8*>(m_pixels.data()), new_width,
new_height, GetPitch(), 4))
{
Panic("stbir_resize_uint8 failed");
return;
}
}
#if 0 #if 0
static bool PNGCommonLoader(RGBA8Image* image, png_structp png_ptr, png_infop info_ptr, std::vector<u32>& new_data, static bool PNGCommonLoader(RGBA8Image* image, png_structp png_ptr, png_infop info_ptr, std::vector<u32>& new_data,
@ -567,7 +604,7 @@ bool STBBufferSaverPNG(const RGBA8Image& image, std::vector<u8>* buffer, int qua
}; };
return (stbi_write_png_to_func(write_func, buffer, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(), return (stbi_write_png_to_func(write_func, buffer, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(),
image.GetByteStride()) != 0); image.GetPitch()) != 0);
} }
bool STBBufferSaverJPEG(const RGBA8Image& image, std::vector<u8>* buffer, int quality) bool STBBufferSaverJPEG(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
@ -590,7 +627,7 @@ bool STBFileSaverPNG(const RGBA8Image& image, const char* filename, std::FILE* f
}; };
return (stbi_write_png_to_func(write_func, fp, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(), return (stbi_write_png_to_func(write_func, fp, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(),
image.GetByteStride()) != 0); image.GetPitch()) != 0);
} }
bool STBFileSaverJPEG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality) bool STBFileSaverJPEG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)

View file

@ -49,7 +49,7 @@ public:
ALWAYS_INLINE bool IsValid() const { return (m_width > 0 && m_height > 0); } ALWAYS_INLINE bool IsValid() const { return (m_width > 0 && m_height > 0); }
ALWAYS_INLINE u32 GetWidth() const { return m_width; } ALWAYS_INLINE u32 GetWidth() const { return m_width; }
ALWAYS_INLINE u32 GetHeight() const { return m_height; } ALWAYS_INLINE u32 GetHeight() const { return m_height; }
ALWAYS_INLINE u32 GetByteStride() const { return (sizeof(PixelType) * m_width); } ALWAYS_INLINE u32 GetPitch() const { return (sizeof(PixelType) * m_width); }
ALWAYS_INLINE const PixelType* GetPixels() const { return m_pixels.data(); } ALWAYS_INLINE const PixelType* GetPixels() const { return m_pixels.data(); }
ALWAYS_INLINE PixelType* GetPixels() { return m_pixels.data(); } ALWAYS_INLINE PixelType* GetPixels() { return m_pixels.data(); }
ALWAYS_INLINE const PixelType* GetRowPixels(u32 y) const { return &m_pixels[y * m_width]; } ALWAYS_INLINE const PixelType* GetRowPixels(u32 y) const { return &m_pixels[y * m_width]; }
@ -125,6 +125,9 @@ public:
bool SaveToFile(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const; bool SaveToFile(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const;
bool SaveToFile(const char* filename, std::FILE* fp, int quality = DEFAULT_SAVE_QUALITY) const; bool SaveToFile(const char* filename, std::FILE* fp, int quality = DEFAULT_SAVE_QUALITY) const;
std::optional<std::vector<u8>> SaveToBuffer(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const; std::optional<std::vector<u8>> SaveToBuffer(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const;
void Resize(u32 new_width, u32 new_height);
void Resize(const RGBA8Image* src_image, u32 new_width, u32 new_height);
}; };
} // namespace Common } // namespace Common

View file

@ -752,7 +752,7 @@ bool GPU_HW_D3D11::BlitVRAMReplacementTexture(const TextureReplacementTexture* t
{ {
if (!m_vram_replacement_texture.Create(m_device.Get(), tex->GetWidth(), tex->GetHeight(), 1, 1, 1, if (!m_vram_replacement_texture.Create(m_device.Get(), tex->GetWidth(), tex->GetHeight(), 1, 1, 1,
DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, tex->GetPixels(), DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, tex->GetPixels(),
tex->GetByteStride(), true)) tex->GetPitch(), true))
{ {
return false; return false;
} }
@ -767,13 +767,13 @@ bool GPU_HW_D3D11::BlitVRAMReplacementTexture(const TextureReplacementTexture* t
return false; return false;
} }
const u32 copy_size = std::min(tex->GetByteStride(), sr.RowPitch); const u32 copy_size = std::min(tex->GetPitch(), sr.RowPitch);
const u8* src_ptr = reinterpret_cast<const u8*>(tex->GetPixels()); const u8* src_ptr = reinterpret_cast<const u8*>(tex->GetPixels());
u8* dst_ptr = static_cast<u8*>(sr.pData); u8* dst_ptr = static_cast<u8*>(sr.pData);
for (u32 i = 0; i < tex->GetHeight(); i++) for (u32 i = 0; i < tex->GetHeight(); i++)
{ {
std::memcpy(dst_ptr, src_ptr, copy_size); std::memcpy(dst_ptr, src_ptr, copy_size);
src_ptr += tex->GetByteStride(); src_ptr += tex->GetPitch();
dst_ptr += sr.RowPitch; dst_ptr += sr.RowPitch;
} }

View file

@ -800,7 +800,7 @@ bool GPU_HW_D3D12::BlitVRAMReplacementTexture(const TextureReplacementTexture* t
// buffer -> texture // buffer -> texture
const u32 sb_offset = m_texture_replacment_stream_buffer.GetCurrentOffset(); const u32 sb_offset = m_texture_replacment_stream_buffer.GetCurrentOffset();
D3D12::Texture::CopyToUploadBuffer(tex->GetPixels(), tex->GetByteStride(), tex->GetHeight(), D3D12::Texture::CopyToUploadBuffer(tex->GetPixels(), tex->GetPitch(), tex->GetHeight(),
m_texture_replacment_stream_buffer.GetCurrentHostPointer(), copy_pitch); m_texture_replacment_stream_buffer.GetCurrentHostPointer(), copy_pitch);
m_texture_replacment_stream_buffer.CommitMemory(required_size); m_texture_replacment_stream_buffer.CommitMemory(required_size);
m_vram_write_replacement_texture.CopyFromBuffer(0, 0, tex->GetWidth(), tex->GetHeight(), copy_pitch, m_vram_write_replacement_texture.CopyFromBuffer(0, 0, tex->GetWidth(), tex->GetHeight(), copy_pitch,

View file

@ -1831,7 +1831,7 @@ bool GPU_HW_Vulkan::BlitVRAMReplacementTexture(const TextureReplacementTexture*
} }
m_vram_write_replacement_texture.Update(0, 0, tex->GetWidth(), tex->GetHeight(), 0, 0, tex->GetPixels(), m_vram_write_replacement_texture.Update(0, 0, tex->GetWidth(), tex->GetHeight(), 0, 0, tex->GetPixels(),
tex->GetByteStride()); tex->GetPitch());
// texture -> vram // texture -> vram
const VkImageBlit blit = { const VkImageBlit blit = {

View file

@ -4217,7 +4217,7 @@ void System::UpdateSoftwareCursor()
if (image && image->IsValid()) if (image && image->IsValid())
{ {
g_host_display->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetByteStride(), g_host_display->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetPitch(),
image_scale); image_scale);
} }
else else

View file

@ -266,7 +266,7 @@ std::shared_ptr<HostDisplayTexture> ImGuiFullscreen::UploadTexture(const char* p
{ {
std::unique_ptr<HostDisplayTexture> texture = std::unique_ptr<HostDisplayTexture> texture =
g_host_display->CreateTexture(image.GetWidth(), image.GetHeight(), 1, 1, 1, HostDisplayPixelFormat::RGBA8, g_host_display->CreateTexture(image.GetWidth(), image.GetHeight(), 1, 1, 1, HostDisplayPixelFormat::RGBA8,
image.GetPixels(), image.GetByteStride()); image.GetPixels(), image.GetPitch());
if (!texture) if (!texture)
{ {
Log_ErrorPrintf("failed to create %ux%u texture for resource", image.GetWidth(), image.GetHeight()); Log_ErrorPrintf("failed to create %ux%u texture for resource", image.GetWidth(), image.GetHeight());