sandpiles

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

common.c (3226B)


      1 #include <rcx/all.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 
      5 #include "common.h"
      6 
      7 static u8
      8 hex_value[] = {
      9 	['0'] = 0x0, ['1'] = 0x1, ['2'] = 0x2, ['3'] = 0x3, ['4'] = 0x4,
     10 	['5'] = 0x5, ['6'] = 0x6, ['7'] = 0x7, ['8'] = 0x8, ['9'] = 0x9,
     11 	['A'] = 0xA, ['B'] = 0xB, ['C'] = 0xC, ['D'] = 0xD, ['E'] = 0xE, ['F'] = 0xF,
     12 	['a'] = 0xA, ['b'] = 0xB, ['c'] = 0xC, ['d'] = 0xD, ['e'] = 0xE, ['f'] = 0xF,
     13 };
     14 
     15 static bool
     16 is_hex_numeral(char c) {
     17 	return ('0' <= c && c <= '9')
     18 		|| ('A' <= c && c <= 'F')
     19 		|| ('a' <= c && c <= 'f');
     20 }
     21 
     22 u16
     23 parse_rgba_channel(char *s, bool sixteen) {
     24 	u16 v = 0;
     25 	for (usize i = 0; i < (sixteen ? 4 : 2); i++) {
     26 		if (!is_hex_numeral(s[i]))
     27 			r_fatalf("expected hexadecimal numeral");
     28 		v = 16u * v + hex_value[(usize)s[i]];
     29 	}
     30 	return sixteen ? v : (v << 8) | v;
     31 }
     32 
     33 void
     34 ff_fwrite(FILE *f, Image img) {
     35 	usize w = img.w;
     36 	usize h = img.h;
     37 
     38 	char header[16];
     39 	memcpy(header, "farbfeld", 8);
     40 	r_writeb32(header + 8, w);
     41 	r_writeb32(header + 12, h);
     42 	if (!fwrite(header, sizeof header, 1, f))
     43 		r_fatalf("ff_fwrite: failed to write header");
     44 
     45 	for (usize y = 0; y < h; y++) {
     46 		for (usize x = 0; x < w; x++) {
     47 			Rgba p = img.pixels[y * w + x];
     48 			u16 buf[4] = {
     49 				r_htob16(p.r),
     50 				r_htob16(p.g),
     51 				r_htob16(p.b),
     52 				r_htob16(p.a),
     53 			};
     54 			if (!fwrite(buf, sizeof buf, 1, f))
     55 				r_fatalf("ff_fwrite: failed to write pixel data");
     56 		}
     57 	}
     58 }
     59 
     60 Image
     61 ff_fread(FILE *f) {
     62 	char header[16];
     63 	if (!fread(header, sizeof header, 1, f))
     64 		r_fatalf("ff_fread: failed to read header");
     65 	if (memcmp(header, "farbfeld", 8) != 0)
     66 		r_fatalf("ff_fread: invalid magic");
     67 	usize w = r_readb32(header + 8);
     68 	usize h = r_readb32(header + 12);
     69 
     70 	Rgba *pixels = r_ealloc(w * h * sizeof *pixels);
     71 	for (usize y = 0; y < h; y++) {
     72 		for (usize x = 0; x < w; x++) {
     73 			char buf[8];
     74 			if (!fread(buf, sizeof buf, 1, f))
     75 				r_fatalf("ff_fread: failed to read pixel data");
     76 			pixels[y * w + x] = (Rgba){
     77 				.r = r_readb16(buf + 0),
     78 				.g = r_readb16(buf + 2),
     79 				.b = r_readb16(buf + 4),
     80 				.a = r_readb16(buf + 6),
     81 			};
     82 		}
     83 	}
     84 
     85 	return (Image){.w = w, .h = h, .pixels = pixels};
     86 }
     87 
     88 void
     89 sp_fwrite(FILE *f, Sandpile sp) {
     90 	usize w = sp.w;
     91 	usize h = sp.h;
     92 
     93 	char header[16];
     94 	memcpy(header, "sandpile", 8);
     95 	r_writeb32(header + 8, w);
     96 	r_writeb32(header + 12, h);
     97 	if (!fwrite(header, sizeof header, 1, f))
     98 		r_fatalf("sp_fwrite: failed to write header");
     99 
    100 	for (usize y = 1; y <= h; y++) {
    101 		for (usize x = 1; x <= w; x++) {
    102 			char buf[4];
    103 			r_writeb32(buf, sp.sand[y * (w + 2) + x]);
    104 			if (!fwrite(buf, sizeof buf, 1, f))
    105 				r_fatalf("sp_fwrite: failed to write sand data");
    106 		}
    107 	}
    108 }
    109 
    110 Sandpile
    111 sp_fread(FILE *f) {
    112 	char header[16];
    113 	if (!fread(header, sizeof header, 1, f))
    114 		r_fatalf("sp_fread: failed to read header");
    115 	if (memcmp(header, "sandpile", 8) != 0)
    116 		r_fatalf("sp_fread: invalid magic");
    117 	usize w = r_readb32(header + 8);
    118 	usize h = r_readb32(header + 12);
    119 
    120 	u32 *sand = r_eallocz((w + 2) * (h + 2) * sizeof(u32));
    121 	for (usize y = 1; y <= h; y++) {
    122 		for (usize x = 1; x <= w; x++) {
    123 			char buf[4];
    124 			if (!fread(buf, sizeof buf, 1, f))
    125 				r_fatalf("sp_fread: failed to read sand data");
    126 			sand[y * (w + 2) + x] = r_readb32(buf);
    127 		}
    128 	}
    129 
    130 	return (Sandpile){.w = w, .h = h, .sand = sand};
    131 }