HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
pixel_map.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "required.hpp"
8#include "geometry/axis_aligned_rectangle.hpp"
9#include "geometry/extent.hpp"
10#include <span>
11#include <string>
12#include <algorithm>
13#include <vector>
14
15namespace tt {
16
19template<typename T>
20class pixel_row {
21public:
22 pixel_row(T *pixels, ssize_t width) noexcept : _pixels(pixels), _width(width) {}
23
24 [[nodiscard]] ssize_t width() const noexcept
25 {
26 return _width;
27 }
28
31 [[nodiscard]] T const *data() const noexcept
32 {
33 return _pixels;
34 }
35
38 [[nodiscard]] T *data() noexcept
39 {
40 return _pixels;
41 }
42
47 [[nodiscard]] T const &operator[](ssize_t columnNr) const noexcept
48 {
49 return _pixels[columnNr];
50 }
51
56 [[nodiscard]] T &operator[](ssize_t columnNr) noexcept
57 {
58 return _pixels[columnNr];
59 }
60
67 [[nodiscard]] T const &at(ssize_t columnNr) const noexcept
68 {
69 tt_assert(columnNr >= 0 && columnNr < _width);
70 return _pixels[columnNr];
71 }
72
79 [[nodiscard]] T &at(ssize_t columnNr) noexcept
80 {
81 tt_assert(columnNr >= 0 && columnNr < _width);
82 return _pixels[columnNr];
83 }
84
85private:
88 T *_pixels;
89
92 ssize_t _width;
93};
94
99template<typename T>
101public:
104 pixel_map() noexcept : _pixels(nullptr), _width(0), _height(0), _stride(0), _self_allocated(true) {}
105
112 pixel_map(T *pixels, ssize_t width, ssize_t height, ssize_t stride) noexcept :
113 _pixels(pixels), _width(width), _height(height), _stride(stride), _self_allocated(false)
114 {
115 tt_assert(_stride >= _width);
116 tt_assert(_width >= 0);
117 tt_assert(_height >= 0);
118
119 if (pixels == nullptr) {
120 _self_allocated = true;
121 _pixels = new T[_height * _stride];
122 }
123 }
124
131 pixel_map(T *pixels, ssize_t width, ssize_t height) noexcept : pixel_map(pixels, width, height, width) {}
132
138 pixel_map(ssize_t width, ssize_t height, ssize_t stride) noexcept : pixel_map(nullptr, width, height, stride) {}
139
145 pixel_map(ssize_t width, ssize_t height) noexcept : pixel_map(nullptr, width, height, width) {}
146
147 ~pixel_map()
148 {
149 if (_self_allocated) {
150 delete[] _pixels;
151 }
152 }
153
156 pixel_map(pixel_map const &other) = delete;
157
158 pixel_map copy() const noexcept
159 {
160 if (_self_allocated) {
161 auto r = pixel_map(_width, _height);
162
163 for (ssize_t y = 0; y != _height; ++y) {
164 ttlet src_row = (*this)[y];
165 auto dst_row = r[y];
166 for (ssize_t x = 0; x != _width; ++x) {
167 dst_row[x] = src_row[x];
168 }
169 }
170
171 return r;
172 } else {
173 return submap(0, 0, _width, _height);
174 }
175 }
176
177 pixel_map(pixel_map &&other) noexcept :
178 _pixels(other._pixels),
179 _width(other._width),
180 _height(other._height),
181 _stride(other._stride),
182 _self_allocated(other._self_allocated)
183 {
184 tt_axiom(this != &other);
185 other._self_allocated = false;
186 }
187
188 [[nodiscard]] operator bool() const noexcept
189 {
190 return _pixels != nullptr;
191 }
192
193 [[nodiscard]] ssize_t width() const noexcept
194 {
195 return _width;
196 }
197
198 [[nodiscard]] ssize_t height() const noexcept
199 {
200 return _height;
201 }
202
203 [[nodiscard]] ssize_t stride() const noexcept
204 {
205 return _stride;
206 }
207
210 pixel_map &operator=(pixel_map const &other) = delete;
211
212 pixel_map &operator=(pixel_map &&other) noexcept
213 {
214 // Compatible with self-move.
215 if (_self_allocated) {
216 delete[] _pixels;
217 }
218 _pixels = other._pixels;
219 _width = other._width;
220 _height = other._height;
221 _stride = other._stride;
222 _self_allocated = other._self_allocated;
223 other._self_allocated = false;
224 return *this;
225 }
226
227 extent2 extent() const noexcept
228 {
229 return {narrow_cast<float>(_width), narrow_cast<float>(_height)};
230 }
231
239 pixel_map<T> submap(ssize_t x, ssize_t y, ssize_t width, ssize_t height) const noexcept
240 {
241 tt_axiom((x >= 0) && (y >= 0));
242 tt_assert((x + width <= _width) && (y + height <= _height));
243
244 ttlet offset = y * _stride + x;
245
246 return {_pixels + offset, width, height, _stride};
247 }
248
250 {
251 tt_axiom(round(rectangle) == rectangle);
252 return submap(
253 narrow_cast<ssize_t>(rectangle.left()),
254 narrow_cast<ssize_t>(rectangle.bottom()),
255 narrow_cast<ssize_t>(rectangle.width()),
256 narrow_cast<ssize_t>(rectangle.height()));
257 }
258
259 pixel_row<T> const operator[](ssize_t rowNr) const noexcept
260 {
261 return {_pixels + (rowNr * _stride), _width};
262 }
263
264 pixel_row<T> operator[](ssize_t rowNr) noexcept
265 {
266 return {_pixels + (rowNr * _stride), _width};
267 }
268
269 pixel_row<T> const at(ssize_t rowNr) const noexcept
270 {
271 tt_assert(rowNr < _height);
272 return (*this)[rowNr];
273 }
274
275 pixel_row<T> at(ssize_t rowNr) noexcept
276 {
277 tt_assert(rowNr < _height);
278 return (*this)[rowNr];
279 }
280
281private:
284 T *_pixels;
285
288 ssize_t _width;
289
292 ssize_t _height;
293
297 ssize_t _stride;
298
301 bool _self_allocated;
302};
303
304template<typename T>
305void copy(pixel_map<T> const &src, pixel_map<T> &dst) noexcept
306{
307 ssize_t width = std::min(src.width(), dst.width());
308 ssize_t height = std::min(src.height(), dst.height());
309
310 for (ssize_t y = 0; y != height; ++y) {
311 ttlet src_row = src[y];
312 auto dst_row = dst[y];
313 for (ssize_t x = 0; x != width; ++x) {
314 dst_row[x] = src_row[x];
315 }
316 }
317}
318
319template<int KERNEL_SIZE, typename KERNEL>
320void horizontalFilterRow(pixel_row<uint8_t> row, KERNEL kernel) noexcept;
321
322template<int KERNEL_SIZE, typename T, typename KERNEL>
323void horizontalFilter(pixel_map<T> &pixels, KERNEL kernel) noexcept;
324
327template<typename T>
328void fill(pixel_map<T> &dst) noexcept;
329
332template<typename T>
333void fill(pixel_map<T> &dst, T color) noexcept;
334
337template<typename T>
338void rotate90(pixel_map<T> &dst, pixel_map<T> const &src) noexcept;
339
342template<typename T>
343void rotate270(pixel_map<T> &dst, pixel_map<T> const &src) noexcept;
344
347void mergeMaximum(pixel_map<uint8_t> &dst, pixel_map<uint8_t> const &src) noexcept;
348
354template<typename T>
355inline void makeTransparentBorder(pixel_map<T> &pixel_map) noexcept;
356
357} // namespace tt
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:18
Class which represents an rectangle.
Definition rectangle.hpp:16
A 2D canvas of pixels.
Definition pixel_map.hpp:100
pixel_map(T *pixels, ssize_t width, ssize_t height) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:131
pixel_map(ssize_t width, ssize_t height) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:145
pixel_map() noexcept
Construct an empty pixel-map.
Definition pixel_map.hpp:104
pixel_map(ssize_t width, ssize_t height, ssize_t stride) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:138
pixel_map< T > submap(ssize_t x, ssize_t y, ssize_t width, ssize_t height) const noexcept
Get a (smaller) view of the map.
Definition pixel_map.hpp:239
pixel_map & operator=(pixel_map const &other)=delete
Disallowing copying so that life-time of selfAllocated pixels is easy to understand.
pixel_map(T *pixels, ssize_t width, ssize_t height, ssize_t stride) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:112
pixel_map(pixel_map const &other)=delete
Disallowing copying so that life-time of selfAllocated pixels is easy to understand.
A row of pixels.
Definition pixel_map.hpp:20
T const * data() const noexcept
Get a pointer to the pixel data.
Definition pixel_map.hpp:31
T const & operator[](ssize_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:47
T * data() noexcept
Get a pointer to the pixel data.
Definition pixel_map.hpp:38
T const & at(ssize_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:67
T & at(ssize_t columnNr) noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:79
T & operator[](ssize_t columnNr) noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:56
T copy(T... args)
T fill(T... args)
T min(T... args)