blind-translate.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
blind-translate.c (4130B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "common.h" | |
3 | |
4 USAGE("[-wp] translation-stream") | |
5 | |
6 static int invtrans = 0; | |
7 static char zeroes[BUFSIZ]; | |
8 | |
9 static void* | |
10 next_pixel(struct stream *stream, size_t *ptr) | |
11 { | |
12 void *ret; | |
13 if (*ptr + stream->pixel_size >= stream->ptr) { | |
14 memmove(stream->buf, stream->buf + *ptr, stream->ptr -= … | |
15 *ptr = 0; | |
16 while (stream->ptr < stream->pixel_size) | |
17 if (!eread_stream(stream, SIZE_MAX)) | |
18 return NULL; | |
19 } | |
20 ret = stream->buf + *ptr; | |
21 *ptr += stream->pixel_size; | |
22 return ret; | |
23 } | |
24 | |
25 static int | |
26 process_frame(struct stream *stream, char *buf, size_t above, size_t bel… | |
27 { | |
28 #define ZEROES(N) ewritezeroes(STDOUT_FILENO, zeroes, sizeof(zeroes), N,… | |
29 | |
30 size_t i, w = stream->row_size - left - right; | |
31 int first = 1; | |
32 | |
33 if (!eread_row(stream, buf)) | |
34 return 0; | |
35 | |
36 for (i = 0; i < above; i++) | |
37 ZEROES(stream->row_size); | |
38 for (i = 0; i < below; i++, first = 0) | |
39 if (!first && !eread_row(stream, buf)) | |
40 goto eof; | |
41 | |
42 for (i = above + below; i < stream->height; i++, first = 0) { | |
43 if (!first && !eread_row(stream, buf)) | |
44 goto eof; | |
45 ZEROES((size_t)left); | |
46 ewriteall(STDOUT_FILENO, buf + right, w, "<stdout>"); | |
47 ZEROES((size_t)right); | |
48 } | |
49 | |
50 for (i = 0; i < below; i++) | |
51 ZEROES(stream->row_size); | |
52 for (i = 0; i < above; i++, first = 0) | |
53 if (!first && !eread_row(stream, buf)) | |
54 goto eof; | |
55 | |
56 return 1; | |
57 eof: | |
58 eprintf("%s: file is shorter than expected\n", stream->file); | |
59 } | |
60 | |
61 static void | |
62 process(struct stream *stream, struct stream *trstream) | |
63 { | |
64 char *buf; | |
65 size_t p = 0; | |
66 double *trans, tmp; | |
67 ssize_t trx = 0, try = 0; | |
68 size_t above = 0, below = 0, left = 0, right = 0; | |
69 | |
70 memset(zeroes, 0, sizeof(zeroes)); | |
71 | |
72 echeck_dimensions(stream, WIDTH, NULL); | |
73 buf = emalloc(stream->row_size); | |
74 | |
75 do { | |
76 if ((trans = next_pixel(trstream, &p))) { | |
77 trx = (ssize_t)(tmp = round(invtrans ? -trans[0]… | |
78 try = (ssize_t)(tmp = round(invtrans ? -trans[1]… | |
79 | |
80 above = try > 0 ? (size_t)try : 0; | |
81 below = try < 0 ? (size_t)-try : 0; | |
82 left = (trx > 0 ? (size_t)trx : 0) * stream->p… | |
83 right = (trx < 0 ? (size_t)-trx : 0) * stream->p… | |
84 | |
85 above = MIN(above, stream->height); | |
86 below = MIN(below, stream->height); | |
87 left = MIN(left, stream->row_size); | |
88 right = MIN(right, stream->row_size); | |
89 } | |
90 } while (process_frame(stream, buf, above, below, left, right)); | |
91 | |
92 free(buf); | |
93 } | |
94 | |
95 static void | |
96 process_wrap(struct stream *stream, struct stream *trstream) | |
97 { | |
98 char *buf, *row; | |
99 size_t p = 0; | |
100 double *trans, tmp; | |
101 ssize_t trx = 0, try = 0, py; | |
102 size_t off = 0, y; | |
103 | |
104 echeck_dimensions(stream, WIDTH | HEIGHT, NULL); | |
105 buf = emalloc(stream->frame_size); | |
106 | |
107 while (eread_frame(stream, buf)) { | |
108 if ((trans = next_pixel(trstream, &p))) { | |
109 trx = (ssize_t)(tmp = round(invtrans ? -trans[0]… | |
110 try = (ssize_t)(tmp = round(invtrans ? -trans[1]… | |
111 trx %= (ssize_t)stream->width; | |
112 if (trx < 0) | |
113 trx += (ssize_t)stream->width; | |
114 off = (stream->width - (size_t)trx) % stream->wi… | |
115 off = off * stream->pixel_size; | |
116 } | |
117 | |
118 for (y = 0; y < stream->height; y++) { | |
119 py = ((ssize_t)y - try) % (ssize_t)stream->heigh… | |
120 if (py < 0) | |
121 py += (ssize_t)stream->height; | |
122 row = buf + (size_t)py * stream->row_size; | |
123 ewriteall(STDOUT_FILENO, row + off, stream->row_… | |
124 ewriteall(STDOUT_FILENO, row, off, "<stdout>"); | |
125 } | |
126 } | |
127 | |
128 free(buf); | |
129 } | |
130 | |
131 int | |
132 main(int argc, char *argv[]) | |
133 { | |
134 struct stream stream; | |
135 struct stream trstream; | |
136 int wrap = 0; | |
137 | |
138 ARGBEGIN { | |
139 case 'w': | |
140 wrap = 1; | |
141 break; | |
142 case 'p': | |
143 invtrans = 1; | |
144 break; | |
145 default: | |
146 usage(); | |
147 } ARGEND; | |
148 | |
149 if (argc != 1) | |
150 usage(); | |
151 | |
152 eopen_stream(&stream, NULL); | |
153 eopen_stream(&trstream, argv[0]); | |
154 | |
155 if (trstream.width != 1 || trstream.height != 1) | |
156 eprintf("translation-stream does not have 1x1 geometry\n… | |
157 | |
158 if (strcmp(trstream.pixfmt, "xyza")) | |
159 eprintf("pixel format of translation-stream %s " | |
160 "is not supported, try xyza\n", trstream.pixfmt); | |
161 | |
162 fprint_stream_head(stdout, &stream); | |
163 efflush(stdout, "<stdout>"); | |
164 | |
165 (wrap ? process_wrap : process)(&stream, &trstream); | |
166 close(trstream.fd); | |
167 return 0; | |
168 } |