colour.c

///
// @module Lil
// @license MPL-2.0
// @author eiko
#include <math.h>

#include "inc.h"

lil_ColourLab lil_rgb2Lab(lil_Colour col){
	lil_Number rgb[3];
	for(int i = 0; i < 3; i++){
		lil_Number val = (lil_Number)col.arr[i] / 255.0;
		if(val > 0.04045)
			val = pow((val + 0.055) / 1.055, 2.4);
		else
			val = val / 12.92;
		rgb[i] = val * 100.;
	}
	lil_Number xyz[3];
	lil_Number x = rgb[0] * 0.4124 + rgb[1] * 0.3576 + rgb[2] * 0.1805;
	lil_Number y = rgb[0] * 0.2126 + rgb[1] * 0.7152 + rgb[2] * 0.0722;
	lil_Number z = rgb[0] * 0.0193 + rgb[1] * 0.1192 + rgb[2] * 0.9505;
	xyz[0] = x / 95.047;
	xyz[1] = y / 100.0;
	xyz[2] = z / 108.883;
	for(int i = 0; i < 3; i++){
		lil_Number val = xyz[i];
		if(val > 0.008856)
			val = pow(val, 1./3.);
		else
			val = (7.787 * val) + (16. / 116.);
		xyz[i] = val;
	}
	lil_ColourLab Lab = {
		.L = ((116. *  xyz[1]) - 16.)    ,
		.a =  (500. * (xyz[0] - xyz[1])),
		.b =  (200. * (xyz[1] - xyz[2]))
	};
	return Lab;
}
lil_ColourHsv lil_rgb2hsv(lil_Colour col){
	lil_ColourHsv hsv;
	lil_Number r = col.r / (lil_Number)0xff;
	lil_Number g = col.g / (lil_Number)0xff;
	lil_Number b = col.b / (lil_Number)0xff;
	lil_Number cmax = max(max(r, g), b);
	lil_Number cmin = min(min(r, g), b);
	lil_Number diff = cmax - cmin;
	if(cmax == cmin) {
		hsv.h = 0;
	} else if(cmax == r){
		hsv.h = fmod(60 * ((g - b) / diff) + 360, 360);
	} else if(cmax == g){
		hsv.h = fmod(60 * ((b - r) / diff) + 120, 360);
	} else if(cmax == b){
		hsv.h = fmod(60 * ((r - g) / diff) + 240, 360);
	}
	if(cmax == 0)
		hsv.s = 0;
	else
		hsv.s = (diff / cmax) * 100;
	hsv.v = cmax * 100;
	return hsv;
}
lil_Colour lil_hsv2rgb(lil_ColourHsv hsv){
	assert(hsv.h <= 360 && hsv.h >= 0);
	assert(hsv.s <= 100 && hsv.s >= 0);
	assert(hsv.v <= 100 && hsv.v >= 0);
	hsv.s /= 100;
	hsv.v /= 100;
	if(hsv.h == 360) hsv.h = 0;
	else             hsv.h = hsv.h / 60;
	int i = hsv.h;
	lil_Number f, p, q, t;
	f = hsv.h - i;
	p = hsv.v * (1.0 - hsv.s);
	q = hsv.v * (1.0 - (hsv.s * f));
	t = hsv.v * (1.0 - (hsv.s * (1.0 - f)));
	lil_Number r, g, b;
	switch(i){
		case 0:
			r = hsv.v;
			g = t;
			b = p;
			break;
		case 1:
			r = q;
			g = hsv.v;
			b = p;
			break;
		case 2:
			r = p;
			g = hsv.v;
			b = t;
			break;
		case 3:
			r = p;
			g = q;
			b = hsv.v;
			break;
		case 4:
			r = t;
			g = p;
			b = hsv.v;
			break;
		default:
			r = hsv.v;
			g = p;
			b = q;
			break;
	}
	lil_Colour rgb;
	rgb.a = 0xff;
	rgb.r = r * 255;
	rgb.g = g * 255;
	rgb.b = b * 255;
	return rgb;
}

#define ENTRY(id) static LUAFUNC(colour_ ## id)

///
// @function parseColour
// @colour colour
// @return r, g, b, a
ENTRY(parseColour){
	lil_Colour col = lil_getColour(L, 1, NULL);
	for(int i = 0; i < 4; i++)
		lua_pushnumber(L, col.arr[i] / (lil_Number)0xff);
	return 4;
}
///
// @function rgb2hsv
// @colour colour
// @return h, s, v, a
ENTRY(rgb2hsv){
	lil_Colour col = lil_getColour(L, 1, NULL);
	lil_ColourHsv hsv = lil_rgb2hsv(col);
	for(int i = 0; i < 3; i++)
		lua_pushnumber(L, hsv.arr[i]);
	lua_pushnumber(L, col.a);
	return 4;
}
///
// @function hsv2rgb
// @float h
// @float s
// @float v
// @float[opt=1] a
// @return r, g, b, a
ENTRY(hsv2rgb){
	lil_ColourHsv hsv;
	for(int i = 0; i < 3; i++)
		hsv.arr[i] = luaL_checknumber(L, i+1);
	lil_Colour rgb = lil_hsv2rgb(hsv);
	int st = lua_type(L, 4);
	for(int i = 0; i < 3; i++)
		lua_pushnumber(L, rgb.arr[i] / (lil_Number)0xff);
	switch(st){
		case LUA_TNONE:
			break;
		case LUA_TNUMBER:
			lua_pushvalue(L, 4);
			return 4;
		default:
			luaL_argerror(L, 4, "Not a number");
	}
	lua_pushnumber(L, 1);
	return 4;
}

#undef ENTRY
#define ENTRY(id) { #id, LUAFUNCD(colour_ ## id) }

LUAREG(colourLib) = {
	ENTRY(parseColour),
	ENTRY(rgb2hsv),
	ENTRY(hsv2rgb),
	{ NULL, NULL }
};

#undef ENTRY
generated by LDoc 1.4.6 Last updated 2023-04-13 13:58:34