Ocean
FrameConverterYUV24.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_CONVERTER_YUV_24_H
9 #define META_OCEAN_CV_FRAME_CONVERTER_YUV_24_H
10 
11 #include "ocean/cv/CV.h"
12 #include "ocean/cv/FrameChannels.h"
14 
15 #include "ocean/base/Worker.h"
16 
17 namespace Ocean
18 {
19 
20 namespace CV
21 {
22 
23 /**
24  * This class provides functions to convert frames with YUV24 pixel format to other pixel formats.
25  * See Frame::PixelFormat for details of the YUV24 pixel format.<br>
26  * @ingroup cv
27  */
28 class OCEAN_CV_EXPORT FrameConverterYUV24 : public FrameConverter
29 {
30  public:
31 
32  /**
33  * Converts a YUV 24 bit frame to a BGR 24 bit frame.
34  * @param source The source frame buffer, must be valid
35  * @param target The target frame buffer, must be valid
36  * @param width The width of the frame in pixel, with range [1, infinity)
37  * @param height The height of the frame in pixel, with range [1, infinity)
38  * @param flag Determining the type of conversion
39  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
40  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
41  * @param worker Optional worker object to distribute the computation
42  */
43  static inline void convertYUV24ToBGR24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
44 
45  /**
46  * Converts a YUV 24 bit frame to a BGRA 32 bit frame with 6 bit precision.
47  * @param source The source frame buffer, must be valid
48  * @param target The target frame buffer, must be valid
49  * @param width The width of the frame in pixel, with range [1, infinity)
50  * @param height The height of the frame in pixel, with range [1, infinity)
51  * @param flag Determining the type of conversion
52  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
53  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
54  * @param alphaValue The value of the alpha channel to be set, with range [0, 255]
55  * @param worker Optional worker object to distribute the computation
56  */
57  static inline void convertYUV24ToBGRA32Precision6Bit(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t alphaValue = 0xFF, Worker* worker = nullptr);
58 
59  /**
60  * Converts a YUV 24 bit frame to a RGB 24 bit frame.
61  * @param source The source frame buffer, must be valid
62  * @param target The target frame buffer, must be valid
63  * @param width The width of the frame in pixel, with range [1, infinity)
64  * @param height The height of the frame in pixel, with range [1, infinity)
65  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
66  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
67  * @param flag Determining the type of conversion
68  * @param worker Optional worker object to distribute the computation
69  */
70  static inline void convertYUV24ToRGB24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
71 
72  /**
73  * Converts a YUV 24 bit frame to a RGB 24 bit frame with 6 bit precision.
74  * @param source The source frame buffer, must be valid
75  * @param target The target frame buffer, must be valid
76  * @param width The width of the frame in pixel, with range [1, infinity)
77  * @param height The height of the frame in pixel, with range [1, infinity)
78  * @param flag Determining the type of conversion
79  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
80  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
81  * @param worker Optional worker object to distribute the computation
82  */
83  static inline void convertYUV24ToRGB24Precision6Bit(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
84 
85  /**
86  * Converts a YUV 24 bit frame to a Y 8 bit frame.
87  * @param source The source frame buffer, must be valid
88  * @param target The target frame buffer, must be valid
89  * @param width The width of the frame in pixel, with range [1, infinity)
90  * @param height The height of the frame in pixel, with range [1, infinity)
91  * @param flag Determining the type of conversion
92  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
93  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
94  * @param worker Optional worker object to distribute the computation
95  */
96  static inline void convertYUV24ToY8(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
97 
98  /**
99  * Converts a YUV 24 bit frame to a YUV 24 bit frame.
100  * @param source The source frame buffer, must be valid
101  * @param target The target frame buffer, must be valid
102  * @param width The width of the frame in pixel, with range [1, infinity)
103  * @param height The height of the frame in pixel, with range [1, infinity)
104  * @param flag Determining the type of conversion
105  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
106  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
107  * @param worker Optional worker object to distribute the computation
108  */
109  static inline void convertYUV24ToYUV24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
110 
111  /**
112  * Converts a YUV 24 bit frame to a YVU 24 bit frame.
113  * @param source The source frame buffer, must be valid
114  * @param target The target frame buffer, must be valid
115  * @param width The width of the frame in pixel, with range [1, infinity)
116  * @param height The height of the frame in pixel, with range [1, infinity)
117  * @param flag Determining the type of conversion
118  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
119  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
120  * @param worker Optional worker object to distribute the computation
121  */
122  static inline void convertYUV24ToYVU24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
123 
124  /**
125  * Converts a YUV 24 bit frame to a Y_U_V 12 bit frame.
126  * @param source The source frame buffer, with (width * 3 + targetPaddingElements) * height elements, must be valid
127  * @param yTarget The y target frame buffer, with (width + yPaddingElements) * height elements, must be valid
128  * @param uTarget The u target frame buffer, with (2 * width/2 + uPaddingElements) * height/2 elements, must be valid
129  * @param vTarget The v target frame buffer, with (2 * width/2 + vPaddingElements) * height/2 elements, must be valid
130  * @param width The width of the frame in pixel, with range [2, infinity), must be a multiple of 2
131  * @param height The height of the frame in pixel, with range [2, infinity), must be a multiple of 2
132  * @param flag Determining the type of conversion
133  * @param sourcePaddingElements The number of padding elements at the end of each source row, in (uint8_t) elements, with range [0, infinity)
134  * @param yTargetPaddingElements The number of padding elements at the end of each y-target row, in (uint8_t) elements, with range [0, infinity)
135  * @param uTargetPaddingElements The number of padding elements at the end of each u-target row, in (uint8_t) elements, with range [0, infinity)
136  * @param vTargetPaddingElements The number of padding elements at the end of each v-target row, in (uint8_t) elements, with range [0, infinity)
137  * @param worker Optional worker object to distribute the computation
138  */
139  static inline void convertYUV24ToY_U_V12(const uint8_t* source, uint8_t* yTarget, uint8_t* uTarget, uint8_t* vTarget, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int yTargetPaddingElements, const unsigned int uTargetPaddingElements, const unsigned int vTargetPaddingElements, Worker* worker = nullptr);
140 
141  /**
142  * Converts one YUV 24 bit pixel to a RGB 24 bit pixel.
143  * @param y Y pixel value to convert
144  * @param u U pixel value to convert
145  * @param v V pixel value to convert
146  * @param r Resulting r pixel value
147  * @param g Resulting g pixel value
148  * @param b Resulting b pixel value
149  */
150  static inline void convertYUV24ToRGB24Pixel(const uint8_t y, const uint8_t u, const uint8_t v, uint8_t& r, uint8_t& g, uint8_t& b);
151 
152  protected:
153 
154 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
155 
156  /**
157  * Converts a YUV 24 bit row to a RGB 24 bit row by using NEON instructions.
158  * Beware: This function uses hard-coded conversion parameters which improves execution performance while also increases binary size when used.
159  * @param source The pointer to the source pixels, must be valid
160  * @param target The pointer to the target pixels receiving the converted pixel data, must be valid
161  * @param size The number of source (and target pixels) to convert, with range [1, infinity)
162  * @param parameters Unused parameters, must be nullptr
163  */
164  static void convertYUV24ToRGB24RowPrecision6BitNEON(const uint8_t* source, uint8_t* target, const size_t size, const void* parameters);
165 
166  /**
167  * Converts 16 YUV24 pixels to 16 RGB24 pixels by using NEON instructions.
168  * Beware: This function uses hardcoded conversion parameters which improves execution performance while also increases binary size when used.
169  * @param source The pointer to the 16 source pixels (with 3 channels = 48 bytes) to convert, must be valid
170  * @param target The pointer to the 16 target pixels (with 3 channels = 48 bytes) receiving the converted pixel data, must be valid
171  */
172  static OCEAN_FORCE_INLINE void convert16PixelsYUV24ToRGB24Precision6BitNEON(const uint8_t* const source, uint8_t* const target);
173 
174 #endif // OCEAN_HARDWARE_NEON_VERSION >= 10
175 
176 };
177 
178 inline void FrameConverterYUV24::convertYUV24ToBGR24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
179 {
180  ocean_assert(source != nullptr && target != nullptr);
181  ocean_assert(width >= 1u && height >= 1u);
182 
183  const unsigned int sourceStrideElements = width * 3u + sourcePaddingElements;
184  const unsigned int targetStrideElements = width * 3u + targetPaddingElements;
185 
186  // precise color space conversion:
187  // | B | | 1.1639404296875 2.0179443359375 0.0 -276.919921875 | | Y |
188  // | G | = | 1.1639404296875 -0.3909912109375 -0.81298828125 135.486328125 | * | U |
189  // | R | | 1.1639404296875 0.0 1.595947265625 -222.904296875 | | V |
190  // | 1 |
191 
192  // approximation:
193  // | B | | 1192 2066 0 -277 | | Y |
194  // | G | = | 1192 -400 -833 135 | * | U |
195  // | R | | 1192 0 1634 -223 | | V |
196  // | 1 |
197 
198  const int parameters[12] = {1192, 1192, 1192, 2066, -400, 0, 0, -833, 1634, -277, 135, -223};
199 
200  const bool areContinuous = sourcePaddingElements == 0u && targetPaddingElements == 0u;
201 
202  FrameConverter::convertGenericPixelFormat(source, target, width, height, sourceStrideElements, targetStrideElements, flag, CV::FrameChannels::convertRow3ChannelsTo3Channels8BitPerChannel10BitPrecision, CV::FrameChannels::reverseRowPixelOrderInPlace<uint8_t, 3u>, areContinuous, parameters, worker);
203 }
204 
205 inline void FrameConverterYUV24::convertYUV24ToBGRA32Precision6Bit(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t alphaValue, Worker* worker)
206 {
207  ocean_assert(source != nullptr && target != nullptr);
208  ocean_assert(width >= 1u && height >= 1u);
209 
210  const unsigned int sourceStrideElements = width * 3u + sourcePaddingElements;
211  const unsigned int targetStrideElements = width * 4u + targetPaddingElements;
212 
213  // | B | | 1.0 1.732446 0.0 -221.753088 | | Y |
214  // | G | | 1.0 -0.337633 -0.698001 132.561152 | | U |
215  // | R | = | 1.0 0.0 1.370705 -175.45024 | * | V |
216 
217  // B = Y + 1.732446 * (U - 128);
218  // G = Y - 0.337633 * (U - 128) - 0.698001 * (V - 128);
219  // R = Y + 1.370705 * (V - 128);
220 
221  // | B | | 64 111 0 | * | Y - 0 |
222  // | G | = | 64 -22 -45 | * | U - 128 |
223  // | R | | 64 0 88 | * | V - 128 |
224 
225  const int parameters[13] = {64, 64, 64, 111, -22, 0, 0, -45, 88, 0, 128, 128, int(alphaValue)};
226 
227  const bool areContinuous = sourcePaddingElements == 0u && targetPaddingElements == 0u;
228 
229  FrameConverter::convertGenericPixelFormat(source, target, width, height, sourceStrideElements, targetStrideElements, flag, CV::FrameChannels::convertRow3ChannelsTo4Channels8BitPerChannel6BitPrecision, CV::FrameChannels::reverseRowPixelOrderInPlace<uint8_t, 4u>, areContinuous, parameters, worker);
230 }
231 
232 inline void FrameConverterYUV24::convertYUV24ToRGB24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
233 {
234  ocean_assert(source != nullptr && target != nullptr);
235  ocean_assert(width >= 1u && height >= 1u);
236 
237  const unsigned int sourceStrideElements = width * 3u + sourcePaddingElements;
238  const unsigned int targetStrideElements = width * 3u + targetPaddingElements;
239 
240  // precise color space conversion:
241  // | R | | 1.1639404296875 0.0 1.595947265625 -222.904296875 | | Y |
242  // | G | = | 1.1639404296875 -0.3909912109375 -0.81298828125 135.486328125 | * | U |
243  // | B | | 1.1639404296875 2.0179443359375 0.0 -276.919921875 | | V |
244  // | 1 |
245 
246  // approximation:
247  // | R | | 1192 0 1634 -223 | | Y |
248  // | G | = | 1192 -400 -833 135 | * | U |
249  // | B | | 1192 2066 0 -277 | | V |
250  // | 1 |
251 
252  const int parameters[12] = {1192, 1192, 1192, 0, -400, 2066, 1634, -833, 0, -223, 135, -277};
253 
254  const bool areContinuous = sourcePaddingElements == 0u && targetPaddingElements == 0u;
255 
256  FrameConverter::convertGenericPixelFormat(source, target, width, height, sourceStrideElements, targetStrideElements, flag, CV::FrameChannels::convertRow3ChannelsTo3Channels8BitPerChannel10BitPrecision, CV::FrameChannels::reverseRowPixelOrderInPlace<uint8_t, 3u>, areContinuous, parameters, worker);
257 }
258 
259 inline void FrameConverterYUV24::convertYUV24ToRGB24Precision6Bit(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
260 {
261  ocean_assert(source != nullptr && target != nullptr);
262  ocean_assert(width >= 1u && height >= 1u);
263 
264  const unsigned int sourceStrideElements = width * 3u + sourcePaddingElements;
265  const unsigned int targetStrideElements = width * 3u + targetPaddingElements;
266 
267 #if defined(OCEAN_USE_HARDCODED_YUV24_TO_RGB24_CONVERTER) && OCEAN_HARDWARE_NEON_VERSION >= 10
268 
269  // we keep this function mainly to show the performance difference between the hard-coded implementation and a variable implementation
270 
271  FrameConverter::convertGenericPixelFormat(source, target, width, height, sourceStrideElements, targetStrideElements, flag, FrameConverterYUV24::convertYUV24ToRGB24RowPrecision6BitNEON, CV::FrameChannels::reverseRowPixelOrderInPlace<uint8_t, 3u>, nullptr, worker);
272 
273 #else
274 
275  // R = Y + 1.370705 * (V - 128);
276  // G = Y - 0.337633 * (U - 128) - 0.698001 * (V - 128);
277  // B = Y + 1.732446 * (U - 128);
278 
279  const int parameters[12] = {64, 64, 64, 0, -22, 111, 88, -45, 0, 0, 128, 128};
280 
281  const bool areContinuous = sourcePaddingElements == 0u && targetPaddingElements == 0u;
282 
283  FrameConverter::convertGenericPixelFormat(source, target, width, height, sourceStrideElements, targetStrideElements, flag, CV::FrameChannels::convertRow3ChannelsTo3Channels8BitPerChannel6BitPrecision, CV::FrameChannels::reverseRowPixelOrderInPlace<uint8_t, 3u>, areContinuous, parameters, worker);
284 
285 #endif
286 }
287 
288 inline void FrameConverterYUV24::convertYUV24ToY8(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
289 {
290  ocean_assert(source != nullptr && target != nullptr);
291  ocean_assert(width >= 1u && height >= 1u);
292 
293  // source frame Y U V
294  // 0 1 2
295  // target frame Y
296  // pattern 0
297  constexpr unsigned int shufflePattern = 0x0u;
298 
299  FrameChannels::shuffleChannels<uint8_t, 3u, 1u, shufflePattern>(source, target, width, height, flag, sourcePaddingElements, targetPaddingElements, worker);
300 }
301 
302 inline void FrameConverterYUV24::convertYUV24ToYUV24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
303 {
304  ocean_assert(source != nullptr && target != nullptr);
305  ocean_assert(width >= 1u && height >= 1u);
306 
307  FrameChannels::transformGeneric<uint8_t, 3u>(source, target, width, height, flag, sourcePaddingElements, targetPaddingElements, worker);
308 }
309 
310 inline void FrameConverterYUV24::convertYUV24ToYVU24(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
311 {
312  ocean_assert(source != nullptr && target != nullptr);
313  ocean_assert(width >= 1u && height >= 1u);
314 
315  // source frame Y U V
316  // 0 1 2
317  // target frame Y V U
318  // pattern 0 2 1
319 
320  constexpr unsigned int shufflePattern = 0x120u;
321 
322  FrameChannels::shuffleChannels<uint8_t, 3u, 3u, shufflePattern>(source, target, width, height, flag, sourcePaddingElements, targetPaddingElements, worker);
323 }
324 
325 inline void FrameConverterYUV24::convertYUV24ToY_U_V12(const uint8_t* source, uint8_t* yTarget, uint8_t* uTarget, uint8_t* vTarget, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int yTargetPaddingElements, const unsigned int uTargetPaddingElements, const unsigned int vTargetPaddingElements, Worker* worker)
326 {
327  ocean_assert(source != nullptr && yTarget != nullptr && uTarget != nullptr && vTarget != nullptr);
328 
329  ocean_assert(width >= 2u && width % 2u == 0u);
330  ocean_assert(height >= 2u && height % 2u == 0u);
331 
332  if (width < 2u || height < 2u || width % 2u != 0u || height % 2u != 0u)
333  {
334  return;
335  }
336 
337  const unsigned int options[4] = {sourcePaddingElements, yTargetPaddingElements, uTargetPaddingElements, vTargetPaddingElements};
338 
339  void* targets[3] =
340  {
341  yTarget,
342  uTarget,
343  vTarget
344  };
345 
346  FrameConverter::convertArbitraryPixelFormat((const void**)(&source), targets, width, height, flag, 2u, FrameConverter::mapTwoRows_1Plane3Channels_To_1Plane1ChannelAnd2Planes1ChannelDownsampled2x2_8BitPerChannel<0u, 1u, 2u>, options, worker);
347 }
348 
349 inline void FrameConverterYUV24::convertYUV24ToRGB24Pixel(const uint8_t y, const uint8_t u, const uint8_t v, uint8_t& r, uint8_t& g, uint8_t& b)
350 {
351  const int y_ = (y - 16) * 298 + 128;
352  const int u_ = u - 128;
353  const int v_ = v - 128;
354 
355  r = (uint8_t)(minmax(0, (y_ + 409 * v_) >> 8, 255));
356  g = (uint8_t)(minmax(0, (y_ - 100 * u_ - 208 * v_) >> 8, 255));
357  b = (uint8_t)(minmax(0, (y_ + 516 * u_) >> 8, 255));
358 }
359 
360 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
361 
362 OCEAN_FORCE_INLINE void FrameConverterYUV24::convert16PixelsYUV24ToRGB24Precision6BitNEON(const uint8_t* const source, uint8_t* const target)
363 {
364  ocean_assert(source != nullptr && target != nullptr);
365 
366  // the documentation of this function designed for YUV24 to RGB24 conversion
367 
368  // precise color space conversion:
369  // | R | | 1 0.0 1.370705 -175.45024 | | Y |
370  // | G | = | 1 -0.3376335 -0.698001 132.561152 | * | U |
371  // | B | | 1 1.732446 0.0 -221.753088 | | V |
372  // | 1 |
373 
374  // approximation:
375  // R = 64 * Y + 0 * (U - 128) + 88 * (V - 128)
376  // G = 64 * Y - 22 * (U - 128) - 45 * (V - 128)
377  // B = 64 * Y + 111 * (U - 128) + 0 * (V - 128)
378 
379  const uint8x8_t constant_128_u_8x8 = vdup_n_u8(128);
380  const int16x8_t constant_22_s_16x8 = vdupq_n_s16(-22);
381  const int16x8_t constant_111_s_16x8 = vdupq_n_s16(111);
382  const int16x8_t constant_88_s_16x8 = vdupq_n_s16(88);
383  const int16x8_t constant_45_s_16x8 = vdupq_n_s16(-45);
384 
385  const uint8x16x3_t source_u_8x16x3 = vld3q_u8(source);
386 
387  // Y' = Y * 64, U' = U - 128, V' = V - 128
388  const int16x8_t sourceMultiplied0_low_s_16x8 = vreinterpretq_s16_u16(vshll_n_u8(vget_low_u8(source_u_8x16x3.val[0]), 6));
389  const int16x8_t source1_low_s_16x8 = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(source_u_8x16x3.val[1]), constant_128_u_8x8));
390  const int16x8_t source2_low_s_16x8 = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(source_u_8x16x3.val[2]), constant_128_u_8x8));
391 
392  const int16x8_t sourceMultiplied0_high_s_16x8 = vreinterpretq_s16_u16(vshll_n_u8(vget_high_u8(source_u_8x16x3.val[0]), 6));
393  const int16x8_t source1_high_s_16x8 = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(source_u_8x16x3.val[1]), constant_128_u_8x8));
394  const int16x8_t source2_high_s_16x8 = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(source_u_8x16x3.val[2]), constant_128_u_8x8));
395 
396  // now we apply the 3x3 matrix multiplication
397 
398  int16x8_t intermediateResults1_low_s_16x8 = vmlaq_s16(sourceMultiplied0_low_s_16x8, source1_low_s_16x8, constant_22_s_16x8);
399  int16x8_t intermediateResults2_low_s_16x8 = vmlaq_s16(sourceMultiplied0_low_s_16x8, source1_low_s_16x8, constant_111_s_16x8);
400 
401  int16x8_t intermediateResults1_high_s_16x8 = vmlaq_s16(sourceMultiplied0_high_s_16x8, source1_high_s_16x8, constant_22_s_16x8);
402  int16x8_t intermediateResults2_high_s_16x8 = vmlaq_s16(sourceMultiplied0_high_s_16x8, source1_high_s_16x8, constant_111_s_16x8);
403 
404  int16x8_t intermediateResults0_low_s_16x8 = vmlaq_s16(sourceMultiplied0_low_s_16x8, source2_low_s_16x8, constant_88_s_16x8);
405  intermediateResults1_low_s_16x8 = vmlaq_s16(intermediateResults1_low_s_16x8, source2_low_s_16x8, constant_45_s_16x8);
406 
407  int16x8_t intermediateResults0_high_s_16x8 = vmlaq_s16(sourceMultiplied0_high_s_16x8, source2_high_s_16x8, constant_88_s_16x8);
408  intermediateResults1_high_s_16x8 = vmlaq_s16(intermediateResults1_high_s_16x8, source2_high_s_16x8, constant_45_s_16x8);
409 
410  uint8x16x3_t results_u_8x16x3;
411 
412  // saturated narrow signed to unsigned, normalized by 2^6
413  results_u_8x16x3.val[0] = vcombine_u8(vqrshrun_n_s16(intermediateResults0_low_s_16x8, 6), vqrshrun_n_s16(intermediateResults0_high_s_16x8, 6));
414  results_u_8x16x3.val[1] = vcombine_u8(vqrshrun_n_s16(intermediateResults1_low_s_16x8, 6), vqrshrun_n_s16(intermediateResults1_high_s_16x8, 6));
415  results_u_8x16x3.val[2] = vcombine_u8(vqrshrun_n_s16(intermediateResults2_low_s_16x8, 6), vqrshrun_n_s16(intermediateResults2_high_s_16x8, 6));
416 
417  // and we can store the result
418  vst3q_u8(target, results_u_8x16x3);
419 }
420 
421 #endif // OCEAN_HARDWARE_NEON_VERSION >= 10
422 
423 }
424 
425 }
426 
427 #endif // META_OCEAN_CV_FRAME_CONVERTER_RGB_24_H
static void convertRow3ChannelsTo3Channels8BitPerChannel6BitPrecision(const uint8_t *source, uint8_t *target, const size_t size, const void *parameters)
Converts a row of pixels with 3 channels to pixels with 3 channels by a linear combination of the thr...
static void convertRow3ChannelsTo4Channels8BitPerChannel6BitPrecision(const uint8_t *source, uint8_t *target, const size_t size, const void *parameters)
Converts a row of pixels with 3 channels to pixels with 4 channels by a linear combination of the thr...
static void convertRow3ChannelsTo3Channels8BitPerChannel10BitPrecision(const uint8_t *source, uint8_t *target, const size_t size, const void *parameters)
Converts a row of pixels with 3 channels to pixels with 3 channels by a linear combination of the thr...
This is the base class for all frame converter classes.
Definition: FrameConverter.h:32
ConversionFlag
Definition of individual conversion flags.
Definition: FrameConverter.h:39
static void convertGenericPixelFormat(const TSource *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourceStrideElements, const unsigned int targetStrideElements, const ConversionFlag flag, const RowConversionFunction< TSource, TTarget > rowConversionFunction, const RowReversePixelOrderInPlaceFunction< TTarget > targetReversePixelOrderInPlaceFunction, const bool areContinuous, const void *options, Worker *worker)
Converts a frame with generic pixel format (e.g., RGBA32, BGR24, YUV24, ...) to a frame with generic ...
Definition: FrameConverter.h:3211
static void convertArbitraryPixelFormat(const void **sources, void **targets, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int multipleRowsPerIteration, const MultipleRowsConversionFunction multipleRowsConversionFunction, const void *options, Worker *worker)
Converts a frame with arbitrary pixel format (e.g., Y_UV12, Y_VU12, YUYV16, ...) to a frame with arbi...
Definition: FrameConverter.h:3234
This class provides functions to convert frames with YUV24 pixel format to other pixel formats.
Definition: FrameConverterYUV24.h:29
static void convertYUV24ToYUV24(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a YUV 24 bit frame.
Definition: FrameConverterYUV24.h:302
static OCEAN_FORCE_INLINE void convert16PixelsYUV24ToRGB24Precision6BitNEON(const uint8_t *const source, uint8_t *const target)
Converts 16 YUV24 pixels to 16 RGB24 pixels by using NEON instructions.
Definition: FrameConverterYUV24.h:362
static void convertYUV24ToY8(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a Y 8 bit frame.
Definition: FrameConverterYUV24.h:288
static void convertYUV24ToBGRA32Precision6Bit(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t alphaValue=0xFF, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a BGRA 32 bit frame with 6 bit precision.
Definition: FrameConverterYUV24.h:205
static void convertYUV24ToBGR24(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a BGR 24 bit frame.
Definition: FrameConverterYUV24.h:178
static void convertYUV24ToYVU24(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a YVU 24 bit frame.
Definition: FrameConverterYUV24.h:310
static void convertYUV24ToRGB24RowPrecision6BitNEON(const uint8_t *source, uint8_t *target, const size_t size, const void *parameters)
Converts a YUV 24 bit row to a RGB 24 bit row by using NEON instructions.
static void convertYUV24ToRGB24(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a RGB 24 bit frame.
Definition: FrameConverterYUV24.h:232
static void convertYUV24ToRGB24Precision6Bit(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a RGB 24 bit frame with 6 bit precision.
Definition: FrameConverterYUV24.h:259
static void convertYUV24ToRGB24Pixel(const uint8_t y, const uint8_t u, const uint8_t v, uint8_t &r, uint8_t &g, uint8_t &b)
Converts one YUV 24 bit pixel to a RGB 24 bit pixel.
Definition: FrameConverterYUV24.h:349
static void convertYUV24ToY_U_V12(const uint8_t *source, uint8_t *yTarget, uint8_t *uTarget, uint8_t *vTarget, const unsigned int width, const unsigned int height, const ConversionFlag flag, const unsigned int sourcePaddingElements, const unsigned int yTargetPaddingElements, const unsigned int uTargetPaddingElements, const unsigned int vTargetPaddingElements, Worker *worker=nullptr)
Converts a YUV 24 bit frame to a Y_U_V 12 bit frame.
Definition: FrameConverterYUV24.h:325
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
T minmax(const T &lowerBoundary, const T &value, const T &upperBoundary)
This function fits a given parameter into a specified value range.
Definition: base/Utilities.h:903
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15