shithub: ifilter

Download patch

ref: 844c071da04aee8af6b52c23184ce8c533a36c19
parent: 4e545a974d714250dd3d693bccabf612a7c18029
author: phil9 <telephil9@gmail.com>
date: Sun Nov 28 16:48:00 EST 2021

add gaussian blur

--- a/blur.c
+++ b/blur.c
@@ -81,6 +81,63 @@
 	return out;
 }
 
+uchar*
+gaussian(uchar *data, int w, int h, int depth)
+{
+	const double E = 2.7182818284590452354;
+	const double Π = 3.14159265358979323846;
+	uchar *out;
+	int kw, x, y, kx, ky;
+	double *k, σ, s, e, n, d, v, r, g, b;
+
+	if(size < 0)
+		sysfatal("gaussian filter needs a size argument");
+	out = malloc(depth*w*h*sizeof(uchar));
+	if(out == nil)
+		return nil;
+	σ = (double)size / 2.0;
+	kw = 2 * size + 1;
+	k = malloc(kw*kw*sizeof(double));
+	if(k == nil)
+		return nil;
+	s = 0.0f;
+	for(y = -size; y <= size; y++){
+		for(x = -size; x <= size; x++){
+			n = (double)(-(x * x + y * y));
+			d = 2 * σ * σ;
+			e = pow(E, n / d);
+			v = e / (2 * Π * σ * σ);
+			k[(x + size) + kw * (y + size)] = v;
+			s += v;
+		}
+	}
+	for(y = 0; y < kw; y++){
+		for(x = 0; x < kw; x++){
+			k[x + kw * y] /= s;
+		}
+	}
+	for(y = size; y < (h - size); y++){
+		for(x = size; x < (w - size); x++){
+			r = g = b = 0.0;
+			for(ky = -size; ky <= size; ky++){
+				for(kx = -size; kx <= size; kx++){
+					v = k[(kx + size) + kw * (ky + size)];
+#define P(X,Y,C) data[((X) + (w*(Y)))*depth + C]
+					r += (double)P(x - kx, y - ky, 0) * v;
+					g += (double)P(x - kx, y - ky, 1) * v;
+					b += (double)P(x - kx, y - ky, 2) * v;
+#undef P
+				}
+			}
+			out[(x + w*y)*depth + 0] = r;
+			out[(x + w*y)*depth + 1] = g;
+			out[(x + w*y)*depth + 2] = b;
+		}
+	}
+	free(k);
+	return out;
+}
+
 void
 usage(void)
 {
@@ -91,6 +148,7 @@
 static Filter filters[] = {
 	{ "box", box },
 	{ "pixelate", pixelate },
+	{ "gaussian", gaussian },
 };
 
 void