#include #include #include #include static inline int32_t max(int32_t a, int32_t b) { return a > b ? a : b; } static inline int32_t min(int32_t a, int32_t b) { return a < b ? a : b; } image_data_t image_create(uint16_t width, uint16_t height) { image_data_t data; data.width = width; data.height = height; size_t length = width * height * sizeof(image_color_t); data.pixels = (image_color_t*)malloc(length); memset(data.pixels, 255, length); return data; } void image_free(image_data_t image) { if (image.pixels) { free(image.pixels); } } static inline void set_point(image_data_t image, int16_t x, int16_t y, image_color_t color) { image.pixels[x + y * image.width] = color; } void image_draw_point(image_data_t image, int16_t x, int16_t y, image_color_t color) { if (x >= image.width || y >= image.height || x < 0 || y < 0) { return; } set_point(image, x, y, color); } void image_draw_hline(image_data_t image, int16_t x1, int16_t x2, int16_t y, image_color_t color) { if (y < 0 || y >= image.height) { return; } if (x1 > x2) { int16_t temp = x1; x1 = x2; x2 = temp; } if (x1 > image.width || x2 < 0) { return; } x1 = (int16_t)max(0, x1); x2 = (int16_t)min(x2, image.width); do { set_point(image, x1++, y, color); } while (x1 < x2); } void image_draw_vline(image_data_t image, int16_t x, int16_t y1, int16_t y2, image_color_t color) { if (x < 0 || x >= image.width) { return; } if (y1 > y2) { int16_t temp = y1; y1 = y2; y2 = temp; } if (y1 > image.width || y2 < 0) { return; } y1 = (int16_t)max(0, y1); y2 = (int16_t)min(y2, image.height); do { set_point(image, x, y1++, color); } while (y1 < y2); } void image_draw_line(image_data_t image, int16_t x1, int16_t y1, int16_t x2, int16_t y2, image_color_t color) { int dx = abs(x2 - x1); int dy = abs(y2 - y1); int sx = (x1 < x2) ? 1 : -1; int sy = (y1 < y2) ? 1 : -1; int err = dx - dy; int e2; while (1) { if ((x1 >= image.width && x2 >= image.width) || (y1 >= image.height && y2 >= image.height)) { break; } if ((x1 < 0 && x2 < 0) || (y1 < 0 && y2 < 0)) { break; } image_draw_point(image, x1, y1, color); if (x1 == x2 && y1 == y2) { break; } e2 = 2 * err; if (e2 > -dy) { err -= dy; x1 += sx; } if (e2 < dx) { err += dx; y1 += sy; } } } void image_draw_rect(image_data_t image, int16_t x, int16_t y, int16_t w, int16_t h, image_color_t color) { if (w <= 0 || h <= 0) { return; } w = (int16_t)min(image.width - x, w); h = (int16_t)min(image.height - y, h); image_draw_hline(image, x, x + w - 1, y, color); image_draw_hline(image, x, x + w, y + h - 1, color); image_draw_vline(image, x, y, y + h - 1, color); image_draw_vline(image, x + w - 1, y, y + h - 1, color); } void image_fill_rect(image_data_t image, int16_t x, int16_t y, int16_t w, int16_t h, image_color_t color) { if (w <= 0 || h <= 0) { return; } x = (int16_t)max(0, x); y = (int16_t)max(0, y); w = (int16_t)min(image.width - x, w); h = (int16_t)min(image.height - y, h); while (h--) { image_draw_hline(image, x, x + w, y++, color); }; }