sandpiles

sandpile art
git clone git://git.rr3.xyz/sandpiles
Log | Files | Refs | README | LICENSE

ff2sp.c (1488B)


      1 #include <rcx/all.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 
      5 #include "common.h"
      6 
      7 #define USAGE \
      8 	"usage: %s SAND [THRESHOLD]\n" \
      9 	"where SAND is decimal and THRESHOLD is 8 or 16 bit grayscale hex\n"
     10 
     11 u32
     12 parse_dec(char *s) {
     13 	u32 v = 0;
     14 	for (; *s; s++) {
     15 		if (*s < '0' || *s > '9')
     16 			r_fatalf("expected decimal numeral");
     17 		u32 d = *s - '0';
     18 		if (v > U32_MAX / 10 || 10 * v > U32_MAX - d)
     19 			r_fatalf("overflow");
     20 		v = 10 * v + d;
     21 	}
     22 	return v;
     23 }
     24 
     25 Sandpile
     26 sandpilify(Image img, u32 amount, u16 threshold) {
     27 	usize w = img.w;
     28 	usize h = img.h;
     29 
     30 	u32 *sand = r_eallocz((w + 2) * (h + 2) * sizeof(u32));
     31 	for (usize y = 0; y < h; y++) {
     32 		for (usize x = 0; x < w; x++) {
     33 			Rgba p = img.pixels[y * w + x];
     34 			if (p.r != p.g || p.g != p.b)
     35 				r_fatalf("expected grayscale");
     36 			// XXX: Error/warn if alpha != 0xffff ?
     37 			sand[(y + 1) * (w + 2) + (x + 1)] = p.r >= threshold ? amount : 0;
     38 		}
     39 	}
     40 
     41 	return (Sandpile){.w = w, .h = h, .sand = sand};
     42 }
     43 
     44 int
     45 main(int argc, char **argv) {
     46 	CHECK_FOR_HELP_OPTION(USAGE, argc, argv);
     47 
     48 	if (argc < 2 || argc > 3) {
     49 		fprintf(stderr, USAGE, argv[0]);
     50 		return 1;
     51 	}
     52 	u32 amount = parse_dec(argv[1]);
     53 	u16 threshold;
     54 	if (argc == 2) {
     55 		threshold = 0x8888;
     56 	} else {
     57 		usize len = strlen(argv[2]);
     58 		if (len != 2 && len != 4)
     59 			r_fatalf("expected 2 or 4 hexadecimal numerals");
     60 		threshold = parse_rgba_channel(argv[2], len == 4);
     61 	}
     62 
     63 	Image img = ff_fread(stdin);
     64 	Sandpile sp = sandpilify(img, amount, threshold);
     65 	sp_fwrite(stdout, sp);
     66 }