载入中...
搜索中...
未找到
Image.cpp
浏览该文件的文档.
1
2
3#include "Image.h"
4#include "common/Exception.h"
5#include "common/Resource.h"
6#include "common/config.h"
7
8#include "medialoader/image/PNGHandler.h"
9#include "medialoader/image/STBHandler.h"
10#include "medialoader/image/EXRHandler.h"
11
12#include "medialoader/image/ddsHandler.h"
13#include "medialoader/image/PVRHandler.h"
14#include "medialoader/image/KTXHandler.h"
15#include "medialoader/image/PKMHandler.h"
16#include "medialoader/image/ASTCHandler.h"
17
18#include <simplesquirrel/simplesquirrel.hpp>
19
20namespace eve
21{
22namespace image
23{
24
26
28{
29 using namespace medialoader;
30
31 float16Init(); // Makes sure half-float conversions can be used.
32
33 formatHandlers = {
34 new PNGHandler,
35 new STBHandler,
36 new EXRHandler,
37 new DDSHandler,
38 new PVRHandler,
39 new KTXHandler,
40 new PKMHandler,
41 new ASTCHandler,
42 };
43}
44
46{
47 // ImageData objects reference the FormatHandlers in our list, so we should
48 // release them instead of deleting them completely here.
49
50 // TODO: Check if this is necessary
51 // for (FormatHandler *handler : formatHandlers)
52 // handler->release();
53}
54
55
57{
58 return new ImageData(data);
59}
60
62{
63 if (path.empty())
64 throw eve::Exception("Image::newImageDataFromFile: empty path");
65
67 if (!resource)
68 throw eve::Exception("Could not load image file: %s", path.c_str());
69 return static_cast<ImageData *>(resource);
70}
71
72ImageData *Image::newImageData(int width, int height, std::string format)
73{
74 return new ImageData(width, height, format);
75}
76
77ImageData *Image::newImageData(int width, int height, std::string format, void *data, bool own)
78{
79 return new ImageData(width, height, format, data, own);
80}
81
82
84{
85 for (FormatHandler *handler : formatHandlers)
86 {
87 if (handler->canParseCompressed((const char*)data->getData(), data->getSize()))
88 return true;
89 }
90
91 return false;
92}
93
94const std::list<medialoader::FormatHandler *> &Image::getFormatHandlers() const
95{
96 return formatHandlers;
97}
98
99ImageData *Image::newPastedImageData(ImageData *src, int sx, int sy, int w, int h)
100{
101 ImageData *res = newImageData(w, h, src->getFormat());
102 try
103 {
104 res->paste(src, 0, 0, sx, sy, w, h);
105 }
106 catch (eve::Exception &)
107 {
108 // res->release();
109 throw;
110 }
111 return res;
112}
113
114std::vector<eve::ref<ImageData>> Image::newCubeFaces(ImageData *src)
115{
116 // The faces array is always ordered +x, -x, +y, -y, +z, -z.
117 std::vector<eve::ref<ImageData>> faces;
118
119 int totalW = src->getWidth();
120 int totalH = src->getHeight();
121
122 if (totalW % 3 == 0 && totalH % 4 == 0 && totalW / 3 == totalH / 4)
123 {
124 // +y
125 // +z +x -z
126 // -y
127 // -x
128
129 int w = totalW / 3;
130 int h = totalH / 4;
131
132 faces.emplace_back(newPastedImageData(src, 1*w, 1*h, w, h));
133 faces.emplace_back(newPastedImageData(src, 1*w, 3*h, w, h));
134 faces.emplace_back(newPastedImageData(src, 1*w, 0*h, w, h));
135 faces.emplace_back(newPastedImageData(src, 1*w, 2*h, w, h));
136 faces.emplace_back(newPastedImageData(src, 0*w, 1*h, w, h));
137 faces.emplace_back(newPastedImageData(src, 2*w, 1*h, w, h));
138 }
139 else if (totalW % 4 == 0 && totalH % 3 == 0 && totalW / 4 == totalH / 3)
140 {
141 // +y
142 // -x +z +x -z
143 // -y
144
145 int w = totalW / 4;
146 int h = totalH / 3;
147
148 faces.emplace_back(newPastedImageData(src, 2*w, 1*h, w, h));
149 faces.emplace_back(newPastedImageData(src, 0*w, 1*h, w, h));
150 faces.emplace_back(newPastedImageData(src, 1*w, 0*h, w, h));
151 faces.emplace_back(newPastedImageData(src, 1*w, 2*h, w, h));
152 faces.emplace_back(newPastedImageData(src, 1*w, 1*h, w, h));
153 faces.emplace_back(newPastedImageData(src, 3*w, 1*h, w, h));
154 }
155 else if (totalH % 6 == 0 && totalW == totalH / 6)
156 {
157 // +x
158 // -x
159 // +y
160 // -y
161 // +z
162 // -z
163
164 int w = totalW;
165 int h = totalH / 6;
166
167 for (int i = 0; i < 6; i++)
168 faces.emplace_back(newPastedImageData(src, 0, i * h, w, h));
169 }
170 else if (totalW % 6 == 0 && totalW / 6 == totalH)
171 {
172 // +x -x +y -y +z -z
173
174 int w = totalW / 6;
175 int h = totalH;
176
177 for (int i = 0; i < 6; i++)
178 faces.emplace_back(newPastedImageData(src, i * w, 0, w, h));
179 }
180 else
181 throw eve::Exception("Unknown cubemap image dimensions!");
182
183 return faces;
184}
185
186std::vector<eve::ref<ImageData>> Image::newVolumeLayers(ImageData *src)
187{
188 std::vector<eve::ref<ImageData>> layers;
189
190 int totalW = src->getWidth();
191 int totalH = src->getHeight();
192
193 if (totalW % totalH == 0)
194 {
195 for (int i = 0; i < totalW / totalH; i++)
196 layers.emplace_back(newPastedImageData(src, i * totalH, 0, totalH, totalH));
197 }
198 else if (totalH % totalW == 0)
199 {
200 for (int i = 0; i < totalH / totalW; i++)
201 layers.emplace_back(newPastedImageData(src, 0, i * totalW, totalW, totalW));
202 }
203 else
204 throw eve::Exception("Cannot extract volume layers from source ImageData.");
205
206 return layers;
207}
208
209void Image::expose(ssq::Table &table) {
210 auto cls = table.addClass(name, Image::create, false);
211 expose(cls);
212
213 // Single ImageData class for every module that hands image::ImageData*
214 // to scripts (Font glyphs, Model3D embedded textures, this module).
215 auto img = table.addClass<image::ImageData>(
216 "ImageData", std::function<image::ImageData *()>([]() -> image::ImageData * { return nullptr; }),
217 true);
218 img.addFunc("getWidth", &image::ImageData::getWidth);
219 img.addFunc("getHeight", &image::ImageData::getHeight);
220 img.addFunc("getFormat", &image::ImageData::getFormat);
221 img.addFunc("getSize", &image::ImageData::getSize);
222 img.addFunc("getPixelSize", &image::ImageData::getPixelSize);
223 img.addFunc("isSRGB", &image::ImageData::isSRGB);
224 img.addFunc("inside", &image::ImageData::inside);
225 img.addFunc("clone", &image::ImageData::clone);
226 img.addFunc("paste", &image::ImageData::paste);
227 img.addFunc("rotate", &image::ImageData::rotate);
228 img.addFunc("getPixelR", [](image::ImageData *self, int x, int y) -> float {
229 if (!self) return 0.f;
230 return self->getPixel(x, y).r;
231 });
232 img.addFunc("getPixelG", [](image::ImageData *self, int x, int y) -> float {
233 if (!self) return 0.f;
234 return self->getPixel(x, y).g;
235 });
236 img.addFunc("getPixelB", [](image::ImageData *self, int x, int y) -> float {
237 if (!self) return 0.f;
238 return self->getPixel(x, y).b;
239 });
240 img.addFunc("getPixelA", [](image::ImageData *self, int x, int y) -> float {
241 if (!self) return 0.f;
242 return self->getPixel(x, y).a;
243 });
244 img.addFunc("setPixel", [](image::ImageData *self, int x, int y, float r, float g, float b, float a) {
245 if (!self) return;
246 self->setPixel(x, y, image::ImageData::Colorf{r, g, b, a});
247 });
248}
249
250void Image::expose(ssq::Class &cls) {
251 cls.addFunc("getName", &Image::getName);
252 cls.addFunc("newImageData", static_cast<ImageData *(Image::*)(Data *)>(&Image::newImageData));
253 cls.addFunc("newImageDataFromFile", &Image::newImageDataFromFile);
254 cls.addFunc("newEmptyImageData",
255 [](Image *self, int width, int height, const std::string &format) -> ImageData * {
256 if (!self) return nullptr;
257 return self->newImageData(width, height, format);
258 });
259 cls.addFunc("isCompressed", &Image::isCompressed);
260}
261
262} // image
263} // eve
HSQOBJECT cls
Definition ECS.cpp:21
int y
Definition Grass.cpp:135
float height
Definition Grass.cpp:235
int x
Definition Grass.cpp:135
int h
int w
uint32_t a
uint32_t b
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:24
int width
Light2D::Data * data
const char * name
Definition RockMesh.cpp:21
std::string image
virtual std::string getName() const =0
Resource * get(std::string key)
Get the cached resource for key; on a miss, load it through the registered IAssetReloader providers a...
Definition Resource.cpp:56
static ResourceManager & getInstance()
Definition Resource.cpp:8
Resource is a game object that is managed by the ResourceManager. It can be loaded from a file or gen...
Definition Resource.h:35
Represents raw pixel data.
Definition ImageData.h:26
ImageData * clone() const
Definition ImageData.cpp:72
bool inside(int x, int y) const
Checks whether a position is inside this ImageData. Useful for checking bounds.
void getPixel(int x, int y, Colorf &c) const
Gets the pixel at location (x,y).
medialoader::Colorf Colorf
Definition ImageData.h:29
void paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, int sh)
Paste part of one ImageData onto another. The subregion defined by the top-left corner (sx,...
size_t getSize() const
ImageData * rotate(float radians, std::string filter="nearest", bool expand=true) const
Rotate pixels around the image center and return a new ImageData.
size_t getPixelSize() const
std::string getFormat() const
This module is responsible for decoding files such as PNG, GIF, JPEG into raw pixel data,...
Definition Image.h:21
std::vector< ref< ImageData > > newVolumeLayers(ImageData *src)
Definition Image.cpp:186
ImageData * newImageDataFromFile(std::string path)
Loads an image from a VFS path through the unified resource cache. Repeated loads of one path share a...
Definition Image.cpp:61
medialoader::FormatHandler FormatHandler
Definition Image.h:23
bool isCompressed(Data *data)
Creates new CompressedImageData from FileData.
Definition Image.cpp:83
const std::list< FormatHandler * > & getFormatHandlers() const
Definition Image.cpp:94
ImageData * newImageData(Data *data)
Creates new ImageData from FileData.
Definition Image.cpp:56
virtual ~Image()
Definition Image.cpp:45
std::vector< ref< ImageData > > newCubeFaces(ImageData *src)
Definition Image.cpp:114
Definition Build.cpp:11