From 4baf837256b89c9c5d9d114ab4940a6e71b14117 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sat, 20 Jul 2024 17:23:24 +0100 Subject: [PATCH] Move Image struct and add clear image, set pixel and draw_line functions --- src/img.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/img.h | 29 ++++++++++++++++++++++ src/main.c | 26 +++++++++++++------- 3 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 src/img.c create mode 100644 src/img.h diff --git a/src/img.c b/src/img.c new file mode 100644 index 0000000..bdfa4d8 --- /dev/null +++ b/src/img.c @@ -0,0 +1,70 @@ +#include "img.h" +#include "mem_arena.h" +#include "pam.h" +#include "utils.h" +#include +#include + +#define SAMPLES_PER_PIXEL 4 + +bool init_image(Arena *arena, Image *img) { + if (!arena || !img || img->width == 0 || img->height == 0) { + return false; + } + + u64 size = img->width * img->height * SAMPLES_PER_PIXEL; + img->buf = wapp_mem_arena_alloc(arena, size); + + return img->buf != NULL; +} + +void set_pixel(Image *img, u64 x, u64 y, Colour colour) { + u64 idx = (y * img->width + x) * SAMPLES_PER_PIXEL; + for (u64 i = 0; i < SAMPLES_PER_PIXEL; ++i) { + img->buf[idx + i] = *(((u8 *)&colour) + i); + } +} + +void clear_image(Image *img, Colour colour) { + for (u64 y = 0; y < img->height; ++y) { + for (u64 x = 0; x < img->width; ++x) { + set_pixel(img, x, y, colour); + } + } +} + +void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour) { + u64 dx = absolute((i64)x1 - (i64)x0); + u64 dy = absolute((i64)y1 - (i64)y0); + f32 t = 0.0f; + i64 x = 0; + i64 y = 0; + + if (dx > dy) { + if (x0 > x1) { + swap(u64, x0, x1); + swap(u64, y0, y1); + } + + for (u64 x = x0; x < x1; ++x) { + t = (f32)(x - x0) / (f32)(x1 - x0); + y = (i64)y0 + ((i64)y1 - (i64)y0) * t; + set_pixel(img, x, y, colour); + } + } else { + if (y0 > y1) { + swap(u64, x0, x1); + swap(u64, y0, y1); + } + + for (u64 y = y0; y < y1; ++y) { + t = (f32)(y - y0) / (f32)(y1 - y0); + x = (i64)x0 + ((i64)x1 - (i64)x0) * t; + set_pixel(img, x, y, colour); + } + } +} + +void save_image(const Image *img, const char *filename) { + write_p7_image(img->width, img->height, img->buf, filename); +} diff --git a/src/img.h b/src/img.h new file mode 100644 index 0000000..2d80e6c --- /dev/null +++ b/src/img.h @@ -0,0 +1,29 @@ +#ifndef IMG_H +#define IMG_H + +#include "aliases.h" +#include "mem_arena.h" +#include + +typedef struct img Image; +struct img { + u64 width; + u64 height; + u8 *buf; +}; + +typedef struct colour Colour; +struct colour { + u8 r; + u8 g; + u8 b; + u8 a; +}; + +bool init_image(Arena *arena, Image *img); +void set_pixel(Image *img, u64 x, u64 y, Colour colour); +void clear_image(Image *img, Colour colour); +void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour); +void save_image(const Image *img, const char *filename); + +#endif // IMG_H diff --git a/src/main.c b/src/main.c index 5384196..55b26f7 100644 --- a/src/main.c +++ b/src/main.c @@ -1,26 +1,34 @@ -#include "aliases.h" +#include "img.h" #include "mem_arena.h" #include "mem_utils.h" -#include "pam.h" #include #include #include -typedef struct img Image; -struct img { - u64 width; - u64 height; - u8 *buf; +enum { + TINY_EXIT_SUCCESS, + TINY_EXIT_ARENA_INIT_FAILED, + TINY_EXIT_IMAGE_INIT_FAILED, }; int main(void) { Arena *arena = NULL; if (!wapp_mem_arena_init(&arena, 10ul * 1024ul * 1024ul * 1024ul, WAPP_MEM_ALLOC_RESERVE, false)) { - return -1; + return TINY_EXIT_ARENA_INIT_FAILED; } + Colour cyan = {.r = 0, .g = 255, .b = 255, .a = 255}; + Colour red = {.r = 255, .g = 0, .b = 0, .a = 255}; + Image img = {.width = 200, .height = 200}; + if (!init_image(arena, &img)) { + return TINY_EXIT_IMAGE_INIT_FAILED; + } + + clear_image(&img, cyan); + save_image(&img, "result.pam"); + wapp_mem_arena_destroy(&arena); - return 0; + return TINY_EXIT_SUCCESS; }