ref: bba1a7594cf3479de9c836c5004d2cce49fd15f4
parent: 52fd69b721bf44e66fc82f103ce90f74a43fa2a8
author: Sigrid Haflínudóttir <[email protected]>
date: Sat Mar 14 15:52:09 EDT 2020
support alpha channel and RGB/RGBA colors as input
--- a/picker.c
+++ b/picker.c
@@ -7,8 +7,9 @@
#include <keyboard.h>
#include "hsluv.h"
-#define MAX(a,b) ((a)>=(b)?(a):(b))
-#define MIN(a,b) ((a)<=(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define D2C(x) (int)MAX(0, MIN(0xff, x*256.0))
enum
{
@@ -37,7 +38,7 @@
char opt;
void (*torgb)(double *v, double *rgb);
void (*fromrgb)(double *rgb, double *v);
- double max[3];
+ double max[4];
};
static void
@@ -86,7 +87,7 @@
.opt = 's',
.torgb = _hsluv2rgb,
.fromrgb = _rgb2hsluv,
- .max = {360.0, 100.0, 100.0},
+ .max = {360.0, 100.0, 100.0, 1.0},
},
{
.name = "HPLuv",
@@ -93,7 +94,7 @@
.opt = 'l',
.torgb = _hpluv2rgb,
.fromrgb = _rgb2hpluv,
- .max = {360.0, 100.0, 100.0},
+ .max = {360.0, 100.0, 100.0, 1.0},
},
{
.name = "RGB",
@@ -100,7 +101,7 @@
.opt = 'r',
.torgb = _torgb,
.fromrgb = _fromrgb,
- .max = {1.0, 1.0, 1.0},
+ .max = {1.0, 1.0, 1.0, 1.0},
},
};
@@ -117,6 +118,7 @@
double c[4], rgb[3], dt;
Rectangle rect;
int i, n, mi;
+ ulong u;
rect = Rect(0, 0, w, 1);
s = sliders[si];
@@ -124,7 +126,7 @@
buf[si] = realloc(buf[si], 4*w);
if (s != nil)
freeimage(s);
- if ((s = sliders[si] = allocimage(display, rect, BGR24, 1, DNofill)) == nil)
+ if ((s = sliders[si] = allocimage(display, rect, RGBA32, 1, DNofill)) == nil)
sysfatal("allocimage: %r");
}
b = buf[si];
@@ -133,26 +135,28 @@
dt = mode->max[si] / w;
mi = c[si] / dt;
c[si] = 0.0;
- for (i = n = 0; i < w; i++, n += 3) {
+ for (i = n = 0; i < w; i++, n += 4) {
mode->torgb(c, rgb);
- b[n+0] = MAX(0, MIN(0xff, rgb[0]*0xff));
- b[n+1] = MAX(0, MIN(0xff, rgb[1]*0xff));
- b[n+2] = MAX(0, MIN(0xff, rgb[2]*0xff));
+ u = setalpha(D2C(rgb[0])<<24 | D2C(rgb[1])<<16 | D2C(rgb[2])<<8, D2C(c[3]));
+ b[n] = 0xff;
if (mi-2 == i)
- memset(b+n, 0, 3);
+ memset(b+n+1, 0, 3);
else if (mi-1 == i)
- memset(b+n, 0xff, 3);
+ memset(b+n+1, 0xff, 3);
else if (mi+1 == i)
- memset(b+n, 0xff, 3);
+ memset(b+n+1, 0xff, 3);
else if (mi+2 == i)
- memset(b+n, 0, 3);
- else if (mi == i) {
- memmove(colors[curcolor].rgba, rgb, sizeof(rgb));
- colors[curcolor].u = b[n+0]<<24 | b[n+1]<<16 | b[n+2]<<8 | (colors[curcolor].u & 0xff);
+ memset(b+n+1, 0, 3);
+ else {
+ b[n+0] = u & 0xff;
+ b[n+1] = (u>>8) & 0xff;
+ b[n+2] = (u>>16) & 0xff;
+ b[n+3] = (u>>24) & 0xff;
}
+
c[si] = MIN(mode->max[si], c[si] + dt);
}
- loadimage(s, rect, b, 3*w);
+ loadimage(s, rect, b, 4*w);
return s;
}
@@ -194,7 +198,7 @@
colors[i].i = nil;
}
if (colors[i].i == nil) {
- colors[i].i = allocimage(display, Rect(0, 0, 1, 1), BGR24, 1, colors[i].u);
+ colors[i].i = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, setalpha(colors[i].u | 0xff, colors[i].u & 0xff));
if (colors[i].i == nil)
sysfatal("allocimage: %r");
}
@@ -251,6 +255,7 @@
[Cresize] = { nil, nil, CHANRCV },
{ nil, nil, CHANEND },
};
+ Color *c;
char *s;
vlong v;
int i, j;
@@ -283,15 +288,24 @@
}
colors = calloc(ncolors, sizeof(Color));
for (i = 0; i < ncolors; i++) {
- if ((v = strtoll(argv[i], &s, 0)) == 0 && (s == argv[i] || *s || v > 0xffffffff || v < 0)) {
- fprint(2, "invalid color '%s'\n", argv[i]);
+ if (strlen(argv[i]) != nchan*2) {
+ fprint(2, "wrong number of components: '%s'\n", argv[i]);
usage();
}
+ if ((v = strtoll(argv[i], &s, 16)) == 0 && (s == argv[i] || *s || v > 0xffffffff || v < 0)) {
+ fprint(2, "invalid color: '%s'\n", argv[i]);
+ usage();
+ }
+ if (nchan < 4) {
+ v <<= 8;
+ v |= 0xff;
+ }
colors[i].u = v;
for (j = 0; j < 4; j++) {
colors[i].rgba[j] = (double)((v>>24)&0xff) / 255.0;
v <<= 8;
}
+ colors[i].v[3] = colors[i].rgba[3];
mode->fromrgb(colors[i].rgba, colors[i].v);
}
@@ -311,6 +325,8 @@
for (;;) {
next:
+ c = &colors[curcolor];
+
switch (alt(a)) {
case -1:
goto end;
@@ -337,7 +353,9 @@
Rectangle r = srects[i];
r.max.x += 1;
if (ptinrect(m.xy, r)) {
- colors[curcolor].v[i] = MIN(mode->max[i], (m.xy.x - r.min.x) * mode->max[i]/Dx(r));
+ c->v[i] = MIN(mode->max[i], (double)(m.xy.x - r.min.x) * mode->max[i]/(double)(Dx(r)-1));
+ mode->torgb(c->v, c->rgba);
+ c->u = D2C(c->rgba[0])<<24 | D2C(c->rgba[1])<<16 | D2C(c->rgba[2])<<8 | D2C(c->v[3]);
redraw();
goto next;
}