libpaint/painter.c

119 lines
3.2 KiB
C
Raw Normal View History

2022-08-15 22:38:04 +03:00
#include "painter.h"
#include "stdio.h"
lp_pixel lp_rgb(uint8_t r, uint8_t g, uint8_t b) {
return (lp_pixel){r, g, b};
}
lp_painter *lp_painter_create(size_t width, size_t height) {
lp_painter *painter = malloc(sizeof(lp_painter));
lp_pixel *buf = malloc(width * height * sizeof(lp_pixel));
painter->buf = buf;
2022-08-16 20:42:14 +03:00
painter->buf_length = width * height;
2022-08-15 22:38:04 +03:00
painter->width = width;
painter->height = height;
return painter;
}
void lp_painter_free(lp_painter *painter) {
if (painter) {
if (painter->buf) {
free(painter->buf);
}
free(painter);
}
}
2022-08-16 20:42:14 +03:00
static inline void lp_painter_put_pixel(lp_painter *painter, lp_pixel color, size_t x, size_t y) {
size_t index = y * painter->width + x;
painter->buf[index] = color;
}
2022-08-15 22:38:04 +03:00
void lp_painter_fill_rect(lp_painter *painter, lp_pixel fill_color, size_t pos_x, size_t pos_y, size_t width, size_t height) {
for (size_t y = pos_y; y < pos_y + height; y++) {
for (size_t x = pos_x; x < pos_x + width; x++) {
2022-08-16 20:42:14 +03:00
lp_painter_put_pixel(painter, fill_color, pos_x, pos_y);
}
}
}
void _lp_painter_line_low(lp_painter *p, lp_pixel color, int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
int32_t dx = x1 - x0;
int32_t dy = y1 - y0;
int32_t y_inc = 1;
if (dy < 0) {
y_inc = -1;
dy = -dy;
}
int32_t d = dy * 2 - dx;
int32_t y = y0;
for (int32_t x = x0; x < x1; x++) {
lp_painter_put_pixel(p, color, x, y);
if (d > 0) {
y += y_inc;
d += 2 * (dy - dx);
} else {
d += 2 * dy;
}
}
}
void _lp_painter_line_high(lp_painter *p, lp_pixel color, int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
int32_t dx = x1 - x0;
int32_t dy = y1 - y0;
int32_t x_inc = 1;
if (dx < 0) {
x_inc = -1;
dx = -dx;
}
int32_t d = dx * 2 - dy;
int32_t x = x0;
for (int32_t y = y0; y < y1; y++) {
lp_painter_put_pixel(p, color, x, y);
if (d > 0) {
x += x_inc;
d += 2 * (dx - dy);
} else {
d += 2 * dx;
}
}
}
void lp_painter_line(lp_painter *p, lp_pixel color, int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
if (abs(y1 - y0) < abs(x1 -x0)) {
if (x0 > x1) {
_lp_painter_line_low(p, color, x1, y1, x0, y0);
} else {
_lp_painter_line_low(p, color, x0, y0, x1, y1);
}
} else {
if (y0 > y1) {
_lp_painter_line_high(p, color, x1, y1, x0, y0);
} else {
_lp_painter_line_high(p, color, x0, y0, x1, y1);
2022-08-15 22:38:04 +03:00
}
}
}
void lp_painter_save_ppm(lp_painter *painter, const char *filename) {
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open file");
return;
}
fprintf(fp, "P6\n%zu %zu 255\n", painter->width, painter->height);
for (size_t i = 0; i < painter->width * painter->height; i++) {
fwrite(&painter->buf[i].r, sizeof(uint8_t), 1, fp);
fwrite(&painter->buf[i].g, sizeof(uint8_t), 1, fp);
fwrite(&painter->buf[i].b, sizeof(uint8_t), 1, fp);
}
fwrite(painter->buf, sizeof(lp_pixel), painter->width * painter->height, fp);
fclose(fp);
}