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 const bool sourceHasCorrectInfo = (sourceWithAlpha.numberPlanes() == 1u && sourceWithAlpha.dataType() == FrameType::DT_UNSIGNED_INTEGER_8);
504 if (!sourceHasCorrectInfo)
505 {
506 ocean_assert(false && "Invalid pixel format!");
507 return false;
508 }
509
510 bool alphaIsLastChannel = false;
511
512 const bool sourceHasAlpha = FrameType::formatHasAlphaChannel(sourceWithAlpha.pixelFormat(), &alphaIsLastChannel);
513 ocean_assert_and_suppress_unused(sourceHasAlpha, sourceHasAlpha);
514
515 const bool targetHasAlpha = sourceWithAlpha.pixelFormat() == target.pixelFormat();
516
517 switch (sourceWithAlpha.channels())
518 {
519 case 2u:
520 {
521 if (alphaIsLastChannel)
522 {
523 if (targetHasAlpha)
524 {
525 blend8BitPerChannel<2u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
526 }
527 else
528 {
529 blend8BitPerChannel<2u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
530 }
531 }
532 else
533 {
534 if (targetHasAlpha)
535 {
536 blend8BitPerChannel<2u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
537 }
538 else
539 {
540 blend8BitPerChannel<2u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
541 }
542 }
543
544 return true;
545 }
546
547 case 3u:
548 {
549 if (alphaIsLastChannel)
550 {
551 if (targetHasAlpha)
552 {
553 blend8BitPerChannel<3u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
554 }
555 else
556 {
557 blend8BitPerChannel<3u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
558 }
559 }
560 else
561 {
562 if (targetHasAlpha)
563 {
564 blend8BitPerChannel<3u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
565 }
566 else
567 {
568 blend8BitPerChannel<3u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
569 }
570 }
571
572 return true;
573 }
574
575 case 4u:
576 {
577 if (alphaIsLastChannel)
578 {
579 if (targetHasAlpha)
580 {
581 blend8BitPerChannel<4u, false, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
582 }
583 else
584 {
585 blend8BitPerChannel<4u, false, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(),sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
586 }
587 }
588 else
589 {
590 if (targetHasAlpha)
591 {
592 blend8BitPerChannel<4u, true, true, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
593 }
594 else
595 {
596 blend8BitPerChannel<4u, true, false, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha.constdata<uint8_t>(), target.data<uint8_t>(), sourceWithAlpha.width(), sourceWithAlpha.height(), sourceWithAlpha.paddingElements(), target.paddingElements(), worker);
597 }
598 }
599
600 return true;
601 }
602 default: {
603 ocean_assert(false && "Invalid pixel format!");
604 return false;
605 }
606 }
607}
608
609template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
610bool FrameBlender::blend(const Frame& sourceWithAlpha, Frame& result, const uint8_t* backgroundColor, Worker* worker)
611{
612 if (!result.set(FrameType(sourceWithAlpha, FrameType::formatRemoveAlphaChannel(sourceWithAlpha.pixelFormat())), false /*forceOwner*/, true /*forceWritable*/))
613 {
614 return false;
615 }
616
617 result.setValue<uint8_t>(backgroundColor, result.channels(), 0u);
618
619 return blend<tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha, result, worker);
620}
621
622template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
623bool 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)
624{
625 if (!sourceWithAlpha.isValid() || !target.isValid()
626 || sourceWithAlpha.pixelOrigin() != target.pixelOrigin()
627 || (sourceWithAlpha.pixelFormat() != target.pixelFormat() && FrameType::formatRemoveAlphaChannel(sourceWithAlpha.pixelFormat()) != target.pixelFormat())
628 || sourceLeft + width > sourceWithAlpha.width() || sourceTop + height > sourceWithAlpha.height()
629 || targetLeft + width > target.width() || targetTop + height > target.height())
630 {
631 ocean_assert(false && "Invalid pixel format!");
632 return false;
633 }
634
635 if (sourceWithAlpha.numberPlanes() == 1u && sourceWithAlpha.dataType() == FrameType::DT_UNSIGNED_INTEGER_8)
636 {
637 bool alphaIsLastChannel = false;
638
639 const bool hasAlpha = FrameType::formatHasAlphaChannel(sourceWithAlpha.pixelFormat(), &alphaIsLastChannel);
640 ocean_assert_and_suppress_unused(hasAlpha, hasAlpha);
641
642 const bool targetHasAlpha = sourceWithAlpha.pixelFormat() == target.pixelFormat();
643
644 switch (sourceWithAlpha.channels())
645 {
646 case 2u:
647 {
648 if (alphaIsLastChannel)
649 {
650 if (targetHasAlpha)
651 {
652 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);
653 }
654 else
655 {
656 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);
657 }
658 }
659 else
660 {
661 if (targetHasAlpha)
662 {
663 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);
664 }
665 else
666 {
667 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);
668 }
669 }
670
671 return true;
672 }
673
674 case 3u:
675 {
676 if (alphaIsLastChannel)
677 {
678 if (targetHasAlpha)
679 {
680 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);
681 }
682 else
683 {
684 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);
685 }
686 }
687 else
688 {
689 if (targetHasAlpha)
690 {
691 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);
692 }
693 else
694 {
695 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);
696 }
697 }
698
699 return true;
700 }
701
702 case 4u:
703 {
704 if (alphaIsLastChannel)
705 {
706 if (targetHasAlpha)
707 {
708 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);
709 }
710 else
711 {
712 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);
713 }
714 }
715 else
716 {
717 if (targetHasAlpha)
718 {
719 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);
720 }
721 else
722 {
723 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);
724 }
725 }
726
727 return true;
728 }
729
730 default:
731 break;
732 }
733 }
734
735 ocean_assert(false && "Invalid pixel format!");
736 return false;
737}
738
739template <bool tTransparentIs0xFF>
740bool FrameBlender::blend(const Frame& source, Frame& target, const uint8_t alphaValue, Worker* worker)
741{
742 ocean_assert(source && target);
743
744 if (FrameType::areFrameTypesCompatible(source, target, false /*allowDifferentPixelOrigins*/)
745 && source.numberPlanes() == 1u
747 {
748 switch (source.channels())
749 {
750 case 1u:
751 blend8BitPerChannel<1u, 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 2u:
755 blend8BitPerChannel<2u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
756 return true;
757
758 case 3u:
759 blend8BitPerChannel<3u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
760 return true;
761
762 case 4u:
763 blend8BitPerChannel<4u, tTransparentIs0xFF>(source.constdata<uint8_t>(), target.data<uint8_t>(), alphaValue, source.width(), source.height(), source.paddingElements(), target.paddingElements(), worker);
764 return true;
765
766 default:
767 break;
768 }
769 }
770
771 ocean_assert(false && "Invalid frame type!");
772 return false;
773}
774
775template <unsigned int tChannels, bool tTransparentIs0xFF>
776inline 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)
777{
778 static_assert(tChannels >= 1u, "Invalid channel number!");
779
780 ocean_assert(source != nullptr && target != nullptr);
781
782 if (worker)
783 {
784 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, source, target, alphaValue, width, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 6u, 7u, 20u);
785 }
786 else
787 {
788 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(source, target, alphaValue, width, sourcePaddingElements, targetPaddingElements, 0u, height);
789 }
790}
791
792template <unsigned int tChannels, bool tTransparentIs0xFF>
793inline 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)
794{
795 static_assert(tChannels >= 1u, "Invalid channel number!");
796
797 ocean_assert(source != nullptr && alpha != nullptr && target != nullptr);
798
799 if (worker)
800 {
801 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, source, alpha, target, width, sourcePaddingElements, alphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
802 }
803 else
804 {
805 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(source, alpha, target, width, sourcePaddingElements, alphaPaddingElements, targetPaddingElements, 0u, height);
806 }
807}
808
809template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
810inline 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)
811{
812 static_assert(tChannelsWithAlpha > 1u, "Invalid channel number!");
813 ocean_assert(sourceWithAlpha && target);
814
815 if (worker)
816 {
817 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannelsWithAlpha, tAlphaAtFront, tTargetHasAlpha, tTransparentIs0xFF, tAlphaTargetModulation>, sourceWithAlpha, target, width, height, sourceWithAlphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 6u, 7u, 20u);
818 }
819 else
820 {
821 blend8BitPerChannelSubset<tChannelsWithAlpha, tAlphaAtFront, tTargetHasAlpha, tTransparentIs0xFF, tAlphaTargetModulation>(sourceWithAlpha, target, width, height, sourceWithAlphaPaddingElements, targetPaddingElements, 0u, height);
822 }
823}
824
825template <unsigned int tChannels, bool tTransparentIs0xFF>
826inline 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)
827{
828 static_assert(tChannels >= 1u, "Invalid channel number!");
829
830 ocean_assert(alpha != nullptr && target != nullptr && value != nullptr);
831
832 if (worker)
833 {
834 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, alpha, target, width, height, value, alphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
835 }
836 else
837 {
838 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(alpha, target, width, height, value, alphaPaddingElements, targetPaddingElements, 0u, height);
839 }
840}
841
842template <unsigned int tChannels, bool tTransparentIs0xFF>
843inline 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)
844{
845 static_assert(tChannels >= 1u, "Invalid channel number!");
846 ocean_assert(alpha && target && blendFunction);
847
848 if (worker)
849 {
850 worker->executeFunction(Worker::Function::createStatic(&blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>, alpha, target, width, height, blendFunction, alphaPaddingElements, targetPaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
851 }
852 else
853 {
854 blend8BitPerChannelSubset<tChannels, tTransparentIs0xFF>(alpha, target, width, height, blendFunction, alphaPaddingElements, targetPaddingElements, 0u, height);
855 }
856}
857
858template <unsigned int tChannels, bool tTransparentIs0xFF>
859inline 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)
860{
861 ocean_assert(source != nullptr && alpha != nullptr && target != nullptr);
862
863 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
864 const unsigned int alphaStrideElements = sourceWidth + alphaPaddingElements;
865 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
866
867 const uint8_t* const sourceTopLeft = source + sourceTop * sourceStrideElements + sourceLeft * tChannels;
868 const uint8_t* const alphaTopLeft = alpha + sourceTop * alphaStrideElements + sourceLeft;
869 uint8_t* const targetTopLeft = target + targetTop * targetStrideElements + targetLeft * tChannels;
870
871 ocean_assert_and_suppress_unused(width <= sourceWidth && height <= sourceHeight, sourceHeight);
872 ocean_assert_and_suppress_unused(width <= targetWidth && height <= targetHeight, targetHeight);
873
874 const unsigned int subSourcePaddingElements = (sourceWidth - width) * tChannels + sourcePaddingElements;
875 const unsigned int subAlphaPaddingElements = (sourceWidth - width) + alphaPaddingElements;
876 const unsigned int subTargetPaddingElements = (targetWidth - width) * tChannels + targetPaddingElements;
877
878 blend8BitPerChannel<tChannels, tTransparentIs0xFF>(sourceTopLeft, alphaTopLeft, targetTopLeft, width, height, subSourcePaddingElements, subAlphaPaddingElements, subTargetPaddingElements, worker);
879}
880
881template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
882inline 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)
883{
884 static_assert(tChannelsWithAlpha > 1u, "Invalid channel number!");
885
886 ocean_assert(sourceWithAlpha != nullptr && target != nullptr);
887
888 constexpr unsigned int tTargetChannels = TargetOffset<tTargetHasAlpha>::template channels<tChannelsWithAlpha>();
889
890 const unsigned int sourceStrideElements = sourceWidth * tChannelsWithAlpha + sourcePaddingElements;
891 const unsigned int targetStrideElements = targetWidth * tTargetChannels + targetPaddingElements;
892
893 const uint8_t* const sourceTopLeft = sourceWithAlpha + sourceTop * sourceStrideElements + sourceLeft * tChannelsWithAlpha;
894 uint8_t* const targetTopLeft = target + targetTop * targetStrideElements + targetLeft * tTargetChannels;
895
896 ocean_assert_and_suppress_unused(width <= sourceWidth && height <= sourceHeight, sourceHeight);
897 ocean_assert_and_suppress_unused(width <= targetWidth && height <= targetHeight, targetHeight);
898
899 const unsigned int subSourcePaddingElements = (sourceWidth - width) * tChannelsWithAlpha + sourcePaddingElements;
900 const unsigned int subTargetPaddingElements = (targetWidth - width) * tTargetChannels + targetPaddingElements;
901
902 blend8BitPerChannel<tChannelsWithAlpha, tAlphaAtFront, tTargetHasAlpha, tTransparentIs0xFF, tAlphaTargetModulation>(sourceTopLeft, targetTopLeft, width, height, subSourcePaddingElements, subTargetPaddingElements, worker);
903}
904
905template <bool tTransparentIs0xFF>
907{
908 return 0xFF;
909}
910
911template <>
912inline uint8_t FrameBlender::fullTransparent8Bit<false>()
913{
914 return 0x00;
915}
916
917template <bool tTransparentIs0xFF>
919{
920 return 0xFF - fullTransparent8Bit<tTransparentIs0xFF>();
921}
922
923template <bool tTransparentIs0xFF>
924inline uint8_t FrameBlender::alpha8BitToTransparentIs0xFF(const uint8_t alpha)
925{
926 return alpha;
927}
928
929template <>
930inline uint8_t FrameBlender::alpha8BitToTransparentIs0xFF<false>(const uint8_t alpha)
931{
932 return 0xFF - alpha;
933}
934
935template <bool tTransparentIs0xFF>
936inline uint8_t FrameBlender::alpha8BitToOpaqueIs0xFF(const uint8_t alpha)
937{
938 return 0xFF - alpha;
939}
940
941template <>
942inline uint8_t FrameBlender::alpha8BitToOpaqueIs0xFF<false>(const uint8_t alpha)
943{
944 return alpha;
945}
946
947template <unsigned int tChannels, bool tTransparentIs0xFF>
948void 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)
949{
950 static_assert(tChannels >= 1u, "Invalid channel number!");
951
952 ocean_assert(source != nullptr && target != nullptr);
953
954 const uint8_t sourceFactor = sourceBlendFactor<tTransparentIs0xFF>(alphaValue);
955 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(alphaValue);
956
957 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
958 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
959
960 source += firstRow * sourceStrideElements;
961 target += firstRow * targetStrideElements;
962
963 for (unsigned int r = 0u; r < numberRows; ++r)
964 {
965 for (unsigned int x = 0u; x < width; ++x)
966 {
967 for (unsigned int n = 0u; n < tChannels; ++n)
968 {
969 target[n] = Ocean::Utilities::divideBy255(target[n] * targetFactor + source[n] * sourceFactor + 127u);
970 }
971
972 source += tChannels;
973 target += tChannels;
974 }
975
976 source += sourcePaddingElements;
977 target += targetPaddingElements;
978 }
979}
980
981template <unsigned int tChannels, bool tTransparentIs0xFF>
982void 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)
983{
984 static_assert(tChannels >= 1u, "Invalid channel number!");
985
986 ocean_assert(source != nullptr && alpha != nullptr && target != nullptr);
987
988 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
989 const unsigned int alphaStrideElements = width + alphaPaddingElements;
990 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
991
992 source += firstRow * sourceStrideElements;
993 alpha += firstRow * alphaStrideElements;
994 target += firstRow * targetStrideElements;
995
996 for (unsigned int r = 0u; r < numberRows; ++r)
997 {
998 for (unsigned int x = 0u; x < width; ++x)
999 {
1000 const uint8_t sourceFactor = sourceBlendFactor<tTransparentIs0xFF>(alpha[0]);
1001 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(alpha[0]);
1002
1003 for (unsigned int n = 0u; n < tChannels; ++n)
1004 {
1005 target[n] = Ocean::Utilities::divideBy255(target[n] * targetFactor + source[n] * sourceFactor + 127u);
1006 }
1007
1008 source += tChannels;
1009 ++alpha;
1010 target += tChannels;
1011 }
1012
1013 source += sourcePaddingElements;
1014 alpha += alphaPaddingElements;
1015 target += targetPaddingElements;
1016 }
1017}
1018
1019template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
1020void 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)
1021{
1022 static_assert(tChannelsWithAlpha > 1u, "Invalid channel number!");
1023 ocean_assert(sourceWithAlpha != nullptr && target != nullptr);
1024
1025 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1026
1027 const unsigned int sourceWithAlphaStrideElements = width * tChannelsWithAlpha + sourceWithAlphaPaddingElements;
1028 const unsigned int targetStrideElements = width * TargetOffset<tTargetHasAlpha>::template channels<tChannelsWithAlpha>() + targetPaddingElements;
1029
1030 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1031 {
1032 const uint8_t* sourceWithAlphaData = sourceWithAlpha + y * sourceWithAlphaStrideElements;
1033 uint8_t* targetData = target + y * targetStrideElements;
1034
1035 for (unsigned int x = 0u; x < width; ++x)
1036 {
1037 const uint8_t sourceFactor = sourceBlendFactor<tTransparentIs0xFF>(sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]);
1038 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]);
1039
1040 for (unsigned int n = 0u; n < tChannelsWithAlpha - 1u; ++n)
1041 {
1042 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);
1043 }
1044
1045 if constexpr (tTargetHasAlpha && tAlphaTargetModulation == ATM_BLEND)
1046 {
1047 if constexpr (tTransparentIs0xFF)
1048 {
1049 targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] =
1050 Ocean::Utilities::divideBy255(targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] * sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]);
1051 }
1052 else
1053 {
1054 // alphaResult = alphaTarget + alphaSource * (1 - alphaTarget), while 0xFF is interpreted as fully opaque
1055 // alphaResult = (alphaTarget * 255 + alphaSource * (255 - alphaTarget)) / 255, while 0xFF is interpreted as fully opaque
1056
1057 targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] =
1058 Ocean::Utilities::divideBy255(255u * targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]
1059 + sourceWithAlphaData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()] * (255u - targetData[SourceOffset<tAlphaAtFront>::template alpha<tChannelsWithAlpha>()]));
1060 }
1061 }
1062
1063 sourceWithAlphaData += tChannelsWithAlpha;
1064 targetData += TargetOffset<tTargetHasAlpha>::template channels<tChannelsWithAlpha>();
1065 }
1066 }
1067}
1068
1069template <unsigned int tChannels, bool tTransparentIs0xFF>
1070void 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)
1071{
1072 static_assert(tChannels >= 1u, "Invalid channel number!");
1073
1074 ocean_assert(alpha != nullptr && target != nullptr && value != nullptr);
1075 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1076
1077 const unsigned int alphaStrideElements = width + alphaPaddingElements;
1078 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
1079
1080 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1081 {
1082 const uint8_t* alphaRow = alpha + y * alphaStrideElements;
1083 uint8_t* targetRow = target + y * targetStrideElements;
1084
1085 for (unsigned int x = 0u; x < width; ++x)
1086 {
1087 const uint8_t valueFactor = sourceBlendFactor<tTransparentIs0xFF>(*alphaRow);
1088 const uint8_t targetFactor = targetBlendFactor<tTransparentIs0xFF>(*alphaRow);
1089
1090 for (unsigned int n = 0u; n < tChannels; ++n)
1091 {
1092 targetRow[n] = Ocean::Utilities::divideBy255(targetRow[n] * targetFactor + value[n] * valueFactor + 127u);
1093 }
1094
1095 ++alphaRow;
1096 targetRow += tChannels;
1097 }
1098 }
1099}
1100
1101template <unsigned int tChannels, bool tTransparentIs0xFF>
1102void 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)
1103{
1104 static_assert(tChannels >= 1u, "Invalid channel number!");
1105
1106 ocean_assert(alpha != nullptr && target != nullptr && blendFunction != nullptr);
1107 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1108
1109 const unsigned int alphaStrideElements = width + alphaPaddingElements;
1110 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
1111
1112 alpha += firstRow * alphaStrideElements;
1113 target += firstRow * targetStrideElements;
1114
1115 for (unsigned int n = 0u; n < numberRows; ++n)
1116 {
1117 for (unsigned int x = 0u; x < width; ++x)
1118 {
1119 blendFunction(target, targetBlendFactor<tTransparentIs0xFF>(*alpha));
1120
1121 ++alpha;
1122 target += tChannels;
1123 }
1124
1125 alpha += alphaPaddingElements;
1126 target += targetPaddingElements;
1127 }
1128}
1129
1130template <bool tTransparentIs0xFF>
1131inline uint8_t FrameBlender::sourceBlendFactor(const uint8_t alpha)
1132{
1133 return 0xFFu - alpha;
1134}
1135
1136template <>
1137inline uint8_t FrameBlender::sourceBlendFactor<false>(const uint8_t alpha)
1138{
1139 return alpha;
1140}
1141
1142template <bool tTransparentIs0xFF>
1143inline uint8_t FrameBlender::targetBlendFactor(const uint8_t alpha)
1144{
1145 return alpha;
1146}
1147
1148template <>
1149inline uint8_t FrameBlender::targetBlendFactor<false>(const uint8_t alpha)
1150{
1151 return 0xFFu - alpha;
1152}
1153
1154template <bool tAlphaAtFront>
1155template <unsigned int tChannelsWithAlpha>
1157{
1158 return 0u;
1159}
1160
1161template <>
1162template <unsigned int tChannelsWithAlpha>
1163constexpr inline unsigned int FrameBlender::SourceOffset<false>::alpha()
1164{
1165 static_assert(tChannelsWithAlpha >= 1u, "Invalid channel number!");
1166
1167 return tChannelsWithAlpha - 1u;
1168}
1169
1170template <bool tAlphaAtFront>
1172{
1173 return 1u;
1174}
1175
1176template <>
1177constexpr inline unsigned int FrameBlender::SourceOffset<false>::data()
1178{
1179 return 0u;
1180}
1181
1182template <bool tAlphaAtFront>
1183template <bool tSourceHasAlpha>
1184constexpr inline unsigned int FrameBlender::SourceOffset<tAlphaAtFront>::data()
1185{
1186 return tSourceHasAlpha ? 1u : 0u;
1187}
1188
1189template <>
1190template <>
1192{
1193 return 0u;
1194}
1195
1196template <>
1197template <>
1199{
1200 return 0u;
1201}
1202
1203template <bool tTargetHasAlpha>
1204template <unsigned int tChannelsWithAlpha>
1206{
1207 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1208
1209 return tChannelsWithAlpha;
1210}
1211
1212template <>
1213template <unsigned int tChannelsWithAlpha>
1214constexpr inline unsigned int FrameBlender::TargetOffset<false>::channels()
1215{
1216 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel number!");
1217
1218 return tChannelsWithAlpha - 1u;
1219}
1220
1221template <bool tTargetHasAlpha>
1222template <bool tAlphaAtFront>
1224{
1225 return 0u;
1226}
1227
1228template <>
1229template <>
1231{
1232 return 1u;
1233}
1234
1235template <bool tHasAlpha>
1236template <unsigned int tChannels>
1238{
1239 static_assert(tChannels >= 2u, "Invalid channel input!");
1240
1241 // we have a frame with alpha channel
1242 return tChannels - 1u;
1243}
1244
1245template <>
1246template <unsigned int tChannels>
1248{
1249 static_assert(tChannels >= 1u, "Invalid channel input!");
1250
1251 // we have a frame without alpha channel
1252 return tChannels;
1253}
1254
1255template <bool tHasAlpha>
1256template <unsigned int tChannelsWithAlpha>
1258{
1259 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1260
1261 // we have a frame with alpha channel
1262 return tChannelsWithAlpha;
1263}
1264
1265template <>
1266template <unsigned int tChannelsWithAlpha>
1268{
1269 static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1270
1271 // we have a frame without alpha channel
1272 return tChannelsWithAlpha - 1u;
1273}
1274
1275}
1276
1277}
1278
1279#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:1257
static constexpr unsigned int dataChannels()
Returns the number of channels of a frame not counting the possible alpha channel.
Definition FrameBlender.h:1237
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:1156
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:1171
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:1205
static constexpr unsigned int data()
Returns the offset that is applied to access the first data channel.
Definition FrameBlender.h:1223
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:924
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:776
static uint8_t fullTransparent8Bit()
Returns the alpha value for a fully transparent pixel.
Definition FrameBlender.h:906
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:740
static uint8_t alpha8BitToOpaqueIs0xFF(const uint8_t alpha)
Converts a given alpha value so that 0xFF is interpreted as fully opaque.
Definition FrameBlender.h:936
static uint8_t fullOpaque8Bit()
Returns the alpha value for a fully opaque pixel.
Definition FrameBlender.h:918
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:948
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:1131
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:1143
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:2877
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:4251
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition Frame.h:4242
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4531
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:4125
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:878
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