146 lines
4.4 KiB
C++
Executable File
146 lines
4.4 KiB
C++
Executable File
#include <amethyst/image.hpp>
|
|
#include <amethyst/utils.hpp>
|
|
#include <stdexcept>
|
|
|
|
// #define STB_IMAGE_IMPLEMENTATION
|
|
#include <stb_image.h>
|
|
|
|
namespace amy {
|
|
void image::load(cstr& path) {
|
|
int c = 0;
|
|
uc* buf = stbi_load(path.c_str(), &m_w, &m_h, &c, 4);
|
|
if (c == 3) {
|
|
// Releoading the Image with tree channels requestet
|
|
// Still need to find a better way for this :(
|
|
stbi_image_free(buf);
|
|
buf = stbi_load(path.c_str(), &m_w, &m_h, &c, 3);
|
|
m_buffer.assign(buf, buf + (m_w * m_h * 3));
|
|
m_fmt = RGB;
|
|
stbi_image_free(buf);
|
|
} else if (c == 4) {
|
|
m_buffer.assign(buf, buf + (m_w * m_h * 4));
|
|
m_fmt = RGBA;
|
|
stbi_image_free(buf);
|
|
} else {
|
|
throw std::runtime_error(path + " is using an unsupported image format!");
|
|
}
|
|
}
|
|
|
|
void image::load(const std::vector<uc>& data) {
|
|
int c = 0;
|
|
uc* buf = stbi_load_from_memory(data.data(), data.size(), &m_w, &m_h, &c, 4);
|
|
if (c == 3) {
|
|
// Releoading the Image with tree channels requestet
|
|
// Still need to find a better way for this :(
|
|
stbi_image_free(buf);
|
|
buf = stbi_load_from_memory(data.data(), data.size(), &m_w, &m_h, &c, 3);
|
|
m_buffer.assign(buf, buf + (m_w * m_h * 3));
|
|
m_fmt = RGB;
|
|
stbi_image_free(buf);
|
|
} else if (m_fmt == 4) {
|
|
m_buffer.assign(buf, buf + (m_w * m_h * 4));
|
|
m_fmt = RGBA;
|
|
stbi_image_free(buf);
|
|
} else {
|
|
throw std::runtime_error("image mem using an unsupported image format!");
|
|
}
|
|
}
|
|
|
|
void image::copy(const std::vector<uc>& pixels, int w, int h,
|
|
const format& fmt) {
|
|
int f = getBppOfFmt(fmt);
|
|
if (pixels.size() != static_cast<size_t>(w * h * f)) {
|
|
throw std::runtime_error("Connot copy image due to size error!");
|
|
}
|
|
m_fmt = fmt;
|
|
m_w = w;
|
|
m_h = h;
|
|
m_buffer.clear();
|
|
m_buffer.resize(w * h * f);
|
|
for (size_t i = 0; i < m_buffer.size(); i++) {
|
|
m_buffer[i] = pixels[i];
|
|
}
|
|
}
|
|
|
|
int image::getBppOfFmt(const image::format& fmt) {
|
|
switch (fmt) {
|
|
case RGBA:
|
|
case ABGR:
|
|
case BGRA:
|
|
return 4;
|
|
break;
|
|
case RGB:
|
|
case BGR:
|
|
return 3;
|
|
break;
|
|
case RGB565:
|
|
return 2;
|
|
break;
|
|
|
|
default:
|
|
return 0; // Unknown
|
|
break;
|
|
}
|
|
}
|
|
|
|
void image::convert(image& img, const format& dst) {
|
|
if (img.m_fmt == dst) {
|
|
return;
|
|
} else if (img.m_fmt == RGB && dst == BGR) {
|
|
utils::image::reverseBuf(img.m_buffer, img.m_w, img.m_h, 3);
|
|
img.m_fmt = BGR;
|
|
} else if (img.m_fmt == RGB && dst == RGBA) {
|
|
utils::image::addAlphaChannel(img.m_buffer, img.m_w, img.m_h);
|
|
img.m_fmt = RGBA;
|
|
} else if (img.m_fmt == RGBA && dst == RGB) {
|
|
utils::image::removeAlphaChannel(img.m_buffer, img.m_w, img.m_h);
|
|
img.m_fmt = RGB;
|
|
} else if (img.m_fmt == RGBA && dst == ABGR) {
|
|
utils::image::reverseBuf(img.m_buffer, img.m_w, img.m_h, 4);
|
|
img.m_fmt = ABGR;
|
|
} else if (img.m_fmt == RGB && dst == ABGR) {
|
|
convert(img, RGBA);
|
|
convert(img, ABGR);
|
|
} else if (img.m_fmt == RGBA && dst == RGB565) {
|
|
convert(img, RGB);
|
|
convert(img, RGB565);
|
|
} else if (img.m_fmt == RGB && dst == RGB565) {
|
|
// Inlined make pixel 565 func
|
|
auto f = [](uc r, uc g, uc b) -> unsigned short {
|
|
unsigned short _r = (r >> 3);
|
|
unsigned short _g = (g >> 2);
|
|
unsigned short _b = (b >> 3);
|
|
return (_r << 11) | (_g << 5) | _b;
|
|
};
|
|
std::vector<uc> cpy = img.m_buffer;
|
|
img.m_buffer.resize(img.m_w * img.m_h * 2);
|
|
for (int y = 0; y < img.m_w; y++) {
|
|
for (int x = 0; x < img.m_h; x++) {
|
|
int src = (y * img.m_w + x) * 3;
|
|
int dst = (y * img.m_w + x) * 2;
|
|
unsigned short new_px = f(cpy[src + 0], cpy[src + 1], cpy[src + 2]);
|
|
img.m_buffer[dst + 0] = new_px >> 8;
|
|
img.m_buffer[dst + 1] = new_px & 0xff;
|
|
}
|
|
}
|
|
img.m_fmt = RGB565;
|
|
}
|
|
}
|
|
|
|
void image::retile(image& img, std::function<ui(int x, int y, int w)> src,
|
|
std::function<ui(int x, int y, int w)> dst) {
|
|
std::vector<uc> cpy = img.m_buffer;
|
|
/** could use fmt here but for 565 that woulnt work as it is not supported by
|
|
* file loading where fmt is used */
|
|
int bpp = img.bpp();
|
|
for (int y = 0; y < img.m_h; y++) {
|
|
for (int x = 0; x < img.m_w; x++) {
|
|
int src_idx = src(x, y, img.m_w);
|
|
int dst_idx = dst(x, y, img.m_w);
|
|
for (int i = 0; i < bpp; i++) {
|
|
img.m_buffer[dst_idx + i] = cpy[src_idx + i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // namespace amy
|