shithub: hj264

Download patch

ref: 1a3f7ac2dc211ff277d45e3dac690680fdb87bc6
parent: 6ea15ae0d18aa67aa2064137329e285e13a4af9a
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Mar 10 21:29:48 EDT 2025

add -G GAMMA option

--- a/hj264.c
+++ b/hj264.c
@@ -64,6 +64,8 @@
 
 static uvlong tstart, debug;
 static int opt, noenc;
+static double gamma = 1.0;
+static u8int gammatbl[256];
 
 #pragma varargck type "ℏ" int
 static int
@@ -222,25 +224,42 @@
 static void
 encthread(void *p)
 {
-	u8int *data, v[12];
+	u8int *data, v[12], *bgrx;
+	int sz, w, h, x, y;
 	Img *img, *prev;
 	uvlong ts;
-	Hj264 *h;
-	int sz;
+	Hj264 *hj;
 
 	threadsetname("hj264/encthread");
 
-	h = p;
+	hj = p;
 	prev = nil;
 	for(;;){
-		if(recv(h->frame, &img) < 0)
+		if(recv(hj->frame, &img) < 0)
 			break;
-		if(opt && prev != nil && memcmp(img->bgrx, prev->bgrx, img->w*img->h*4) == 0){
+
+		bgrx = img->bgrx;
+		w = img->w;
+		h = img->h;
+
+		if(opt && prev != nil && memcmp(bgrx, prev->bgrx, w*h*4) == 0){
 			free(img);
 			continue;
 		}
 
-		xrgb2yuv420(img->bgrx, img->w, img->h, &h->yuv);
+		if(gamma != 1.0){
+			for(y = 0; y < h; y++){
+				for(x = 0; x < w; x++){
+					bgrx[0] = gammatbl[bgrx[0]];
+					bgrx[1] = gammatbl[bgrx[1]];
+					bgrx[2] = gammatbl[bgrx[2]];
+					bgrx += 4;
+				}
+			}
+			bgrx = img->bgrx;
+		}
+
+		xrgb2yuv420(bgrx, w, h, &hj->yuv);
 		ts = img->ns / Nmsec;
 		if(opt){
 			free(prev);
@@ -251,9 +270,9 @@
 
 		if(noenc)
 			continue;
-		if(hj264_encode(h, &data, &sz) != 0)
+		if(hj264_encode(hj, &data, &sz) != 0)
 			sysfatal("hj264_encode: %r");
-		if(h->fmt == FmtIVF){
+		if(hj->fmt == FmtIVF){
 			v[0] = sz;
 			v[1] = sz >> 8;
 			v[2] = sz >> 16;
@@ -266,18 +285,18 @@
 			v[9] = ts >> 40;
 			v[10] = ts >> 48;
 			v[11] = ts >> 56;
-			if(Bwrite(&h->out, v, 12) != 12)
+			if(Bwrite(&hj->out, v, 12) != 12)
 				break;
 		}
-		if(Bwrite(&h->out, data, sz) != sz)
+		if(Bwrite(&hj->out, data, sz) != sz)
 			break;
 	}
 
-	Bflush(&h->out);
+	Bflush(&hj->out);
 
-	chanclose(h->frame);
-	if(h->done != nil)
-		sendp(h->done, nil);
+	chanclose(hj->frame);
+	if(hj->done != nil)
+		sendp(hj->done, nil);
 
 	free(prev);
 
@@ -327,7 +346,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-D] [-f FPS] [-F FORMAT] [-g GOP] [-n THREADS] [-o] [-k KBPS] [-q 0…10] [-Q QP] FILE\n", argv0);
+	fprint(2, "usage: %s [-D] [-f FPS] [-F FORMAT] [-g GOP] [-G GAMMA] [-n THREADS] [-o] [-k KBPS] [-q 0…10] [-Q QP] FILE\n", argv0);
 	threadexitsall("usage");
 }
 
@@ -334,7 +353,7 @@
 int
 main(int argc, char **argv)
 {
-	int nthreads, fps, kbps, denoise, quality, qp, gop;
+	int i, nthreads, fps, kbps, denoise, quality, qp, gop;
 	uvlong fstart, fend, f₀, nframes;
 	char *s, tmp[61], *f[5];
 	int ww₀, hh₀, ww, hh, in, fmt;
@@ -378,6 +397,9 @@
 	case 'g':
 		gop = atoi(EARGF(usage()));
 		break;
+	case 'G':
+		gamma = atof(EARGF(usage()));
+		break;
 	case 'k':
 		kbps = atoi(EARGF(usage()));
 		break;
@@ -410,6 +432,12 @@
 		sysfatal("input: %r");
 
 	fmtinstall(L'ℏ', hjerror);
+
+	if(gamma != 1.0){
+		gamma = 1.0/gamma;
+		for(i = 0; i < nelem(gammatbl); i++)
+			gammatbl[i] = 255.0*pow((double)i/255.0, gamma);
+	}
 
 	tmp[60] = 0;
 	if(readn(in, tmp, 60) != 60 || tokenize(tmp, f, 5) != 5)
--