diff --git a/src/common/image.cpp b/src/common/image.cpp index f7257e5b6..0a8a6eebd 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -5,6 +5,7 @@ #include "path.h" #include "scoped_guard.h" #include "stb_image.h" +#include "stb_image_resize.h" #include "stb_image_write.h" #include "string_util.h" Log_SetChannel(Image); @@ -167,6 +168,42 @@ std::optional> RGBA8Image::SaveToBuffer(const char* filename, in return ret; } +void RGBA8Image::Resize(u32 new_width, u32 new_height) +{ + if (m_width == new_width && m_height == new_height) + return; + + std::vector resized_texture_data(new_width * new_height); + u32 resized_texture_stride = sizeof(u32) * new_width; + if (!stbir_resize_uint8(reinterpret_cast(m_pixels.data()), m_width, m_height, GetPitch(), + reinterpret_cast(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(src_image->m_pixels.data()), src_image->m_width, + src_image->m_height, src_image->GetPitch(), reinterpret_cast(m_pixels.data()), new_width, + new_height, GetPitch(), 4)) + { + Panic("stbir_resize_uint8 failed"); + return; + } +} + #if 0 static bool PNGCommonLoader(RGBA8Image* image, png_structp png_ptr, png_infop info_ptr, std::vector& new_data, @@ -567,7 +604,7 @@ bool STBBufferSaverPNG(const RGBA8Image& image, std::vector* buffer, int qua }; 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* 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(), - image.GetByteStride()) != 0); + image.GetPitch()) != 0); } bool STBFileSaverJPEG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality) diff --git a/src/common/image.h b/src/common/image.h index c8876a21e..0167d2058 100644 --- a/src/common/image.h +++ b/src/common/image.h @@ -49,7 +49,7 @@ public: ALWAYS_INLINE bool IsValid() const { return (m_width > 0 && m_height > 0); } ALWAYS_INLINE u32 GetWidth() const { return m_width; } 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 PixelType* GetPixels() { return m_pixels.data(); } 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, std::FILE* fp, int quality = DEFAULT_SAVE_QUALITY) const; std::optional> 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 diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index 56d959522..4c424e4c6 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -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, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, tex->GetPixels(), - tex->GetByteStride(), true)) + tex->GetPitch(), true)) { return false; } @@ -767,13 +767,13 @@ bool GPU_HW_D3D11::BlitVRAMReplacementTexture(const TextureReplacementTexture* t 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(tex->GetPixels()); u8* dst_ptr = static_cast(sr.pData); for (u32 i = 0; i < tex->GetHeight(); i++) { std::memcpy(dst_ptr, src_ptr, copy_size); - src_ptr += tex->GetByteStride(); + src_ptr += tex->GetPitch(); dst_ptr += sr.RowPitch; } diff --git a/src/core/gpu_hw_d3d12.cpp b/src/core/gpu_hw_d3d12.cpp index 0b3676534..e4228a72d 100644 --- a/src/core/gpu_hw_d3d12.cpp +++ b/src/core/gpu_hw_d3d12.cpp @@ -800,7 +800,7 @@ bool GPU_HW_D3D12::BlitVRAMReplacementTexture(const TextureReplacementTexture* t // buffer -> texture 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.CommitMemory(required_size); m_vram_write_replacement_texture.CopyFromBuffer(0, 0, tex->GetWidth(), tex->GetHeight(), copy_pitch, diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp index 3fb5f25c9..d9f65d4fa 100644 --- a/src/core/gpu_hw_vulkan.cpp +++ b/src/core/gpu_hw_vulkan.cpp @@ -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(), - tex->GetByteStride()); + tex->GetPitch()); // texture -> vram const VkImageBlit blit = { diff --git a/src/core/system.cpp b/src/core/system.cpp index 1f0d4fe2a..11fa4bd64 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -4217,7 +4217,7 @@ void System::UpdateSoftwareCursor() 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); } else diff --git a/src/frontend-common/imgui_fullscreen.cpp b/src/frontend-common/imgui_fullscreen.cpp index fe3755e45..08933f9b6 100644 --- a/src/frontend-common/imgui_fullscreen.cpp +++ b/src/frontend-common/imgui_fullscreen.cpp @@ -266,7 +266,7 @@ std::shared_ptr ImGuiFullscreen::UploadTexture(const char* p { std::unique_ptr texture = g_host_display->CreateTexture(image.GetWidth(), image.GetHeight(), 1, 1, 1, HostDisplayPixelFormat::RGBA8, - image.GetPixels(), image.GetByteStride()); + image.GetPixels(), image.GetPitch()); if (!texture) { Log_ErrorPrintf("failed to create %ux%u texture for resource", image.GetWidth(), image.GetHeight());