Introduction
Introduction Statistics Contact Development Disclaimer Help
Add blind-mosaic - blind - suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log
Files
Refs
README
LICENSE
---
commit 38dfe2510b19c25901e9db08426319c21fabdf95
parent 2db9b5387a659884cb98284c060a27895c64ae15
Author: Mattias Andrée <[email protected]>
Date: Thu, 13 Jul 2017 17:40:34 +0200
Add blind-mosaic
Signed-off-by: Mattias Andrée <[email protected]>
Diffstat:
M Makefile | 1 +
M README | 7 +++++--
M man/blind-gauss-blur.1 | 2 +-
M man/blind-hexagon-tessellation.1 | 3 ++-
A man/blind-mosaic.1 | 36 +++++++++++++++++++++++++++++…
M man/blind-rectangle-tessellation.1 | 3 ++-
M man/blind-repeat-tessellation.1 | 3 ++-
M man/blind-triangle-tessellation.1 | 3 ++-
M man/blind.7 | 3 +++
A src/blind-mosaic.c | 174 +++++++++++++++++++++++++++++…
10 files changed, 228 insertions(+), 7 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -41,6 +41,7 @@ BIN =\
blind-invert-luma\
blind-linear-gradient\
blind-make-kernel\
+ blind-mosaic\
blind-next-frame\
blind-norm\
blind-quaternion-product\
diff --git a/README b/README
@@ -111,11 +111,14 @@ UTILITIES
blind-invert-luma(1)
Invert the luminosity of a video
+ blind-linear-gradient(1)
+ Generate a video with a linear gradient
+
blind-make-kernel(1)
Create a custom convolution matrix
- blind-linear-gradient(1)
- Generate a video with a linear gradient
+ blind-mosaic(1)
+ Redraw each frame in video as a mosaic
blind-next-frame(1)
Extracts the next frame from a video
diff --git a/man/blind-gauss-blur.1 b/man/blind-gauss-blur.1
@@ -73,7 +73,7 @@ Use the Y value (multiplied by the alpha value) from
.I sd-stream
as the standard deviation all channels.
.SH REQUIREMENTS
-.B blind-compress
+.B blind-gauss-blur
requires enough free memory to load three full frames into
memory. A frame requires 32 bytes per pixel it contains.
.SH SEE ALSO
diff --git a/man/blind-hexagon-tessellation.1 b/man/blind-hexagon-tessellation.1
@@ -28,7 +28,8 @@ for more information.
.BR blind-triangle-tessellation (1),
.BR blind-repeat-tessellation (1),
.BR blind-get-colours (1),
-.BR blind-apply-palette (1)
+.BR blind-apply-palette (1),
+.BR blind-mosaic (1)
.SH AUTHORS
Mattias Andrée
.RI < [email protected] >
diff --git a/man/blind-mosaic.1 b/man/blind-mosaic.1
@@ -0,0 +1,36 @@
+.TH BLIND-MOSAIC 1 blind
+.SH NAME
+blind-mosaic - Redraw each frame in video as a mosaic
+.SH SYNOPSIS
+.B blind-mosaic
+[-xy]
+.I mosaic-stream
+.SH DESCRIPTION
+.B blind-mosaic
+reads a video from stdin and a mosaic pattern video from
+.IR mosaic-stream .
+The video is printed to stdout, with each frame redraw in
+as a mosaic with the pattern found in the same frame in
+.IR mosaic-stream .
+.SH OPTIONS
+.TP
+.B -x
+When encountering the left or right edge of the video,
+wrap around to the opposite edge.
+.TP
+.B -y
+When encountering the upper or lower edge of the video,
+wrap around to the opposite edge.
+.SH REQUIREMENTS
+.B blind-mosaic
+requires enough free memory to load three full frames into
+memory. A frame requires 32 bytes per pixel it contains.
+.SH SEE ALSO
+.BR blind (7),
+.BR blind-hexagon-tessellation (1),
+.BR blind-rectangle-tessellation (1),
+.BR blind-triangle-tessellation (1),
+.BR blind-repeat-tessellation (1)
+.SH AUTHORS
+Mattias Andrée
+.RI < [email protected] >
diff --git a/man/blind-rectangle-tessellation.1 b/man/blind-rectangle-tessellat…
@@ -30,7 +30,8 @@ for more information.
.BR blind-triangle-tessellation (1),
.BR blind-repeat-tessellation (1),
.BR blind-get-colours (1),
-.BR blind-apply-palette (1)
+.BR blind-apply-palette (1),
+.BR blind-mosaic (1)
.SH AUTHORS
Mattias Andrée
.RI < [email protected] >
diff --git a/man/blind-repeat-tessellation.1 b/man/blind-repeat-tessellation.1
@@ -33,7 +33,8 @@ bytes per pixel it contains.
.BR blind-apply-palette (1),
.BR blind-hexagon-tessellation (1),
.BR blind-rectangle-tessellation (1),
-.BR blind-triangle-tessellation (1)
+.BR blind-triangle-tessellation (1),
+.BR blind-mosaic (1)
.SH AUTHORS
Mattias Andrée
.RI < [email protected] >
diff --git a/man/blind-triangle-tessellation.1 b/man/blind-triangle-tessellatio…
@@ -33,7 +33,8 @@ for more information.
.BR blind-triangle-tessellation (1),
.BR blind-repeat-tessellation (1),
.BR blind-get-colours (1),
-.BR blind-apply-palette (1)
+.BR blind-apply-palette (1),
+.BR blind-mosaic (1)
.SH AUTHORS
Mattias Andrée
.RI < [email protected] >
diff --git a/man/blind.7 b/man/blind.7
@@ -133,6 +133,9 @@ Generate a video with a linear gradient
.BR blind-make-kernel (1)
Create a custom convolution matrix
.TP
+.BR blind-mosaic (1)
+Redraw each frame in video as a mosaic
+.TP
.BR blind-next-frame (1)
Extracts the next frame from a video
.TP
diff --git a/src/blind-mosaic.c b/src/blind-mosaic.c
@@ -0,0 +1,174 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-xy] mosaic-stream")
+
+static int tiled_x = 0;
+static int tiled_y = 0;
+
+#define TEST(X, Y)\
+ (!*(size_t *)(img + (Y) * mosaic->width + (X)) &&\
+ mos[(Y) * mosaic->width + (X)][0] == ch1 &&\
+ mos[(Y) * mosaic->width + (X)][1] == ch2 &&\
+ mos[(Y) * mosaic->width + (X)][2] == ch3 &&\
+ mos[(Y) * mosaic->width + (X)][3] == ch4)
+
+#define SEARCH(TYPE, SEARCH_FUNCTION)\
+ do {\
+ typedef TYPE pixel_t[4];\
+ \
+ pixel_t *restrict mos = (pixel_t *)mbuf;\
+ pixel_t *restrict img = (pixel_t *)output;\
+ size_t n, s, e, w;\
+ \
+ *(size_t *)(img + y * mosaic->width + x) = index;\
+ \
+ n = y ? y - 1 : tiled_y ? mosaic->height - 1 : y;\
+ s = y <= mosaic->height ? y + 1 : tiled_y ? 0 : y;\
+ w = x ? x - 1 : tiled_x ? mosaic->width - 1 : x;\
+ e = x <= mosaic->width ? x + 1 : tiled_x ? 0 : x;\
+ \
+ if (TEST(x, n)) SEARCH_FUNCTION(output, mbuf, mosaic, x, n, in…
+ if (TEST(x, s)) SEARCH_FUNCTION(output, mbuf, mosaic, x, s, in…
+ if (TEST(e, y)) SEARCH_FUNCTION(output, mbuf, mosaic, e, y, in…
+ if (TEST(w, y)) SEARCH_FUNCTION(output, mbuf, mosaic, w, y, in…
+ } while (0)\
+
+#define PROCESS(TYPE, SEARCH_FUNCTION)\
+ do {\
+ typedef TYPE pixel_t[4];\
+ \
+ static pixel_t *avg = NULL;\
+ static TYPE *cnt = NULL;\
+ static size_t size = 0;\
+ \
+ pixel_t *restrict clr = (pixel_t *)cbuf;\
+ pixel_t *restrict mos = (pixel_t *)mbuf;\
+ pixel_t *img = (pixel_t *)output;\
+ size_t index = 0;\
+ size_t x, y, i;\
+ \
+ memset(img, 0, mosaic->frame_size);\
+ \
+ for (y = 0; y < mosaic->height; y++)\
+ for (x = 0; x < mosaic->width; x++)\
+ if (!*(size_t *)(img + y * mosaic->width + x))\
+ SEARCH_FUNCTION(img, mos, mosaic, x, y…
+ mos[y * mosaic->width …
+ mos[y * mosaic->width …
+ mos[y * mosaic->width …
+ mos[y * mosaic->width …
+ \
+ if (index > size) {\
+ size = index;\
+ avg = erealloc2(avg, size, sizeof(*avg));\
+ cnt = erealloc2(cnt, size, sizeof(*cnt));\
+ }\
+ memset(avg, 0, index * sizeof(*avg));\
+ memset(cnt, 0, index * sizeof(*cnt));\
+ \
+ for (y = 0; y < mosaic->height; y++) {\
+ for (x = 0; x < mosaic->width; x++) {\
+ i = y * mosaic->width + x;\
+ index = *(size_t *)(img + i) - 1;\
+ cnt[index] += (TYPE)1;\
+ avg[index][0] *= (cnt[index] - (TYPE)1) / cnt[…
+ avg[index][1] *= (cnt[index] - (TYPE)1) / cnt[…
+ avg[index][2] *= (cnt[index] - (TYPE)1) / cnt[…
+ avg[index][3] *= (cnt[index] - (TYPE)1) / cnt[…
+ avg[index][3] += clr[i][3] /= cnt[index];\
+ avg[index][0] += clr[i][0] *= clr[i][3];\
+ avg[index][1] += clr[i][1] *= clr[i][3];\
+ avg[index][2] += clr[i][2] *= clr[i][3];\
+ }\
+ }\
+ \
+ for (i = 0; i < index; i++) {\
+ if (avg[i][3]) {\
+ avg[i][0] /= avg[i][3];\
+ avg[i][1] /= avg[i][3];\
+ avg[i][2] /= avg[i][3];\
+ }\
+ }\
+ \
+ for (y = 0; y < mosaic->height; y++) {\
+ for (x = 0; x < mosaic->width; x++) {\
+ i = y * mosaic->width + x;\
+ index = *(size_t *)(img + i) - 1;\
+ img[i][0] = avg[index][0];\
+ img[i][1] = avg[index][1];\
+ img[i][2] = avg[index][2];\
+ img[i][3] = avg[index][3];\
+ }\
+ }\
+ \
+ (void) colour;\
+ } while (0)
+
+static void
+search_lf(void *restrict output, void *restrict mbuf, struct stream *mosaic,
+ size_t x, size_t y, size_t index, double ch1, double ch2, double ch3…
+{
+ SEARCH(double, search_lf);
+}
+
+static void
+search_f(void *restrict output, void *restrict mbuf, struct stream *mosaic,
+ size_t x, size_t y, size_t index, double ch1, double ch2, double ch3,…
+{
+ SEARCH(float, search_f);
+}
+
+static void
+process_lf(char *restrict output, char *restrict cbuf, char *restrict mbuf,
+ struct stream *colour, struct stream *mosaic)
+{
+ PROCESS(double, search_lf);
+}
+
+static void
+process_f(char *restrict output, char *restrict cbuf, char *restrict mbuf,
+ struct stream *colour, struct stream *mosaic)
+{
+ PROCESS(float, search_f);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct stream colour, mosaic;
+ void (*process)(char *restrict output, char *restrict cbuf, char *rest…
+ struct stream *colour, struct stream *mosaic);
+
+ ARGBEGIN {
+ case 'x':
+ tiled_x = 1;
+ break;
+ case 'y':
+ tiled_y = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc != 1)
+ usage();
+
+ eopen_stream(&colour, NULL);
+ eopen_stream(&mosaic, argv[0]);
+
+ if (!strcmp(colour.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(colour.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", colour…
+
+ echeck_compat(&colour, &mosaic);
+
+ fprint_stream_head(stdout, &colour);
+ efflush(stdout, "<stdout>");
+ process_each_frame_two_streams(&colour, &mosaic, STDOUT_FILENO, "<stdo…
+
+ 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.