225 lines
6.7 KiB
C++
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 ¶m, 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 ¶m, 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 ¶m, 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);
|
|
}
|
|
|
|
}
|