blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

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:
man/blind-kernel.1 | 128++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
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) */