aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-kernel.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-05-14 14:21:02 +0200
committerMattias Andrée <maandree@kth.se>2017-05-14 14:21:02 +0200
commit45c25008cbea5241fb711dc7a9ba21ec631bce64 (patch)
tree2fb70aa8fc0c52ea97cf14adb3fa116f08a5b1e3 /src/blind-kernel.c
parentAdd missing default case and use strcasecmp for cheching selecting direction (diff)
downloadblind-45c25008cbea5241fb711dc7a9ba21ec631bce64.tar.gz
blind-45c25008cbea5241fb711dc7a9ba21ec631bce64.tar.bz2
blind-45c25008cbea5241fb711dc7a9ba21ec631bce64.tar.xz
Fix errors in blind-kernel and add -w to box blur, and update TODO
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/blind-kernel.c')
-rw-r--r--src/blind-kernel.c109
1 files changed, 88 insertions, 21 deletions
diff --git a/src/blind-kernel.c b/src/blind-kernel.c
index 4542e53..3e439ef 100644
--- a/src/blind-kernel.c
+++ b/src/blind-kernel.c
@@ -8,7 +8,6 @@
USAGE("[-xyza] kernel [parameter] ...")
#define SUBUSAGE(FORMAT) "Usage: %s [-xyza] " FORMAT, argv0
-#define MATRIX(...) ((const double[]){__VA_ARGS__});
#define STRCASEEQ3(A, B1, B2, B3) (!strcasecmp(A, B1) || !strcasecmp(A, B2) || !strcasecmp(A, B3))
#define LIST_KERNELS\
@@ -20,18 +19,28 @@ USAGE("[-xyza] kernel [parameter] ...")
static const double *
kernel_kirsch(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
{
+ static const double matrices[][9] = {
+ { 5, 5, 5, -3, 0, -3, -3, -3, -3},
+ { 5, 5, -3, 5, 0, -3, -3, -3, -3},
+ { 5, -3, -3, 5, 0, -3, 5, -3, -3},
+ {-3, -3, -3, 5, 0, -3, 5, 5, -3},
+ {-3, -3, -3, -3, 0, -3, 5, 5, 5},
+ {-3, -3, -3, -3, 0, 5, -3, 5, 5},
+ {-3, -3, 5, -3, 0, 5, -3, -3, 5},
+ {-3, 5, 5, -3, 0, 5, -3, -3, -3},
+ };
*free_this = NULL;
*rows = *cols = 3;
if (argc != 1)
eprintf(SUBUSAGE("'kirsch' direction"));
- if (STRCASEEQ3(argv[0], "1", "N", "N")) return MATRIX( 5, 5, 5, -3, 0, -3, -3, -3, -3);
- if (STRCASEEQ3(argv[0], "2", "NW", "WN")) return MATRIX( 5, 5, -3, 5, 0, -3, -3, -3, -3);
- if (STRCASEEQ3(argv[0], "3", "W", "W")) return MATRIX( 5, -3, -3, 5, 0, -3, 5, -3, -3);
- if (STRCASEEQ3(argv[0], "4", "SW", "WS")) return MATRIX(-3, -3, -3, 5, 0, -3, 5, 5, -3);
- if (STRCASEEQ3(argv[0], "5", "S", "S")) return MATRIX(-3, -3, -3, -3, 0, -3, 5, 5, 5);
- if (STRCASEEQ3(argv[0], "6", "SE", "ES")) return MATRIX(-3, -3, -3, -3, 0, 5, -3, 5, 5);
- if (STRCASEEQ3(argv[0], "7", "E", "E")) return MATRIX(-3, -3, 5, -3, 0, 5, -3, -3, 5);
- if (STRCASEEQ3(argv[0], "8", "NE", "EN")) return MATRIX(-3, 5, 5, -3, 0, 5, -3, -3, -3);
+ if (STRCASEEQ3(argv[0], "1", "N", "N")) return matrices[0];
+ if (STRCASEEQ3(argv[0], "2", "NW", "WN")) return matrices[1];
+ if (STRCASEEQ3(argv[0], "3", "W", "W")) return matrices[2];
+ if (STRCASEEQ3(argv[0], "4", "SW", "WS")) return matrices[3];
+ if (STRCASEEQ3(argv[0], "5", "S", "S")) return matrices[4];
+ if (STRCASEEQ3(argv[0], "6", "SE", "ES")) return matrices[5];
+ if (STRCASEEQ3(argv[0], "7", "E", "E")) return matrices[6];
+ if (STRCASEEQ3(argv[0], "8", "NE", "EN")) return matrices[7];
eprintf("Unrecognised direction: %s\n", argv[0]);
return NULL;
}
@@ -39,41 +48,85 @@ kernel_kirsch(int argc, char *argv[], size_t *rows, size_t *cols, double **free_
static const double *
kernel_box_blur(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
{
- size_t sx, sy, i, n;
- double *cells, value;
+ size_t sx = 1, sy = 1, i, n;
+ double *cells, value, weight = 0;
+ int have_weight = 0;
+ char *arg;
*free_this = NULL;
*rows = *cols = 3;
- if (argc > 3)
- eprintf(SUBUSAGE("'box blur' [spread | x-spread y-spread]"));
- if (!argc)
- return MATRIX(1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0,
- 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0,
- 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0);
+
+#define argv0 arg
+ argc++, argv--;
+ ARGBEGIN {
+ case 'w':
+ if (!(arg = ARGF()))
+ goto usage;
+ weight = etolf_flag('w', arg);
+ have_weight = 1;
+ break;
+ default:
+ goto usage;
+ } ARGEND;
+#undef argv0
+
if (argc == 1) {
sx = sy = etozu_arg("spread", argv[0], 0, SIZE_MAX / 2);
- } else {
+ } else if (argc == 2) {
sx = etozu_arg("x-spread", argv[0], 0, SIZE_MAX / 2);
sy = etozu_arg("y-spread", argv[1], 0, SIZE_MAX / 2);
+ } else if (argc) {
+ goto usage;
}
+
*rows = 2 * sy + 1;
*cols = 2 * sx + 1;
*free_this = cells = emalloc3(*rows, *cols, sizeof(double));
+
n = (2 * sy + 1) * (2 * sx + 1);
value = 1 / (double)n;
+ if (have_weight)
+ value = (1.0 - weight) / (double)(n - 1);
for (i = 0; i < n; i++)
cells[i] = value;
+ if (have_weight)
+ cells[sy * *cols + sx] = weight;
return cells;
+
+usage:
+ eprintf(SUBUSAGE("'box blur' [-w weight] [spread | x-spread y-spread]"));
+ return NULL;
}
static const double *
kernel_sharpen(int argc, char *argv[], size_t *rows, size_t *cols, double **free_this)
{
+ static const double matrices[][9] = {
+ { 0, -1, 0, -1, 5, -1, 0, -1, 0},
+ {-1, -1, -1, -1, 9, -1, -1, -1, -1}
+ };
+ char *arg;
+ int intensified = 0;
*free_this = NULL;
*rows = *cols = 3;
+
+#define argv0 arg
+ argc++, argv--;
+ ARGBEGIN {
+ case 'i':
+ intensified = 1;
+ break;
+ default:
+ goto usage;
+ } ARGEND;
+#undef argv0
if (argc)
- eprintf(SUBUSAGE("'sharpen'"));
- return MATRIX(0, -1, 0, -1, 5, -1, 0, -1, -0);
- (void) argv;
+ goto usage;
+
+ return matrices[intensified];
+usage:
+ eprintf(SUBUSAGE("'sharpen' [-i]"));
+ return NULL;
+ (void) arg;
}
static const double *
@@ -147,6 +200,20 @@ usage:
return NULL;
}
+/* TODO more kernels:
+ Edge detection: MATRIX( 1, 0, -1, 0, 0, 0, -1, 0, 1)
+ Edge detection: MATRIX( 0, 1, 0, 1, -4, 1, 0, 1, 0)
+ 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)
+ */
+
int
main(int argc, char *argv[])
{