HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
pixel_map.hpp
1// Copyright Take Vos 2021-2022.
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 "utility.hpp"
8#include "geometry/axis_aligned_rectangle.hpp"
9#include "geometry/extent.hpp"
10#include <algorithm>
11#include <cassert>
12#include <span>
13#include <string>
14#include <vector>
15
16hi_warning_push();
17// C26401: Do not delete a raw pointer that is not an owner<T> (i.11).
18// pixel map may be a container for pixel data.
19hi_warning_ignore_msvc(26401);
20// C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11).
21// pixel map may be a container for pixel data.
22hi_warning_ignore_msvc(26409);
23
24namespace hi::inline v1 {
25
28template<typename T>
29class pixel_row {
30public:
31 using value_type = T;
32
33 pixel_row(T *pixels, std::size_t width) noexcept : _pixels(pixels), _width(width) {}
34
35 [[nodiscard]] std::size_t width() const noexcept
36 {
37 return _width;
38 }
39
42 [[nodiscard]] T const *data() const noexcept
43 {
44 return _pixels;
45 }
46
49 [[nodiscard]] T *data() noexcept
50 {
51 return _pixels;
52 }
53
58 [[nodiscard]] T const& operator[](std::size_t columnNr) const noexcept
59 {
60 return _pixels[columnNr];
61 }
62
67 [[nodiscard]] T& operator[](std::size_t columnNr) noexcept
68 {
69 return _pixels[columnNr];
70 }
71
78 [[nodiscard]] T const& at(std::size_t columnNr) const noexcept
79 {
80 hi_assert(columnNr >= 0 && columnNr < _width);
81 return _pixels[columnNr];
82 }
83
90 [[nodiscard]] T& at(std::size_t columnNr) noexcept
91 {
92 hi_assert(columnNr >= 0 && columnNr < _width);
93 return _pixels[columnNr];
94 }
95
96private:
99 T *_pixels;
100
103 std::size_t _width;
104};
105
110template<typename T>
112public:
113 using value_type = T;
114
117 pixel_map() noexcept : _pixels(nullptr), _width(0), _height(0), _stride(0), _self_allocated(true) {}
118
125 pixel_map(T *pixels, std::size_t width, std::size_t height, std::size_t stride) noexcept :
126 _pixels(pixels), _width(width), _height(height), _stride(stride), _self_allocated(false)
127 {
128 hi_assert(_stride >= _width);
129 hi_assert(_width >= 0);
130 hi_assert(_height >= 0);
131
132 if (pixels == nullptr) {
133 _self_allocated = true;
134 _pixels = new T[_height * _stride];
135 }
136 }
137
144 pixel_map(T *pixels, std::size_t width, std::size_t height) noexcept : pixel_map(pixels, width, height, width) {}
145
152 pixel_map(std::size_t width, std::size_t height, std::size_t stride) noexcept : pixel_map(nullptr, width, height, stride) {}
153
159 pixel_map(std::size_t width, std::size_t height) noexcept : pixel_map(nullptr, width, height, width) {}
160
161 ~pixel_map()
162 {
163 if (_self_allocated) {
164 delete[] _pixels;
165 }
166 }
167
173 pixel_map(pixel_map const& other) noexcept :
174 _pixels(other._pixels),
175 _width(other._width),
176 _height(other._height),
177 _stride(other._stride),
178 _self_allocated(other._self_allocated)
179 {
180 if (_self_allocated) {
181 _pixels = new T[_height * _stride];
182
183 for (std::size_t y = 0; y != _height; ++y) {
184 hilet src_row = other[y];
185 auto dst_row = (*this)[y];
186 for (std::size_t x = 0; x != _width; ++x) {
187 dst_row[x] = src_row[x];
188 }
189 }
190 }
191 }
192
193 pixel_map(pixel_map&& other) noexcept :
194 _pixels(other._pixels),
195 _width(other._width),
196 _height(other._height),
197 _stride(other._stride),
198 _self_allocated(other._self_allocated)
199 {
200 hi_assert(this != &other);
201 other._self_allocated = false;
202 }
203
204 [[nodiscard]] operator bool() const noexcept
205 {
206 return _pixels != nullptr;
207 }
208
209 [[nodiscard]] std::size_t width() const noexcept
210 {
211 return _width;
212 }
213
214 [[nodiscard]] std::size_t height() const noexcept
215 {
216 return _height;
217 }
218
219 [[nodiscard]] std::size_t stride() const noexcept
220 {
221 return _stride;
222 }
223
227 {
228 hi_return_on_self_assignment(other);
229
230 _pixels = other._pixels;
231 _width = other._width;
232 _height = other._height;
233 _stride = other._stride;
234 _self_allocated = other._self_allocated;
235
236 if (_self_allocated) {
237 _pixels = new T[_height * _stride];
238
239 for (std::size_t y = 0; y != _height; ++y) {
240 hilet src_row = other[y];
241 auto dst_row = (*this)[y];
242 for (std::size_t x = 0; x != _width; ++x) {
243 dst_row[x] = src_row[x];
244 }
245 }
246 }
247 return *this;
248 }
249
250 pixel_map& operator=(pixel_map&& other) noexcept
251 {
252 // Self assignment is allowed.
253 if (_self_allocated) {
254 delete[] _pixels;
255 }
256 _pixels = other._pixels;
257 _width = other._width;
258 _height = other._height;
259 _stride = other._stride;
260 _self_allocated = other._self_allocated;
261 other._self_allocated = false;
262 return *this;
263 }
264
265 extent2 extent() const noexcept
266 {
267 return {narrow_cast<float>(_width), narrow_cast<float>(_height)};
268 }
269
277 pixel_map submap(std::size_t x, std::size_t y, std::size_t width, std::size_t height) const noexcept
278 {
279 hi_assert((x >= 0) && (y >= 0));
280 hi_assert((x + width <= _width) && (y + height <= _height));
281
282 hilet offset = y * _stride + x;
283
284 return pixel_map{_pixels + offset, width, height, _stride};
285 }
286
287 pixel_map submap(aarectangle rectangle) const noexcept
288 {
289 hi_assert(round(rectangle) == rectangle);
290 return submap(
291 narrow_cast<std::size_t>(rectangle.left()),
292 narrow_cast<std::size_t>(rectangle.bottom()),
293 narrow_cast<std::size_t>(rectangle.width()),
294 narrow_cast<std::size_t>(rectangle.height()));
295 }
296
297 pixel_row<T> const operator[](std::size_t rowNr) const noexcept
298 {
299 return {_pixels + (rowNr * _stride), _width};
300 }
301
302 pixel_row<T> operator[](std::size_t rowNr) noexcept
303 {
304 return {_pixels + (rowNr * _stride), _width};
305 }
306
307 pixel_row<T> const at(std::size_t rowNr) const noexcept
308 {
309 hi_assert(rowNr < _height);
310 return (*this)[rowNr];
311 }
312
313 pixel_row<T> at(std::size_t rowNr) noexcept
314 {
315 hi_assert(rowNr < _height);
316 return (*this)[rowNr];
317 }
318
319private:
322 T *_pixels;
323
326 std::size_t _width;
327
330 std::size_t _height;
331
335 std::size_t _stride;
336
339 bool _self_allocated;
340};
341
342template<typename T>
343void copy(pixel_map<T> const& src, pixel_map<T>& dst) noexcept
344{
345 std::size_t width = std::min(src.width(), dst.width());
346 std::size_t height = std::min(src.height(), dst.height());
347
348 for (std::size_t y = 0; y != height; ++y) {
349 hilet src_row = src[y];
350 auto dst_row = dst[y];
351 for (std::size_t x = 0; x != width; ++x) {
352 dst_row[x] = src_row[x];
353 }
354 }
355}
356
357template<int KERNEL_SIZE, typename KERNEL>
358void horizontalFilterRow(pixel_row<uint8_t> row, KERNEL kernel) noexcept;
359
360template<int KERNEL_SIZE, typename T, typename KERNEL>
361void horizontalFilter(pixel_map<T>& pixels, KERNEL kernel) noexcept;
362
365template<typename T>
366void fill(pixel_map<T>& dst) noexcept;
367
370template<typename T>
371void fill(pixel_map<T>& dst, T color) noexcept;
372
375template<typename T>
376void rotate90(pixel_map<T>& dst, pixel_map<T> const& src) noexcept;
377
380template<typename T>
381void rotate270(pixel_map<T>& dst, pixel_map<T> const& src) noexcept;
382
385void mergeMaximum(pixel_map<uint8_t>& dst, pixel_map<uint8_t> const& src) noexcept;
386
392template<typename T>
394
395} // namespace hi::inline v1
396
397hi_warning_pop();
#define hi_assert(expression)
Assert if expression is true.
Definition assert.hpp:86
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
void rotate90(pixel_map< T > &dst, pixel_map< T > const &src) noexcept
void makeTransparentBorder(pixel_map< T > &pixel_map) noexcept
Make a 1 pixel border on the edge of the pixel_map transparent By copying the pixel value from just b...
void rotate270(pixel_map< T > &dst, pixel_map< T > const &src) noexcept
void mergeMaximum(pixel_map< uint8_t > &dst, pixel_map< uint8_t > const &src) noexcept
This is a RGBA floating point color.
Definition color.hpp:39
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:20
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:20
constexpr float height() const noexcept
The height, or length of the up vector.
Definition rectangle.hpp:147
constexpr float width() const noexcept
The width, or length of the right vector.
Definition rectangle.hpp:140
A 2D canvas of pixels.
Definition pixel_map.hpp:111
pixel_map() noexcept
Construct an empty pixel-map.
Definition pixel_map.hpp:117
pixel_map(std::size_t width, std::size_t height, std::size_t stride) noexcept
Construct an pixel-map without a memory association.
Definition pixel_map.hpp:152
pixel_map(T *pixels, std::size_t width, std::size_t height, std::size_t stride) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:125
pixel_map(pixel_map const &other) noexcept
Copy constructor of other.
Definition pixel_map.hpp:173
pixel_map(std::size_t width, std::size_t height) noexcept
Construct an pixel-map without a memory association.
Definition pixel_map.hpp:159
pixel_map & operator=(pixel_map const &other)
Disallowing copying so that life-time of selfAllocated pixels is easy to understand.
Definition pixel_map.hpp:226
pixel_map submap(std::size_t x, std::size_t y, std::size_t width, std::size_t height) const noexcept
Get a (smaller) view of the map.
Definition pixel_map.hpp:277
pixel_map(T *pixels, std::size_t width, std::size_t height) noexcept
Construct an pixel-map from memory received from an API.
Definition pixel_map.hpp:144
A row of pixels.
Definition pixel_map.hpp:29
T * data() noexcept
Get a pointer to the pixel data.
Definition pixel_map.hpp:49
T & operator[](std::size_t columnNr) noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:67
T const & at(std::size_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:78
T const & operator[](std::size_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:58
T const * data() const noexcept
Get a pointer to the pixel data.
Definition pixel_map.hpp:42
T & at(std::size_t columnNr) noexcept
Get a access to a pixel in the row.
Definition pixel_map.hpp:90
T copy(T... args)
T min(T... args)