This repository has been archived on 2025-02-26. You can view files and clone it, but cannot push or open issues or pull requests.
hilbert-os/libraries/daguerre/include/daguerre/impl/image.hpp

225 lines
6.7 KiB
C++

#pragma once
//this file should only be included from <daguerre/image.hpp>
#include <daguerre/fixed-font.hpp>
#include <algorithm>
#include <cstring>
namespace daguerre {
template <class color_t>
image<color_t>::image()
: delete_buffer_on_destruct(false), width(0),
height(0), buffer(0), buffer_pitch(0) {}
template <class color_t>
image<color_t>::image(int width, int height)
: delete_buffer_on_destruct(true), width(width), height(height),
buffer(new color_t[width * height]), buffer_pitch(width) {}
template <class color_t>
image<color_t>::image(
int width, int height, color_t *buffer,
int buffer_pitch, bool delete_buffer_on_destruct)
: delete_buffer_on_destruct(delete_buffer_on_destruct), width(width),
height(height), buffer(buffer), buffer_pitch(buffer_pitch) {}
template <class color_t>
image<color_t>::image(image<color_t> &&other)
: delete_buffer_on_destruct(other.delete_buffer_on_destruct),
width(other.width), height(other.height), buffer(other.buffer),
buffer_pitch(other.buffer_pitch) {
other.width = 0;
other.height = 0;
other.buffer = 0;
}
template<class color_t>
image<color_t> &image<color_t>::operator =(image<color_t> &&other) {
if (delete_buffer_on_destruct && buffer)
delete[] buffer;
delete_buffer_on_destruct = other.delete_buffer_on_destruct;
width = other.width;
height = other.height;
buffer = other.buffer;
buffer_pitch = other.buffer_pitch;
other.width = 0;
other.height = 0;
other.buffer = 0;
return *this;
}
template <class color_t>
template <class other_color_t>
image<color_t>::image(const image<other_color_t> &other,
converter_t<color_t, other_color_t> *conversion)
: delete_buffer_on_destruct(true), width(other.width),
height(other.height), buffer(new color_t[other.width * other.height]),
buffer_pitch(other.width) {
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
conversion(
buffer[y * buffer_pitch + x],
other.buffer[y * other.buffer_pitch + x]);
}
template <class color_t>
image<color_t>::image(const image<color_t> &other, bool)
: delete_buffer_on_destruct(true), width(width), height(other.height),
buffer(new color_t[other.width * other.height]),
buffer_pitch(other.width) {
if (buffer_pitch == other.buffer_pitch)
memcpy(buffer, other.buffer, (height - 1) * buffer_pitch + width);
else
for (int y = 0; y < height; ++y)
memcpy(buffer + y * buffer_pitch,
other.buffer + y * other.buffer_pitch,
sizeof(color_t) * width);
}
template <class color_t>
image<color_t>::~image() {
if (delete_buffer_on_destruct && buffer)
delete[] buffer;
}
template <class color_t>
void image<color_t>::fill(const color_t &color) {
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
buffer[y * buffer_pitch + x] = color;
}
template <class color_t>
void image<color_t>::fill(
const color_t &color, int start_x, int start_y, int width, int height) {
for (int y = start_y; y < start_y + height; ++y)
for (int x = 0; x < start_x + width; ++x)
buffer[y * buffer_pitch + x] = color;
}
template <class color_t>
color_t &image<color_t>::at(int x, int y) {
return buffer[y * buffer_pitch + x];
}
template <class color_t>
const color_t &image<color_t>::at(int x, int y) const {
return buffer[y * buffer_pitch + x];
}
template <class color_t>
image<color_t> image<color_t>::stretch(int new_width, int new_height) {
image<color_t> im(new_width, new_height);
for (int y = 0; y < new_height; ++y)
for (int x = 0; x < new_width; ++x)
im.at(x, y) = at(x * width / new_width, y * height / new_height);
return im;
}
template <class color_t>
void image<color_t>::copy_from(
const image<color_t> &other, int to_x, int to_y,
int from_x, int from_y, int width, int height) {
color_t *to = buffer + to_y * buffer_pitch + to_x;
const color_t *from = other.buffer + from_y * other.buffer_pitch + from_x;
for (int y = 0; y < height; ++y)
memcpy(
to + y * buffer_pitch,
from + y * other.buffer_pitch,
width * sizeof(color_t));
}
template <class color_t>
void image<color_t>::copy_from(
const image<color_t> &other, int to_x, int to_y) {
copy_from(other, to_x, to_y, 0, 0, other.width, other.height);
}
template <class color_t>
template <class other_color_t>
void image<color_t>::convert_from(
const image<other_color_t> &other, int to_x, int to_y,
int from_x, int from_y, int width, int height,
converter_t<color_t, other_color_t> *conversion) {
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
conversion(at(to_x + x, to_y + y), other.at(from_x + x, from_y + y));
}
template <class color_t>
template <class other_color_t>
void image<color_t>::convert_from(
const image<other_color_t> &other, int to_x, int to_y,
converter_t<color_t, other_color_t> *conversion) {
convert_from(other, to_x, to_y, 0, 0, other.width, other.y, conversion);
}
template <class color_t>
template <class other_color_t, class param_t>
void image<color_t>::convert_from(
const param_t &param, const image<other_color_t> &other, int to_x,
int to_y, int from_x, int from_y, int width, int height,
param_converter_t<color_t, other_color_t, param_t> *conversion) {
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
conversion(
at(to_x + x, to_y + y), other.at(from_x + x, from_y + y), param);
}
template <class color_t>
template <class other_color_t, class param_t>
void image<color_t>::convert_from(
const param_t &param, const image<other_color_t> &other, int to_x,
int to_y, param_converter_t<color_t, other_color_t, param_t> *conversion) {
convert_from(
param, other, to_x, to_y, 0, 0, other.width, other.height, conversion);
}
template <class color_t>
template <class font_color_t, class param_t>
void image<color_t>::render_text(
const fixed_font<font_color_t> &font,
const param_t &param, int x, int y, const char *text,
param_converter_t<color_t, font_color_t, param_t> *conversion) {
while (*text) {
int ch = *text;
if (ch >= 0 && ch < 128)
convert_from(param, font.glyphs[ch], x, y, conversion);
++text;
x += font.glyph_width;
}
}
template <class color_t>
void swap(image<color_t> &a, image<color_t> &b) {
std::swap(a.delete_buffer_on_destruct, b.delete_buffer_on_destruct);
std::swap(a.width, b.width);
std::swap(a.height, b.height);
std::swap(a.buffer, b.buffer);
std::swap(a.buffer_pitch, b.buffer_pitch);
}
}