Common: Add an image helper class

This commit is contained in:
Connor McLaughlin 2020-07-01 00:34:22 +10:00
parent 78cf890c6c
commit 7d88bba764
5 changed files with 152 additions and 9 deletions

View File

@ -28,6 +28,8 @@ add_library(common
fifo_queue.h
file_system.cpp
file_system.h
image.cpp
image.h
gl/context.cpp
gl/context.h
gl/program.cpp
@ -91,7 +93,7 @@ add_library(common
target_include_directories(common PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_link_libraries(common PRIVATE glad libcue Threads::Threads cubeb libchdr glslang vulkan-loader)
target_link_libraries(common PRIVATE glad libcue stb Threads::Threads cubeb libchdr glslang vulkan-loader)
if(WIN32)
target_sources(common PRIVATE

View File

@ -62,6 +62,7 @@
<ClInclude Include="gl\texture.h" />
<ClInclude Include="hash_combine.h" />
<ClInclude Include="heap_array.h" />
<ClInclude Include="image.h" />
<ClInclude Include="iso_reader.h" />
<ClInclude Include="jit_code_buffer.h" />
<ClInclude Include="log.h" />
@ -114,6 +115,7 @@
<ClCompile Include="gl\shader_cache.cpp" />
<ClCompile Include="gl\stream_buffer.cpp" />
<ClCompile Include="gl\texture.cpp" />
<ClCompile Include="image.cpp" />
<ClCompile Include="iso_reader.cpp" />
<ClCompile Include="jit_code_buffer.cpp" />
<ClCompile Include="cd_subchannel_replacement.cpp" />
@ -300,7 +302,7 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>
<ConformanceMode>true</ConformanceMode>
@ -326,7 +328,7 @@
<PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=1;WIN32;_DEBUGFAST;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<SupportJustMyCode>false</SupportJustMyCode>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
@ -355,7 +357,7 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>
<ConformanceMode>true</ConformanceMode>
@ -381,7 +383,7 @@
<PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=1;WIN32;_DEBUGFAST;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<SupportJustMyCode>false</SupportJustMyCode>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
@ -411,7 +413,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>
<WholeProgramOptimization>false</WholeProgramOptimization>
@ -441,7 +443,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OmitFramePointers>true</OmitFramePointers>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -471,7 +473,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>
<WholeProgramOptimization>false</WholeProgramOptimization>
@ -501,7 +503,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OmitFramePointers>true</OmitFramePointers>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>

View File

@ -98,6 +98,7 @@
<ClInclude Include="vulkan\shader_cache.h">
<Filter>vulkan</Filter>
</ClInclude>
<ClInclude Include="image.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="jit_code_buffer.cpp" />
@ -188,6 +189,7 @@
<ClCompile Include="vulkan\shader_cache.cpp">
<Filter>vulkan</Filter>
</ClCompile>
<ClCompile Include="image.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include="bitfield.natvis" />

39
src/common/image.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "image.h"
#include "log.h"
#include "stb_image.h"
Log_SetChannel(Common::Image);
namespace Common {
bool LoadImageFromFile(Common::RGBA8Image* image, const char* filename)
{
int width, height, file_channels;
u8* pixel_data = stbi_load(filename, &width, &height, &file_channels, 4);
if (!pixel_data)
{
const char* error_reason = stbi_failure_reason();
Log_ErrorPrintf("Failed to load image from '%s': %s", filename, error_reason ? error_reason : "unknown error");
return false;
}
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(pixel_data));
stbi_image_free(pixel_data);
return true;
}
bool LoadImageFromBuffer(Common::RGBA8Image* image, const void* buffer, std::size_t buffer_size)
{
int width, height, file_channels;
u8* pixel_data = stbi_load_from_memory(static_cast<const stbi_uc*>(buffer), static_cast<int>(buffer_size), &width,
&height, &file_channels, 4);
if (!pixel_data)
{
const char* error_reason = stbi_failure_reason();
Log_ErrorPrintf("Failed to load image from memory: %s", error_reason ? error_reason : "unknown error");
return false;
}
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(pixel_data));
stbi_image_free(pixel_data);
return true;
}
} // namespace Common

98
src/common/image.h Normal file
View File

@ -0,0 +1,98 @@
#pragma once
#include "assert.h"
#include "types.h"
#include <algorithm>
#include <cstring>
#include <optional>
#include <vector>
namespace Common {
template<typename PixelType>
class Image
{
public:
Image() = default;
Image(u32 width, u32 height, const PixelType* pixels) { SetPixels(width, height, pixels); }
Image(const Image& copy)
{
m_width = copy.m_width;
m_height = copy.m_height;
m_pixels = copy.m_pixels;
}
Image(Image&& move)
{
m_width = move.m_width;
m_height = move.m_height;
m_pixels = std::move(move.m_width);
move.m_width = 0;
move.m_height = 0;
}
Image& operator=(const Image& copy)
{
m_width = copy.m_width;
m_height = copy.m_height;
m_pixels = copy.m_pixels;
return *this;
}
Image& operator=(Image&& move)
{
m_width = move.m_width;
m_height = move.m_height;
m_pixels = std::move(move.m_width);
move.m_width = 0;
move.m_height = 0;
return *this;
}
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 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]; }
ALWAYS_INLINE PixelType* GetRowPixels(u32 y) { return &m_pixels[y * m_width]; }
ALWAYS_INLINE void SetPixel(u32 x, u32 y, PixelType pixel) { m_pixels[y * m_width + x] = pixel; }
ALWAYS_INLINE PixelType GetPixel(u32 x, u32 y) const { return m_pixels[y * m_width + x]; }
void Clear(PixelType fill_value = static_cast<PixelType>(0))
{
std::fill(m_pixels.begin(), m_pixels.end(), fill_value);
}
void Invalidate()
{
m_width = 0;
m_height = 0;
m_pixels.clear();
}
void SetSize(u32 new_width, u32 new_height, PixelType fill_value = static_cast<PixelType>(0))
{
m_width = new_width;
m_height = new_height;
m_pixels.resize(new_width * new_height);
Clear(fill_value);
}
void SetPixels(u32 width, u32 height, const PixelType* pixels)
{
m_width = width;
m_height = height;
m_pixels.resize(width * height);
std::memcpy(m_pixels.data(), pixels, width * height * sizeof(PixelType));
}
private:
u32 m_width = 0;
u32 m_height = 0;
std::vector<PixelType> m_pixels;
};
using RGBA8Image = Image<u32>;
bool LoadImageFromFile(Common::RGBA8Image* image, const char* filename);
bool LoadImageFromBuffer(Common::RGBA8Image* image, const void* buffer, std::size_t buffer_size);
} // namespace Common