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