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
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
USAGE("")
static size_t width;
static int
pixcmp(const void *a, const void *b)
{
return memcmp(a, b, width);
}
static size_t
unique(char *base, size_t n)
{
size_t i, r = 1;
for (i = 1; i < n; i++)
if (pixcmp(base + (r - 1) * width, base + i * width) && r++ != i)
memcpy(base + (r - 1) * width, base + i * width, width);
return r;
}
static size_t
merge(char **sink, size_t n, char *new, size_t m, size_t *siz)
{
size_t i, j;
int c;
for (i = j = 0; i < n && j < m; i++) {
c = pixcmp(*sink + i * width, new + j * width);
if (c > 0) {
if (n == *siz) {
*siz = n ? n * 2 : 8;
*sink = erealloc2(*sink, *siz, width);
}
n += 1;
memmove(*sink + (i + 1) * width, *sink + i * width, (n - i - 1) * width);
memcpy(*sink + i * width, new + j * width, width);
}
j += c >= 0;
}
m -= j;
if (n + m > *siz) {
*siz = n + m;
*sink = erealloc2(*sink, *siz, width);
}
memcpy(*sink + n * width, new + j * width, m * width);
return n + m;
}
int
main(int argc, char *argv[])
{
struct stream stream;
char *colours = NULL;
size_t ptr = 0, siz = 0;
size_t n, m;
UNOFLAGS(argc);
eopen_stream(&stream, NULL);
width = stream.pixel_size;
do {
n = stream.ptr / width;
qsort(stream.buf, n, width, pixcmp);
m = unique(stream.buf, n);
ptr = merge(&colours, ptr, stream.buf, m, &siz);
n *= width;
memmove(stream.buf, stream.buf + n, stream.ptr -= n);
} while (eread_stream(&stream, SIZE_MAX));
stream.frames = 1;
stream.width = ptr;
stream.height = 1;
fprint_stream_head(stdout, &stream);
efflush(stdout, "<stdout>");
ewriteall(STDOUT_FILENO, colours, ptr * width, "<stdout>");
return 0;
}
|