Skip to content

Instantly share code, notes, and snippets.

@louisswarren
Last active May 4, 2021
Embed
What would you like to do?
Pipe pattern drawing
CFLAGS += -Ofast
.PHONY: default
default: refactor
.PHONY: refactor
refactor: out.pbm
sha256sum $< | diff -q goal.sum -
refactor-set: out.pbm
sha256sum $< > goal.sum
.PHONY: display
display: out.png
feh -Z $^
out.png: out.pbm Makefile
convert $< $@
out.pbm: pipes
./$^ > $@
pipes: pipes.c
gcc -std=c99 $< -o $@
.PHONY: clean
clean:
rm -r out.png out.pbm pipes
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define IMG_WIDTH 100
#define IMG_HEIGHT 100
#define G_WIDTH (IMG_WIDTH/2)
#define G_HEIGHT (IMG_HEIGHT/2)
#define DENSITY 45
enum colour {
COL_BLACK,
COL_WHITE,
COL_RED,
COL_GREEN,
COL_BLUE,
COL_PURPLE,
COL_YELLOW,
COL__MAX,
};
char colour_map[COL__MAX][3] = { /* COL_BLACK */ { 0, 0, 0},
/* COL_WHITE */ {255, 255, 255},
/* COL_RED */ {255, 0, 0},
/* COL_GREEN */ { 0, 255, 0},
/* COL_BLUE */ { 0, 0, 255},
/* COL_PURPLE */ {255, 0, 255},
/* COL_YELLOW */ {255, 255, 0}};
#define log(...) fprintf(stderr, __VA_ARGS__)
struct position {
uint32_t y;
uint32_t x;
};
void
recolour(
char *img_p,
uint32_t width,
uint32_t height,
uint32_t y,
uint32_t x,
enum colour old,
enum colour new)
{
static struct position *stack = NULL;
if (stack == NULL)
stack = calloc(width * height, sizeof(*stack));
if (stack == NULL) {
log("Allocation failed.\n");
exit(1);
}
char (*img)[width] = (char (*)[width])img_p;
size_t stack_sz = 1;
stack[0].y = y;
stack[0].x = x;
struct position p;
while (stack_sz) {
p = stack[--stack_sz];
img[p.y][p.x] = new;
if (p.y > 0 && img[p.y-1][p.x] == old) {
stack[stack_sz].y = p.y - 1;
stack[stack_sz].x = p.x;
stack_sz++;
img[p.y-1][p.x] = COL__MAX;
}
if (p.y < height-1 && img[p.y+1][p.x] == old) {
stack[stack_sz].y = p.y + 1;
stack[stack_sz].x = p.x;
stack_sz++;
img[p.y+1][p.x] = COL__MAX;
}
if (p.x > 0 && img[p.y][p.x-1] == old) {
stack[stack_sz].y = p.y;
stack[stack_sz].x = p.x - 1;
stack_sz++;
img[p.y][p.x-1] = COL__MAX;
}
if (p.x < width-1 && img[p.y][p.x+1] == old) {
stack[stack_sz].y = p.y;
stack[stack_sz].x = p.x + 1;
stack_sz++;
img[p.y][p.x+1] = COL__MAX;
}
}
}
int
main(void)
{
size_t i, j;
uint32_t width = IMG_WIDTH;
uint32_t height = IMG_HEIGHT;
char (*img)[width] = calloc(height, sizeof(*img));
srand(2018);
for (i = 0; i < G_HEIGHT; ++i) {
for (j = 0; j < G_WIDTH; ++j) {
img[2*i+0][2*j+1] = rand() % 100 < DENSITY;
img[2*i+1][2*j+0] = rand() % 100 < DENSITY;
}
}
for (i = 0; i < G_HEIGHT; ++i)
img[2*i][0] = img[2*i][1];
for (j = 0; j < G_WIDTH; ++j)
img[0][2*j] = img[1][2*j];
for (i = 1; i < G_HEIGHT; ++i) {
for (j = 1; j < G_WIDTH; ++j) {
img[2*i][2*j] = img[2*i-1][2*j+0]
| img[2*i+1][2*j+0]
| img[2*i+0][2*j-1]
| img[2*i+0][2*j+1];
}
}
enum colour c = COL_RED;
for (i = 0; i < IMG_HEIGHT; ++i) {
for (j = 0; j < IMG_WIDTH; ++j) {
if (img[i][j] == COL_WHITE) {
recolour(img[0], width, height, i, j, COL_WHITE, c);
if (++c == COL__MAX) c = COL_RED;
}
}
}
printf("P6\n");
printf("%d %d\n", IMG_WIDTH, IMG_HEIGHT);
printf("255\n");
for (i = 0; i < IMG_HEIGHT; ++i) {
for (j = 0; j < IMG_WIDTH; ++j)
fwrite(colour_map[img[i][j]], 1, 3, stdout);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment