Ocean
Loading...
Searching...
No Matches
FrameBlender.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_BLENDER_H
9#define META_OCEAN_CV_FRAME_BLENDER_H
10
11#include "ocean/cv/CV.h"
13
14#include "ocean/base/DataType.h"
15#include "ocean/base/Frame.h"
17#include "ocean/base/Worker.h"
18
19namespace Ocean
20{
21
22namespace CV
23{
24
25/**
26 * This class implements a frame blender using an alpha channel to blend frames.
27 * @ingroup cv
28 */
29class OCEAN_CV_EXPORT FrameBlender
30{
31 public:
32
33 /**
34 * Definition of individual target alpha channel modulation functions.
35 */
37 {
38 /// Undefined target alpha channel modulation.
39 ATM_UNDEFINED = 0,
40 /// The target alpha channel is constant and is not changed.
42 /// The target alpha channel is blended by alphaResult = alphaTarget + alphaSource * (1 - alphaTarget).
43 ATM_BLEND
44 };
45
46 /**
47 * Definition of a blend function allowing to apply a more complex blend operation than a simple linear blending for one pixel (and thus for all channels of this pixel).
48 * If e.g., the target frame holds 3 channels, than all three channels have to be handled by one call of the blend function.<br>
49 * The first parameter provides the target pixel
50 * The second parameter provides the target blend factor, with range [0, 255]
51 */
52 typedef void (*BlendFunction)(uint8_t*, const uint8_t);
53
54 /**
55 * Helper class allowing to determine the offset that is necessary to access the alpha channel.
56 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
57 */
58 template <bool tAlphaAtFront>
60 {
61 public:
62
63 /**
64 * Returns the offset that is applied to access the alpha channel.
65 * @return Offset for the alpha channel
66 * @tparam tChannelsWithAlpha Number of channels in the source frame (including the alpha channel)
67 */
68 template <unsigned int tChannelsWithAlpha>
69 static constexpr unsigned int alpha();
70
71 /**
72 * Returns the offset that is applied to access the first data channel.
73 * @return Offset for the first data channel
74 */
75 static constexpr unsigned int data();
76
77 /**
78 * Returns the offset that is applied to access the first data channel.
79 * @return Offset for the first data channel
80 */
81 template <bool tSourceHasAlpha>
82 static constexpr unsigned int data();
83 };
84
85 /**
86 * Helper class allowing to determine the number of channels of the target frame.
87 * @tparam tTargetHasAlpha True, if the target frame holds an alpha channel
88 */
89 template <bool tTargetHasAlpha>
91 {
92 public:
93
94 /**
95 * Returns the number of channels of the target frame.
96 * @return Number of target frame channels
97 * @tparam tChannelsWithAlpha Number of channels in the source frame (including the alpha channel)
98 */
99 template <unsigned int tChannelsWithAlpha>
100 static constexpr unsigned int channels();
101
102 /**
103 * Returns the offset that is applied to access the first data channel.
104 * @return Offset for the first data channel
105 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
106 */
107 template <bool tAlphaAtFront>
108 static constexpr unsigned int data();
109 };
110
111 /**
112 * Helper class allowing to determine the number of channels of a frame.
113 * @tparam tHasAlpha True, if the frame holds an alpha channel
114 */
115 template <bool tHasAlpha>
117 {
118 public:
119
120 /**
121 * Returns the number of channels of a frame not counting the possible alpha channel.
122 * @return Number of channels without the possible alpha channel
123 * @tparam tChannels The number of channels of a frame including a possible alpha channel
124 */
125 template <unsigned int tChannels>
126 static constexpr unsigned int dataChannels();
127
128 /**
129 * Returns the number of channels of a frame for that is known whether is has an alpha channel or not.
130 * @return The number of channels of a frame
131 * @tparam tChannelsWithAlpha The number of channels that include an alpha channel, with range [2, infinity)
132 */
133 template <unsigned int tChannelsWithAlpha>
134 static constexpr unsigned int channels();
135 };
136
137 public:
138
139 /**
140 * Blends two frames with same frame type by application of one unique blending factor for all pixels.
141 * The blend function is defined as follows:
142 * <pre>
143 * tTransparentIs0xFF == true: targetPixel = sourcePixel * (0xFF - alpha) + targetPixel * alpha
144 * tTransparentIs0xFF == false: targetPixel = sourcePixel * alpha + targetPixel * (0xFF - alpha)
145 * </pre>
146 * @param source The source frame that is blended with the target frame, must be valid
147 * @param target The target frame that receives the blending result from source and target pixels, this frame must have the same frame format as the source frame, must be valid
148 * @param alphaValue Blending factor for all pixels, with range [0, 255]
149 * @param worker Optional worker object to distribute the computation
150 * @return True, if succeeded
151 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
152 */
153 template <bool tTransparentIs0xFF>
154 static bool blend(const Frame& source, Frame& target, const uint8_t alphaValue, Worker* worker = nullptr);
155
156 /**
157 * Blends an entire source frame holding an alpha channel with a target frame without an alpha channel.
158 * An alpha value of 0xFF may specifies a fully transparent source pixel or may specify a fully opaque source pixel.<br>
159 * Both frames must have the same frame dimension and pixel origin.<br>
160 * Further, the pixel format of the source frame must match to the pixel format of the target frame.<br>
161 * Valid combinations of pixel formats are e.g. (FORMAT_RGBA32, FORMAT_RGBA32) or (FORMAT_RGBA32, FORMAT_RGB24) or (FORMAT_ABGR32, FORMAT_ABGR32) or (FORMAT_ABGR32, FORMAT_BGR24).<br>
162 * @param sourceWithAlpha Source frame with alpha channel
163 * @param target The target frame with or without alpha channel, if this frame has an alpha channel this channel will be untouched
164 * @param worker Optional worker object to distribute the computation
165 * @return True, if succeeded
166 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent value
167 * @tparam tAlphaTargetModulation The target alpha channel modulation function
168 */
169 template <bool tTransparentIs0xFF, AlphaTargetModulation tAlphaTargetModulation>
170 static bool blend(const Frame& sourceWithAlpha, Frame& target, Worker* worker = nullptr);
171
172 /**
173 * Blends an entire source frame holding an alpha channel with a static background color and creates a new frame without alpha channel.
174 * An alpha value of 0xFF may specifies a fully transparent source pixel or may specify a fully opaque source pixel.<br>
175 * @param sourceWithAlpha Source frame with alpha channel
176 * @param result The resulting frame
177 * @param backgroundColor The static background color for the resulting frame, ensure that the given buffer is large enough for the resulting pixel format (the source pixel format without alpha channel)
178 * @param worker Optional worker object to distribute the computation
179 * @return True, if succeeded
180 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent value
181 * @tparam tAlphaTargetModulation The target alpha channel modulation function
182 */
183 template <bool tTransparentIs0xFF, AlphaTargetModulation tAlphaTargetModulation>
184 static bool blend(const Frame& sourceWithAlpha, Frame& result, const uint8_t* backgroundColor, Worker* worker = nullptr);
185
186 /**
187 * Blends a sub-region of a source frame with a target frame without an alpha channel.
188 * An alpha value of 0xFF may specifies a fully transparent source pixel or may specify a fully opaque source pixel.<br>
189 * The pixel format of the source frame must match to the pixel format of the target frame.<br>
190 * Valid combinations of pixel formats are e.g. (FORMAT_RGBA32, FORMAT_RGBA32) or (FORMAT_RGBA32, FORMAT_RGB24) or (FORMAT_ABGR32, FORMAT_ABGR32) or (FORMAT_ABGR32, FORMAT_BGR24).
191 * @param sourceWithAlpha Source frame with alpha channel, must be valid
192 * @param target The target frame with or without alpha channel, if this frame has an alpha channel this channel will be untouched, must be valid
193 * @param sourceLeft Horizontal start position inside the source frame, with range [0, sourceWidth)
194 * @param sourceTop Vertical start position inside the source frame, with range [0, sourceHeight)
195 * @param targetLeft Horizontal start position inside the target frame, with range [0, targetWidth)
196 * @param targetTop Vertical start position inside the target frame, with range [0, targetHeight)
197 * @param width The width of the blending sub-region in pixel, with range [1, min(sourceWidth - sourceLeft, targetWidth - targetLeft)]
198 * @param height The height of the blending sub-region in pixel, with range [1, min(sourceHeight - sourceTop, targetHeight - targetTop)]
199 * @param worker Optional worker object to distribute the computation
200 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
201 * @tparam tAlphaTargetModulation The target alpha channel modulation function
202 */
203 template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
204 static bool blend(const Frame& sourceWithAlpha, Frame& target, const unsigned int sourceLeft, const unsigned int sourceTop, const unsigned int targetLeft, const unsigned int targetTop, const unsigned int width, const unsigned int height, Worker* worker = nullptr);
205
206 /**
207 * Blends two 8 bit per channel frames with same frame type by application of one unique blending factor for all pixels.
208 * The blend function is defined as follows:
209 * <pre>
210 * tTransparentIs0xFF == true: targetPixel = sourcePixel * (0xFF - alpha) + targetPixel * alpha
211 * tTransparentIs0xFF == false: targetPixel = sourcePixel * alpha + targetPixel * (0xFF - alpha)
212 * </pre>
213 * @param source The source frame that is blended with the target frame, must be valid
214 * @param target The target frame that receives the blending result from source and target pixels, this frame must have the same frame format as the source frame, must be valid
215 * @param alphaValue The blending factor for all pixels, with range [0, 255]
216 * @param width The width of both frames in pixel, with range [1, infinity)
217 * @param height The height of the both frames in pixel, with range [1, infinity)
218 * @param sourcePaddingElements The optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
219 * @param targetPaddingElements The optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
220 * @param worker Optional worker object to distribute the computation
221 * @tparam tChannels Number of channels of both frames (without any alpha channel), with range [1, infinity)
222 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent; False, if 0x00 is interpreted as fully transparent
223 */
224 template <unsigned int tChannels, bool tTransparentIs0xFF>
225 static inline void blend8BitPerChannel(const uint8_t* source, uint8_t* target, const uint8_t alphaValue, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
226
227 /**
228 * Blends an entire source and target frame while the alpha channel is provided in a third frame.
229 * <pre>
230 * tTransparentIs0xFF == true: targetPixel = sourcePixel * (0xFF - alphaPixel) + targetPixel * alphaPixel
231 * tTransparentIs0xFF == false: targetPixel = sourcePixel * alphaPixel + targetPixel * (0xFF - alphaPixel)
232 * </pre>
233 * @param source The source frame without alpha channel, which is blended with the target frame, must be valid
234 * @param alpha The alpha frame with defining one alpha blending factor for each pixel, must be valid
235 * @param target The target frame without alpha channel, must be valid
236 * @param width The width of both frames in pixel, with range [1, infinity)
237 * @param height The height of the both frames in pixel, with range [1, infinity)
238 * @param sourcePaddingElements The optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
239 * @param alphaPaddingElements The optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
240 * @param targetPaddingElements The optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
241 * @param worker Optional worker object to distribute the computation
242 * @tparam tChannels Number of channels of both frames (without any alpha channel), with range [1, infinity)
243 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent; False, if 0x00 is interpreted as fully transparent
244 */
245 template <unsigned int tChannels, bool tTransparentIs0xFF>
246 static inline void blend8BitPerChannel(const uint8_t* source, const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
247
248 /**
249 * Blends an entire source and target frame while the alpha channel is in front of the data channels or behind the data channels.
250 * @param sourceWithAlpha Source frame with alpha channel, must be valid
251 * @param target The target frame which may also hold an alpha channel depending on tTargetHasAlpha, must be valid
252 * @param width The width of both frames in pixel, with range [1, infinity)
253 * @param height The height of both frames in pixel, with range [1, infinity)
254 * @param sourceWithAlphaPaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
255 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
256 * @param worker Optional worker object to distribute the computation
257 * @tparam tChannelsWithAlpha Number of channels in the source frame (including the alpha channel)
258 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
259 * @tparam tTargetHasAlpha True, if not only the source frame holds an alpha channel but also the target frame, however values in a target alpha channel will be untouched
260 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
261 * @tparam tAlphaTargetModulation The target alpha channel modulation function
262 */
263 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, AlphaTargetModulation tAlphaTargetModulation>
264 static inline void blend8BitPerChannel(const uint8_t* sourceWithAlpha, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourceWithAlphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
265
266 /**
267 * Blends a target frame with a specified constant value for all pixels, while each pixel might have a different blending factor.
268 * @param alpha The alpha frame defining the value blending factor that is applied for each pixel, must be valid
269 * @param target The target frame without alpha channel that will be blended with the constant value parameter, must be valid
270 * @param width The width of the target (and alpha) frame in pixel, with range [1, infinity)
271 * @param height The height of the target (and alpha) frame in pixel, with range [1, infinity)
272 * @param value Constant blending value that is used for each pixel, must be valid
273 * @param alphaPaddingElements The number of padding elements at the end of each alpha frame row, in elements, with range [0, infinity)
274 * @param targetPaddingElements The number of padding elements at the end of each target frame row, in elements, with range [0, infinity)
275 * @param worker Optional worker object to distribute the computation
276 * @tparam tChannels Number of channels of both data frame (without any alpha channel)
277 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
278 */
279 template <unsigned int tChannels, bool tTransparentIs0xFF>
280 static inline void blend8BitPerChannel(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const uint8_t* value, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
281
282 /**
283 * Blends a target frame with a specified blending function, while each pixel might have a different blending factor.
284 * @param alpha The alpha frame defining the target blending factor that is applied for each pixel, must be valid
285 * @param target The target frame without alpha channel that will be blended with the constant value parameter, must be valid
286 * @param width The width of the target (and alpha) frame in pixel, with range [1, infinity)
287 * @param height The height of the target (and alpha) frame in pixel, with range [1, infinity)
288 * @param blendFunction Blending function allowing to apply a more complex blending function than a simple linear blending, the blend function will receive 0x00 for opaque pixels and 0xFF for transparent pixels as blend factor
289 * @param alphaPaddingElements The number of padding elements at the end of each alpha frame row, in elements, with range [0, infinity)
290 * @param targetPaddingElements The number of padding elements at the end of each target frame row, in elements, with range [0, infinity)
291 * @param worker Optional worker object to distribute the computation
292 * @tparam tChannels Number of channels of both data frame (without any alpha channel)
293 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
294 */
295 template <unsigned int tChannels, bool tTransparentIs0xFF>
296 static inline void blend8BitPerChannel(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const BlendFunction blendFunction, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
297
298 /**
299 * Blends a sub-region of a source frame with a target frame while the alpha channel is provided in a third frame with frame size identical to the source frame.
300 * @param source The source frame without alpha channel, must be valid
301 * @param alpha The alpha frame defining the alpha channel connected with the source frame, must be valid
302 * @param target The target frame without alpha channel, must be valid
303 * @param sourceWidth Width of the source (and alpha) frame in pixel, with range [1, infinity)
304 * @param sourceHeight Height of the source (and alpha) frame in pixel, with range [1, infinity)
305 * @param targetWidth Width of the target frame in pixel, with range [1, infinity)
306 * @param targetHeight Height of the target frame in pixel, with range [1, infinity)
307 * @param sourceLeft Horizontal start position inside the source frame, with range [0, sourceWidth)
308 * @param sourceTop Vertical start position inside the source frame, with range [0, sourceHeight)
309 * @param targetLeft Horizontal start position inside the target frame, with range [0, targetWidth)
310 * @param targetTop Vertical start position inside the target frame, with range [0, targetHeight)
311 * @param width The width of the blending sub-region in pixel, with range [1, min(sourceWidth - sourceLeft, targetWidth - targetLeft)]
312 * @param height The height of the blending sub-region in pixel, with range [1, min(sourceHeight - sourceTop, targetHeight - targetTop)]
313 * @param sourcePaddingElements The number of padding elements at the end of each row in the source frame, in elements, with range [0, infinity)
314 * @param alphaPaddingElements The number of padding elements at the end of each row in the alpha frame, in elements, with range [0, infinity)
315 * @param targetPaddingElements The number of padding elements at the end of each row in the target frame, in elements, with range [0, infinity)
316 * @param worker Optional worker object to distribute the computation
317 * @tparam tChannels Number of channels of both data frame (without any alpha channel)
318 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
319 */
320 template <unsigned int tChannels, bool tTransparentIs0xFF>
321 static inline void blend8BitPerChannel(const uint8_t* source, const uint8_t* alpha, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourceLeft, const unsigned int sourceTop, const unsigned int targetLeft, const unsigned int targetTop, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
322
323 /**
324 * Blends a sub-region of a source frame with a target frame while the alpha channel is in front of the data channels or behind the data channels.
325 * @param sourceWithAlpha Source frame with alpha channel, must be valid
326 * @param target The target frame which may also hold an alpha channel depending on tTargetHasAlpha, must be valid
327 * @param sourceWidth Width of the source frame in pixel, with range [1, infinity)
328 * @param sourceHeight Height of the source frame in pixel, with range [1, infinity)
329 * @param targetWidth Width of the target frame in pixel, with range [1, infinity)
330 * @param targetHeight Height of the target frame in pixel, with range [1, infinity)
331 * @param sourceLeft Horizontal start position inside the source frame, with range [0, sourceWidth)
332 * @param sourceTop Vertical start position inside the source frame, with range [0, sourceHeight)
333 * @param targetLeft Horizontal start position inside the target frame, with range [0, targetWidth)
334 * @param targetTop Vertical start position inside the target frame, with range [0, targetHeight)
335 * @param width The width of the blending sub-region in pixel, with range [1, min(sourceWidth - sourceLeft, targetWidth - targetLeft)]
336 * @param height The height of the blending sub-region in pixel, with range [1, min(sourceHeight - sourceTop, targetHeight - targetTop)]
337 * @param sourcePaddingElements The number of padding elements at the end of each row in the source frame, in elements, with range [0, infinity)
338 * @param targetPaddingElements The number of padding elements at the end of each row in the target frame, in elements, with range [0, infinity)
339 * @param worker Optional worker object to distribute the computation
340 * @tparam tChannelsWithAlpha Number of channels in the source frame (including the alpha channel)
341 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
342 * @tparam tTargetHasAlpha True, if not only the source frame holds an alpha channel but also the target frame, however values in a target alpha channel will be untouched
343 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
344 * @tparam tAlphaTargetModulation The target alpha channel modulation function
345 */
346 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
347 static inline void blend8BitPerChannel(const uint8_t* sourceWithAlpha, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourceLeft, const unsigned int sourceTop, const unsigned int targetLeft, const unsigned int targetTop, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
348
349 /**
350 * Returns the alpha value for a fully transparent pixel.
351 * @return Fully transparent alpha value
352 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
353 */
354 template <bool tTransparentIs0xFF>
355 static inline uint8_t fullTransparent8Bit();
356
357 /**
358 * Returns the alpha value for a fully opaque pixel.
359 * @return Fully opaque alpha value
360 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
361 */
362 template <bool tTransparentIs0xFF>
363 static inline uint8_t fullOpaque8Bit();
364
365 /**
366 * Converts a given alpha value so that 0xFF is interpreted as fully transparent.
367 * @param alpha The alpha value that will be converted
368 * @tparam tTransparentIs0xFF True, if the given alpha is defined so that 0xFF is interpreted as fully transparent
369 * @return Resulting converted alpha value
370 */
371 template <bool tTransparentIs0xFF>
372 static inline uint8_t alpha8BitToTransparentIs0xFF(const uint8_t alpha);
373
374 /**
375 * Converts a given alpha value so that 0xFF is interpreted as fully opaque.
376 * @param alpha The alpha value that will be converted
377 * @tparam tTransparentIs0xFF True, if the given alpha is defined so that 0xFF is interpreted as fully transparent
378 * @return Resulting converted alpha value
379 */
380 template <bool tTransparentIs0xFF>
381 static inline uint8_t alpha8BitToOpaqueIs0xFF(const uint8_t alpha);
382
383 protected:
384
385 /**
386 * Blends a subset of two 8 bit per channels frames by application of one unique blending factor for all pixels.
387 * @param source The source frame that is blended with the target frame, must be valid
388 * @param target The target frame that receives the blending result from source and target pixels, this frame must have the same frame format as the source frame, must be valid
389 * @param alphaValue The blending factor for all pixels, with range [0, 255]
390 * @param width The width of both frames in pixel, with range [1, infinity)
391 * @param sourcePaddingElements The optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
392 * @param targetPaddingElements The optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
393 * @param firstRow First row to be handled, with range [0, height - 1]
394 * @param numberRows Number of rows to be handled, with range [1, height - firstRow]
395 * @tparam tChannels Number of channels of both data frame (without any alpha channel), with range [1, infinity)
396 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent; False, if 0x00 is interpreted as fully transparent
397 */
398 template <unsigned int tChannels, bool tTransparentIs0xFF>
399 static void blend8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const uint8_t alphaValue, const unsigned int width, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
400
401 /**
402 * Blends a subset of a source and target frame (each 8 bit per channel) while the alpha channel is provided as a third frame.
403 * @param source The source frame that is blended with the target frame, must be valid
404 * @param alpha The alpha frame with defining one alpha blending factor for each pixel, must be valid
405 * @param target The target frame that receives the blending result from source and target pixels, this frame must have the same frame format as the source frame, must be valid
406 * @param width The width of all frames, in pixel, with range [1, infinity)
407 * @param sourcePaddingElements The optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
408 * @param alphaPaddingElements The optional number of padding elements at the end of each alpha row, in elements, with range [0, infinity)
409 * @param targetPaddingElements The optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
410 * @param firstRow The first row to be handled, with range [0, height - 1]
411 * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
412 * @tparam tChannels Number of channels of both data frame (without any alpha channel), with range [1, infinity)
413 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent; False, if 0x00 is interpreted as fully transparent
414 */
415 template <unsigned int tChannels, bool tTransparentIs0xFF>
416 static void blend8BitPerChannelSubset(const uint8_t* source, const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int sourcePaddingElements, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
417
418 /**
419 * Blends a subset of a source and target frame while the alpha channel is in front of the data channels or behind the data channels.
420 * @param sourceWithAlpha Source frame with alpha channel, must be valid
421 * @param target The target frame which may also hold an alpha channel depending on tTargetHasAlpha, must be valid
422 * @param width The width of both frames in pixel, with range [1, infinity)
423 * @param height The height of both frames in pixel, with range [1, infinity)
424 * @param sourceWithAlphaPaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
425 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
426 * @param firstRow First row to be handled, with range [0, height - 1]
427 * @param numberRows Number of rows to be handled, with range [1, height - firstRow]
428 * @tparam tChannelsWithAlpha Number of channels in the source frame (including the alpha channel), with range [2, infinity)
429 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
430 * @tparam tTargetHasAlpha True, if not only the source frame holds an alpha channel but also the target frame, however values in a target alpha channel will be untouched
431 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
432 * @tparam tAlphaTargetModulation The target alpha channel modulation function
433 */
434 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, AlphaTargetModulation tAlphaTargetModulation>
435 static void blend8BitPerChannelSubset(const uint8_t* sourceWithAlpha, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourceWithAlphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
436
437 /**
438 * Blends a subset of a target frame with a specified constant value for all pixels, while each pixel might have a different blending factor.
439 * @param alpha The alpha frame defining the value blending factor that is applied for each pixel
440 * @param target The target frame without alpha channel that will be blended with the constant value parameter
441 * @param width The width of the target (and alpha) frame in pixel, with range [1, infinity)
442 * @param height The height of the target (and alpha) frame in pixel, with range [1, infinity)
443 * @param value Constant blending value that is used for each pixel
444 * @param alphaPaddingElements The number of padding elements at the end of each alpha frame row, in elements, with range [0, infinity)
445 * @param targetPaddingElements The number of padding elements at the end of each target frame row, in elements, with range [0, infinity)
446 * @param firstRow First row to be handled, with range [0, height - 1]
447 * @param numberRows Number of rows to be handled, with range [1, height - firstRow]
448 * @tparam tChannels Number of channels of both data frame (without any alpha channel), with range [1, infinity)
449 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
450 */
451 template <unsigned int tChannels, bool tTransparentIs0xFF>
452 static void blend8BitPerChannelSubset(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const uint8_t* value, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
453
454 /**
455 * Blends a subset of a target frame with a specified blending function, while each pixel might have a different blending factor.
456 * @param alpha The alpha frame defining the target blending factor that is applied for each pixel
457 * @param target The target frame without alpha channel that will be blended with the constant value parameter
458 * @param width The width of the target (and alpha) frame in pixel, with range [1, infinity)
459 * @param height The height of the target (and alpha) frame in pixel, with range [1, infinity)
460 * @param blendFunction Blending function allowing to apply a more complex blending function than a simple linear blending, the blend function will receive 0x00 for opaque pixels and 0xFF for transparent pixels as blend factor
461 * @param alphaPaddingElements The optional number of padding elements at the end of each alpha row, in elements, with range [0, infinity)
462 * @param targetPaddingElements The optional number of padding elements at the end of each target row, in elements, with range [0, infinity)
463 * @param firstRow First row of the sub-region to be handled, with range [0, height - 1]
464 * @param numberRows Number of rows of the sub-region to be handled, with range [1, height - firstRow]
465 * @tparam tChannels Number of channels of both data frame (without any alpha channel), with range [1, infinity)
466 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
467 */
468 template <unsigned int tChannels, bool tTransparentIs0xFF>
469 static void blend8BitPerChannelSubset(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const BlendFunction blendFunction, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
470
471 /**
472 * Returns the blend factor for the source frame depending whether 0xFF is interpreted as transparent or opaque.
473 * @param alpha The alpha value for which the blending factor is returned, with range [0, 255]
474 * @return Resulting blending factor, with range [0, 255]
475 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent value; False, if 0x00 is interpreted as fully transparent
476 * @see targetBlendFactor().
477 */
478 template <bool tTransparentIs0xFF>
479 static uint8_t inline sourceBlendFactor(const uint8_t alpha);
480
481 /**
482 * Returns the blend factor for the target frame depending whether 0xFF is interpreted as transparent or opaque.
483 * @param alpha The alpha value for which the blending factor is returned, with range [0, 255]
484 * @return Resulting blending factor, with range [0, 255]
485 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent value; False, if 0x00 is interpreted as fully transparent
486 * @see sourceBlendFactor().
487 */
488 template <bool tTransparentIs0xFF>
489 static inline uint8_t targetBlendFactor(const uint8_t alpha);
490};
491
492template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
493bool FrameBlender::blend(const Frame& sourceWithAlpha, Frame& target, Worker* worker)
494{
495 if (!sourceWithAlpha.isValid() || !target.isValid() || sourceWithAlpha.width() != target.width() || sourceWithAlpha.height() != target.height()
496 || sourceWithAlpha.pixelOrigin() != target.pixelOrigin()
497 || (sourceWithAlpha.pixelFormat() != target.pixelFormat() && FrameType::formatRemoveAlphaChannel(sourceWithAlpha.pixelFormat()) != target.pixelFormat()))
498 {
499 ocean_assert(false && "Invalid pixel format!");
500 return false;
501 }
502
503 if (sourceWithAlpha.numberPlanes() == 1u && sourceWithAlpha.dataType() == FrameType::DT_UNSIGNED_INTEGER_8)
504 {
505 bool alphaIsLastChannel = false;
506
507 const bool sourceHasAlpha = FrameType::formatHasAlphaChannel(sourceWithAlpha.pixelFormat(), &alphaIsLastChannel);
508 ocean_assert_and_suppress_unused(sourceHasAlpha, sourceHasAlpha);
509
510 const bool targetHasAlpha = sourceWithAlpha.pixelFormat() == target.pixelFormat();
511
512 switch (sourceWithAlpha.channels())
513 {
514 case 2u:
515 {
516 if (alphaIsLastChannel)
517 {
518 if (targetHasAlpha)
519 {
520 blend8BitPerChannel<2u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
521 }
522 else
523 {
524 blend8BitPerChannel<2u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
525 }
526 }
527 else
528 {
529 if (targetHasAlpha)
530 {
531 blend8BitPerChannel<2u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
532 }
533 else
534 {
535 blend8BitPerChannel<2u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
536 }
537 }
538
539 return true;
540 }
541
542 case 3u:
543 {
544 if (alphaIsLastChannel)
545 {
546 if (targetHasAlpha)
547 {
548 blend8BitPerChannel<3u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
549 }
550 else
551 {
552 blend8BitPerChannel<3u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
553 }
554 }
555 else
556 {
557 if (targetHasAlpha)
558 {
559 blend8BitPerChannel<3u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
560 }
561 else
562 {
563 blend8BitPerChannel<3u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
564 }
565 }
566
567 return true;
568 }
569
570 case 4u:
571 {
572 if (alphaIsLastChannel)
573 {
574 if (targetHasAlpha)
575 {
576 blend8BitPerChannel<4u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
577 }
578 else
579 {
580 blend8BitPerChannel<4u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(),sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
581 }
582 }
583 else
584 {
585 if (targetHasAlpha)
586 {
587 blend8BitPerChannel<4u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
588 }
589 else
590 {
591 blend8BitPerChannel<4u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
592 }
593 }
594
595 return true;
596 }
597 }
598 }
599
600 ocean_assert(false && "Invalid pixel format!");
601 return false;
602}
603
604template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
605bool FrameBlender::blend(const Frame& sourceWithAlpha, Frame& result, const uint8_t* backgroundColor, Worker* worker)
606{
607 if (!result.set(FrameType(sourceWithAlpha, FrameType::formatRemoveAlphaChannel(sourceWithAlpha.pixelFormat())), false /*forceOwner*/, true /*forceWritable*/))
608 {
609 return false;
610 }
611
612 result.setValue<uint8_t>(backgroundColor, result.channels(), 0u);
613
614 return blend<tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha, result, worker);
615}
616
617template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
618bool FrameBlender::blend(const Frame& sourceWithAlpha, Frame& target, const unsigned int sourceLeft, const unsigned int sourceTop, const unsigned int targetLeft, const unsigned int targetTop, const unsigned int width, const unsigned int height, Worker* worker)
619{
620 if (!sourceWithAlpha.isValid() || !target.isValid()
621 || sourceWithAlpha.pixelOrigin() != target.pixelOrigin()
622 || (sourceWithAlpha.pixelFormat() != target.pixelFormat() && FrameType::formatRemoveAlphaChannel(sourceWithAlpha.pixelFormat()) != target.pixelFormat())
623 || sourceLeft + width > sourceWithAlpha.width() || sourceTop + height > sourceWithAlpha.height()
624 || targetLeft + width > target.width() || targetTop + height > target.height())
625 {
626 ocean_assert(false && "Invalid pixel format!");
627 return false;
628 }
629
630 if (sourceWithAlpha.numberPlanes() == 1u && sourceWithAlpha.dataType() == FrameType::DT_UNSIGNED_INTEGER_8)
631 {
632 bool alphaIsLastChannel = false;
633
634 const bool hasAlpha = FrameType::formatHasAlphaChannel(sourceWithAlpha.pixelFormat(), &alphaIsLastChannel);
635 ocean_assert_and_suppress_unused(hasAlpha, hasAlpha);
636
637 const bool targetHasAlpha = sourceWithAlpha.pixelFormat() == target.pixelFormat();
638
639 switch (sourceWithAlpha.channels())
640 {
641 case 2u:
642 {
643 if (alphaIsLastChannel)
644 {
645 if (targetHasAlpha)
646 {
647 blend8BitPerChannel<2u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
648 }
649 else
650 {
651 blend8BitPerChannel<2u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
652 }
653 }
654 else
655 {
656 if (targetHasAlpha)
657 {
658 blend8BitPerChannel<2u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
659 }
660 else
661 {
662 blend8BitPerChannel<2u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
663 }
664 }
665
666 return true;
667 }
668
669 case 3u:
670 {
671 if (alphaIsLastChannel)
672 {
673 if (targetHasAlpha)
674 {
675 blend8BitPerChannel<3u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
676 }
677 else
678 {
679 blend8BitPerChannel<3u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
680 }
681 }
682 else
683 {
684 if (targetHasAlpha)
685 {
686 blend8BitPerChannel<3u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
687 }
688 else
689 {
690 blend8BitPerChannel<3u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
691 }
692 }
693
694 return true;
695 }
696
697 case 4u:
698 {
699 if (alphaIsLastChannel)
700 {
701 if (targetHasAlpha)
702 {
703 blend8BitPerChannel<4u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
704 }
705 else
706 {
707 blend8BitPerChannel<4u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
708 }
709 }
710 else
711 {
712 if (targetHasAlpha)
713 {
714 blend8BitPerChannel<4u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
715 }
716 else
717 {
718 blend8BitPerChannel<4u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), target.width(), target.height(), sourceLeft, sourceTop, targetLeft, targetTop, width, height, sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
719 }
720 }
721
722 return true;
723 }
724 }
725 }
726
727 ocean_assert(false && "Invalid pixel format!");
728 return false;
729}
730
731template <bool tTransparentIs0xFF>
732bool FrameBlender::blend(const Frame& source, Frame& target, const uint8_t alphaValue, Worker* worker)
733{
734 ocean_assert(source && target);
735
736 if (FrameType::areFrameTypesCompatible(source, target, false /*allowDifferentPixelOrigins*/)
737 && source.numberPlanes() == 1u
739 {
740 switch (source.channels())
741 {
742 case 1u:
743 blend8BitPerChannel<1u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
744 return true;
745
746 case 2u:
747 blend8BitPerChannel<2u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
748 return true;
749
750 case 3u:
751 blend8BitPerChannel<3u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
752 return true;
753
754 case 4u:
755 blend8BitPerChannel<4u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
756 return true;
757 }
758 }
759
760 ocean_assert(false && "Invalid frame type!");
761 return false;
762}
763
764template <unsigned int tChannels, bool tTransparentIs0xFF>
765inline void FrameBlender::blend8BitPerChannel(const uint8_t* source, uint8_t* target, const uint8_t alphaValue, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
766{
767 static_assert(tChannels >= 1u, "Invalid channel number!");
768
769 ocean_assert(source != nullptr && target != nullptr);
770
771 if (worker)
772 {
773 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, source, target, alphaValue, width, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 6u, 7u, 20u);
774 }
775 else
776 {
777 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(source, target, alphaValue, width, sourcePaddingElements, targetPaddingElements, 0u, height);
778 }
779}
780
781template <unsigned int tChannels, bool tTransparentIs0xFF>
782inline void FrameBlender::blend8BitPerChannel(const uint8_t* source, const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker)
783{
784 static_assert(tChannels >= 1u, "Invalid channel number!");
785
786 ocean_assert(source != nullptr && alpha != nullptr && target != nullptr);
787
788 if (worker)
789 {
790 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, source, alpha, target, width, sourcePaddingElements, alphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
791 }
792 else
793 {
794 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(source, alpha, target, width, sourcePaddingElements, alphaPaddingElements, targetPaddingElements, 0u, height);
795 }
796}
797
798template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
799inline void FrameBlender::blend8BitPerChannel(const uint8_t* sourceWithAlpha, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourceWithAlphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker)
800{
801 static_assert(tChannelsWithAlpha > 1u, "Invalid channel number!");
802 ocean_assert(sourceWithAlpha && target);
803
804 if (worker)
805 {
806 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannelsWithAlpha, tAlphaAtFront, tTargetHasAlpha, tTransparentIs0xFF, tAlphaTargetModulation>, sourceWithAlpha, target, width, height, sourceWithAlphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 6u, 7u, 20u);
807 }
808 else
809 {
810 blend8BitPerChannelSubset<tChannelsWithAlpha, tAlphaAtFront, tTargetHasAlpha, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha, target, width, height, sourceWithAlphaPaddingElements, targetPaddingElements, 0u, height);
811 }
812}
813
814template <unsigned int tChannels, bool tTransparentIs0xFF>
815inline void FrameBlender::blend8BitPerChannel(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const uint8_t* value, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker)
816{
817 static_assert(tChannels >= 1u, "Invalid channel number!");
818
819 ocean_assert(alpha != nullptr && target != nullptr && value != nullptr);
820
821 if (worker)
822 {
823 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, alpha, target, width, height, value, alphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
824 }
825 else
826 {
827 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(alpha, target, width, height, value, alphaPaddingElements, targetPaddingElements, 0u, height);
828 }
829}
830
831template <unsigned int tChannels, bool tTransparentIs0xFF>
832inline void FrameBlender::blend8BitPerChannel(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const BlendFunction blendFunction, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker)
833{
834 static_assert(tChannels >= 1u, "Invalid channel number!");
835 ocean_assert(alpha && target && blendFunction);
836
837 if (worker)
838 {
839 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, alpha, target, width, height, blendFunction, alphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
840 }
841 else
842 {
843 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(alpha, target, width, height, blendFunction, alphaPaddingElements, targetPaddingElements, 0u, height);
844 }
845}
846
847template <unsigned int tChannels, bool tTransparentIs0xFF>
848inline void FrameBlender::blend8BitPerChannel(const uint8_t* source, const uint8_t* alpha, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourceLeft, const unsigned int sourceTop, const unsigned int targetLeft, const unsigned int targetTop, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, Worker* worker)
849{
850 ocean_assert(source != nullptr && alpha != nullptr && target != nullptr);
851
852 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
853 const unsigned int alphaStrideElements = sourceWidth + alphaPaddingElements;
854 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
855
856 const uint8_t* const sourceTopLeft = source + sourceTop * sourceStrideElements + sourceLeft * tChannels;
857 const uint8_t* const alphaTopLeft = alpha + sourceTop * alphaStrideElements + sourceLeft;
858 uint8_t* const targetTopLeft = target + targetTop * targetStrideElements + targetLeft * tChannels;
859
860 ocean_assert_and_suppress_unused(width <= sourceWidth && height <= sourceHeight, sourceHeight);
861 ocean_assert_and_suppress_unused(width <= targetWidth && height <= targetHeight, targetHeight);
862
863 const unsigned int subSourcePaddingElements = (sourceWidth - width) * tChannels + sourcePaddingElements;
864 const unsigned int subAlphaPaddingElements = (sourceWidth - width) + alphaPaddingElements;
865 const unsigned int subTargetPaddingElements = (targetWidth - width) * tChannels + targetPaddingElements;
866
867 blend8BitPerChannel<tChannels, tTransparentIs0xFF>(sourceTopLeft, alphaTopLeft, targetTopLeft, width, height, subSourcePaddingElements, subAlphaPaddingElements, subTargetPaddingElements, worker);
868}
869
870template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
871inline void FrameBlender::blend8BitPerChannel(const uint8_t* sourceWithAlpha, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourceLeft, const unsigned int sourceTop, const unsigned int targetLeft, const unsigned int targetTop, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
872{
873 static_assert(tChannelsWithAlpha > 1u, "Invalid channel number!");
874
875 ocean_assert(sourceWithAlpha != nullptr && target != nullptr);
876
877 constexpr unsigned int tTargetChannels = TargetOffset<tTargetHasAlpha>::template channels<tChannelsWithAlpha>();
878
879 const unsigned int sourceStrideElements = sourceWidth * tChannelsWithAlpha + sourcePaddingElements;
880 const unsigned int targetStrideElements = targetWidth * tTargetChannels + targetPaddingElements;
881
882 const uint8_t* const sourceTopLeft = sourceWithAlpha + sourceTop * sourceStrideElements + sourceLeft * tChannelsWithAlpha;
883 uint8_t* const targetTopLeft = target + targetTop * targetStrideElements + targetLeft * tTargetChannels;
884
885 ocean_assert_and_suppress_unused(width <= sourceWidth && height <= sourceHeight, sourceHeight);
886 ocean_assert_and_suppress_unused(width <= targetWidth && height <= targetHeight, targetHeight);
887
888 const unsigned int subSourcePaddingElements = (sourceWidth - width) * tChannelsWithAlpha + sourcePaddingElements;
889 const unsigned int subTargetPaddingElements = (targetWidth - width) * tTargetChannels + targetPaddingElements;
890
891 blend8BitPerChannel<tChannelsWithAlpha, tAlphaAtFront, tTargetHasAlpha, tTransparentIs0xFF, tAlphaTargetModulation>(sourceTopLeft, targetTopLeft, width, height, subSourcePaddingElements, subTargetPaddingElements, worker);
892}
893
894template <bool tTransparentIs0xFF>
896{
897 return 0xFF;
898}
899
900template <>
901inline uint8_t FrameBlender::fullTransparent8Bit<false>()
902{
903 return 0x00;
904}
905
906template <bool tTransparentIs0xFF>
908{
909 return 0xFF - fullTransparent8Bit<tTransparentIs0xFF>();
910}
911
912template <bool tTransparentIs0xFF>
913inline uint8_t FrameBlender::alpha8BitToTransparentIs0xFF(const uint8_t alpha)
914{
915 return alpha;
916}
917
918template <>
919inline uint8_t FrameBlender::alpha8BitToTransparentIs0xFF<false>(const uint8_t alpha)
920{
921 return 0xFF - alpha;
922}
923
924template <bool tTransparentIs0xFF>
925inline uint8_t FrameBlender::alpha8BitToOpaqueIs0xFF(const uint8_t alpha)
926{
927 return 0xFF - alpha;
928}
929
930template <>
931inline uint8_t FrameBlender::alpha8BitToOpaqueIs0xFF<false>(const uint8_t alpha)
932{
933 return alpha;
934}
935
936template <unsigned int tChannels, bool tTransparentIs0xFF>
937void FrameBlender::blend8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const uint8_t alphaValue, const unsigned int width, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
938{
939 static_assert(tChannels >= 1u, "Invalid channel number!");
940
941 ocean_assert(source != nullptr && target != nullptr);
942
943 const uint8_t sourceFactor = sourceBlendFactor<tTransparentIs0xFF>(alphaValue);
944 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(alphaValue);
945
946 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
947 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
948
949 source += firstRow * sourceStrideElements;
950 target += firstRow * targetStrideElements;
951
952 for (unsigned int r = 0u; r < numberRows; ++r)
953 {
954 for (unsigned int x = 0u; x < width; ++x)
955 {
956 for (unsigned int n = 0u; n < tChannels; ++n)
957 {
958 target[n] = Ocean::Utilities::divideBy255(target[n] * targetFactor + source[n] * sourceFactor + 127u);
959 }
960
961 source += tChannels;
962 target += tChannels;
963 }
964
965 source += sourcePaddingElements;
966 target += targetPaddingElements;
967 }
968}
969
970template <unsigned int tChannels, bool tTransparentIs0xFF>
971void FrameBlender::blend8BitPerChannelSubset(const uint8_t* source, const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int sourcePaddingElements, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
972{
973 static_assert(tChannels >= 1u, "Invalid channel number!");
974
975 ocean_assert(source != nullptr && alpha != nullptr && target != nullptr);
976
977 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
978 const unsigned int alphaStrideElements = width + alphaPaddingElements;
979 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
980
981 source += firstRow * sourceStrideElements;
982 alpha += firstRow * alphaStrideElements;
983 target += firstRow * targetStrideElements;
984
985 for (unsigned int r = 0u; r < numberRows; ++r)
986 {
987 for (unsigned int x = 0u; x < width; ++x)
988 {
989 const uint8_t sourceFactor = sourceBlendFactor<tTransparentIs0xFF>(alpha[0]);
990 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(alpha[0]);
991
992 for (unsigned int n = 0u; n < tChannels; ++n)
993 {
994 target[n] = Ocean::Utilities::divideBy255(target[n] * targetFactor + source[n] * sourceFactor + 127u);
995 }
996
997 source += tChannels;
998 ++alpha;
999 target += tChannels;
1000 }
1001
1002 source += sourcePaddingElements;
1003 alpha += alphaPaddingElements;
1004 target += targetPaddingElements;
1005 }
1006}
1007
1008template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
1009void FrameBlender::blend8BitPerChannelSubset(const uint8_t* sourceWithAlpha, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourceWithAlphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1010{
1011 static_assert(tChannelsWithAlpha > 1u, "Invalid channel number!");
1012 ocean_assert(sourceWithAlpha != nullptr && target != nullptr);
1013
1014 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1015
1016 const unsigned int sourceWithAlphaStrideElements = width * tChannelsWithAlpha + sourceWithAlphaPaddingElements;
1017 const unsigned int targetStrideElements = width * TargetOffset<tTargetHasAlpha>::template channels<tChannelsWithAlpha>() + targetPaddingElements;
1018
1019 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1020 {
1021 const uint8_t* sourceWithAlphaData = sourceWithAlpha + y * sourceWithAlphaStrideElements;
1022 uint8_t* targetData = target + y * targetStrideElements;
1023
1024 for (unsigned int x = 0u; x < width; ++x)
1025 {
1026 const uint8_t sourceFactor = sourceBlendFactor<tTransparentIs0xFF>(sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]);
1027 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]);
1028
1029 for (unsigned int n = 0u; n < tChannelsWithAlpha - 1u; ++n)
1030 {
1031 targetData[n + TargetOffset<tTargetHasAlpha>::template data<tAlphaAtFront>()] = Ocean::Utilities::divideBy255(targetData[n + TargetOffset<tTargetHasAlpha>::template data<tAlphaAtFront>()] * targetFactor + sourceWithAlphaData[n + SourceOffset<tAlphaAtFront>::data()] * sourceFactor + 127u);
1032 }
1033
1034 if constexpr (tTargetHasAlpha && tAlphaTargetModulation == ATM_BLEND)
1035 {
1036 if constexpr (tTransparentIs0xFF)
1037 {
1038 targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] =
1039 Ocean::Utilities::divideBy255(targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] * sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]);
1040 }
1041 else
1042 {
1043 // alphaResult = alphaTarget + alphaSource * (1 - alphaTarget), while 0xFF is interpreted as fully opaque
1044 // alphaResult = (alphaTarget * 255 + alphaSource * (255 - alphaTarget)) / 255, while 0xFF is interpreted as fully opaque
1045
1046 targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] =
1047 Ocean::Utilities::divideBy255(255u * targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]
1048 + sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] * (255u - targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]));
1049 }
1050 }
1051
1052 sourceWithAlphaData += tChannelsWithAlpha;
1053 targetData += TargetOffset<tTargetHasAlpha>::template channels<tChannelsWithAlpha>();
1054 }
1055 }
1056}
1057
1058template <unsigned int tChannels, bool tTransparentIs0xFF>
1059void FrameBlender::blend8BitPerChannelSubset(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const uint8_t* value, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1060{
1061 static_assert(tChannels >= 1u, "Invalid channel number!");
1062
1063 ocean_assert(alpha != nullptr && target != nullptr && value != nullptr);
1064 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1065
1066 const unsigned int alphaStrideElements = width + alphaPaddingElements;
1067 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
1068
1069 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1070 {
1071 const uint8_t* alphaRow = alpha + y * alphaStrideElements;
1072 uint8_t* targetRow = target + y * targetStrideElements;
1073
1074 for (unsigned int x = 0u; x < width; ++x)
1075 {
1076 const uint8_t valueFactor = sourceBlendFactor<tTransparentIs0xFF>(*alphaRow);
1077 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(*alphaRow);
1078
1079 for (unsigned int n = 0u; n < tChannels; ++n)
1080 {
1081 targetRow[n] = Ocean::Utilities::divideBy255(targetRow[n] * targetFactor + value[n] * valueFactor + 127u);
1082 }
1083
1084 ++alphaRow;
1085 targetRow += tChannels;
1086 }
1087 }
1088}
1089
1090template <unsigned int tChannels, bool tTransparentIs0xFF>
1091void FrameBlender::blend8BitPerChannelSubset(const uint8_t* alpha, uint8_t* target, const unsigned int width, const unsigned int height, const BlendFunction blendFunction, const unsigned int alphaPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1092{
1093 static_assert(tChannels >= 1u, "Invalid channel number!");
1094
1095 ocean_assert(alpha != nullptr && target != nullptr && blendFunction != nullptr);
1096 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1097
1098 const unsigned int alphaStrideElements = width + alphaPaddingElements;
1099 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
1100
1101 alpha += firstRow * alphaStrideElements;
1102 target += firstRow * targetStrideElements;
1103
1104 for (unsigned int n = 0u; n < numberRows; ++n)
1105 {
1106 for (unsigned int x = 0u; x < width; ++x)
1107 {
1108 blendFunction(target, targetBlendFactor<tTransparentIs0xFF>(*alpha));
1109
1110 ++alpha;
1111 target += tChannels;
1112 }
1113
1114 alpha += alphaPaddingElements;
1115 target += targetPaddingElements;
1116 }
1117}
1118
1119template <bool tTransparentIs0xFF>
1120inline uint8_t FrameBlender::sourceBlendFactor(const uint8_t alpha)
1121{
1122 return 0xFFu - alpha;
1123}
1124
1125template <>
1126inline uint8_t FrameBlender::sourceBlendFactor<false>(const uint8_t alpha)
1127{
1128 return alpha;
1129}
1130
1131template <bool tTransparentIs0xFF>
1132inline uint8_t FrameBlender::targetBlendFactor(const uint8_t alpha)
1133{
1134 return alpha;
1135}
1136
1137template <>
1138inline uint8_t FrameBlender::targetBlendFactor<false>(const uint8_t alpha)
1139{
1140 return 0xFFu - alpha;
1141}
1142
1143template <bool tAlphaAtFront>
1144template <unsigned int tChannelsWithAlpha>
1146{
1147 return 0u;
1148}
1149
1150template <>
1151template <unsigned int tChannelsWithAlpha>
1152constexpr inline unsigned int FrameBlender::SourceOffset<false>::alpha()
1153{
1154 static_assert(tChannelsWithAlpha >= 1u, "Invalid channel number!");
1155
1156 return tChannelsWithAlpha - 1u;
1157}
1158
1159template <bool tAlphaAtFront>
1161{
1162 return 1u;
1163}
1164
1165template <>
1166constexpr inline unsigned int FrameBlender::SourceOffset<false>::data()
1167{
1168 return 0u;
1169}
1170
1171template <bool tAlphaAtFront>
1172template <bool tSourceHasAlpha>
1173constexpr inline unsigned int FrameBlender::SourceOffset<tAlphaAtFront>::data()
1174{
1175 return tSourceHasAlpha ? 1u : 0u;
1176}
1177
1178template <>
1179template <>
1181{
1182 return 0u;
1183}
1184
1185template <>
1186template <>
1188{
1189 return 0u;
1190}
1191
1192template <bool tTargetHasAlpha>
1193template <unsigned int tChannelsWithAlpha>
1195{
1196 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1197
1198 return tChannelsWithAlpha;
1199}
1200
1201template <>
1202template <unsigned int tChannelsWithAlpha>
1203constexpr inline unsigned int FrameBlender::TargetOffset<false>::channels()
1204{
1205 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel number!");
1206
1207 return tChannelsWithAlpha - 1u;
1208}
1209
1210template <bool tTargetHasAlpha>
1211template <bool tAlphaAtFront>
1213{
1214 return 0u;
1215}
1216
1217template <>
1218template <>
1220{
1221 return 1u;
1222}
1223
1224template <bool tHasAlpha>
1225template <unsigned int tChannels>
1227{
1228 static_assert(tChannels >= 2u, "Invalid channel input!");
1229
1230 // we have a frame with alpha channel
1231 return tChannels - 1u;
1232}
1233
1234template <>
1235template <unsigned int tChannels>
1237{
1238 static_assert(tChannels >= 1u, "Invalid channel input!");
1239
1240 // we have a frame without alpha channel
1241 return tChannels;
1242}
1243
1244template <bool tHasAlpha>
1245template <unsigned int tChannelsWithAlpha>
1247{
1248 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1249
1250 // we have a frame with alpha channel
1251 return tChannelsWithAlpha;
1252}
1253
1254template <>
1255template <unsigned int tChannelsWithAlpha>
1257{
1258 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1259
1260 // we have a frame without alpha channel
1261 return tChannelsWithAlpha - 1u;
1262}
1263
1264}
1265
1266}
1267
1268#endif // META_OCEAN_CV_FRAME_BLENDER_H
Helper class allowing to determine the number of channels of a frame.
Definition FrameBlender.h:117
static constexpr unsigned int channels()
Returns the number of channels of a frame for that is known whether is has an alpha channel or not.
Definition FrameBlender.h:1246
static constexpr unsigned int dataChannels()
Returns the number of channels of a frame not counting the possible alpha channel.
Definition FrameBlender.h:1226
Helper class allowing to determine the offset that is necessary to access the alpha channel.
Definition FrameBlender.h:60
static constexpr unsigned int alpha()
Returns the offset that is applied to access the alpha channel.
Definition FrameBlender.h:1145
static constexpr unsigned int data()
Returns the offset that is applied to access the first data channel.
static constexpr unsigned int data()
Returns the offset that is applied to access the first data channel.
Definition FrameBlender.h:1160
Helper class allowing to determine the number of channels of the target frame.
Definition FrameBlender.h:91
static constexpr unsigned int channels()
Returns the number of channels of the target frame.
Definition FrameBlender.h:1194
static constexpr unsigned int data()
Returns the offset that is applied to access the first data channel.
Definition FrameBlender.h:1212
This class implements a frame blender using an alpha channel to blend frames.
Definition FrameBlender.h:30
static uint8_t alpha8BitToTransparentIs0xFF(const uint8_t alpha)
Converts a given alpha value so that 0xFF is interpreted as fully transparent.
Definition FrameBlender.h:913
static void blend8BitPerChannel(const uint8_t *source, uint8_t *target, const uint8_t alphaValue, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Blends two 8 bit per channel frames with same frame type by application of one unique blending factor...
Definition FrameBlender.h:765
static uint8_t fullTransparent8Bit()
Returns the alpha value for a fully transparent pixel.
Definition FrameBlender.h:895
static bool blend(const Frame &source, Frame &target, const uint8_t alphaValue, Worker *worker=nullptr)
Blends two frames with same frame type by application of one unique blending factor for all pixels.
Definition FrameBlender.h:732
static uint8_t alpha8BitToOpaqueIs0xFF(const uint8_t alpha)
Converts a given alpha value so that 0xFF is interpreted as fully opaque.
Definition FrameBlender.h:925
static uint8_t fullOpaque8Bit()
Returns the alpha value for a fully opaque pixel.
Definition FrameBlender.h:907
AlphaTargetModulation
Definition of individual target alpha channel modulation functions.
Definition FrameBlender.h:37
@ ATM_CONSTANT
The target alpha channel is constant and is not changed.
Definition FrameBlender.h:41
@ ATM_BLEND
The target alpha channel is blended by alphaResult = alphaTarget + alphaSource * (1 - alphaTarget).
Definition FrameBlender.h:43
static void blend8BitPerChannelSubset(const uint8_t *source, uint8_t *target, const uint8_t alphaValue, const unsigned int width, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Blends a subset of two 8 bit per channels frames by application of one unique blending factor for all...
Definition FrameBlender.h:937
static uint8_t sourceBlendFactor(const uint8_t alpha)
Returns the blend factor for the source frame depending whether 0xFF is interpreted as transparent or...
Definition FrameBlender.h:1120
static uint8_t targetBlendFactor(const uint8_t alpha)
Returns the blend factor for the target frame depending whether 0xFF is interpreted as transparent or...
Definition FrameBlender.h:1132
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
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition Frame.h:4248
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition Frame.h:4239
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4528
bool set(const FrameType &frameType, const bool forceOwner, const bool forceWritable=false, const Indices32 &planePaddingElements=Indices32(), const Timestamp &timestamp=Timestamp(false), bool *reallocated=nullptr)
Sets a new frame type for this frame.
bool setValue(const uint8_t value, const unsigned int planeIndex=0u, const bool skipPaddingData=true)
Sets the memory of the frame to a specified byte value (the memory of one plane).
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition Frame.h:4122
Definition of a frame type composed by the frame dimension, pixel format and pixel origin.
Definition Frame.h:30
unsigned int width() const
Returns the width of the frame format in pixel.
Definition Frame.h:3170
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition Frame.h:3215
uint32_t numberPlanes() const
Returns the number of planes of the pixel format of this frame.
Definition Frame.h:3210
static PixelFormat formatRemoveAlphaChannel(const PixelFormat pixelFormat)
Removes an alpha channel from a given pixel format.
static bool areFrameTypesCompatible(const FrameType &frameTypeA, const FrameType &frameTypeB, const bool allowDifferentPixelOrigins)
Returns whether two given frame types are compatible.
static bool formatHasAlphaChannel(const PixelFormat pixelFormat, bool *isLastChannel=nullptr)
Returns whether a given pixel format holds an alpha channel.
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition Frame.h:3180
@ DT_UNSIGNED_INTEGER_8
Unsigned 8 bit integer data type (uint8_t).
Definition Frame.h:41
unsigned int height() const
Returns the height of the frame in pixel.
Definition Frame.h:3175
unsigned int channels() const
Returns the number of individual channels the frame has.
Definition Frame.h:3200
DataType dataType() const
Returns the data type of the pixel format of this frame.
Definition Frame.h:3190
static unsigned char divideBy255(const unsigned int value)
This function applies a fast division by 255 for unsigned integer values.
Definition base/Utilities.h:854
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