Skip to content

Instantly share code, notes, and snippets.

@louisswarren

louisswarren/Makefile

Last active Oct 23, 2020
Embed
What would you like to do?
Tiny library for PPM output
#include <stdio.h>
#include <stdlib.h>
#include "problem.h"
int
main(void)
{
int width = 50;
int height = 20;
int i, j;
size_t psz;
struct problem *p;
if ((psz = problem_size(width, height)) == 0) {
fprintf(stderr, "Invalid image dimensions\n");
exit(1);
} else if ((p = calloc(1, psz)) == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
problem_init(p, width, height);
for (i = 4; i < 14; ++i) {
for (j = 0; j < 20; ++j)
problem_set(p, j, i, 0xFF00FF);
for (j = 20; j < 35; ++j)
problem_set(p, j, i, 0x00FFFF);
for (j = 35; j < 50; ++j)
problem_set(p, j, i, 0xFFFF00);
}
fwrite(p->raw, p->len, 1, stdout);
return 0;
}
.PHONY: test test-video
test: nz.png
sxiv $^
test-video: fire
./fire | mpv --no-correct-pts --fps=30 --scale=oversample -
%.png: %.ppm
convert $< $@
%.ppm: %
./$< > $@
example: example.c problem.o
$(CC) $(CFLAGS) -o $@ $^
video: video.c problem.o
$(CC) $(CFLAGS) -o $@ $^
fire: fire.c problem.o
$(CC) $(CFLAGS) -o $@ $^
nz: nz.c problem.o
$(CC) $(CFLAGS) -o $@ $^
problem.o: problem.c problem.h
$(CC) -c $(CFLAGS) -o $@ $<
.PHONY: clean
clean:
rm output.* example problem.o
#include <stdio.h>
#include <stdlib.h>
#include "problem.h"
#define P186C 0xC8102E
#define P280C 0x012169
#define PSAFE 0xFFFFFF
#define SQRT5 (2.236067977499790)
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
#define max(X, Y) ((X) < (Y) ? (Y) : (X))
int
main(void)
{
int scale = 10;
int height = 60 * scale;
int width = 120 * scale;
int i, j;
size_t psz;
struct problem *p;
if ((psz = problem_size(width, height)) == 0) {
fprintf(stderr, "Invalid image dimensions\n");
exit(1);
} else if ((p = calloc(1, psz)) == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
problem_init(p, width, height);
/* Background */
for (i = 0; i < height; ++i)
for (j = 0; j < width; ++j)
problem_set(p, j, i, P280C);
/* St Andrew's Cross */
for (i = 10 * scale; i < 20 * scale; ++i)
for (j = 0; j < 60 * scale; ++j)
problem_set(p, j, i, PSAFE);
for (i = 0; i < 30 * scale; ++i)
for (j = 25 * scale; j < 35 * scale; ++j)
problem_set(p, j, i, PSAFE);
/* Diagonals */
for (i = 0; i < 30 * scale; ++i) {
for (j = max(2*i - 3*SQRT5 * scale, 0);
j < min(2*i + 3*SQRT5 * scale, 60 * scale); ++j) {
problem_set(p, j, i, PSAFE);
problem_set(p, 60*scale - j, i, PSAFE);
}
}
/* St Patrick's Cross */
for (i = 0; i < 10 * scale; ++i) {
for (j = max(2*i - 2*SQRT5 * scale, 0); j < 2*i; ++j) {
problem_set(p, j, i, P186C);
problem_set(p, 60 * scale - j, 30 * scale - i, P186C);
}
for (j = 2*i; j < min(2*i + 2*SQRT5 * scale, 60 * scale); ++j) {
problem_set(p, j, 30 * scale - i, P186C);
problem_set(p, 60 * scale - j, i, P186C);
}
}
/* St George's Cross */
for (i = 12 * scale; i < 18 * scale; ++i)
for (j = 0; j < 60 * scale; ++j)
problem_set(p, j, i, P186C);
for (i = 0; i < 30 * scale; ++i)
for (j = 27 * scale; j < 33 * scale; ++j)
problem_set(p, j, i, P186C);
fwrite(p->raw, p->len, 1, stdout);
return 0;
}
#include <stdint.h>
#include <stdio.h>
#include "problem.h"
#define PPM_HDR_FMT_NONL "P6\n%d %d 255"
#define PPM_HDR_FMT (PPM_HDR_FMT_NONL "\n")
size_t
problem_size(long width, long height)
{
size_t header_len = sizeof(struct problem);
header_len += snprintf(NULL, 0, PPM_HDR_FMT, width, height);
if (width == SIZE_MAX)
return 0;
else if (height > (SIZE_MAX - header_len) / width / 3)
return 0;
return header_len + width * height * 3;
}
void
problem_init(struct problem *p, long width, long height)
{
long i;
p->width = width;
p->height = height;
/* Don't write out the null after the header in case the memory was
* already set (though this could be treated as misuse, I suppose). */
p->len = sprintf(p->raw, PPM_HDR_FMT_NONL, width, height);
p->raw[p->len++] = '\n';
p->image = p->raw + p->len;
p->len += 3 * width * height;
}
void
problem_set(struct problem *p, long x, long y, unsigned long colour)
{
p->image[3 * (p->width * y + x) + 0] = (colour >> 16) & 0xFF;
p->image[3 * (p->width * y + x) + 1] = (colour >> 8) & 0xFF;
p->image[3 * (p->width * y + x) + 2] = colour & 0xFF;
}
unsigned long
problem_get(struct problem *p, long x, long y)
{
unsigned long c = 0;
c += p->image[3 * (p->width * y + x) + 0] << 16;
c += p->image[3 * (p->width * y + x) + 1] << 8;
c += p->image[3 * (p->width * y + x) + 0];
return c;
}
#include <stddef.h>
struct problem {
long width;
long height;
char *image;
size_t len;
char raw[];
};
size_t problem_size(long width, long height);
void problem_init(struct problem *p, long width, long height);
void problem_set(struct problem *p, long x, long y, unsigned long colour);
unsigned long problem_get(struct problem *p, long x, long y);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "problem.h"
void render(struct problem *p);
void render_ball(struct problem *p, float x, float y, float r, unsigned long c);
void
render(struct problem *p)
{
static int b = 0;
int i, j;
memset(p->image, 0x11, p->width * p->height * 3);
for (i = p->height / 4; i < p->height / 4 * 3; ++i) {
for (j = 0; j < p->width / 3; ++j)
problem_set(p, (j + b) % p->width, i, 0xFF00FF);
for (j = p->width / 3; j < p->width / 3 * 2; ++j)
problem_set(p, (j + b) % p->width, i, 0x00FFFF);
for (j = p->width / 3 * 2; j < p->width; ++j)
problem_set(p, (j + b) % p->width, i, 0xFFFF00);
}
render_ball(p, (320 + b) % p->width, (240 + b) % p->height, 25, 0xFF8822);
b += 10;
}
void
render_ball(struct problem *p, float x, float y, float r, unsigned long c)
{
int i, j;
int min_i = y - r < 0 ? 0 : y - r;
int min_j = x - r < 0 ? 0 : x - r;
int max_i = y + r + 1 <= p->height ? y + r + 1 : p->height;
int max_j = x + r + 1 <= p->width ? x + r + 1 : p->width;
for (i = min_i; i < max_i; ++i)
for (j = min_j; j < max_j; ++j)
if ((x - (float) j) * (x - (float) j) + (y - (float) i) * (y - (float) i) < r * r)
problem_set(p, j, i, c);
}
int
main(void)
{
int width = 640;
int height = 480;
size_t psz;
struct problem *p;
if ((psz = problem_size(width, height)) == 0) {
fprintf(stderr, "Invalid image dimensions\n");
exit(1);
} else if ((p = calloc(1, psz)) == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
problem_init(p, width, height);
do {
render(p);
} while (fwrite(p->raw, p->len, 1, stdout));
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "problem.h"
void render(struct problem *p);
void plot(struct problem *p, float x, float y, float r, unsigned long c);
void advance_colour(unsigned long *c);
void
render(struct problem *p)
{
static int j = 0;
static unsigned long c = 0;
int i, k;
double x, y;
float g = 0.01;
for (k = 0; k < 1.0 / g; ++k) {
x = 2 * M_PI * (g * k + j) / p->width * 4;
y = sin(x);
i = (1 - y) * p->height / 2;
i = i < 0 ? 0 : i;
i = i >= p->height ? p->height : i;
plot(p, j, i, 2, c);
advance_colour(&c);
if (c > 0xFFFFFF)
c = 0;
fprintf(stderr, "Colour: %d\t%d\t%d\n", c >> 32, (c >> 16) & 0xFF, (c >> 32) & 0xFF);
}
j = (j + 1) % p->width;
if (!j) {
memset(p->image, 0xFF, p->width * p->height * 3);
}
}
void
advance_colour(unsigned long *c)
{
if ((*c >> 32) % 2 == (*c >> 16) % 2) {
if (*c & 0xFF == 0xFF) {
if ((*c >> 16) & 0xFF == 0xFF)
*c += 0x10000;
else
*c += 0x100;
} else {
*c += 0x1;
}
} else {
if (*c & 0xFF == 0) {
if ((*c >> 16) & 0xFF == 0)
*c += 0x10000;
else
*c -= 0x100;
} else {
*c -= 0x1;
}
}
}
void
plot(struct problem *p, float x, float y, float r, unsigned long c)
{
int i, j;
int min_i = y - r < 0 ? 0 : y - r;
int min_j = x - r < 0 ? 0 : x - r;
int max_i = y + r + 1 <= p->height ? y + r + 1 : p->height;
int max_j = x + r + 1 <= p->width ? x + r + 1 : p->width;
for (i = min_i; i < max_i; ++i)
for (j = min_j; j < max_j; ++j)
if ((x - (float) j) * (x - (float) j) + (y - (float) i) * (y - (float) i) < r * r)
problem_set(p, j, i, c);
}
int
main(void)
{
int width = 640;
int height = 480;
int k;
size_t psz;
struct problem *p;
if ((psz = problem_size(width, height)) == 0) {
fprintf(stderr, "Invalid image dimensions\n");
exit(1);
} else if ((p = calloc(1, psz)) == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
problem_init(p, width, height);
memset(p->image, 0xFF, p->width * p->height * 3);
do {
for (k = 0; k < 10; ++k)
render(p);
} while (fwrite(p->raw, p->len, 1, stdout));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment