aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-get-colours.c
blob: 900ebcec1d03aece406663f586fc653b506c5f0d (plain) (blame)
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
/* 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;
}