#pragma once #include #include #include #include namespace daguerre { typedef uint32_t hilbert_color; struct rgb24 { uint8_t r; uint8_t g; uint8_t b; }; template static inline void default_overlay(color_t &dest, const color_t &src) { dest = src; } static inline void default_overlay(hilbert_color &dest, const rgb24 &src) { dest = __euler_encode_color(src.r, src.g, src.b); } static inline void default_overlay(rgb24 &dest, const bool &src) { dest.r = src ? 255 : 0; dest.g = src ? 255 : 0; dest.b = src ? 255 : 0; } template class image { public: bool delete_buffer_on_destruct; color_t *buffer; unsigned width; unsigned height; unsigned pitch;//in sizeof(color_t) image() : delete_buffer_on_destruct(false), buffer(0), width(0), height(0), pitch(0) {} image(unsigned width, unsigned height) : delete_buffer_on_destruct(true), buffer(new color_t[width * height]), width(width), height(height), pitch(width) {} image( color_t *buffer, unsigned width, unsigned height, unsigned pitch, bool delete_buffer_on_destruct) : delete_buffer_on_destruct(delete_buffer_on_destruct), buffer(buffer), width(width), height(height), pitch(pitch) {} ~image() { if (delete_buffer_on_destruct && buffer) delete[] buffer; } template image(const image &other) : delete_buffer_on_destruct(true), buffer(new color_t[other.width * other.height]), width(other.width), height(other.height), pitch(other.width) { overlay_from(other, 0, 0, 0, 0, width, height); } image(image &&other) : delete_buffer_on_destruct(other.delete_buffer_on_destruct), buffer(other.buffer), width(other.width), height(other.height), pitch(other.pitch) { other.buffer = 0; } template image &operator =(const image &other) { if (delete_buffer_on_destruct && buffer) delete[] buffer; delete_buffer_on_destruct = true; width = other.width; height = other.height; pitch = width; buffer = new color_t[width * height]; overlay_from(other, 0, 0, 0, 0, width, height); return *this; } image &operator =(image &&other) { if (delete_buffer_on_destruct && buffer) delete[] buffer; delete_buffer_on_destruct = other.delete_buffer_on_destruct; buffer = other.buffer; width = other.width; height = other.height; pitch = other.pitch; other.buffer = 0; return *this; } color_t get(unsigned x, unsigned y) const { return buffer[y * pitch + x]; } void set(unsigned x, unsigned y, const color_t &c) { buffer[y * pitch + x] = c; } void copy_from( const image &other, unsigned to_x, unsigned to_y, unsigned from_x, unsigned from_y, unsigned width, unsigned height) { color_t *to_start = buffer + pitch * to_y + to_x; const color_t *from_start = other.buffer + other.pitch * from_y + from_x; for (unsigned y = 0; y < height; ++y) std::memcpy( to_start + pitch * y, from_start + other.pitch * y, width * sizeof(color_t)); } template void overlay_from( const image &other, unsigned to_x, unsigned to_y, unsigned from_x, unsigned from_y, unsigned width, unsigned height) { color_t *to_start = buffer + pitch * to_y + to_x; const other_color_t *from_start = other.buffer + other.pitch * from_y + from_x; for (unsigned y = 0; y < height; ++y) for (unsigned x = 0; x < width; ++x) overlay(to_start[pitch * y + x], from_start[other.pitch * y + x]); } }; template void swap(image &a, image &b) { std::swap(a.delete_buffer_on_destruct, b.delete_buffer_on_destruct); std::swap(a.buffer, b.buffer); std::swap(a.width, b.width); std::swap(a.height, b.height); std::swap(a.pitch, b.pitch); } image get_hilbert_framebuffer(); bool try_load_ppm(std::FILE *input, image &into); static inline bool try_load_ppm(const char *path, image &into) { std::FILE *f = std::fopen(path, "r"); if (!f) return false; bool success = try_load_ppm(f, into); std::fclose(f); return success; } //TODO: unicode template class fixed_bitmap_font { public: unsigned width; unsigned height; image glyphs[128]; template void overlay_text( image &target, unsigned x, unsigned y, const char *text) const { while (1) { uint8_t ch = (uint8_t)*text; if (ch == 0) return; if (ch < 128) { target.template overlay_from( glyphs[ch], x, y, 0, 0, width, height); x += width; } ++text; } } }; bool try_load_psf(std::FILE *input, fixed_bitmap_font &into); static inline bool try_load_psf( const char *path, fixed_bitmap_font &into) { std::FILE *f = std::fopen(path, "r"); if (!f) return false; bool success = try_load_psf(f, into); std::fclose(f); return success; } }