palladium/source/Rubidium.cpp
2024-12-08 19:26:21 +01:00

124 lines
3.7 KiB
C++

#include <pd/external/stb_image.h>
#include <pd/Rubidium.hpp>
#include <pd/base/Color.hpp>
void d7_pixel_blend(Palladium::Rubidium* rb, int x, int y, unsigned int clr,
float blend) {
Palladium::Color::RGBA cl(clr);
cl.fade_to(Palladium::Color::RGBA(0.f, 0.f, 0.f, 1.f), blend);
rb->DrawPixel(x, y, cl.toRGBA());
}
namespace Palladium {
Rubidium::Rubidium(int w, int h) { image = Palladium::nimg(w, h); }
Rubidium::Rubidium() { image = Palladium::nimg(1, 1); }
Rubidium::~Rubidium() {
// Do nothing
}
void Rubidium::LoadFile(const std::string& path) {
int w, h, c;
uint8_t* dat = stbi_load(path.c_str(), &w, &h, &c, 4);
image = nimg(w, h);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int pos = (y * w + x) * 4;
image.pixel_buffer[pos + 0] = dat[pos + 0];
image.pixel_buffer[pos + 1] = dat[pos + 1];
image.pixel_buffer[pos + 2] = dat[pos + 2];
image.pixel_buffer[pos + 3] = dat[pos + 3];
}
}
stbi_image_free(dat);
}
void Rubidium::LoadNimg(const std::string& path) {
image = Palladium::NIMG_Load(path);
}
void Rubidium::DrawPixel(int x, int y, unsigned int color) {
if (x > image.width || x < 0 || y > image.height || y < 0) return;
Palladium::Color::RGBA splitter(color);
image.pixel_buffer[((y * image.width + x) * 4) + 0] = splitter.m_r;
image.pixel_buffer[((y * image.width + x) * 4) + 1] = splitter.m_g;
image.pixel_buffer[((y * image.width + x) * 4) + 2] = splitter.m_b;
image.pixel_buffer[((y * image.width + x) * 4) + 3] = splitter.m_a;
}
void Rubidium::DrawRect(int x, int y, int w, int h, unsigned int color, int t) {
DrawLine(x, y, x + w, y, color, t);
DrawLine(x, y, x, y + h, color, t);
DrawLine(x, y + h, x + w, y + h, color, t);
DrawLine(x + w, y, x + w, y + h, color, t);
}
void Rubidium::DrawRectSolid(int x, int y, int w, int h, unsigned int color) {
for (int ix = x; ix < x + w; ix++) {
for (int iy = y; iy < y + h; iy++) {
DrawPixel(ix, iy, color);
}
}
}
void Rubidium::DrawLine(int x1, int y1, int x2, int y2, unsigned int color,
int t) {
// Reference
// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
int ht = t / 2;
while (true) {
for (int i = -ht; i <= ht; i++) {
if (dy <= dx) {
DrawPixel(x1, y1 + i, color);
} else {
DrawPixel(x1 + i, y1, color);
}
}
if (x1 == x2 && y1 == y2) break;
int e2 = err * 2;
if (e2 > -dy) {
err -= dy;
x1 += sx;
}
if (e2 < dx) {
err += dx;
y1 += sy;
}
}
}
void Rubidium::Flip(bool h, bool v) {
const nimg _bak = image;
if (h) {
for (int x = 0; x < image.width; x++) {
for (int y = 0; y < image.height; y++) {
int src = (y * image.width + x) * 4;
int dst = ((image.height - 1 - y) * image.width + x) * 4;
image.pixel_buffer[src + 0] = _bak.pixel_buffer[dst + 0];
image.pixel_buffer[src + 1] = _bak.pixel_buffer[dst + 1];
image.pixel_buffer[src + 2] = _bak.pixel_buffer[dst + 2];
image.pixel_buffer[src + 3] = _bak.pixel_buffer[dst + 3];
}
}
}
if (v) {
for (int x = 0; x < image.width; x++) {
for (int y = 0; y < image.height; y++) {
int src = (y * image.width + x) * 4;
int dst = (y * image.width + (image.width - 1 - x)) * 4;
image.pixel_buffer[src + 0] = _bak.pixel_buffer[dst + 0];
image.pixel_buffer[src + 1] = _bak.pixel_buffer[dst + 1];
image.pixel_buffer[src + 2] = _bak.pixel_buffer[dst + 2];
image.pixel_buffer[src + 3] = _bak.pixel_buffer[dst + 3];
}
}
}
}
} // namespace Palladium