commit a79568e8ab6bd516bef02e87855c23526356f20a
parent ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3
Author: Mattias Andrée <maandree@kth.se>
Date: Wed, 26 Jul 2017 17:50:58 +0200
blind-kernel: add more kernels
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
M | man/blind-kernel.1 | | | 128 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
M | src/blind-kernel.c | | | 98 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
2 files changed, 198 insertions(+), 28 deletions(-)
diff --git a/man/blind-kernel.1 b/man/blind-kernel.1
@@ -20,6 +20,85 @@ argument and is tuned with
.IR parameter s.
.SH KERNELS
.TP
+.RI ' \fBbox\ blur\fP '\ [-w\ weight ]\ [ spread \ |\ x-spread \ y-spread ]
+Creates a box blur kernel. Unless
+.B -w
+is used, the kernel is unweighted, otherwise it has the specified
+.IR weight .
+The kernel will have the spread 1, the specified
+.IR spread ,
+or
+.I x-spread
+as the horizontal spread and
+.I y-spread
+as the vertical spread.
+.TP
+.BR emboss \ [\fIdirection\fP]
+Create an emboss kernel with the specified
+.IR direction .
+The
+.I direction
+must be
+.BR N ;
+.BR NW
+or
+.BR WN ;
+.BR W ;
+.BR SW
+or
+.BR WS ;
+.BR S ;
+.BR SE
+or
+.BR ES ;
+.BR E ;
+.BR NE
+or
+.BR EN .
+If no
+.I direction
+is specified,
+.B SE
+is used.
+.TP
+.RI \fBgaussian\fP\ [-s\ spread ]\ [-u]\ standard-deviation
+Creates a Gaussian blur kernel with the standard deviation
+.IR standard-deviation .
+If
+.B -u
+is used, the a Gaussian unsharpen kernel is created. If
+.B -s
+is specified, the specified
+.I spread
+will be used, otherwise the spread will be selected automatically.
+.TP
+.BI gradient\ direction
+Create a gradient detection kernel with the specified
+.IR direction .
+The
+.I direction
+must be
+.BR N ;
+.BR NW
+or
+.BR WN ;
+.BR W ;
+.BR SW
+or
+.BR WS ;
+.BR S
+or
+.BR H ;
+.BR SE
+or
+.BR ES ;
+.BR E
+or
+.BR V ;
+.BR NE
+or
+.BR EN .
+.TP
.BI kirsch\ direction
Create a Kirsch kernel with the specified
.IR direction .
@@ -56,34 +135,37 @@ or
or
.BR EN .
.TP
-.RI ' \fBbox\ blur\fP '\ [-w\ weight ]\ [ spread \ |\ x-spread \ y-spread ]
-Creates a box blur kernel. Unless
-.B -w
-is used, the kernel is unweighted, otherwise it has the specified
-.IR weight .
-The kernel will have the spread 1, the specified
-.IR spread ,
-or
-.I x-spread
-as the horizontal spread and
-.I y-spread
-as the vertical spread.
-.TP
.BR sharpen \ [-i]
Creates a sharpen kernel. If
.B -i
is used, an intensified sharpen kernel is created.
.TP
-.RI \fBgaussian\fP\ [-s\ spread ]\ [-u]\ standard-deviation
-Creates a Gaussian blur kernel with the standard deviation
-.IR standard-deviation .
-If
-.B -u
-is used, the a Gaussian unsharpen kernel is created. If
-.B -s
-is specified, the specified
-.I spread
-will be used, otherwise the spread will be selected automatically.
+.BI sobel\ direction
+Create a Sobel operator kernel with the specified
+.IR direction .
+The
+.I direction
+must be
+.BR N
+or
+.BR H ;
+.BR NW
+or
+.BR WN ;
+.BR W
+or
+.BR V ;
+.BR SW
+or
+.BR WS ;
+.BR S ;
+.BR SE
+or
+.BR ES ;
+.BR E ;
+.BR NE
+or
+.BR EN .
.SH OPTIONS
.TP
.B -a
diff --git a/src/blind-kernel.c b/src/blind-kernel.c
@@ -5,9 +5,13 @@ USAGE("[-xyza] kernel [parameter] ...")
#define SUBUSAGE(FORMAT) "usage: %s [-xyza] " FORMAT "\n", argv0
#define STRCASEEQ3(A, B1, B2, B3) (!strcasecmp(A, B1) || !strcasecmp(A, B2) || !strcasecmp(A, B3))
+#define STRCASEEQ2(A, B1, B2) (!strcasecmp(A, B1) || !strcasecmp(A, B2))
#define LIST_KERNELS\
X(kernel_kirsch, "kirsch")\
+ X(kernel_gradient, "gradient")\
+ X(kernel_sobel, "sobel")\
+ X(kernel_emboss, "emboss")\
X(kernel_box_blur, "box blur")\
X(kernel_sharpen, "sharpen")\
X(kernel_gaussian, "gaussian")
@@ -42,6 +46,95 @@ kernel_kirsch(int argc, char *argv[], size_t *rows, size_t *cols, double **free_
}
static const double *
+kernel_gradient(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
+{
+ static const double matrices[][9] = {
+ { 1, 1, 1, 0, 0, 0, -1, -1, -1},
+ { 1, 1, 0, 1, 0, -1, 0, -1, -1},
+ { 1, 0, -1, 1, 0, -1, 1, 0, -1},
+ { 0, -1, -1, 1, 0, -1, 1, 1, 0},
+ {-1, -1, -1, 0, 0, 0, 1, 1, 1},
+ {-1, -1, 0, -1, 0, 1, 0, 1, 1},
+ {-1, 0, 1, -1, 0, 1, -1, 0, 1},
+ { 0, 1, 1, -1, 0, 1, -1, -1, 0},
+ };
+ *free_this = NULL;
+ *rows = *cols = 3;
+ if (argc != 1)
+ eprintf(SUBUSAGE("'gradient' direction"));
+ if (STRCASEEQ2(argv[0], "N", "N")) return matrices[0];
+ if (STRCASEEQ2(argv[0], "NW", "WN")) return matrices[1];
+ if (STRCASEEQ2(argv[0], "W", "W")) return matrices[2];
+ if (STRCASEEQ2(argv[0], "SW", "WS")) return matrices[3];
+ if (STRCASEEQ2(argv[0], "S", "H")) return matrices[4];
+ if (STRCASEEQ2(argv[0], "SE", "ES")) return matrices[5];
+ if (STRCASEEQ2(argv[0], "E", "V")) return matrices[6];
+ if (STRCASEEQ2(argv[0], "NE", "EN")) return matrices[7];
+ eprintf("unrecognised direction: %s\n", argv[0]);
+ return NULL;
+}
+
+static const double *
+kernel_sobel(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
+{
+ static const double matrices[][9] = {
+ { 1, 2, 1, 0, 0, 0, -1, -2, -1},
+ { 2, 1, 0, 1, 0, -1, 0, -1, -2},
+ { 1, 0, -1, 2, 0, -2, 1, 0, -1},
+ { 0, -1, -2, 1, 0, -1, 2, 1, 0},
+ {-1, -2, -1, 0, 0, 0, 1, 2, 1},
+ {-2, -1, 0, -1, 0, 1, 0, 1, 2},
+ {-1, 0, 1, -2, 0, 2, -1, 0, 1},
+ { 0, 1, 2, -1, 0, 1, -2, -1, 0},
+ };
+ *free_this = NULL;
+ *rows = *cols = 3;
+ if (argc != 1)
+ eprintf(SUBUSAGE("'sobel' direction"));
+ if (STRCASEEQ2(argv[0], "N", "H")) return matrices[0];
+ if (STRCASEEQ2(argv[0], "NW", "WN")) return matrices[1];
+ if (STRCASEEQ2(argv[0], "W", "V")) return matrices[2];
+ if (STRCASEEQ2(argv[0], "SW", "WS")) return matrices[3];
+ if (STRCASEEQ2(argv[0], "S", "S")) return matrices[4];
+ if (STRCASEEQ2(argv[0], "SE", "ES")) return matrices[5];
+ if (STRCASEEQ2(argv[0], "E", "E")) return matrices[6];
+ if (STRCASEEQ2(argv[0], "NE", "EN")) return matrices[7];
+ eprintf("unrecognised direction: %s\n", argv[0]);
+ return NULL;
+}
+
+static const double *
+kernel_emboss(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
+{
+ static const double matrices[][9] = {
+ { 1, 2, 1, 0, 1, 0, -1, -2, -1},
+ { 2, 1, 0, 1, 1, -1, 0, -1, -2},
+ { 1, 0, -1, 2, 1, -2, 1, 0, -1},
+ { 0, -1, -2, 1, 1, -1, 2, 1, 0},
+ {-1, -2, -1, 0, 1, 0, 1, 2, 1},
+ {-2, -1, 0, -1, 1, 1, 0, 1, 2},
+ {-1, 0, 1, -2, 1, 2, -1, 0, 1},
+ { 0, 1, 2, -1, 1, 1, -2, -1, 0},
+ };
+ *free_this = NULL;
+ *rows = *cols = 3;
+ if (argc > 1)
+ eprintf(SUBUSAGE("'emboss' [direction]"));
+ if (!argc)
+ return matrices[5];
+ if (STRCASEEQ2(argv[0], "N", "N")) return matrices[0];
+ if (STRCASEEQ2(argv[0], "NW", "WN")) return matrices[1];
+ if (STRCASEEQ2(argv[0], "W", "W")) return matrices[2];
+ if (STRCASEEQ2(argv[0], "SW", "WS")) return matrices[3];
+ if (STRCASEEQ2(argv[0], "S", "S")) return matrices[4];
+ if (STRCASEEQ2(argv[0], "SE", "ES")) return matrices[5];
+ if (STRCASEEQ2(argv[0], "E", "E")) return matrices[6];
+ if (STRCASEEQ2(argv[0], "NE", "EN")) return matrices[7];
+ eprintf("unrecognised direction: %s\n", argv[0]);
+ return NULL;
+}
+
+static const double *
kernel_box_blur(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
{
size_t sx = 1, sy = 1, i, n;
@@ -191,11 +284,6 @@ usage:
Edge detection: MATRIX(-1, -1, -1, -1, 8, -1, -1, -1, -1)
Edge detection: MATRIX( 0, 0, 0, -1, 2, -1, 0, 0, 0) [H]
Edge detection: MATRIX( 0, -1, 0, 0, 2, 0, 0, -1, 0) [V]
- Gradient detection: MATRIX(-1, -1, -1, 0, 0, 0, 1, 1, 1) [H]
- Gradient detection: MATRIX(-1, 0, 1, -1, 0, 1, -1, 0, 1) [V]
- Sobel operator: MATRIX( 1, 2, 1, 0, 0, 0, -1, -2, -1) [H]
- Sobel operator: MATRIX( 1, 0, -1, 2, 0, -2, 1, 0, -1) [V]
- Emboss: MATRIX(-2, -1, 0, -1, 1, 1, 0, 1, 2)
Edge enhance: MATRIX( 0, 0, 0, -1, 1, 0, 0, 0, 0)
*/