Skip to content

Instantly share code, notes, and snippets.

@louisswarren
Last active June 15, 2020 06:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save louisswarren/311f1f55409f7c5cf7940c662a31275b to your computer and use it in GitHub Desktop.
Save louisswarren/311f1f55409f7c5cf7940c662a31275b to your computer and use it in GitHub Desktop.
Farbfeld test
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define S_WIDTH 80
#define S_HEIGHT 80
#define S_IDX(X, Y) ((X) + (S_WIDTH) * (Y))
#define ftoff(X) htons((X) >= 1.0 ? 0xFFFF : (X) * 0x10000)
struct colour {
float r, g, b;
};
int
main(void)
{
uint32_t ff_width = htonl(S_WIDTH);
uint32_t ff_height = htonl(S_HEIGHT);
struct {
uint16_t r, g, b, a;
} ff_pixel = {.a = 0xFFFF};
struct colour *image = calloc(S_WIDTH * S_HEIGHT, sizeof(*image));
/* Draw something abstract */
for (int i = 0; i < S_WIDTH; i++) {
for (int j = 0; j < 10; j++) {
image[S_IDX(10 + j, i)].r = 0.7;
image[S_IDX(i, 10 + j)].g = 0.7;
image[S_IDX(i, 60 + j)].b = 0.7;
image[S_IDX(60 + j, i)].r = 1.0;
image[S_IDX(60 + j, i)].g = 1.0;
image[S_IDX(60 + j, i)].b = 1.0;
}
}
/* Write image as farbfeld */
fwrite("farbfeld", 8, 1, stdout);
fwrite(&ff_width, sizeof(ff_width), 1, stdout);
fwrite(&ff_height, sizeof(ff_width), 1, stdout);
for (int i = 0; i < S_WIDTH * S_HEIGHT; ++i) {
ff_pixel.r = ftoff(image[i].r);
ff_pixel.g = ftoff(image[i].g);
ff_pixel.b = ftoff(image[i].b);
fwrite(&ff_pixel, sizeof(ff_pixel), 1, stdout);
}
return 0;
}
CC = gcc
CFLAGS = -fopenmp -lm -std=c99 -pedantic -Wall
TARGETS = abstract.ff
.PHONY: default
default: $(TARGETS) $(TARGETS:.ff=.png)
%.png: %.ff
ff2png < $< > $@
%.ff: %.c
$(CC) $(CFLAGS) -o $(@:.ff=) $^
./$(@:.ff=) > $@
%: %.c
.PHONY: clean
clean:
rm -f *.png *.ff $(TARGETS) $(TARGETS:.ff=.png) $(TARGETS:.ff=)
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <omp.h>
#include <complex.h>
#define REALMIN -0.80
#define REALMAX -0.70
#define IMAGMIN 0.1
#define IMAGMAX 0.2
#define REALMID -0.75
#define IMAGMID 0.15
#define S_SCALE 6000
#define S_WIDTH 600
#define S_HEIGHT 600
#define S_IDX(X, Y) ((X) + S_WIDTH * (Y))
#define MAXITER 1000
#define ftoff(X) htons((X) >= 1.0 ? 0xFFFF : (X) * 0x10000)
#define ftoffspecr(X) ftoff(1.0 - (X))
#define ftoffspecg(X) ftoff((X) * (1.0 - (X)))
#define ftoffspecb(X) ftoff(X)
struct rgba {
uint16_t r, g, b, a;
};
int
escape_time(double complex c)
{
double complex z = c;
int t = 0;
for (; cabs(z) < 2 && t < MAXITER; ++t) {
z = z * z + c;
}
if (t == MAXITER)
t = -1;
return t;
}
/*
void
log_mb(double complex c)
{
int cv;
if ((cv = escape_time(c)) > 0)
fprintf(stderr, "%f + %fi escapes in %d iterations\n",
creal(c), cimag(c), cv);
else
fprintf(stderr, "%f + %fi is in the mandlebrot set\n",
creal(c), cimag(c));
}
*/
int
main(void)
{
uint32_t ff_width = htonl(S_WIDTH);
uint32_t ff_height = htonl(S_HEIGHT);
struct rgba *ff_image = calloc(S_WIDTH * S_HEIGHT, sizeof(*ff_image));
for (int i = 0; i < S_WIDTH * S_HEIGHT; ++i)
ff_image[i].a = 0xFFFF;
/* Projection values */
double xscale = ((double) REALMAX - REALMIN) / S_WIDTH;
double yscale = ((double) IMAGMAX - IMAGMIN) / S_HEIGHT;
double xshift = REALMIN + xscale / 2;
double yshift = IMAGMIN + yscale / 2;
#pragma omp parallel for
for (int j = 0; j < S_HEIGHT; j++) {
struct rgba *pixel;
double complex c;
int cv;
for (int i = 0; i < S_WIDTH; i++) {
c = (xscale * i + xshift) + I * (yscale * j + yshift);
if ((cv = escape_time(c)) > 0) {
pixel = &ff_image[S_IDX(i, S_HEIGHT - j)];
pixel->r = ftoffspecr((double) MAXITER / cv);
pixel->g = ftoffspecg((double) MAXITER / cv);
pixel->b = ftoffspecb((double) MAXITER / cv);
}
}
}
/* Write image as farbfeld */
fwrite("farbfeld", 8, 1, stdout);
fwrite(&ff_width, sizeof(ff_width), 1, stdout);
fwrite(&ff_height, sizeof(ff_width), 1, stdout);
fwrite(ff_image, sizeof(struct rgba), S_WIDTH * S_HEIGHT, stdout);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment