summaryrefslogtreecommitdiff
path: root/libraries/daguerre
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-01-20 17:59:40 -0500
committerBenji Dial <benji@benjidial.net>2024-01-20 17:59:40 -0500
commit7199e74aa22e592a3b77bdd81f735edca5470596 (patch)
tree66e935372acc5d6e013f764965f2a9d81814f809 /libraries/daguerre
parent53135e2592c21cb9b2609bf95242aaf1f19233da (diff)
downloadhilbert-os-7199e74aa22e592a3b77bdd81f735edca5470596.tar.gz
update
Diffstat (limited to 'libraries/daguerre')
-rw-r--r--libraries/daguerre/include/daguerre/image.hpp155
-rw-r--r--libraries/daguerre/ppm.cpp52
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;
+
+ }
+
+}