duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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 };