diff options
author | Benji Dial <benji@benjidial.net> | 2024-01-20 17:59:40 -0500 |
---|---|---|
committer | Benji Dial <benji@benjidial.net> | 2024-01-20 17:59:40 -0500 |
commit | 7199e74aa22e592a3b77bdd81f735edca5470596 (patch) | |
tree | 66e935372acc5d6e013f764965f2a9d81814f809 /libraries/daguerre | |
parent | 53135e2592c21cb9b2609bf95242aaf1f19233da (diff) | |
download | hilbert-os-7199e74aa22e592a3b77bdd81f735edca5470596.tar.gz |
update
Diffstat (limited to 'libraries/daguerre')
-rw-r--r-- | libraries/daguerre/include/daguerre/image.hpp | 155 | ||||
-rw-r--r-- | libraries/daguerre/ppm.cpp | 52 |
2 files changed, 207 insertions, 0 deletions
diff --git a/libraries/daguerre/include/daguerre/image.hpp b/libraries/daguerre/include/daguerre/image.hpp new file mode 100644 index 0000000..6129306 --- /dev/null +++ b/libraries/daguerre/include/daguerre/image.hpp @@ -0,0 +1,155 @@ +#pragma once + +#include <euler/syscall.hpp> +#include <cassert> +#include <cstdint> +#include <cstdio> + +namespace daguerre { + + struct color24 { + uint8_t r; + uint8_t g; + uint8_t b; + }; + + using hilbert_color = euler::syscall::encoded_color; + + static inline hilbert_color to_hilbert_color(const color24 &c) { + return _syscall_encode_color(c.r, c.g, c.b); + } + + template <class pixel_type = color24> + class image { + + pixel_type *buffer; + unsigned width; + unsigned height; + unsigned pitch; //in pixels + + bool buffer_owned; + + public: + image() : buffer(0) {} + + image(pixel_type *buffer, unsigned width, + unsigned height, unsigned pitch, bool buffer_owned + ) : buffer(buffer), width(width), height(height), + pitch(pitch), buffer_owned(buffer_owned) {} + + image(unsigned width, unsigned height) + : buffer(new pixel_type[width * height]), width(width), + height(height), pitch(width), buffer_owned(true) {} + + image(const image<pixel_type> &other) = delete; + + image(image<pixel_type> &&other) + : buffer(other.buffer), width(other.width), height(other.height), + pitch(other.pitch), buffer_owned(other.buffer_owned) { + other.buffer = 0; + } + + ~image() { + if (buffer && buffer_owned) + delete[] buffer; + } + + image &operator =(const image<pixel_type> &other) = delete; + + image &operator =(image<pixel_type> &&other) { + if (buffer && buffer_owned) + delete[] buffer; + buffer = other.buffer; + width = other.width; + height = other.height; + pitch = other.pitch; + buffer_owned = other.buffer_owned; + other.buffer = 0; + return *this; + } + + pixel_type &get(unsigned x, unsigned y) { + return buffer[y * pitch + x]; + } + + const pixel_type &get(unsigned x, unsigned y) const { + return buffer[y * pitch + x]; + } + + pixel_type *get_buffer() { + return buffer; + } + + const pixel_type *get_buffer() const { + return buffer; + } + + unsigned get_width() const { + return width; + } + + unsigned get_height() const { + return height; + } + + unsigned get_pitch() const { + return pitch; + } + + }; + + template <class pixel_type> + void default_converter(const pixel_type &i, pixel_type &o) { + o = i; + } + + static inline void default_converter(const color24 &i, hilbert_color &o) { + o = to_hilbert_color(i); + } + + //copies a rectangle of size width x height from source to destination. the + //rectangle starts in source at (source_x, source_y), and in destination at + //(destination_x, destination_y). every pixel is passed through the converter + //template argument. + template < + class source_pixel_type, class destination_pixel_type, + void (*converter)(const source_pixel_type &, destination_pixel_type &) = + &default_converter> + void copy_image(const image<source_pixel_type> &source, + image<destination_pixel_type> &destination, unsigned source_x, + unsigned source_y, unsigned destination_x, unsigned destination_y, + unsigned width, unsigned height + ) { + + assert(source_x + width <= source.get_width()); + assert(source_y + height <= source.get_height()); + assert(destination_x + width <= destination.get_width()); + assert(destination_y + height <= destination.get_height()); + + unsigned source_pitch = source.get_pitch(); + unsigned destination_pitch = destination.get_pitch(); + + const source_pixel_type *source_buffer = + &source.get_buffer()[source_y * source_pitch + source_x]; + destination_pixel_type *destination_buffer = &destination.get_buffer()[ + destination_y * destination_pitch + destination_x]; + + for (unsigned y = 0; y < height; ++y) + for (unsigned x = 0; x < width; ++x) + converter(source_buffer[y * source_pitch + x], + destination_buffer[y * destination_pitch + x]); + + } + + static inline image<hilbert_color> get_hilbert_framebuffer() { + hilbert_color *ptr; + uint32_t width; + uint32_t height; + uint32_t pitch; + _syscall_get_framebuffer(ptr, width, height, pitch); + return image<hilbert_color>(ptr, width, height, pitch, false); + } + + bool try_load_ppm(std::FILE *from, image<color24> &into); + +} diff --git a/libraries/daguerre/ppm.cpp b/libraries/daguerre/ppm.cpp new file mode 100644 index 0000000..e909503 --- /dev/null +++ b/libraries/daguerre/ppm.cpp @@ -0,0 +1,52 @@ +#include <daguerre/image.hpp> +#include <cctype> + +namespace daguerre { + + static unsigned read_int(std::FILE *from) { + unsigned out = 0; + int ch; + do + ch = std::fgetc(from); + while (std::isspace(ch)); + while (true) { + if (ch == EOF) + return out; + if (ch < '0' || ch > '9') { + std::ungetc(ch, from); + return out; + } + out = out * 10 + (ch - '0'); + ch = std::fgetc(from); + } + } + + bool try_load_ppm(std::FILE *from, image<color24> &into) { + + if (std::fgetc(from) != 'P' || std::fgetc(from) != '6' || + std::fgetc(from) != '\n') + return false; + + unsigned width = read_int(from); + unsigned height = read_int(from); + unsigned max = read_int(from); + std::fgetc(from);//newline + + if (max != 255) + return false; + + into = image<color24>(width, height); + color24 *buffer = into.get_buffer(); + + for (unsigned y = 0; y < height; ++y) + for (unsigned x = 0; x < width; ++x) { + buffer[y * width + x].r = std::fgetc(from); + buffer[y * width + x].g = std::fgetc(from); + buffer[y * width + x].b = std::fgetc(from); + } + + return true; + + } + +} |