#pragma once #include #include #include #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"); } }