Ocean
Loading...
Searching...
No Matches
FrameInverter.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_CV_FRAME_INVERTER_H
9#define META_OCEAN_CV_FRAME_INVERTER_H
10
11#include "ocean/cv/CV.h"
12
13#include "ocean/base/Frame.h"
14#include "ocean/base/Worker.h"
15
16namespace Ocean
17{
18
19namespace CV
20{
21
22/**
23 * This class implements a frame inverter inverting the internal frame data.
24 * @ingroup cv
25 */
26class OCEAN_CV_EXPORT FrameInverter
27{
28 public:
29
30 /**
31 * Inverts the pixel values of a given frame.
32 * @param source The source frame to be inverted
33 * @param target The target frame receiving the inverted pixel values
34 * @param worker Optional worker object to distribute the computation
35 * @return True, if succeeded
36 */
37 static bool invert(const Frame& source, Frame& target, Worker* worker = nullptr);
38
39 /**
40 * Inverts the pixel values of a given frame.
41 * @param frame The frame to be inverted
42 * @param worker Optional worker object to distribute the computation
43 * @return True, if succeeded
44 */
45 static bool invert(Frame& frame, Worker* worker = nullptr);
46
47 /**
48 * Inverts one channel of an 8 bit per channel frame.
49 * @param frame The frame in that one channel will be inverted
50 * @param width The width of the frame in pixel
51 * @param height The height of the frame in pixel
52 * @param worker Optional worker object to distribute the computation
53 * @tparam tChannel Index of the channel that will be inverted, with range [0, tChannels)
54 * @tparam tChannels Number of data channels of the frames
55 */
56 template <unsigned int tChannel, unsigned int tChannels>
57 static inline void invert8BitChannel(uint8_t* frame, const unsigned int width, const unsigned int height, Worker* worker = nullptr);
58
59 /**
60 * Inverts one channel of an 8 bit per channel frame.
61 * @param source The source frame data to be inverted
62 * @param target The target frame data receiving the inverted data
63 * @param width The width of the frame in pixel
64 * @param height The height of the frame in pixel
65 * @param worker Optional worker object to distribute the computation
66 * @tparam tChannel Index of the channel that will be inverted, with range [0, tChannels)
67 * @tparam tChannels Number of data channels of the frames
68 */
69 template <unsigned int tChannel, unsigned int tChannels>
70 static inline void invert8BitChannel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, Worker* worker = nullptr);
71
72 /**
73 * Inverts several channels of an 8 bit per channel frame.
74 * @param frame The frame in that one channel will be inverted
75 * @param width The width of the frame in pixel
76 * @param height The height of the frame in pixel
77 * @param worker Optional worker object to distribute the computation
78 * @tparam tChannelFirst Index of the first channel that will be inverted, with range [0, tChannels)
79 * @tparam tChannelLast Index of the last (including) channel that will be inverted, with range [tChannelFirst, tChannels)
80 * @tparam tChannels Number of data channels of the frames
81 */
82 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
83 static inline void invert8BitChannels(uint8_t* frame, const unsigned int width, const unsigned int height, Worker* worker = nullptr);
84
85 /**
86 * Inverts several channels of an 8 bit per channel frame.
87 * @param source The source frame data to be inverted
88 * @param target The target frame data receiving the inverted data
89 * @param width The width of the frame in pixel
90 * @param height The height of the frame in pixel
91 * @param worker Optional worker object to distribute the computation
92 * @tparam tChannelFirst Index of the first channel that will be inverted, with range [0, tChannels)
93 * @tparam tChannelLast Index of the last (including) channel that will be inverted, with range [tChannelFirst, tChannels)
94 * @tparam tChannels Number of data channels of the frames
95 */
96 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
97 static inline void invert8BitChannels(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, Worker* worker = nullptr);
98
99 /**
100 * Inverts an 8 bit per channel frame.
101 * @param source The source frame data to be inverted, must be valid
102 * @param target The target frame data receiving the inverted data, must be valid
103 * @param width The width of the frame in pixel, with range [1, infinity)
104 * @param height The height of the frame in pixel, with range [1, infinity)
105 * @param channels Number of data channels of both frames, with range [1, infinity)
106 * @param sourcePaddingElements Optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
107 * @param targetPaddingElements Optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
108 * @param worker Optional worker object to distribute the computation
109 */
110 static inline void invert8BitPerChannel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
111
112 protected:
113
114 /**
115 * Inverts one channel of a subset of an 8 bit per channel frame.
116 * @param frame The frame in that one channel will be inverted
117 * @param width The width of the frame in pixel
118 * @param height The height of the frame in pixel
119 * @param firstRow First row to be handled
120 * @param numberRows Number of rows to be handled
121 * @tparam tChannel Index of the channel that will be inverted, with range [0, tChannels)
122 * @tparam tChannels Number of data channels of the frames
123 */
124 template <unsigned int tChannel, unsigned int tChannels>
125 static void invert8BitChannelSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows);
126
127 /**
128 * Inverts one channel of a subset of an 8 bit per channel frame.
129 * @param source The source frame data to be inverted
130 * @param target The target frame data receiving the inverted data
131 * @param width The width of the frame in pixel
132 * @param height The height of the frame in pixel
133 * @param firstRow First row to be handled
134 * @param numberRows Number of rows to be handled
135 * @tparam tChannel Index of the channel that will be inverted, with range [0, tChannels)
136 * @tparam tChannels Number of data channels of the frames
137 */
138 template <unsigned int tChannel, unsigned int tChannels>
139 static void invert8BitChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows);
140
141 /**
142 * Inverts several channels of a subset of an 8 bit per channel frame.
143 * @param frame The frame in that one channel will be inverted
144 * @param width The width of the frame in pixel
145 * @param height The height of the frame in pixel
146 * @param firstRow First row to be handled
147 * @param numberRows Number of rows to be handled
148 * @tparam tChannelFirst Index of the first channel that will be inverted, with range [0, tChannels)
149 * @tparam tChannelLast Index of the last (including) channel that will be inverted, with range [tChannelFirst, tChannels)
150 * @tparam tChannels Number of data channels of the frames
151 */
152 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
153 static void invert8BitChannelsSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows);
154
155 /**
156 * Inverts several channels of a subset of an 8 bit per channel frame.
157 * @param source The source frame data to be inverted
158 * @param target The target frame data receiving the inverted data
159 * @param width The width of the frame in pixel
160 * @param height The height of the frame in pixel
161 * @param firstRow First row to be handled
162 * @param numberRows Number of rows to be handled
163 * @tparam tChannelFirst Index of the first channel that will be inverted, with range [0, tChannels)
164 * @tparam tChannelLast Index of the last (including) channel that will be inverted, with range [tChannelFirst, tChannels)
165 * @tparam tChannels Number of data channels of the frames
166 */
167 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
168 static void invert8BitChannelsSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows);
169
170 /**
171 * Inverts the pixel values of a subset of a given frame.
172 * @param source The source frame to be inverted, must be valid
173 * @param target The target frame receiving the inverted pixel values, must be valid
174 * @param horizontalElements The number of horizontal elements to be inverted (which is width * channels), with range [1, infinity)
175 * @param sourcePaddingElements Optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
176 * @param targetPaddingElements Optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
177 * @param firstRow The first row to be handled, with range [0, height - 1]
178 * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
179 */
180 static void invert8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int horizontalElements, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
181
182#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
183
184 /**
185 * Inverts the pixel values of a subset of a given frame.
186 * @param source The source frame to be inverted, must be valid
187 * @param target The target frame receiving the inverted pixel values, must be valid
188 * @param horizontalElements The number of horizontal elements to be inverted (which is width * channels), with range [16, infinity)
189 * @param sourcePaddingElements Optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
190 * @param targetPaddingElements Optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
191 * @param firstRow The first row to be handled, with range [0, height - 1]
192 * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
193 */
194 static void invert8BitPerChannelSubsetNEON(const uint8_t* source, uint8_t* target, const unsigned int horizontalElements, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
195
196#endif // OCEAN_HARDWARE_NEON_VERSION >= 10
197
198};
199
200template <unsigned int tChannel, unsigned int tChannels>
201inline void FrameInverter::invert8BitChannel(uint8_t* frame, const unsigned int width, const unsigned int height, Worker* worker)
202{
203 ocean_assert(frame);
204
205 if (worker)
206 {
207 worker->executeFunction(Worker::Function::createStatic(&invert8BitChannelSubset<tChannel, tChannels>, frame, width, height, 0u, 0u), 0u, height);
208 }
209 else
210 {
211 invert8BitChannelSubset<tChannel, tChannels>(frame, width, height, 0u, height);
212 }
213}
214
215template <unsigned int tChannel, unsigned int tChannels>
216inline void FrameInverter::invert8BitChannel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, Worker* worker)
217{
218 ocean_assert(source && target);
219
220 if (worker)
221 {
222 worker->executeFunction(Worker::Function::createStatic(&invert8BitChannelSubset<tChannel, tChannels>, source, target, width, height, 0u, 0u), 0u, height);
223 }
224 else
225 {
226 invert8BitChannelSubset<tChannel, tChannels>(source, target, width, height, 0u, height);
227 }
228}
229
230template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
231inline void FrameInverter::invert8BitChannels(uint8_t* frame, const unsigned int width, const unsigned int height, Worker* worker)
232{
233 ocean_assert(frame);
234
235 if (worker)
236 {
237 worker->executeFunction(Worker::Function::createStatic(&invert8BitChannelsSubset<tChannelFirst, tChannelLast, tChannels>, frame, width, height, 0u, 0u), 0u, height);
238 }
239 else
240 {
241 invert8BitChannelsSubset<tChannelFirst, tChannelLast, tChannels>(frame, width, height, 0u, height);
242 }
243}
244
245template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
246inline void FrameInverter::invert8BitChannels(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, Worker* worker)
247{
248 ocean_assert(source && target);
249
250 if (worker)
251 {
252 worker->executeFunction(Worker::Function::createStatic(&invert8BitChannelsSubset<tChannelFirst, tChannelLast, tChannels>, source, target, width, height, 0u, 0u), 0u, height);
253 }
254 else
255 {
256 invert8BitChannelsSubset<tChannelFirst, tChannelLast, tChannels>(source, target, width, height, 0u, height);
257 }
258}
259
260inline void FrameInverter::invert8BitPerChannel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
261{
262 ocean_assert(source != nullptr && target != nullptr);
263 ocean_assert(width != 0u && height != 0u);
264 ocean_assert(channels != 0u);
265
266 const unsigned int horizontalElements = width * channels;
267
268 if (worker && width * height > 1920u * 1080u)
269 {
270#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
271 if (width * channels >= 32u)
272 {
273 worker->executeFunction(Worker::Function::createStatic(&FrameInverter::invert8BitPerChannelSubsetNEON, source, target, horizontalElements, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 5u, 6u, 20u);
274 return;
275 }
276#endif
277
278 worker->executeFunction(Worker::Function::createStatic(&FrameInverter::invert8BitPerChannelSubset, source, target, horizontalElements, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 5u, 6u, 20u);
279 }
280 else
281 {
282#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
283 if (width * channels >= 32u)
284 {
285 invert8BitPerChannelSubsetNEON(source, target, horizontalElements, sourcePaddingElements, targetPaddingElements, 0u, height);
286 return;
287 }
288#endif
289
290 invert8BitPerChannelSubset(source, target, horizontalElements, sourcePaddingElements, targetPaddingElements, 0u, height);
291 }
292}
293
294template <unsigned int tChannel, unsigned int tChannels>
295void FrameInverter::invert8BitChannelSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
296{
297 static_assert(tChannels >= 1u, "Invalid channel number!");
298 static_assert(tChannel < tChannels, "Invalid channel index!");
299
300 ocean_assert(frame != nullptr);
301 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
302
303 frame += firstRow * width * tChannels + tChannel;
304
305 uint8_t* const frameEnd = frame + numberRows * width * tChannels;
306
307 while (frame != frameEnd)
308 {
309 ocean_assert(frame < frameEnd);
310
311 *frame = 0xFF - *frame;
312 frame += tChannels;
313 }
314}
315
316template <unsigned int tChannel, unsigned int tChannels>
317void FrameInverter::invert8BitChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
318{
319 static_assert(tChannels >= 1u, "Invalid channel number!");
320 static_assert(tChannel < tChannels, "Invalid channel index!");
321
322 ocean_assert(source && target);
323 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
324
325 source += firstRow * width * tChannels + tChannel;
326 target += firstRow * width * tChannels + tChannel;
327
328 const uint8_t* const sourceEnd = source + numberRows * width * tChannels;
329
330 while (source != sourceEnd)
331 {
332 ocean_assert(source < sourceEnd);
333
334 *target = 0xFF - *source;
335
336 source += tChannels;
337 target += tChannels;
338 }
339}
340
341template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
342void FrameInverter::invert8BitChannelsSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
343{
344 static_assert(tChannels >= 1u, "Invalid channel number!");
345 static_assert(tChannelFirst < tChannels, "Invalid channel index!");
346 static_assert(tChannelFirst <= tChannelLast, "Invalid channel index!");
347 static_assert(tChannelLast < tChannels, "Invalid channel index!");
348
349 ocean_assert(frame);
350 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
351
352 frame += firstRow * width * tChannels + tChannelFirst;
353
354 uint8_t* const frameEnd = frame + numberRows * width * tChannels;
355
356 while (frame != frameEnd)
357 {
358 ocean_assert(frame < frameEnd);
359
360 for (unsigned int n = 0u; n < tChannelLast - tChannelFirst + 1u; ++n)
361 frame[n] = 0xFF - frame[n];
362
363 frame += tChannels;
364 }
365}
366
367template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
368void FrameInverter::invert8BitChannelsSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
369{
370 static_assert(tChannels >= 1u, "Invalid channel number!");
371 static_assert(tChannelFirst < tChannels, "Invalid channel index!");
372 static_assert(tChannelFirst <= tChannelLast, "Invalid channel index!");
373 static_assert(tChannelLast < tChannels, "Invalid channel index!");
374
375 ocean_assert(source && target);
376 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
377
378 source += firstRow * width * tChannels + tChannelFirst;
379 target += firstRow * width * tChannels + tChannelFirst;
380
381 const uint8_t* const sourceEnd = source + numberRows * width * tChannels;
382
383 while (source != sourceEnd)
384 {
385 ocean_assert(source < sourceEnd);
386
387 for (unsigned int n = 0u; n < tChannelLast - tChannelFirst + 1u; ++n)
388 target[n] = 0xFF - source[n];
389
390 source += tChannels;
391 target += tChannels;
392 }
393}
394
395}
396
397}
398
399#endif // META_OCEAN_CV_FRAME_INVERTER_H
This class implements a frame inverter inverting the internal frame data.
Definition FrameInverter.h:27
static void invert8BitPerChannelSubset(const uint8_t *source, uint8_t *target, const unsigned int horizontalElements, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Inverts the pixel values of a subset of a given frame.
static void invert8BitChannelsSubset(uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
Inverts several channels of a subset of an 8 bit per channel frame.
Definition FrameInverter.h:342
static bool invert(const Frame &source, Frame &target, Worker *worker=nullptr)
Inverts the pixel values of a given frame.
static void invert8BitPerChannelSubsetNEON(const uint8_t *source, uint8_t *target, const unsigned int horizontalElements, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Inverts the pixel values of a subset of a given frame.
static void invert8BitChannelSubset(uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
Inverts one channel of a subset of an 8 bit per channel frame.
Definition FrameInverter.h:295
static void invert8BitChannel(uint8_t *frame, const unsigned int width, const unsigned int height, Worker *worker=nullptr)
Inverts one channel of an 8 bit per channel frame.
Definition FrameInverter.h:201
static bool invert(Frame &frame, Worker *worker=nullptr)
Inverts the pixel values of a given frame.
static void invert8BitChannels(uint8_t *frame, const unsigned int width, const unsigned int height, Worker *worker=nullptr)
Inverts several channels of an 8 bit per channel frame.
Definition FrameInverter.h:231
static void invert8BitPerChannel(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Inverts an 8 bit per channel frame.
Definition FrameInverter.h:260
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition Caller.h:2876
This class implements Ocean's image class.
Definition Frame.h:1808
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
The namespace covering the entire Ocean framework.
Definition Accessor.h:15