shithub: brokentoys

Download patch

ref: f64d365463e5d7b8c0d06bbf0930eeb96d1130a3
parent: a71ef347b03036c8e0a175f4084bc2440d0751e0
author: rodri <rgl@antares-labs.eu>
date: Sun Apr 27 19:25:27 EDT 2025

image: big refactoring

--- a/image/add.c
+++ b/image/add.c
@@ -2,17 +2,20 @@
 #include <libc.h>
 #include <draw.h>
 #include <memdraw.h>
+#include "fns.h"
 
-#define min(a,b)	((a)<(b)?(a):(b))
-#define max(a,b)	((a)>(b)?(a):(b))
-#define clamp(a,b,c)	min(max(a,b),c)
-
 static int saturate;
 
+static int
+opadd(uchar b1, uchar b2)
+{
+	return b1 + b2;
+}
+
 static void
 usage(void)
 {
-	fprint(2, "usage: %s img1 img2\n", argv0);
+	fprint(2, "usage: %s [-s] img1 img2 [imgs...]\n", argv0);
 	exits(nil);
 }
 
@@ -19,53 +22,30 @@
 void
 main(int argc, char *argv[])
 {
-	Memimage *img1, *img2;
-	uchar *p1, *p2;
-	uchar *p1e;
-	ulong c;
-	int fd;
+	Memimage *imgs[2];
+	int i, j, fd;
 
 	ARGBEGIN{
 	case 's': saturate++; break;
 	default: usage();
 	}ARGEND;
-	if(argc != 2)
+	if(argc < 2)
 		usage();
 
-	fd = open(argv[0], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	img1 = readmemimage(fd);
-	if(img1 == nil)
-		sysfatal("readmemimage: %r");
-	close(fd);
+	for(i = 0; i < argc; i++){
+		j = i != 0;
+		fd = eopen(argv[i], OREAD);
+		imgs[j] = ereadmemimage(fd);
+		close(fd);
 
-	fd = open(argv[1], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	img2 = readmemimage(fd);
-	if(img2 == nil)
-		sysfatal("readmemimage: %r");
-	close(fd);
-
-	if(img1->chan != img2->chan || !eqrect(img1->r, img2->r))
-		sysfatal("images shapes differ");
-
-	p1 = img1->data->bdata;
-	p2 = img2->data->bdata;
-	p1e = p1 + Dx(img1->r)*Dy(img1->r)*img1->nchan;
-	while(p1 < p1e){
-		c = *p1;
-		c += *p2++;
-		if(saturate)
-			c = clamp(c, 0, 0xFF);
-		*p1++ += c;
+		if(j){
+			imgbinop(imgs[0], imgs[1], opadd, saturate);
+			freememimage(imgs[1]);
+		}
 	}
 
-	if(writememimage(1, img1) < 0)
-		sysfatal("writememimage: %r");
+	ewritememimage(1, imgs[0]);
+	freememimage(imgs[0]);
 
-	freememimage(img2);
-	freememimage(img1);
 	exits(nil);
 }
--- a/image/convolution.c
+++ b/image/convolution.c
@@ -3,11 +3,8 @@
 #include <bio.h>
 #include <draw.h>
 #include <memdraw.h>
+#include "fns.h"
 
-#define min(a,b)	((a)<(b)?(a):(b))
-#define max(a,b)	((a)>(b)?(a):(b))
-#define clamp(a,b,c)	min(max(a,b),c)
-
 static int dim;
 static int saturate;
 
@@ -48,9 +45,7 @@
 			sysfatal("Brdline: %r");
 		dim = tokenize(line, f, nelem(f));
 	}while(dim < 1);
-	kern = malloc(dim*dim*sizeof(double));
-	if(kern == nil)
-		sysfatal("malloc: %r");
+	kern = emalloc(dim*dim*sizeof(double));
 	for(j = i = 0; i < dim; i++)
 		kern[j*dim+i] = strtod(f[i], nil);
 	j++;
@@ -105,9 +100,7 @@
 	double *ck;
 	int i, j;
 
-	ck = malloc(dim*dim*sizeof(double));
-	if(ck == nil)
-		sysfatal("malloc: %r");
+	ck = emalloc(dim*dim*sizeof(double));
 
 	for(j = 0; j < dim; j++)
 	for(i = 0; i < dim; i++)
@@ -157,14 +150,9 @@
 	double denom, c;
 	int i;
 
-	im = malloc(d->nchan*sizeof(double*));
-	if(im == nil)
-		sysfatal("malloc: %r");
-	for(i = 0; i < d->nchan; i++){
-		im[i] = malloc(dim*dim*sizeof(double));
-		if(im[i] == nil)
-			sysfatal("malloc: %r");
-	}
+	im = emalloc(d->nchan*sizeof(double*));
+	for(i = 0; i < d->nchan; i++)
+		im[i] = emalloc(dim*dim*sizeof(double));
 
 	imr = Rect(0,0,dim,dim);
 	imc = Pt(dim/2, dim/2);
@@ -196,7 +184,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s kernfile\n", argv0);
+	fprint(2, "usage: %s [-s] kernfile\n", argv0);
 	exits("usage");
 }
 
@@ -214,9 +202,7 @@
 	if(argc != 1)
 		usage();
 
-	fd = open(argv[0], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
+	fd = eopen(argv[0], OREAD);
 	kern = readkernel(fd);
 	close(fd);
 	ckern = reverse(kern, dim);
@@ -223,17 +209,11 @@
 	free(kern);
 	kern = ckern;
 
-	in = readmemimage(0);
-	if(in == nil)
-		sysfatal("readmemimage: %r");
+	in = ereadmemimage(0);
+	out = eallocmemimage(in->r, in->chan);
 
-	out = allocmemimage(in->r, in->chan);
-	if(out == nil)
-		sysfatal("allocmemimage: %r");
-
 	imgconvolution(out, in, kern, dim);
-	if(writememimage(1, out) < 0)
-		sysfatal("writememimage: %r");
+	ewritememimage(1, out);
 
 	freememimage(out);
 	freememimage(in);
--- /dev/null
+++ b/image/edge.diag.mat
@@ -1,0 +1,3 @@
+-1 0 1
+0 0 0
+1 0 -1
--- /dev/null
+++ b/image/fns.h
@@ -1,0 +1,11 @@
+#define min(a,b)	((a)<(b)?(a):(b))
+#define max(a,b)	((a)>(b)?(a):(b))
+#define clamp(a,b,c)	min(max(a,b),c)
+
+void *emalloc(ulong);
+void *erealloc(void*, ulong);
+int eopen(char*, int);
+Memimage *eallocmemimage(Rectangle, ulong);
+Memimage *ereadmemimage(int);
+int ewritememimage(int, Memimage*);
+void imgbinop(Memimage*, Memimage*, int(*)(uchar, uchar), int);
--- a/image/mkfile
+++ b/image/mkfile
@@ -7,4 +7,9 @@
 	sub\
 	sobel\
 
+OFILES=\
+	utils.$O\
+
+HFILES=fns.h
+
 </sys/src/cmd/mkmany
--- a/image/sobel.c
+++ b/image/sobel.c
@@ -2,17 +2,27 @@
 #include <libc.h>
 #include <draw.h>
 #include <memdraw.h>
+#include "fns.h"
 
-#define min(a,b)	((a)<(b)?(a):(b))
-#define max(a,b)	((a)>(b)?(a):(b))
-#define clamp(a,b,c)	min(max(a,b),c)
-
 static int saturate;
+static int byangle;
 
+static int
+opsobelΔ(uchar b1, uchar b2)
+{
+	return sqrt(b1*b1 + b2*b2);
+}
+
+static int
+opsobelΘ(uchar b1, uchar b2)
+{
+	return atan2(b2, b1);
+}
+
 static void
 usage(void)
 {
-	fprint(2, "usage: %s img1 img2\n", argv0);
+	fprint(2, "usage: %s [-sa] Gx Gy\n", argv0);
 	exits(nil);
 }
 
@@ -19,52 +29,27 @@
 void
 main(int argc, char *argv[])
 {
-	Memimage *img1, *img2;
-	uchar *p1, *p2;
-	uchar *p1e;
-	ulong c;
-	int fd;
+	Memimage *imgs[2];
+	int i, fd;
 
 	ARGBEGIN{
 	case 's': saturate++; break;
+	case 'a': byangle++; break;
 	default: usage();
 	}ARGEND;
 	if(argc != 2)
 		usage();
 
-	fd = open(argv[0], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	img1 = readmemimage(fd);
-	if(img1 == nil)
-		sysfatal("readmemimage: %r");
-	close(fd);
-
-	fd = open(argv[1], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	img2 = readmemimage(fd);
-	if(img2 == nil)
-		sysfatal("readmemimage: %r");
-	close(fd);
-
-	if(img1->chan != img2->chan || !eqrect(img1->r, img2->r))
-		sysfatal("images shapes differ");
-
-	p1 = img1->data->bdata;
-	p2 = img2->data->bdata;
-	p1e = p1 + Dx(img1->r)*Dy(img1->r)*img1->nchan;
-	while(p1 < p1e){
-		c = sqrt(*p1**p1 + *p2**p2++);
-		if(saturate)
-			c = clamp(c, 0, 0xFF);
-		*p1++ = c;
+	for(i = 0; i < argc; i++){
+		fd = eopen(argv[i], OREAD);
+		imgs[i] = ereadmemimage(fd);
+		close(fd);
 	}
 
-	if(writememimage(1, img1) < 0)
-		sysfatal("writememimage: %r");
+	imgbinop(imgs[0], imgs[1], byangle? opsobelΘ: opsobelΔ, saturate);
+	ewritememimage(1, imgs[0]);
 
-	freememimage(img2);
-	freememimage(img1);
+	freememimage(imgs[1]);
+	freememimage(imgs[0]);
 	exits(nil);
 }
--- a/image/sub.c
+++ b/image/sub.c
@@ -2,11 +2,20 @@
 #include <libc.h>
 #include <draw.h>
 #include <memdraw.h>
+#include "fns.h"
 
+static int saturate;
+
+static int
+opsub(uchar b1, uchar b2)
+{
+	return b1 - b2;
+}
+
 static void
 usage(void)
 {
-	fprint(2, "usage: %s img1 img2\n", argv0);
+	fprint(2, "usage: %s [-s] img1 img2\n", argv0);
 	exits(nil);
 }
 
@@ -13,46 +22,26 @@
 void
 main(int argc, char *argv[])
 {
-	Memimage *img1, *img2;
-	uchar *p1, *p2;
-	uchar *p1e;
-	int fd;
+	Memimage *imgs[2];
+	int i, fd;
 
 	ARGBEGIN{
+	case 's': saturate++; break;
 	default: usage();
 	}ARGEND;
 	if(argc != 2)
 		usage();
 
-	fd = open(argv[0], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	img1 = readmemimage(fd);
-	if(img1 == nil)
-		sysfatal("readmemimage: %r");
-	close(fd);
+	for(i = 0; i < argc; i++){
+		fd = eopen(argv[i], OREAD);
+		imgs[i] = ereadmemimage(fd);
+		close(fd);
+	}
 
-	fd = open(argv[1], OREAD);
-	if(fd < 0)
-		sysfatal("open: %r");
-	img2 = readmemimage(fd);
-	if(img2 == nil)
-		sysfatal("readmemimage: %r");
-	close(fd);
+	imgbinop(imgs[0], imgs[1], opsub, saturate);
+	ewritememimage(1, imgs[0]);
 
-	if(img1->chan != img2->chan || !eqrect(img1->r, img2->r))
-		sysfatal("images shapes differ");
-
-	p1 = img1->data->bdata;
-	p2 = img2->data->bdata;
-	p1e = p1 + Dx(img1->r)*Dy(img1->r)*img1->nchan;
-	while(p1 < p1e)
-		*p1++ -= *p2++;
-
-	if(writememimage(1, img1) < 0)
-		sysfatal("writememimage: %r");
-
-	freememimage(img2);
-	freememimage(img1);
+	freememimage(imgs[1]);
+	freememimage(imgs[0]);
 	exits(nil);
 }
--- /dev/null
+++ b/image/utils.c
@@ -1,0 +1,100 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include "fns.h"
+
+void *
+emalloc(ulong n)
+{
+	void *p;
+
+	p = malloc(n);
+	if(p == nil)
+		sysfatal("malloc: %r");
+	setmalloctag(p, getcallerpc(&n));
+	return p;
+}
+
+void *
+erealloc(void *p, ulong n)
+{
+	void *np;
+
+	np = realloc(p, n);
+	if(np == nil){
+		if(n == 0)
+			return nil;
+		sysfatal("realloc: %r");
+	}
+	if(p == nil)
+		setmalloctag(np, getcallerpc(&p));
+	else
+		setrealloctag(np, getcallerpc(&p));
+	return np;
+}
+
+int
+eopen(char *file, int omode)
+{
+	int fd;
+
+	fd = open(file, omode);
+	if(fd < 0)
+		sysfatal("open: %r");
+	return fd;
+}
+
+Memimage *
+eallocmemimage(Rectangle r, ulong chan)
+{
+	Memimage *i;
+
+	i = allocmemimage(r, chan);
+	if(i == nil)
+		sysfatal("allocmemimage: %r");
+	memfillcolor(i, DTransparent);
+	return i;
+}
+
+Memimage *
+ereadmemimage(int fd)
+{
+	Memimage *i;
+
+	i = readmemimage(fd);
+	if(i == nil)
+		sysfatal("readmemimage: %r");
+	return i;
+}
+
+int
+ewritememimage(int fd, Memimage *i)
+{
+	int rc;
+
+	rc = writememimage(fd, i);
+	if(rc < 0)
+		sysfatal("writememimage: %r");
+	return rc;
+}
+
+void
+imgbinop(Memimage *i1, Memimage *i2, int(*op)(uchar, uchar), int saturate)
+{
+	uchar *p1, *p1e, *p2;
+	int c;
+
+	if(i1->chan != i2->chan || !eqrect(i1->r, i2->r))
+		sysfatal("images shapes differ");
+
+	p1 = i1->data->bdata;
+	p2 = i2->data->bdata;
+	p1e = p1 + Dx(i1->r)*Dy(i1->r)*i1->nchan;
+	while(p1 < p1e){
+		c = op(*p1, *p2++);
+		if(saturate)
+			c = clamp(c, 0, 0xFF);
+		*p1++ = c;
+	}
+}
--