code: plan9front

Download patch

ref: 7fcf96b44dc4765605b827ba49d389b5711d7e72
parent: 7a5a9b592af208aac719a6cfc0dacf44a5eebcef
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Nov 13 13:36:46 EST 2022

nusb/cam: rewrite yuy2convert with integer arithmetic

--- a/sys/src/cmd/nusb/cam/video.c
+++ b/sys/src/cmd/nusb/cam/video.c
@@ -63,38 +63,34 @@
 yuy2convert(Format *, VSUncompressedFrame *g, uchar *in, VFrame *out)
 {
 	int y, x, w, h;
-	double Y0, Y1, U, V, R, G, B;
-	uchar *ip, *op;
-	
+	int R₀, G₀, B₀, R₁, G₁, B₁;
+	int Cb, Cr, z, Y₀, Y₁;
+	uchar *op;
+
 	w = GET2(g->wWidth);
 	h = GET2(g->wHeight);
 	op = out->d + out->n;
-	ip = in;
 	for(y = 0; y < h; y++)
-		for(x = 0; x < w; x += 2){
-			Y0 = ((int)ip[0] - 16) / 219.0;
-			Y1 = ((int)ip[2] - 16) / 219.0;
-			U = ((int)ip[1] - 128) / 224.0;
-			V = ((int)ip[3] - 128) / 224.0;
-			ip += 4;
-			R = Y0 + V;
-			B = Y0 + U;
-			G = Y0 - 0.509 * V - 0.194 * U;
-			if(R < 0) R = 0; if(R > 1) R = 1;
-			if(G < 0) G = 0; if(G > 1) G = 1;
-			if(B < 0) B = 0; if(B > 1) B = 1;
-			*op++ = R * 255;
-			*op++ = G * 255;
-			*op++ = B * 255;
-			R = Y1 + V;
-			B = Y1 + U;
-			G = Y1 - 0.509 * V - 0.194 * U;
-			if(R < 0) R = 0; if(R > 1) R = 1;
-			if(G < 0) G = 0; if(G > 1) G = 1;
-			if(B < 0) B = 0; if(B > 1) B = 1;
-			*op++ = R * 255;
-			*op++ = G * 255;
-			*op++ = B * 255;
+		for(x = 0; x < w; x += 2, in += 4){
+			Y₀ = in[0] * 0x10101;
+			Cb = in[1] - 0x80;
+			Y₁ = in[2] * 0x10101;
+			Cr = in[3] - 0x80;
+			z = 22554*Cb + 46802*Cr;
+			Cb *= 116130;
+			Cr *= 91881;
+			R₀ = Y₀ + Cr;
+			G₀ = Y₀ - z;
+			B₀ = Y₀ + Cb;
+			R₁ = Y₁ + Cr;
+			G₁ = Y₁ - z;
+			B₁ = Y₁ + Cb;
+			*op++ = (R₀>>24) ? ~(R₀>>31) : (R₀>>16);
+			*op++ = (G₀>>24) ? ~(G₀>>31) : (G₀>>16);
+			*op++ = (B₀>>24) ? ~(B₀>>31) : (B₀>>16);
+			*op++ = (R₁>>24) ? ~(R₁>>31) : (R₁>>16);
+			*op++ = (G₁>>24) ? ~(G₁>>31) : (G₁>>16);
+			*op++ = (B₁>>24) ? ~(B₁>>31) : (B₁>>16);
 		}
 	out->n = op - out->d;
 }