13template <
typename PixelT>
class Image {
15 std::is_base_of_v<
Pixel<
typename PixelT::value_type >, PixelT>,
16 "Image<PixelT>: PixelT must derive from Pixel<NumberT>"
24 Image(
int width,
int height, PixelT fill = PixelT())
27 , data(width * height, fill) {
30 template <
typename ConverterT>
36 std::is_same_v<
decltype(converter.convert((
const uint8_t*)
nullptr)), PixelT>,
37 "Converter return type must match PixelT"
41 this->height = height;
42 const int pixelCount = getPixelCount();
43 data.resize(pixelCount);
44 for (
int i = 0; i < pixelCount; ++i) {
45 data[i] = converter.convert(&buffer[i * converter.bytesPerPixel]);
49 void fill(
const PixelT& color) {
50 std::fill(data.begin(), data.end(), color);
53 using iter =
typename std::vector<PixelT>::iterator;
60 using const_iter =
typename std::vector<PixelT>::const_iterator;
61 const_iter begin()
const {
64 const_iter end()
const {
68 int getWidth()
const {
71 int getHeight()
const {
74 int getPixelCount()
const {
75 return width * height;
78 return getPixelCount();
81 const std::vector<PixelT>& getData()
const {
85 const PixelT& getPixel(
int x,
int y)
const {
86 return data[index(x, y)];
88 PixelT& getPixel(
int x,
int y) {
89 return data[index(x, y)];
92 void setPixel(
int x,
int y,
const PixelT& p) {
93 data[index(x, y)] = p;
97 PixelT& operator[](
int idx) {
100 const PixelT& operator[](
int idx)
const {
105 PixelT& operator()(
int x,
int y) {
106 return data.at(index(x, y));
108 const PixelT& operator()(
int x,
int y)
const {
109 return data.at(index(x, y));
113 std::vector<PixelT> data;
116 int index(
int x,
int y)
const {
117 if (x < 0 || y < 0 || x >= width || y >= height)
118 throw std::out_of_range(
"Pixel coordinates out of bounds");
119 return y * width + x;