shithub: libgraphics

Download patch

ref: 19f4448a73daebe4a5218639839d5982ad1e7a44
parent: fe912350508c4d8a96db16c151df0af574a1e84f
author: rodri <rgl@antares-labs.eu>
date: Mon Feb 16 14:28:45 EST 2026

texture: use integers until the very end in memreadcolor()

--- a/color.c
+++ b/color.c
@@ -173,6 +173,30 @@
 	return c;
 }
 
+ulong
+srgb2linearul(ulong c)
+{
+	ulong l;
+
+	l = c & 0xff;
+	l |= srgb2lineartab[c>>8  & 0xff] << 8;
+	l |= srgb2lineartab[c>>16 & 0xff] << 16;
+	l |= srgb2lineartab[c>>24 & 0xff] << 24;
+	return l;
+}
+
+ulong
+linear2srgbul(ulong c)
+{
+	ulong l;
+
+	l = c & 0xff;
+	l |= linear2srgbtab[c>>8  & 0xff] << 8;
+	l |= linear2srgbtab[c>>16 & 0xff] << 16;
+	l |= linear2srgbtab[c>>24 & 0xff] << 24;
+	return l;
+}
+
 
 /* tone mapping */
 
--- a/graphics.h
+++ b/graphics.h
@@ -512,6 +512,8 @@
 int hasalpha(ulong);
 Color srgb2linear(Color);
 Color linear2srgb(Color);
+ulong srgb2linearul(ulong);
+ulong linear2srgbul(ulong);
 Color aces(Color);
 Color aces2(Color);
 
--- a/texture.c
+++ b/texture.c
@@ -28,56 +28,59 @@
 	return Pt(uv.x*Dx(t->image->r), (1 - uv.y)*Dy(t->image->r));
 }
 
-static Color
-cbuf2col(uchar b[4])
+#define divalpha1(a, v)		((((v)<<8)-(v))/(a))
+
+static ulong
+divalpha(ulong c)
 {
-	Color c;
+	ushort r, g, b, a;
 
-	c.a = b[0] / 255.0;
-	c.b = b[1] / 255.0;
-	c.g = b[2] / 255.0;
-	c.r = b[3] / 255.0;
-	return c;
+	a = c     & 0xff;
+	b = c>>8  & 0xff;
+	g = c>>16 & 0xff;
+	r = c>>24 & 0xff;
+	r = divalpha1(a, r);
+	g = divalpha1(a, g);
+	b = divalpha1(a, b);
+	return (r<<24)|(g<<16)|(b<<8)|a;
 }
 
 static Color
 memreadcolor(Texture *t, Point sp)
 {
-	Color c;
-	uchar cbuf[4];
+	union {
+		uchar b[4];
+		ulong c;
+	} cbuf;
 
 	switch(t->image->chan){
 	default: sysfatal("unsupported texture format");
 	case RGB24:
-		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf+1, sizeof cbuf - 1);
-		cbuf[0] = 0xFF;
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf.b+1, sizeof cbuf - 1);
+		cbuf.b[0] = 0xFF;
 		break;
 	case RGBA32:
-		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf, sizeof cbuf);
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf.b, sizeof cbuf);
 		break;
 	case XRGB32:
-		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf, sizeof cbuf);
-		memmove(cbuf+1, cbuf, 3);
-		cbuf[0] = 0xFF;
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf.b, sizeof cbuf);
+		memmove(cbuf.b+1, cbuf.b, 3);
+		cbuf.b[0] = 0xFF;
 		break;
 	case GREY8:
-		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf+1, 1);
-		memset(cbuf+2, cbuf[1], 2);
-		cbuf[0] = 0xFF;
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf.b+1, 1);
+		memset(cbuf.b+2, cbuf.b[1], 2);
+		cbuf.b[0] = 0xFF;
 		break;
 	}
-
-	c = cbuf2col(cbuf);
 	/* remove pre-multiplied alpha */
-	if(hasalpha(t->image->chan) && c.a > 0 && c.a < 1){
-		c.r /= c.a;
-		c.g /= c.a;
-		c.b /= c.a;
-	}
+	if(hasalpha(t->image->chan) && cbuf.b[0] != 0)
+		cbuf.c = divalpha(cbuf.c);
+
 	if(t->type == sRGBTexture)
-		c = srgb2linear(c);
+		cbuf.c = srgb2linearul(cbuf.c);
 
-	return c;
+	return ul2col(cbuf.c);
 }
 
 /*
--