A simple colours manipulation library in c
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

#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);
}