HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
PixelMap.hpp
1// Copyright 2019 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/required.hpp"
7#include "TTauri/Foundation/iaarect.hpp"
8#include <nonstd/span>
9#include <string>
10#include <algorithm>
11#include <vector>
12
13namespace tt {
14
17template <typename T>
18struct PixelRow {
22
26
29 T const *data() const noexcept {
30 return pixels;
31 }
32
35 T *data() noexcept {
36 return pixels;
37 }
38
43 T const &operator[](ssize_t columnNr) const noexcept {
44 return pixels[columnNr];
45 }
46
51 T &operator[](ssize_t columnNr) noexcept {
52 return pixels[columnNr];
53 }
54
61 T const &at(ssize_t columnNr) const noexcept {
62 tt_assert(columnNr >= 0 && columnNr < width);
63 return pixels[columnNr];
64 }
65
72 T &at(ssize_t columnNr) noexcept {
73 tt_assert(columnNr >= 0 && columnNr < width);
74 return pixels[columnNr];
75 }
76};
77
82template <typename T>
83struct PixelMap {
87
91
95
100
103 bool selfAllocated = false;
104
107 PixelMap() noexcept : pixels(nullptr), width(0), height(0), stride(0) {}
108
116 if (pixels) {
117 tt_assert(stride >= width);
118 tt_assert(width > 0);
119 tt_assert(height > 0);
120 } else {
121 tt_assert(width == 0);
122 tt_assert(height == 0);
123 }
124 }
125
134 if (pixels) {
135 tt_assert(stride >= width);
136 tt_assert(width > 0);
137 tt_assert(height > 0);
138 } else {
139 tt_assert(width == 0);
140 tt_assert(height == 0);
141 }
142 }
143
149 PixelMap(ivec extent) noexcept : PixelMap(extent.x(), extent.y()) {}
150
157
162 PixelMap(T *pixels, ivec extent) noexcept : PixelMap(pixels, extent.x(), extent.y()) {}
163
169 PixelMap(T *pixels, ivec extent, ssize_t stride) noexcept : PixelMap(pixels, extent.x(), extent.y(), stride) {}
170
171 gsl_suppress2(r.11,i.11)
172 ~PixelMap() {
173 if (selfAllocated) {
174 delete[] pixels;
175 }
176 }
177
180 PixelMap(PixelMap const &other) = delete;
181
182 PixelMap copy() const noexcept {
183 if (selfAllocated) {
184 auto r = PixelMap(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 PixelMap(PixelMap &&other) noexcept : pixels(other.pixels), width(other.width), height(other.height), stride(other.stride), selfAllocated(other.selfAllocated) {
201 tt_assume(this != &other);
202 other.selfAllocated = false;
203 }
204
205 operator bool() const noexcept {
206 return pixels;
207 }
208
211 PixelMap &operator=(PixelMap const &other) = delete;
212
213 gsl_suppress2(r.11,i.11)
214 PixelMap &operator=(PixelMap &&other) noexcept {
215 // Compatible with self-move.
216 if (selfAllocated) {
217 delete[] pixels;
218 }
219 pixels = other.pixels;
220 width = other.width;
221 height = other.height;
222 stride = other.stride;
223 selfAllocated = other.selfAllocated;
224 other.selfAllocated = false;
225 return *this;
226 }
227
228 ivec extent() const noexcept {
229 return {width, height};
230 }
231
236 PixelMap<T> submap(iaarect rect) const noexcept {
237 tt_assert(
238 (rect.x1() >= 0) &&
239 (rect.y2() >= 0) &&
240 (rect.width() >= 0) &&
241 (rect.height() >= 0)
242 );
243 tt_assert(
244 (rect.x2() <= width) &&
245 (rect.y2() <= height)
246 );
247
248 ttlet offset = rect.y1() * stride + rect.x1();
249
250 return { pixels + offset, rect.width(), rect.height(), stride };
251 }
252
260 PixelMap<T> submap(ssize_t x, ssize_t y, ssize_t _width, ssize_t _height) const noexcept {
261 return submap(iaarect{x, y, _width, _height});
262 }
263
264 PixelRow<T> const operator[](ssize_t rowNr) const noexcept {
265 return { pixels + (rowNr * stride), width };
266 }
267
268 PixelRow<T> operator[](ssize_t rowNr) noexcept {
269 return { pixels + (rowNr * stride), width };
270 }
271
272 PixelRow<T> const at(ssize_t rowNr) const noexcept {
273 tt_assert(rowNr < height);
274 return (*this)[rowNr];
275 }
276
277 PixelRow<T> at(ssize_t rowNr) noexcept {
278 tt_assert(rowNr < height);
279 return (*this)[rowNr];
280 }
281};
282
283template<typename T>
284void copy(PixelMap<T> const &src, PixelMap<T> &dst) noexcept {
285 ssize_t width = std::min(src.width, dst.width);
286 ssize_t height = std::min(src.height, dst.height);
287
288 for (ssize_t y = 0; y != height; ++y) {
289 ttlet src_row = src[y];
290 auto dst_row = dst[y];
291 for (ssize_t x = 0; x != width; ++x) {
292 dst_row[x] = src_row[x];
293 }
294 }
295}
296
297template<int KERNEL_SIZE, typename KERNEL>
298void horizontalFilterRow(PixelRow<uint8_t> row, KERNEL kernel) noexcept;
299
300template<int KERNEL_SIZE, typename T, typename KERNEL>
301void horizontalFilter(PixelMap<T>& pixels, KERNEL kernel) noexcept;
302
305template<typename T>
306void fill(PixelMap<T> &dst) noexcept;
307
310template<typename T>
311void fill(PixelMap<T> &dst, T color) noexcept;
312
315template<typename T>
316void rotate90(PixelMap<T> &dst, PixelMap<T> const &src) noexcept;
317
320template<typename T>
321void rotate270(PixelMap<T> &dst, PixelMap<T> const &src) noexcept;
322
325void mergeMaximum(PixelMap<uint8_t> &dst, PixelMap<uint8_t> const &src) noexcept;
326
332template<typename T>
333inline void makeTransparentBorder(PixelMap<T> & pixelMap) noexcept;
334
335}
A 4D vector.
Definition ivec.hpp:37
A 2D canvas of pixels.
Definition PixelMap.hpp:83
PixelMap(PixelMap const &other)=delete
Disallowing copying so that life-time of selfAllocated pixels is easy to understand.
PixelMap(T *pixels, ivec extent) noexcept
Construct an pixel-map from memory received from an API.
Definition PixelMap.hpp:162
gsl_suppress(r.11) PixelMap(ssize_t width
Construct an pixel-map.
ssize_t height
Number of vertical pixels.
Definition PixelMap.hpp:94
ssize_t width
Number of horizontal pixels.
Definition PixelMap.hpp:90
ssize_t stride
Number of pixel element until the next row.
Definition PixelMap.hpp:99
bool selfAllocated
True if the memory was allocated by this class, false if the canvas was received from another API.
Definition PixelMap.hpp:103
PixelMap(T *pixels, ssize_t width, ssize_t height, ssize_t stride) noexcept
Construct an pixel-map from memory received from an API.
Definition PixelMap.hpp:115
T * pixels
Pointer to a 2D canvas of pixels.
Definition PixelMap.hpp:86
PixelMap() noexcept
Construct an empty pixel-map.
Definition PixelMap.hpp:107
PixelMap & operator=(PixelMap const &other)=delete
Disallowing copying so that life-time of selfAllocated pixels is easy to understand.
PixelMap(ivec extent) noexcept
Construct an pixel-map.
Definition PixelMap.hpp:149
PixelMap(T *pixels, ssize_t width, ssize_t height) noexcept
Construct an pixel-map from memory received from an API.
Definition PixelMap.hpp:156
PixelMap(T *pixels, ivec extent, ssize_t stride) noexcept
Construct an pixel-map from memory received from an API.
Definition PixelMap.hpp:169
A row of pixels.
Definition PixelMap.hpp:18
T const * data() const noexcept
Get a pointer to the pixel data.
Definition PixelMap.hpp:29
T const & at(ssize_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition PixelMap.hpp:61
ssize_t width
Number of pixels in the row.
Definition PixelMap.hpp:25
T * pixels
Pointer to an array of pixels.
Definition PixelMap.hpp:21
T * data() noexcept
Get a pointer to the pixel data.
Definition PixelMap.hpp:35
T const & operator[](ssize_t columnNr) const noexcept
Get a access to a pixel in the row.
Definition PixelMap.hpp:43
T & at(ssize_t columnNr) noexcept
Get a access to a pixel in the row.
Definition PixelMap.hpp:72
T & operator[](ssize_t columnNr) noexcept
Get a access to a pixel in the row.
Definition PixelMap.hpp:51
T copy(T... args)
T fill(T... args)
T min(T... args)