shithub: ifilter

Download patch

ref: dbbdb0ac0c7f7f41541b71d042519b5bdb0b95a8
parent: 989ecb1ad9eab0de1363c8a59a3ed33616e1b8c8
author: phil9 <telephil9@gmail.com>
date: Fri Nov 26 16:11:38 EST 2021

add blur(1) a simple blurring filter

	new tool that implements blur filters (only one atm).
	It works the same way as ifilter.

--- a/README
+++ b/README
@@ -1,18 +1,29 @@
 ifilter
 =======
-Basic image color filters.
+Basic image filters.
 
-ifilter reads an image from standard input, applies a color filter
+Filters read an image from standard input, apply a transformation
 and dumps the resulting image to standard output.
 
-Available color filters are:
+ifilter:
+--------
+ifilter implements basic color filters.
+
+Usage: cfilter [-f factor] [grayscale|sepia|invert|shade|tint]
+
+Available filters are:
 - grayscale
 - sepia
 - invert
-- shade
-- tint
+- shade(1)
+- tint(1)
 
-usage: ifilter [-f factor] [grayscale|sepia|invert|shade|tint]
+1: these filters use the factor argument
 
-Note: factor is used for the shade and tint filters and ignored otherwise.
+blur:
+-----
+blur implements blurring algorithms.
+
+Available filters are:
+- box: 3x3 box blur
 
--- /dev/null
+++ b/blur.c
@@ -1,0 +1,105 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+
+typedef struct Filter Filter;
+
+struct Filter
+{
+	const char *name;
+	uchar* (*filter)(uchar *data, int w, int h, int depth);
+};
+
+enum { R, G, B };
+
+uchar*
+box(uchar *data, int w, int h, int depth)
+{
+	uchar *out;
+	int x, y, r, c, s;
+
+	r = w * depth;
+	out = malloc(depth*w*h*sizeof(uchar));
+	if(out == nil)
+		return nil;
+	/* box blur is not defined for edge points */
+	for(y = 1; y < h - 1; y++){
+		for(x = 1; x < w - 1; x++){
+			for(c = 0; c < 3; c++){ /* R G B */
+				s = data[(x - 1)*depth + r * (y + 1) + c] +
+					data[(x + 0)*depth + r * (y + 1) + c] +
+					data[(x + 1)*depth + r * (y + 1) + c] +
+					data[(x - 1)*depth + r * (y + 0) + c] +
+					data[(x + 0)*depth + r * (y + 0) + c] +
+					data[(x + 1)*depth + r * (y + 0) + c] +
+					data[(x - 1)*depth + r * (y - 1) + c] +
+					data[(x + 0)*depth + r * (y - 1) + c] +
+					data[(x + 1)*depth + r * (y - 1) + c];
+				out[x * depth + r * y + c] = s / 9;
+			}
+		}
+	}
+	return out;
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [box]\n", argv0);
+	exits("usage");
+}
+
+static Filter filters[] = {
+	{ "box", box },
+};
+
+void
+main(int argc, char *argv[])
+{
+	Memimage *o, *i;
+	int w, h, n;
+	uchar *buf, *out;
+	Filter *f;
+
+	f = nil;
+	ARGBEGIN{
+	default:
+		usage();
+		break;
+	}ARGEND;
+	if(argc!=1)
+		usage();
+	for(n=0; n<nelem(filters); n++){
+		if(strcmp(*argv, filters[n].name)==0){
+			f = filters+n;
+			break;
+		}
+	}
+	if(f==nil)
+		usage();
+	if(memimageinit()<0)
+		sysfatal("memimageinit: %r");
+	o = readmemimage(0);
+	if(o==nil)
+		sysfatal("readmemimage: %r");
+	i = allocmemimage(rectsubpt(o->r, o->r.min), XRGB32);
+	memimagedraw(i, i->r, o, o->r.min, nil, ZP, S);
+	freememimage(o);
+	w = Dx(i->r);
+	h = Dy(i->r);
+	n = 4*w*h*sizeof(uchar);
+	buf = malloc(n);
+	if(buf==nil)
+		sysfatal("malloc: %r");
+	if(unloadmemimage(i, i->r, buf, n)<0)
+		sysfatal("unloadmemimage: %r");
+	freememimage(i);
+	out = f->filter(buf, w, h, 4);
+	if(out == nil)
+		sysfatal("filter '%s' failed: %r", f->name);
+	print("   x8r8g8b8 %11d %11d %11d %11d ", 0, 0, w, h);
+	write(1, out, n);
+	exits(nil);
+}
+
--- a/mkfile
+++ b/mkfile
@@ -2,8 +2,9 @@
 
 BIN=/$objtype/bin
 CFLAGS=-FTVw
-TARG=ifilter
-OFILES=ifilter.$O
+TARG=ifilter blur
 
-</sys/src/cmd/mkone
+default:V: all
+
+</sys/src/cmd/mkmany