Introduction
Introduction Statistics Contact Development Disclaimer Help
Add blind-find-rectangle - blind - suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log
Files
Refs
README
LICENSE
---
commit b87d6efb6fdca579c23020a93212f8f35375e1fe
parent 533819598030141394a67cb8b80047622c478f44
Author: Mattias Andrée <[email protected]>
Date: Sun, 4 Jun 2017 16:46:14 +0200
Add blind-find-rectangle
Signed-off-by: Mattias Andrée <[email protected]>
Diffstat:
M Makefile | 1 +
M README | 3 +++
A man/blind-find-rectangle.1 | 70 +++++++++++++++++++++++++++++…
M man/blind.7 | 3 +++
A src/blind-find-rectangle.c | 135 +++++++++++++++++++++++++++++…
5 files changed, 212 insertions(+), 0 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -16,6 +16,7 @@ BIN =\
blind-disperse\
blind-dissolve\
blind-extend\
+ blind-find-rectangle\
blind-flip\
blind-flop\
blind-from-image\
diff --git a/README b/README
@@ -48,6 +48,9 @@ UTILITIES
blind-extend(1)
Add margins to a video
+ blind-find-rectangle(1)
+ Locate a coloured rectangle
+
blind-flip(1)
Mirror a video vertically
diff --git a/man/blind-find-rectangle.1 b/man/blind-find-rectangle.1
@@ -0,0 +1,70 @@
+.TH BLIND-FIND-RECTANGLE 1 blind
+.SH NAME
+blind-find-rectangle - Locate a coloured rectangle
+.SH SYNOPSIS
+.B blind-find-rectangle
+[-a
+.IR min-area ]
+[-h
+.IR min-height ]
+[-w
+.IR min-width ]
+.I X
+.I Y
+.I Z
+.RI [ alpha ]
+.SH DESCRIPTION
+.B blind-find-rectangle
+reads a video from stdin, and locates the largest
+rectangle of a specified colour. If there are two
+or more maximal rectangles, one is choosen arbitrarily.
+The specified by the arguments
+.IR X ,
+.IR Y ,
+and
+.IR Z ,
+and the selected
+.I alpha
+value. The colour is specified in CIE XYZ. If
+.I X
+and
+.I Z
+are not specified, the colour will be CIE Standard Illuminant
+D65-grey with the luminosity
+.IR Y .
+If
+.I alpha
+is not specified, 1, which means fully opaque, will be used.
+.SH STDOUT
+The location and dimensions of the rectangle is printed stdout.
+Exactly one line is printed per frame. Each line has the format
+.nf
+
+ \fB"%zu %zu %zu %zu\\n"\fP, <\fIleft\fP>, <\fItop\fP>, <\fIwidth\fP>, …
+
+.fi
+where
+.I left
+is position on the X-axis (measured from the left) on the
+left-most pixels in the rectangle,
+.I top
+is position on the Y-axis (measured from the top) on the
+top-most pixels in the rectangle,
+.I width
+is the width of the rectangle, and
+.I height
+is the width of the rectangle.
+.SH NOTES
+.B blind-find-rectangle
+may be changed in the future to use some other colour model,
+therefore, it is recommended to also use
+.BR blind-colour-ciexyz (1)
+if you are specifying the colour in CIE XYZ. If however
+your values are colour space-agnostic, you should not.
+.SH SEE ALSO
+.BR blind (7),
+.BR blind-colour-ciexyz (1),
+.BR blind-colour-srgb (1)
+.SH AUTHORS
+Mattias Andrée
+.RI < [email protected] >
diff --git a/man/blind.7 b/man/blind.7
@@ -61,6 +61,9 @@ Framewise split a video into multiple videos
.BR blind-extend (1)
Add margins to a video
.TP
+.BR blind-find-rectangle (1)
+Locate a coloured rectangle
+.TP
.BR blind-flip (1)
Mirror a video vertically
.TP
diff --git a/src/blind-find-rectangle.c b/src/blind-find-rectangle.c
@@ -0,0 +1,135 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a min-area] [-h min-height] [-w min-width] X Y Z [alpha]")
+
+struct pair {
+ size_t x;
+ size_t w;
+};
+
+static struct stream stream;
+static double X, Y, Z, alpha = 1;
+static size_t min_width = 1;
+static size_t min_height = 1;
+static size_t min_area = 1;
+static struct pair *stack = NULL;
+static size_t *cache = NULL;
+static char *buf = NULL;
+
+static void
+process(const void *colour)
+{
+ size_t y, x, x0, w, w0, h, top, area;
+ size_t best_area, x1, x2, y1, y2;
+ for (;;) {
+ top = x1 = x2 = y1 = y2 = best_area = 0;
+ memset(cache, 0, (stream.width + 1) * sizeof(*cache));
+ for (y = 0; eread_row(&stream, buf); y++) {
+ w = 0;
+ for (x = 0; x <= stream.width; x++) {
+ if (x != stream.width) {
+ if (!memcmp(buf + x * stream.pixel_siz…
+ cache[x] += 1;
+ else
+ cache[x] = 0;
+ }
+ if (cache[x] > w) {
+ stack[top].x = x;
+ stack[top++].w = w;
+ w = cache[x];
+ } else if (cache[x] < w) {
+ do {
+ x0 = stack[--top].x;
+ w0 = stack[top].w;
+ area = w * (x - x0);
+ if (area > best_area) {
+ best_area = area;
+ x1 = x0;
+ x2 = x - 1;
+ y1 = y - w + 1;
+ y2 = y;
+ }
+ w = w0;
+ } while (cache[x] < w);
+ if ((w = cache[x])) {
+ stack[top].x = x0;
+ stack[top++].w = w0;
+ }
+ }
+ }
+ fprintf(stderr, "%zu\n", y);
+ }
+ if (!y)
+ break;
+ w = x2 - x1 + 1;
+ h = y2 - y1 + 1;
+ if (best_area < min_area || w < min_width || h < min_height)
+ printf("0 0 0 0\n");
+ else
+ printf("%zu %zu %zu %zu\n", x1, y1, w, h);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ double colour_lf[4];
+ double colour_f[4];
+
+ ARGBEGIN {
+ case 'a':
+ min_area = etozu_flag('a', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ min_height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'w':
+ min_width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc != 3 && argc != 4)
+ usage();
+
+ X = etolf_arg("the X value", argv[0]);
+ Y = etolf_arg("the Y value", argv[1]);
+ Z = etolf_arg("the Z value", argv[2]);
+ if (argc > 3)
+ alpha = etolf_arg("the alpha value", argv[3]);
+
+ eopen_stream(&stream, NULL);
+ echeck_dimensions(&stream, WIDTH, NULL);
+ if (stream.width == SIZE_MAX)
+ eprintf("video is too wide\n");
+ if (stream.width > SIZE_MAX / stream.height)
+ eprintf("video is too large\n");
+
+ stack = emalloc2(stream.width + 1, sizeof(*stack));
+ cache = emalloc2(stream.width + 1, sizeof(*cache));
+ buf = emalloc(stream.row_size);
+
+ if (!strcmp(stream.pixfmt, "xyza")) {
+ colour_lf[0] = X;
+ colour_lf[1] = Y;
+ colour_lf[2] = Z;
+ colour_lf[3] = alpha;
+ process(colour_lf);
+ } else if (!strcmp(stream.pixfmt, "xyza f")) {
+ colour_f[0] = (float)X;
+ colour_f[1] = (float)Y;
+ colour_f[2] = (float)Z;
+ colour_f[3] = (float)alpha;
+ process(colour_f);
+ } else {
+ eprintf("pixel format %s is not supported, try xyza\n", stream…
+ }
+
+ fshut(stdout, "<stdout>");
+ free(stack);
+ free(cache);
+ free(buf);
+ return 0;
+}
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.