-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathimage.cpp
136 lines (111 loc) · 3.04 KB
/
image.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "image.hpp"
#include <cstdio>
#include <string_view>
#include "platform.hpp"
#include "stb_image.h"
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#endif
class File : private NonCopyable {
public:
File();
File(const std::string_view path);
~File();
void Open(const std::string_view path);
void Close();
operator FILE *();
operator bool() const;
private:
FILE *fp;
};
File::File() : fp(nullptr) {}
File::File(const std::string_view path) {
Open(path);
}
File::~File() {
Close();
}
void File::Open(const std::string_view path) {
#ifdef PLATFORM_WINDOWS
std::wstring wpath;
const int size = MultiByteToWideChar(CP_UTF8, MB_COMPOSITE, path.data(), -1, nullptr, 0);
wpath.resize(size - 1, '\0');
const int status =
MultiByteToWideChar(CP_UTF8, MB_COMPOSITE, path.data(), -1, wpath.data(), size);
if (!status)
Err::Exit("String conversion failed: from:", path);
fp = _wfopen(wpath.c_str(), L"rb");
#else
fp = std::fopen(path.data(), "rb");
#endif
}
void File::Close() {
if (fp) {
std::fclose(fp);
fp = nullptr;
}
}
File::operator FILE *() {
return fp;
}
File::operator bool() const {
return fp != nullptr;
}
Image::Image() : width(0), height(0), dataSize(0), hasAlpha(false) {}
Image::Image(Image&& image) {
*this = std::move(image);
}
Image& Image::operator=(Image&& rhs) {
width = rhs.width;
height = rhs.height;
dataSize = rhs.dataSize;
pixels = rhs.pixels;
hasAlpha = rhs.hasAlpha;
return *this;
}
bool Image::loadFromFile(const std::string_view path) {
// TODO: Is this really needed?
stbi_set_flip_vertically_on_load(true);
File file(path);
if (!file) {
Err::Log("Failed to open file:", path);
return false;
}
int comp = 0;
const int ret = stbi_info_from_file(file, &width, &height, &comp);
if (ret == 0) {
Err::Log("Failed to read info:", path, ':', stbi_failure_reason());
return false;
}
if (comp == 4)
hasAlpha = true;
else
hasAlpha = false;
uint8_t *const image = stbi_load_from_file(file, &width, &height, &comp, STBI_rgb_alpha);
dataSize = width * height * 4;
pixels.resize(dataSize);
std::copy(image, image + dataSize, pixels.data());
stbi_image_free(image);
return true;
}
bool Image::loadFromMemory(const Resource::View& resource) {
stbi_set_flip_vertically_on_load(true);
int comp = 0;
const int ret =
stbi_info_from_memory(resource.data(), resource.length(), &width, &height, &comp);
if (ret == 0) {
Err::Log("Failed to read info:", __func__, ':', stbi_failure_reason());
return false;
}
if (comp == 4)
hasAlpha = true;
else
hasAlpha = false;
uint8_t *const image = stbi_load_from_memory(
resource.data(), resource.length(), &width, &height, &comp, STBI_rgb_alpha);
dataSize = width * height * 4;
pixels.resize(dataSize);
std::copy(image, image + dataSize, pixels.data());
stbi_image_free(image);
return true;
}