ref: c3b6c54fe0c7ad567a5e6843c7339275e88d49fe
parent: d4e9ed1e23f08ffc95abc4143c3af6713f67bf69
author: phil9 <telephil9@gmail.com>
date: Thu Dec 1 14:38:55 EST 2022
implement HSV color mode and add colorMode() function it is now possible to specify colors in HSV format by first calling `colorMode(HSV)` The two constants RGB and HSV are used to switch between color modes.
--- a/a.h
+++ b/a.h
@@ -15,7 +15,7 @@
void initstate(lua_State*);
void registerapi(lua_State*);
-Image* color(int, int, int);
+Image* color(int, int, int, int);
extern int drawing;
extern Image *canvas;
--- a/api.c
+++ b/api.c
@@ -1,8 +1,15 @@
#include "a.h"
+enum
+{
+ Crgb,
+ Chsv,
+};
+
Image *canvas;
int width;
int height;
+int colormode;
int nostroke;
int strokecap;
Image *stroke;
@@ -20,6 +27,7 @@
height = 500;
r = Rect(0, 0, width, height);
canvas = allocimage(display, r, screen->chan, 0, DWhite);
+ colormode = Crgb;
nostroke = 0;
strokecap = Endsquare;
stroke = display->black;
@@ -63,22 +71,35 @@
c = lua_gettop(L);
if(c == 1){
- r = luaL_checkinteger(L, 1);
- g = r;
- b = r;
+ g = luaL_checkinteger(L, 1);
+ i = color(g, g, g, 0);
}else if(c == 3){
r = luaL_checkinteger(L, 1);
g = luaL_checkinteger(L, 2);
b = luaL_checkinteger(L, 3);
+ i = color(r, g, b, colormode == Chsv);
}else{
fprint(2, "invalid color request\n");
return nil;
}
- i = color(r, g, b);
return i;
}
int
+ccolormode(lua_State *L)
+{
+ int n;
+
+ n = luaL_checkinteger(L, 1);
+ if(n != Crgb && n != Chsv){
+ fprint(2, "error: invalid color mode\n");
+ return LUA_ERRRUN;
+ }
+ colormode = n;
+ return LUA_OK;
+}
+
+int
cbackground(lua_State *L)
{
Image *i;
@@ -354,10 +375,13 @@
void
registerapi(lua_State *L)
{
+ lset(L, "RGB", Crgb);
+ lset(L, "HSV", Chsv);
lset(L, "SQUARE", Endsquare);
lset(L, "ROUND", Enddisc);
registerfunc(L, "size", csize);
+ registerfunc(L, "colorMode", ccolormode);
registerfunc(L, "background", cbackground);
registerfunc(L, "noStroke", cnostroke);
registerfunc(L, "strokeCap", cstrokecap);
--- a/color.c
+++ b/color.c
@@ -22,13 +22,79 @@
return i;
}
+void
+hsvtorgb(int h, int s, int v, int *r, int *g, int *b)
+{
+ double dh, ds, dv, hh, p, q, t, ff;
+ long i;
+
+ dh = h;
+ ds = s/100.0;
+ dv = v/100.0;
+ if(ds <= 0.0){
+ *r = v;
+ *g = v;
+ *b = v;
+ }
+ hh = dh;
+ if(hh >= 360.0)
+ hh = 0.0;
+ hh /= 60.0;
+ i = (long)hh;
+ ff = hh - i;
+ p = dv * (1.0 - ds);
+ q = dv * (1.0 - (ds * ff));
+ t = dv * (1.0 - (ds * (1.0 - ff)));
+
+ switch(i) {
+ case 0:
+ *r = 255 * dv;
+ *g = 255 * t;
+ *b = 255 * p;
+ break;
+ case 1:
+ *r = 255 * q;
+ *g = 255 * dv;
+ *b = 255 * p;
+ break;
+ case 2:
+ *r = 255 * p;
+ *g = 255 * dv;
+ *b = 255 * t;
+ break;
+ case 3:
+ *r = 255 * p;
+ *g = 255 * q;
+ *b = 255 * dv;
+ break;
+ case 4:
+ *r = 255 * t;
+ *g = 255 * p;
+ *b = 255 * dv;
+ break;
+ case 5:
+ default:
+ *r = 255 * dv;
+ *g = 255 * p;
+ *b = 255 * q;
+ break;
+ }
+}
+
Image*
-color(int r, int g, int b)
+color(int x, int y, int z, int hsv)
{
ulong n;
Image *c;
- int i;
+ int i, r, g, b;
+ if(hsv)
+ hsvtorgb(x, y, z, &r, &g, &b);
+ else{
+ r = x;
+ g = y;
+ b = z;
+ }
c = nil;
n = (r << 24) | (g << 16) | (b << 8) | 0xFF;
for(i = 0; i < nelem(cache); i++){