blind-apply-kernel.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
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 != kerne… | |
55 eprintf("videos use incompatible pixel formats"); | |
56 if (per_pixel && !(kernel.width % colour.width || kernel.height … | |
57 eprintf("-p is specified but the dimensions of kernel-st… | |
58 "are not multiples of the dimensions of stdin."); | |
59 | |
60 kern_w = per_pixel ? kernel.width / colour.width : kernel.widt… | |
61 kern_h = per_pixel ? kernel.height / colour.height : kernel.heig… | |
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, … | |
106 goto done; | |
107 for (x = 0; x < colour->width; x++, pix += colou… | |
108 kern = per_pixel ? (krn + x * kern_w * k… | |
109 for (y2 = 0; y2 < kern_h; y2++, kern += … | |
110 cy = (ssize_t)(y + y2) - yoff; | |
111 if (cy < 0 || (size_t)cy >= colo… | |
112 if (!wrap_y) | |
113 continue; | |
114 cy %= (ssize_t)(colour->… | |
115 if (cy < 0) | |
116 cy += (ssize_t)(… | |
117 } | |
118 for (x2 = 0; x2 < kern_w; x2++) { | |
119 cx = (ssize_t)(x + x2) -… | |
120 if (cx < 0 || (size_t)cx… | |
121 if (!wrap_x) | |
122 continue; | |
123 cx %= (ssize_t)(… | |
124 if (cx < 0) | |
125 cx += (s… | |
126 } | |
127 for (i = 0; i < colour->… | |
128 pix[i] += kern[x… | |
129 clr[((… | |
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, "<stdo… | |
153 } | |
154 done: | |
155 | |
156 free(out); | |
157 free(clr); | |
158 free(krn); | |
159 } | |
160 | |
161 #endif |