shithub: picker

Download patch

ref: bba1a7594cf3479de9c836c5004d2cce49fd15f4
parent: 52fd69b721bf44e66fc82f103ce90f74a43fa2a8
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
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;
 					}