blind-apply-kernel.c - blind - suckless command-line video editing utility
(HTM) git clone git://git.suckless.org/blind
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
blind-apply-kernel.c (3898B)
---
1 /* See LICENSE file for copyright and license details. */
2 #ifndef TYPE
3 #include "common.h"
4
5 USAGE("[-apPxy] kernel-stream")
6
7 static int no_alpha = 0;
8 static int dont_premultiply = 0;
9 static int per_pixel = 0;
10 static int wrap_x = 0;
11 static int wrap_y = 0;
12 static size_t kern_w;
13 static size_t kern_h;
14
15 #define FILE "blind-apply-kernel.c"
16 #include "define-functions.h"
17
18 int
19 main(int argc, char *argv[])
20 {
21 struct stream colour, kernel;
22 void (*process)(struct stream *colour, struct stream *kernel);
23 size_t tmp;
24
25 ARGBEGIN {
26 case 'a':
27 no_alpha = 1;
28 break;
29 case 'p':
30 per_pixel = 1;
31 break;
32 case 'P':
33 dont_premultiply = 1;
34 break;
35 case 'x':
36 wrap_x = 1;
37 break;
38 case 'y':
39 wrap_y = 1;
40 break;
41 default:
42 usage();
43 } ARGEND;
44
45 if (argc != 1)
46 usage();
47
48 eopen_stream(&colour, NULL);
49 eopen_stream(&kernel, argv[0]);
50
51 SELECT_PROCESS_FUNCTION(&colour);
52 CHECK_ALPHA_CHAN(&colour);
53 CHECK_N_CHAN(&colour, 4, 4);
54 if (colour.encoding != kernel.encoding || colour.n_chan != kernel.n_chan)
55 eprintf("videos use incompatible pixel formats");
56 if (per_pixel && !(kernel.width % colour.width || kernel.height % colour.height))
57 eprintf("-p is specified but the dimensions of kernel-stream "
58 "are not multiples of the dimensions of stdin.");
59
60 kern_w = per_pixel ? kernel.width / colour.width : kernel.width;
61 kern_h = per_pixel ? kernel.height / colour.height : kernel.height;
62
63 tmp = kernel.height, kernel.height = kern_h;
64 echeck_dimensions(&colour, WIDTH | HEIGHT, NULL);
65 echeck_dimensions(&kernel, WIDTH | HEIGHT, NULL);
66 kernel.height = tmp;
67
68 fprint_stream_head(stdout, &colour);
69 efflush(stdout, "<stdout>");
70 process(&colour, &kernel);
71 return 0;
72 }
73
74 #else
75
76 static void
77 PROCESS(struct stream *colour, struct stream *kernel)
78 {
79 TYPE *out, *clr, *krn, *kern, *pix;
80 size_t i, x, y, n, x2, y2;
81 ssize_t cx, cy, xoff, yoff;
82
83 out = emalloc(colour->frame_size);
84 clr = emalloc(colour->frame_size);
85 krn = emalloc2(kern_h, kernel->row_size);
86
87 xoff = (ssize_t)(kern_w / 2);
88 yoff = (ssize_t)(kern_h / 2);
89
90 n = colour->width * colour->height * colour->n_chan;
91 while (eread_frame(colour, clr)) {
92 /* premultiply */
93 if (!no_alpha && !dont_premultiply) {
94 for (i = 0; i < n; i += 4) {
95 clr[i + 0] *= clr[i + 3];
96 clr[i + 1] *= clr[i + 3];
97 clr[i + 2] *= clr[i + 3];
98 }
99 }
100
101 /* apply kernel */
102 memset(out, 0, colour->frame_size);
103 pix = out;
104 for (y = 0; y < colour->height; y++) {
105 if ((!y || per_pixel) && !eread_segment(kernel, krn, kern_h * kernel->row_size))
106 goto done;
107 for (x = 0; x < colour->width; x++, pix += colour->n_chan) {
108 kern = per_pixel ? (krn + x * kern_w * kernel->n_chan) : krn;
109 for (y2 = 0; y2 < kern_h; y2++, kern += kernel->width * kernel->n_chan) {
110 cy = (ssize_t)(y + y2) - yoff;
111 if (cy < 0 || (size_t)cy >= colour->height) {
112 if (!wrap_y)
113 continue;
114 cy %= (ssize_t)(colour->height);
115 if (cy < 0)
116 cy += (ssize_t)(colour->height);
117 }
118 for (x2 = 0; x2 < kern_w; x2++) {
119 cx = (ssize_t)(x + x2) - xoff;
120 if (cx < 0 || (size_t)cx >= colour->width) {
121 if (!wrap_x)
122 continue;
123 cx %= (ssize_t)(colour->width);
124 if (cx < 0)
125 cx += (ssize_t)(colour->width);
126 }
127 for (i = 0; i < colour->n_chan; i++)
128 pix[i] += kern[x2 * kernel->n_chan + i] *
129 clr[((size_t)cy * colour->width + (size_t)cx) * colour->n_chan + i];
130 }
131 }
132 }
133 }
134
135 /* unpremultiply */
136 if (!dont_premultiply) {
137 for (i = 0; i < n; i += 4) {
138 if (out[i + 3]) {
139 out[i + 0] /= out[i + 3];
140 out[i + 1] /= out[i + 3];
141 out[i + 2] /= out[i + 3];
142 }
143 }
144 }
145
146 /* ensure video is opaque if -a was used */
147 if (no_alpha)
148 for (i = 0; i < n; i += 4)
149 out[i + 3] = 1;
150
151 /* output video */
152 ewriteall(STDOUT_FILENO, out, colour->frame_size, "<stdout>");
153 }
154 done:
155
156 free(out);
157 free(clr);
158 free(krn);
159 }
160
161 #endif