84 lines
1.7 KiB
C
84 lines
1.7 KiB
C
#pragma once
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#include "tuples.h"
|
|
|
|
#ifndef CANVAS_MAX
|
|
#define CANVAS_MAX 32
|
|
#endif
|
|
|
|
struct canvas {
|
|
int width;
|
|
int height;
|
|
struct tuple pixels[CANVAS_MAX * CANVAS_MAX];
|
|
};
|
|
|
|
inline static struct canvas canvas(int width, int height)
|
|
{
|
|
struct canvas c;
|
|
assert(width < CANVAS_MAX);
|
|
assert(height < CANVAS_MAX);
|
|
c.width = width;
|
|
c.height = height;
|
|
|
|
for (int i = 0; i < c.width * c.height; i++) {
|
|
c.pixels[i] = tuple(0.0f, 0.0f, 0.0f, 0.0f);
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
inline static void canvas_write_pixel(struct canvas * canvas, int x, int y, struct tuple color)
|
|
{
|
|
struct tuple * pixel = &canvas->pixels[y * canvas->width + x];
|
|
pixel->r = color.r;
|
|
pixel->g = color.g;
|
|
pixel->b = color.b;
|
|
pixel->a = color.a;
|
|
}
|
|
|
|
inline static struct tuple canvas_pixel_at(struct canvas * canvas, int x, int y)
|
|
{
|
|
return canvas->pixels[y * canvas->width + x];
|
|
}
|
|
|
|
inline static int clamp_0_255(float n)
|
|
{
|
|
if (n > 1.0f) {
|
|
return 255;
|
|
} else if (n < 0.0f) {
|
|
return 0;
|
|
} else {
|
|
return (int)(n * 255.0f);
|
|
}
|
|
}
|
|
|
|
inline static void canvas_to_ppm(struct canvas * canvas, const char * pathname)
|
|
{
|
|
FILE * f = fopen(pathname, "w");
|
|
if (f == NULL) {
|
|
perror("fopen");
|
|
}
|
|
|
|
fwrite("P6\n", 3, 1, f);
|
|
fprintf(f, "%d %d\n", canvas->width, canvas->height);
|
|
fwrite("255\n", 4, 1, f);
|
|
|
|
for (int i = 0; i < canvas->width * canvas->height; i++) {
|
|
struct tuple * pixel = &canvas->pixels[i];
|
|
char buf[3];
|
|
buf[0] = clamp_0_255(pixel->r);
|
|
buf[1] = clamp_0_255(pixel->g);
|
|
buf[2] = clamp_0_255(pixel->b);
|
|
fwrite(buf, 3, 1, f);
|
|
}
|
|
|
|
int ret = fclose(f);
|
|
if (ret != 0) {
|
|
perror("fclose");
|
|
}
|
|
}
|