Ocean
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 
16 namespace Ocean
17 {
18 
19 namespace CV
20 {
21 
22 /**
23  * This class implements a frame inverter inverting the internal frame data.
24  * @ingroup cv
25  */
26 class 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 
200 template <unsigned int tChannel, unsigned int tChannels>
201 inline 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 
215 template <unsigned int tChannel, unsigned int tChannels>
216 inline 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 
230 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
231 inline 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 
245 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
246 inline 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 
260 inline 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 
294 template <unsigned int tChannel, unsigned int tChannels>
295 void 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 
316 template <unsigned int tChannel, unsigned int tChannels>
317 void 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 
341 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
342 void 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 
367 template <unsigned int tChannelFirst, unsigned int tChannelLast, unsigned int tChannels>
368 void 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:1760
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