image.h (4051B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0) 3 4 #pragma once 5 6 #include "common/types.h" 7 8 #include <algorithm> 9 #include <cstdio> 10 #include <cstring> 11 #include <optional> 12 #include <string_view> 13 #include <vector> 14 15 template<typename PixelType> 16 class Image 17 { 18 public: 19 Image() = default; 20 Image(u32 width, u32 height) { SetSize(width, height); } 21 Image(u32 width, u32 height, const PixelType* pixels) { SetPixels(width, height, pixels); } 22 Image(u32 width, u32 height, std::vector<PixelType> pixels) { SetPixels(width, height, std::move(pixels)); } 23 Image(const Image& copy) 24 { 25 m_width = copy.m_width; 26 m_height = copy.m_height; 27 m_pixels = copy.m_pixels; 28 } 29 Image(Image&& move) 30 { 31 m_width = move.m_width; 32 m_height = move.m_height; 33 m_pixels = std::move(move.m_pixels); 34 move.m_width = 0; 35 move.m_height = 0; 36 } 37 38 Image& operator=(const Image& copy) 39 { 40 m_width = copy.m_width; 41 m_height = copy.m_height; 42 m_pixels = copy.m_pixels; 43 return *this; 44 } 45 Image& operator=(Image&& move) 46 { 47 m_width = move.m_width; 48 m_height = move.m_height; 49 m_pixels = std::move(move.m_pixels); 50 move.m_width = 0; 51 move.m_height = 0; 52 return *this; 53 } 54 55 ALWAYS_INLINE bool IsValid() const { return (m_width > 0 && m_height > 0); } 56 ALWAYS_INLINE u32 GetWidth() const { return m_width; } 57 ALWAYS_INLINE u32 GetHeight() const { return m_height; } 58 ALWAYS_INLINE u32 GetPitch() const { return (sizeof(PixelType) * m_width); } 59 ALWAYS_INLINE const PixelType* GetPixels() const { return m_pixels.data(); } 60 ALWAYS_INLINE PixelType* GetPixels() { return m_pixels.data(); } 61 ALWAYS_INLINE const PixelType* GetRowPixels(u32 y) const { return &m_pixels[y * m_width]; } 62 ALWAYS_INLINE PixelType* GetRowPixels(u32 y) { return &m_pixels[y * m_width]; } 63 ALWAYS_INLINE void SetPixel(u32 x, u32 y, PixelType pixel) { m_pixels[y * m_width + x] = pixel; } 64 ALWAYS_INLINE PixelType GetPixel(u32 x, u32 y) const { return m_pixels[y * m_width + x]; } 65 66 void Clear(PixelType fill_value = static_cast<PixelType>(0)) 67 { 68 std::fill(m_pixels.begin(), m_pixels.end(), fill_value); 69 } 70 71 void Invalidate() 72 { 73 m_width = 0; 74 m_height = 0; 75 m_pixels.clear(); 76 } 77 78 void SetSize(u32 new_width, u32 new_height, PixelType fill_value = static_cast<PixelType>(0)) 79 { 80 m_width = new_width; 81 m_height = new_height; 82 m_pixels.resize(new_width * new_height); 83 Clear(fill_value); 84 } 85 86 void SetPixels(u32 width, u32 height, const PixelType* pixels) 87 { 88 m_width = width; 89 m_height = height; 90 m_pixels.resize(width * height); 91 std::memcpy(m_pixels.data(), pixels, width * height * sizeof(PixelType)); 92 } 93 94 void SetPixels(u32 width, u32 height, std::vector<PixelType> pixels) 95 { 96 m_width = width; 97 m_height = height; 98 m_pixels = std::move(pixels); 99 } 100 101 std::vector<PixelType> TakePixels() 102 { 103 m_width = 0; 104 m_height = 0; 105 return std::move(m_pixels); 106 } 107 108 protected: 109 u32 m_width = 0; 110 u32 m_height = 0; 111 std::vector<PixelType> m_pixels; 112 }; 113 114 class RGBA8Image : public Image<u32> 115 { 116 public: 117 static constexpr u8 DEFAULT_SAVE_QUALITY = 85; 118 119 RGBA8Image(); 120 RGBA8Image(u32 width, u32 height); 121 RGBA8Image(u32 width, u32 height, const u32* pixels); 122 RGBA8Image(u32 width, u32 height, std::vector<u32> pixels); 123 RGBA8Image(const RGBA8Image& copy); 124 RGBA8Image(RGBA8Image&& move); 125 126 RGBA8Image& operator=(const RGBA8Image& copy); 127 RGBA8Image& operator=(RGBA8Image&& move); 128 129 bool LoadFromFile(const char* filename); 130 bool LoadFromFile(std::string_view filename, std::FILE* fp); 131 bool LoadFromBuffer(std::string_view filename, const void* buffer, size_t buffer_size); 132 133 bool SaveToFile(const char* filename, u8 quality = DEFAULT_SAVE_QUALITY) const; 134 bool SaveToFile(std::string_view filename, std::FILE* fp, u8 quality = DEFAULT_SAVE_QUALITY) const; 135 std::optional<std::vector<u8>> SaveToBuffer(std::string_view filename, u8 quality = DEFAULT_SAVE_QUALITY) const; 136 };