You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
5.3 KiB
243 lines
5.3 KiB
|
|
#include <cassert> |
|
#include <iomanip> |
|
#include <iostream> |
|
#include <pybind11/pybind11.h> |
|
#include <pybind11/stl.h> |
|
#include <sstream> |
|
#include <vector> |
|
|
|
namespace py = pybind11; |
|
|
|
extern "C" { |
|
#include "colours.h" |
|
} |
|
|
|
class Colour { |
|
Colour(struct colour col) : col(col) {} |
|
|
|
public: |
|
struct colour col {}; |
|
Colour(int r, int g, int b) { |
|
col.r = r; |
|
col.g = g; |
|
col.b = b; |
|
col.sp = colour_space::CS_RGB; |
|
} |
|
|
|
Colour(double h, double s, double v) { |
|
col.h = h; |
|
col.s = s; |
|
col.v = v; |
|
col.sp = colour_space::CS_HSV; |
|
} |
|
|
|
Colour() { |
|
col = {}; |
|
col.r = 255; |
|
} |
|
|
|
void set_r(int r) { col.r = r; } |
|
|
|
void set_g(int g) { col.g = g; } |
|
|
|
void set_b(int b) { col.b = b; } |
|
|
|
void set_h(double h) { |
|
if (col.sp == CS_RGB) |
|
col.sp = CS_HSV; |
|
col.h = h; |
|
} |
|
|
|
void set_s(double s) { |
|
|
|
if (col.sp == CS_RGB) |
|
col.sp = CS_HSV; |
|
col.s = s; |
|
} |
|
|
|
void set_v(double v) { |
|
col.v = v; |
|
col.sp = CS_HSV; |
|
} |
|
|
|
void set_l(double l) { |
|
col.l = l; |
|
col.sp = CS_HSL; |
|
} |
|
|
|
Colour rgb() { return Colour{get_rgb(col)}; } |
|
|
|
Colour hsv() { return Colour{get_hsv(col)}; } |
|
|
|
Colour hsl() { return Colour{get_hsl(col)}; } |
|
|
|
int get_r() { |
|
// assert(col.sp == CS_RGB); |
|
col = get_rgb(col); |
|
return rgb().col.r; |
|
} |
|
|
|
int get_g() { |
|
// assert(col.sp == CS_RGB); |
|
col = get_rgb(col); |
|
return col.g; |
|
} |
|
|
|
int get_b() { |
|
// assert(col.sp == CS_RGB); |
|
col = get_rgb(col); |
|
return col.b; |
|
} |
|
|
|
double get_h() { |
|
// assert(col.sp == CS_HSV || col.sp == CS_HSL); |
|
col = get_hsv(col); |
|
return col.h; |
|
} |
|
|
|
double get_s() { |
|
// assert(col.sp == CS_HSV || col.sp == CS_HSL); |
|
col = get_hsv(col); |
|
return col.s; |
|
} |
|
|
|
double get_v() { |
|
// assert(col.sp == CS_HSV); |
|
col = get_hsv(col); |
|
return col.v; |
|
} |
|
|
|
double get_l() { |
|
assert(col.sp == CS_HSL); |
|
return col.l; |
|
} |
|
|
|
std::string to_term() { |
|
std::stringstream s{}; |
|
auto col = rgb(); |
|
s << "\x1b[38;2;" << col.get_r() << ";" << col.get_g() << ";" << col.get_b() |
|
<< "m"; |
|
s << to_hex() << "\x1b[0m"; |
|
return s.str(); |
|
} |
|
|
|
std::string to_hex() { |
|
Colour rgbcol = rgb(); |
|
char colour[20]; |
|
snprintf(colour, 20, "#%02x%02x%02x", rgbcol.get_r(), rgbcol.get_g(), |
|
rgbcol.get_b()); |
|
return std::string(colour); |
|
} |
|
|
|
std::string str() { |
|
std::stringstream s{}; |
|
s << "rgb(" << col.r << "," << col.g << "," << col.b << "):hsv(" << col.h |
|
<< "," << col.s << "," << col.v << "):hsl(" << col.h << "," << col.s |
|
<< "," << col.l << ");"; |
|
return s.str(); |
|
} |
|
}; |
|
|
|
Colour rgb(int r, int g, int b) { return Colour(r, g, b); } |
|
|
|
Colour hsv(double h, double s, double v) { return Colour(h, s, v); } |
|
|
|
Colour hsl(double h, double s, double l) { |
|
auto c = Colour(h, s, 0.0); |
|
c.set_l(l); |
|
return c; |
|
} |
|
|
|
std::vector<Colour> lerp_gradient(Colour from, Colour to, int length) { |
|
|
|
std::vector<Colour> gradient{}; |
|
gradient.reserve(length); |
|
Colour start = from.rgb(); |
|
Colour end = to.rgb(); |
|
|
|
double r = start.get_r(); |
|
double g = start.get_g(); |
|
double b = start.get_b(); |
|
|
|
double r_step = (r - end.get_r()) / (length - 1); |
|
double g_step = (g - end.get_g()) / (length - 1); |
|
double b_step = (b - end.get_b()) / (length - 1); |
|
|
|
gradient.push_back(start); |
|
for (int i = 1; i < length - 1; i++) { |
|
gradient.push_back(Colour((int)r, (int)g, (int)b)); |
|
|
|
r -= r_step; |
|
g -= g_step; |
|
b -= b_step; |
|
} |
|
gradient.push_back(end); |
|
|
|
return gradient; |
|
} |
|
|
|
std::vector<Colour> make_gradient(Colour from, Colour to, int length) { |
|
|
|
std::vector<Colour> gradient{}; |
|
gradient.reserve(length); |
|
Colour start = from.hsv(); |
|
Colour end = to.hsv(); |
|
|
|
double h = start.get_h(); |
|
double s = start.get_s(); |
|
double v = start.get_v(); |
|
|
|
double left = end.get_h() - start.get_h(); |
|
double right = -end.get_h() + start.get_h(); |
|
double hue_step = (abs(left) < abs(right) ? left : right) / (length - 1); |
|
hue_step = left / (length - 1); |
|
double sat_step = (end.get_s() - start.get_s()) / (length - 1); |
|
double val_step = (end.get_v() - start.get_v()) / (length - 1); |
|
|
|
gradient.push_back(start); |
|
for (int i = 1; i < length; i++) { |
|
gradient.emplace_back(h, s, v); |
|
h = fmod(h + hue_step, 360); |
|
if (h < 0) { |
|
h = 360 + h; |
|
} |
|
s += sat_step; |
|
v += val_step; |
|
} |
|
|
|
return gradient; |
|
} |
|
|
|
PYBIND11_MODULE(colourpal, m) { |
|
m.doc() = "Colour conversion lib"; // optional module docstring |
|
// |
|
m.def("rgb", &rgb) |
|
.def("hsv", &hsv) |
|
.def("hsl", &hsl) |
|
.def("make_gradient", &make_gradient) |
|
.def("lerp_gradient", &lerp_gradient); |
|
|
|
py::class_<Colour>(m, "CColour") |
|
.def(py::init<>()) |
|
.def("hexstring", &Colour::to_hex) |
|
.def("terminal", &Colour::to_term) |
|
.def("rgb", &Colour::rgb) |
|
.def("hsv", &Colour::hsv) |
|
.def("hsl", &Colour::hsl) |
|
.def("get_h", &Colour::get_h) |
|
.def("get_s", &Colour::get_s) |
|
.def("get_v", &Colour::get_v) |
|
.def("get_l", &Colour::get_l) |
|
.def("get_r", &Colour::get_r) |
|
.def("get_g", &Colour::get_g) |
|
.def("get_b", &Colour::get_b) |
|
.def("set_h", &Colour::set_h) |
|
.def("set_s", &Colour::set_s) |
|
.def("set_v", &Colour::set_v) |
|
.def("set_l", &Colour::set_l) |
|
.def("set_r", &Colour::set_r) |
|
.def("set_g", &Colour::set_g) |
|
.def("set_b", &Colour::set_b) |
|
.def("str", &Colour::str); |
|
}
|
|
|