Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/util/animated_image.h
4802 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
6
#include "common/align.h"
7
#include "common/heap_array.h"
8
#include "common/types.h"
9
10
#include <cstdio>
11
#include <optional>
12
#include <span>
13
#include <string_view>
14
15
class Error;
16
17
class AnimatedImage
18
{
19
public:
20
struct FrameDelay
21
{
22
u16 numerator;
23
u16 denominator;
24
};
25
26
static constexpr u8 DEFAULT_SAVE_QUALITY = 85;
27
28
public:
29
using PixelType = u32;
30
using PixelStorage = DynamicHeapArray<PixelType>;
31
32
AnimatedImage();
33
AnimatedImage(u32 width, u32 height, u32 frames, const FrameDelay& default_delay);
34
AnimatedImage(const AnimatedImage& copy);
35
AnimatedImage(AnimatedImage&& move);
36
37
AnimatedImage& operator=(const AnimatedImage& copy);
38
AnimatedImage& operator=(AnimatedImage&& move);
39
40
static u32 CalculatePitch(u32 width, u32 height);
41
42
ALWAYS_INLINE bool IsValid() const { return (m_width > 0 && m_height > 0); }
43
ALWAYS_INLINE u32 GetWidth() const { return m_width; }
44
ALWAYS_INLINE u32 GetHeight() const { return m_height; }
45
ALWAYS_INLINE u32 GetPitch() const { return (m_width * sizeof(u32)); }
46
ALWAYS_INLINE u32 GetFrames() const { return m_frames; }
47
ALWAYS_INLINE u32 GetFrameSize() const { return m_frame_size; }
48
ALWAYS_INLINE const u32* GetPixels(u32 frame) const { return &m_pixels[frame * m_frame_size]; }
49
ALWAYS_INLINE PixelType* GetPixels(u32 frame) { return &m_pixels[frame * m_frame_size]; }
50
ALWAYS_INLINE const PixelType* GetRowPixels(u32 frame, u32 y) const
51
{
52
return &m_pixels[frame * m_frame_size + y * m_width];
53
}
54
ALWAYS_INLINE PixelType* GetRowPixels(u32 frame, u32 y) { return &m_pixels[frame * m_frame_size + y * m_width]; }
55
ALWAYS_INLINE const FrameDelay& GetFrameDelay(u32 frame) const { return m_frame_delay[frame]; }
56
57
std::span<const PixelType> GetPixelsSpan(u32 frame) const;
58
std::span<PixelType> GetPixelsSpan(u32 frame);
59
60
void Clear();
61
void Invalidate();
62
63
void Resize(u32 new_width, u32 new_height, u32 num_frames, const FrameDelay& default_delay, bool preserve);
64
65
void SetPixels(u32 frame, const void* pixels, u32 pitch);
66
void SetDelay(u32 frame, const FrameDelay& delay);
67
68
PixelStorage TakePixels();
69
70
bool LoadFromFile(const char* filename, Error* error = nullptr);
71
bool LoadFromFile(std::string_view filename, std::FILE* fp, Error* error = nullptr);
72
bool LoadFromBuffer(std::string_view filename, std::span<const u8> data, Error* error = nullptr);
73
74
bool SaveToFile(const char* filename, u8 quality = DEFAULT_SAVE_QUALITY, Error* error = nullptr) const;
75
bool SaveToFile(std::string_view filename, std::FILE* fp, u8 quality = DEFAULT_SAVE_QUALITY,
76
Error* error = nullptr) const;
77
std::optional<DynamicHeapArray<u8>> SaveToBuffer(std::string_view filename, u8 quality = DEFAULT_SAVE_QUALITY,
78
Error* error = nullptr) const;
79
80
protected:
81
using FrameDelayStorage = DynamicHeapArray<FrameDelay>;
82
83
u32 m_width = 0;
84
u32 m_height = 0;
85
u32 m_frame_size = 0;
86
u32 m_frames = 0;
87
PixelStorage m_pixels;
88
FrameDelayStorage m_frame_delay;
89
};
90
91