blind-get-colours.c (1721B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "common.h" 3 4 USAGE("") 5 6 static size_t width; 7 8 static int 9 pixcmp(const void *a, const void *b) 10 { 11 return memcmp(a, b, width); 12 } 13 14 static size_t 15 unique(char *base, size_t n) 16 { 17 size_t i, r = 1; 18 for (i = 1; i < n; i++) 19 if (pixcmp(base + (r - 1) * width, base + i * width) && r++ != i) 20 memcpy(base + (r - 1) * width, base + i * width, width); 21 return r; 22 } 23 24 static size_t 25 merge(char **sink, size_t n, char *new, size_t m, size_t *siz) 26 { 27 size_t i, j; 28 int c; 29 for (i = j = 0; i < n && j < m; i++) { 30 c = pixcmp(*sink + i * width, new + j * width); 31 if (c > 0) { 32 if (n == *siz) { 33 *siz = n ? n * 2 : 8; 34 *sink = erealloc2(*sink, *siz, width); 35 } 36 n += 1; 37 memmove(*sink + (i + 1) * width, *sink + i * width, (n - i - 1) * width); 38 memcpy(*sink + i * width, new + j * width, width); 39 } 40 j += c >= 0; 41 } 42 m -= j; 43 if (n + m > *siz) { 44 *siz = n + m; 45 *sink = erealloc2(*sink, *siz, width); 46 } 47 memcpy(*sink + n * width, new + j * width, m * width); 48 return n + m; 49 } 50 51 int 52 main(int argc, char *argv[]) 53 { 54 struct stream stream; 55 char *colours = NULL; 56 size_t ptr = 0, siz = 0; 57 size_t n, m; 58 59 UNOFLAGS(argc); 60 61 eopen_stream(&stream, NULL); 62 width = stream.pixel_size; 63 64 do { 65 n = stream.ptr / width; 66 qsort(stream.buf, n, width, pixcmp); 67 m = unique(stream.buf, n); 68 ptr = merge(&colours, ptr, stream.buf, m, &siz); 69 n *= width; 70 memmove(stream.buf, stream.buf + n, stream.ptr -= n); 71 } while (eread_stream(&stream, SIZE_MAX)); 72 73 stream.frames = 1; 74 stream.width = ptr; 75 stream.height = 1; 76 fprint_stream_head(stdout, &stream); 77 efflush(stdout, "<stdout>"); 78 ewriteall(STDOUT_FILENO, colours, ptr * width, "<stdout>"); 79 80 return 0; 81 }