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 "aarect.hpp"
9#include <span>
10#include <string>
11#include <algorithm>
12#include <vector>
13
14namespace tt {
15
18template<typename T>
19class pixel_row {
20public:
21 pixel_row(T *pixels, ssize_t width) noexcept : _pixels(pixels), _width(width) {}
22
23 [[nodiscard]] ssize_t width() const noexcept
24 {
25 return _width;
26 }
27
30 [[nodiscard]] T const *data() const noexcept
31 {
32 return _pixels;
33 }
34
37 [[nodiscard]] T *data() noexcept
38 {
39 return _pixels;
40 }
41
46 [[nodiscard]] T const &operator[](ssize_t columnNr) const noexcept
47 {
48 return _pixels[columnNr];
49 }
50
55 [[nodiscard]] T &operator[](ssize_t columnNr) noexcept
56 {
57 return _pixels[columnNr];
58 }
59
66 [[nodiscard]] T const &at(ssize_t columnNr) const noexcept
67 {
68 tt_assert(columnNr >= 0 && columnNr < _width);
69 return _pixels[columnNr];
70 }
71
78 [[nodiscard]] T &at(ssize_t columnNr) noexcept
79 {
80 tt_assert(columnNr >= 0 && columnNr < _width);
81 return _pixels[columnNr];
82 }
83
84private:
87 T *_pixels;
88
91 ssize_t _width;
92};
93
98template<typename T>
99class pixel_map {
100public:
103 pixel_map() noexcept : _pixels(nullptr), _width(0), _height(0), _stride(0) {}
104
111 pixel_map(T *pixels, ssize_t width, ssize_t height, ssize_t stride) noexcept :
112 _pixels(pixels), _width(width), _height(height), _stride(stride)
113 {
114 if (pixels) {
115 tt_assert(_stride >= _width);
116 tt_assert(_width > 0);
117 tt_assert(_height > 0);
118 } else {
119 tt_assert(_width == 0);
120 tt_assert(_height == 0);
121 }
122 }
123
130 pixel_map(ssize_t width, ssize_t height) noexcept :
131 _pixels(new T[width * height]), _width(width), _height(height), _stride(width), _self_allocated(true)
132 {
133 if (_pixels) {
134 tt_assert(_stride >= _width);
135 tt_assert(_width > 0);
136 tt_assert(_height > 0);
137 } else {
138 tt_assert(_width == 0);
139 tt_assert(_height == 0);
140 }
141 }
142
148 pixel_map(i32x4 extent) noexcept : pixel_map(extent.x(), extent.y()) {}
149
155 pixel_map(T *pixels, ssize_t width, ssize_t height) noexcept : pixel_map(pixels, width, height, width) {}
156
161 pixel_map(T *pixels, i32x4 extent) noexcept : pixel_map(pixels, extent.x(), extent.y()) {}
162
168 pixel_map(T *pixels, i32x4 extent, ssize_t stride) noexcept : pixel_map(pixels, extent.x(), extent.y(), stride) {}
169
170 ~pixel_map()
171 {
172 if (_self_allocated) {
173 delete[] _pixels;
174 }
175 }
176
179 pixel_map(pixel_map const &other) = delete;
180
181 pixel_map copy() const noexcept
182 {
183 if (_self_allocated) {
184 auto r = pixel_map(_width, _height);
185
186 for (ssize_t y = 0; y != _height; ++y) {
187 ttlet src_row = (*this)[y];
188 auto dst_row = r[y];
189 for (ssize_t x = 0; x != _width; ++x) {
190 dst_row[x] = src_row[x];
191 }
192 }
193
194 return r;
195 } else {
196 return submap(0, 0, _width, _height);
197 }
198 }
199
200 pixel_map(pixel_map &&other) noexcept :
201 _pixels(other._pixels), _width(other._width), _height(other._height), _stride(other._stride), _self_allocated(other._self_allocated)
202 {
203 tt_axiom(this != &other);
204 other._self_allocated = false;
205 }
206
207 [[nodiscard]] operator bool() const noexcept
208 {
209 return _pixels != nullptr;
210 }
211
212 [[nodiscard]] ssize_t width() const noexcept
213 {
214 return _width;
215 }
216
217 [[nodiscard]] ssize_t height() const noexcept
218 {
219 return _height;
220 }
221
222 [[nodiscard]] ssize_t stride() const noexcept
223 {
224 return _stride;
225 }
226
229 pixel_map &operator=(pixel_map const &other) = delete;
230
231 pixel_map &operator=(pixel_map &&other) noexcept
232 {
233 // Compatible with self-move.
234 if (_self_allocated) {
235 delete[] _pixels;
236 }
237 _pixels = other._pixels;
238 _width = other._width;
239 _height = other._height;
240 _stride = other._stride;
241 _self_allocated = other._self_allocated;
242 other._self_allocated = false;
243 return *this;
244 }
245
246 i32x4 extent() const noexcept
247 {
248 return {narrow_cast<int>(_width), narrow_cast<int>(_height)};
249 }
250
256 {
257 tt_axiom((rect.left() >= 0) && (rect.bottom() >= 0));
258 tt_assert((rect.right() <= _width) && (rect.top() <= _height));
259
260 ttlet offset = rect.bottom() * _stride + rect.left();
261
262 return {_pixels + offset, rect.width(), rect.height(), _stride};
263 }
264
272 pixel_map<T> submap(ssize_t x, ssize_t y, ssize_t width, ssize_t height) const noexcept
273 {
274 return submap(iaarect{x, y, width, height});
275 }
276
277 pixel_row<T> const operator[](ssize_t rowNr) const noexcept
278 {
279 return {_pixels + (rowNr * _stride), _width};
280 }
281
282 pixel_row<T> operator[](ssize_t rowNr) noexcept
283 {
284 return {_pixels + (rowNr * _stride), _width};
285 }
286
287 pixel_row<T> const at(ssize_t rowNr) const noexcept
288 {
289 tt_assert(rowNr < _height);
290 return (*this)[rowNr];
291 }
292
293 pixel_row<T> at(ssize_t rowNr) noexcept
294 {
295 tt_assert(rowNr < _height);
296 return (*this)[rowNr];
297 }
298
299private:
302 T *_pixels;
303
306 ssize_t _width;
307
310 ssize_t _height;
311
315 ssize_t _stride;
316
319 bool _self_allocated = false;
320};
321
322template<typename T>
323void copy(pixel_map<T> const &src, pixel_map<T> &dst) noexcept
324{
325 ssize_t width = std::min(src.width(), dst.width());
326 ssize_t height = std::min(src.height(), dst.height());
327
328 for (ssize_t y = 0; y != height; ++y) {
329 ttlet src_row = src[y];
330 auto dst_row = dst[y];
331 for (ssize_t x = 0; x != width; ++x) {
332 dst_row[x] = src_row[x];
333 }
334 }
335}
336
337template<int KERNEL_SIZE, typename KERNEL>
338void horizontalFilterRow(pixel_row<uint8_t> row, KERNEL kernel) noexcept;
339
340template<int KERNEL_SIZE, typename T, typename KERNEL>
341void horizontalFilter(pixel_map<T> &pixels, KERNEL kernel) noexcept;
342
345template<typename T>
346void fill(pixel_map<T> &dst) noexcept;
347
350template<typename T>
351void fill(pixel_map<T> &dst, T color) noexcept;
352
355template<typename T>
356void rotate90(pixel_map<T> &dst, pixel_map<T> const &src) noexcept;
357
360template<typename T>
361void rotate270(pixel_map<T> &dst, pixel_map<T> const &src) noexcept;
362
365void mergeMaximum(pixel_map<uint8_t> &dst, pixel_map<uint8_t> const &src) noexcept;
366
372template<typename T>
373inline void makeTransparentBorder(pixel_map<T> &pixel_map) noexcept;
374
375} // namespace tt
A 2D canvas of pixels.
Definition pixel_map.hpp:99
pixel_map< T > submap(iaarect rect) const noexcept
Get a (smaller) view of the map.
Definition pixel_map.hpp:255
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:155
pixel_map(ssize_t width, ssize_t height) noexcept
Construct an pixel-map.
Definition pixel_map.hpp:130
pixel_map(i32x4 extent) noexcept
Construct an pixel-map.
Definition pixel_map.hpp:148
pixel_map() noexcept
Construct an empty pixel-map.
Definition pixel_map.hpp:103
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:272
pixel_map(T *pixels, i32x4 extent, ssize_t stride) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:168
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:111
pixel_map(pixel_map const &other)=delete
Disallowing copying so that life-time of selfAllocated pixels is easy to understand.
pixel_map(T *pixels, i32x4 extent) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:161
A 4D vector.
Definition ivec.hpp:38
A row of pixels.
Definition pixel_map.hpp:19
T const * data() const noexcept
Get a pointer to the pixel data.
Definition pixel_map.hpp:30
T const & operator[](ssize_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:46
T * data() noexcept
Get a pointer to the pixel data.
Definition pixel_map.hpp:37
T const & at(ssize_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:66
T & at(ssize_t columnNr) noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:78
T & operator[](ssize_t columnNr) noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:55
Class which represents an rectangle.
Definition rect.hpp:16
T copy(T... args)
T fill(T... args)
T min(T... args)