-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathff-glitch.c
149 lines (132 loc) · 3.04 KB
/
ff-glitch.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// ┳━┓┳━┓ ┏━┓┳ o┏┓┓┏━┓┳ ┳
// ┣━ ┣━ ━━┃ ┳┃ ┃ ┃ ┃ ┃━┫
// ┇ ┇ ┇━┛┇━┛┇ ┇ ┗━┛┇ ┻
// ff-glitch: the farbfeld glitcher.
// usage: <farbfeld source> | ff-glitch | <farbfeld sink>
// thanks to xero for the idea! you rock.
// made by vifino. ISC (C) vifino 2018
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/time.h>
#include <arpa/inet.h>
// TODO: replace ntohl
static uint32_t w, h;
static unsigned char buf[8] = {0};
static unsigned char img;
static struct timeval tv;
typedef struct {
unsigned short r, g, b, a;
} pixel;
// IO helpers.
static inline void bread(int bytes) {
if (!fread(buf, bytes, 1, stdin)) {
fprintf(stderr, "wanted more bytes, didn't get any?\n");
exit(1);
}
}
static inline void bwrite(unsigned char* buffer, size_t bytes) {
if (!fwrite(buffer, bytes, 1, stdout)) {
fprintf(stderr, "write failed.\n");
exit(1);
}
}
// random helper, random from 0-n, inclusive.
// tries to get evenly spread out random.
unsigned int randn(unsigned int n) {
if (!n) return 0;
if (n == RAND_MAX) return rand();
n++;
long end = RAND_MAX / n;
end *= n;
int r;
while ((r = rand()) >= end);
return r % n;
}
// Glitch a short.
#define GLITCHPX() randn(2 * UINT8_MAX)
int main(int argc, char* argv[]) {
// TODO: parse argv[1] for range;
unsigned int glitches = 40 + randn(50);
bread(8);
if (strncmp(buf, "farbfeld", 8) != 0) {
fprintf(stderr, "stdin is not a farbfeld image?\n");
return 1;
}
bwrite(buf, 8);
// seed like a dumbass.
if (gettimeofday(&tv, NULL)) {
fprintf(stderr, "failed to get the time? that's messed up.\n");
return 2;
}
srand(tv.tv_usec);
// parse width and height
bread(8);
uint32_t w = ntohl(*(uint32_t*)buf);
uint32_t h = ntohl(*((uint32_t*)(buf + 4)));
if (!w && !h) {
fprintf(stderr, "image size has zero dimension? %i*%i\n", w, h);
return 1;
}
bwrite(buf, 8);
unsigned int pxn;
unsigned int end = w*h;
unsigned int trash = 0;
unsigned int skipped = 0;
int glitchpx = 0;
unsigned short gv;
unsigned char gp = 0;
pixel glitchp;
for(pxn = 0; pxn < end; pxn++) {
if (randn(end / glitches) == 0) {
// glitch it. glitch it hard.
trash = randn(end / 10 / glitches);
if (randn(1) == 0) {
glitchpx = randn((end * 4) / glitches);
gp = randn(2);
gv = GLITCHPX();
}
}
if (trash) {
// trash it.
pxn = pxn + trash - 1;
while (trash > 1) {
if (randn(1) == 0) {
bread(8); // throw away
} else {
skipped++;
}
pixel* px = (pixel*) buf;
px->r = GLITCHPX();
px->g = GLITCHPX();
px->b = GLITCHPX();
trash--;
bwrite(buf, 8);
}
}
bread(8);
if (glitchpx) {
pixel* px = (pixel*) buf;
if ((glitchpx - 1) >= 0) {
switch (gp) {
case 0:
px->r = gv;
break;
case 1:
px->g = gv;
break;
case 2:
px->b = gv;
break;
}
glitchpx--;
}
if (glitchpx < 0) glitchpx = 0;
}
bwrite(buf, 8);
}
for (; skipped > 0; skipped--)
bread(8);
return 0;
}