Ocean
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"
16 #include "ocean/base/Utilities.h"
17 #include "ocean/base/Worker.h"
18 
19 namespace Ocean
20 {
21 
22 namespace CV
23 {
24 
25 /**
26  * This class implements a frame blender using an alpha channel to blend frames.
27  * @ingroup cv
28  */
29 class 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 
492 template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
493 bool 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 
604 template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
605 bool 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 
617 template <bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
618 bool 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 
731 template <bool tTransparentIs0xFF>
732 bool 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 
764 template <unsigned int tChannels, bool tTransparentIs0xFF>
765 inline 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 
781 template <unsigned int tChannels, bool tTransparentIs0xFF>
782 inline 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 
798 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
799 inline 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 
814 template <unsigned int tChannels, bool tTransparentIs0xFF>
815 inline 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 
831 template <unsigned int tChannels, bool tTransparentIs0xFF>
832 inline 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 
847 template <unsigned int tChannels, bool tTransparentIs0xFF>
848 inline 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 
870 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
871 inline 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 
894 template <bool tTransparentIs0xFF>
896 {
897  return 0xFF;
898 }
899 
900 template <>
901 inline uint8_t FrameBlender::fullTransparent8Bit<false>()
902 {
903  return 0x00;
904 }
905 
906 template <bool tTransparentIs0xFF>
908 {
909  return 0xFF - fullTransparent8Bit<tTransparentIs0xFF>();
910 }
911 
912 template <bool tTransparentIs0xFF>
913 inline uint8_t FrameBlender::alpha8BitToTransparentIs0xFF(const uint8_t alpha)
914 {
915  return alpha;
916 }
917 
918 template <>
919 inline uint8_t FrameBlender::alpha8BitToTransparentIs0xFF<false>(const uint8_t alpha)
920 {
921  return 0xFF - alpha;
922 }
923 
924 template <bool tTransparentIs0xFF>
925 inline uint8_t FrameBlender::alpha8BitToOpaqueIs0xFF(const uint8_t alpha)
926 {
927  return 0xFF - alpha;
928 }
929 
930 template <>
931 inline uint8_t FrameBlender::alpha8BitToOpaqueIs0xFF<false>(const uint8_t alpha)
932 {
933  return alpha;
934 }
935 
936 template <unsigned int tChannels, bool tTransparentIs0xFF>
937 void 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 
970 template <unsigned int tChannels, bool tTransparentIs0xFF>
971 void 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 
1008 template <unsigned int tChannelsWithAlpha, bool tAlphaAtFront, bool tTargetHasAlpha, bool tTransparentIs0xFF, FrameBlender::AlphaTargetModulation tAlphaTargetModulation>
1009 void 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 
1058 template <unsigned int tChannels, bool tTransparentIs0xFF>
1059 void 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 
1090 template <unsigned int tChannels, bool tTransparentIs0xFF>
1091 void 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 
1119 template <bool tTransparentIs0xFF>
1120 inline uint8_t FrameBlender::sourceBlendFactor(const uint8_t alpha)
1121 {
1122  return 0xFFu - alpha;
1123 }
1124 
1125 template <>
1126 inline uint8_t FrameBlender::sourceBlendFactor<false>(const uint8_t alpha)
1127 {
1128  return alpha;
1129 }
1130 
1131 template <bool tTransparentIs0xFF>
1132 inline uint8_t FrameBlender::targetBlendFactor(const uint8_t alpha)
1133 {
1134  return alpha;
1135 }
1136 
1137 template <>
1138 inline uint8_t FrameBlender::targetBlendFactor<false>(const uint8_t alpha)
1139 {
1140  return 0xFFu - alpha;
1141 }
1142 
1143 template <bool tAlphaAtFront>
1144 template <unsigned int tChannelsWithAlpha>
1146 {
1147  return 0u;
1148 }
1149 
1150 template <>
1151 template <unsigned int tChannelsWithAlpha>
1152 constexpr inline unsigned int FrameBlender::SourceOffset<false>::alpha()
1153 {
1154  static_assert(tChannelsWithAlpha >= 1u, "Invalid channel number!");
1155 
1156  return tChannelsWithAlpha - 1u;
1157 }
1158 
1159 template <bool tAlphaAtFront>
1161 {
1162  return 1u;
1163 }
1164 
1165 template <>
1166 constexpr inline unsigned int FrameBlender::SourceOffset<false>::data()
1167 {
1168  return 0u;
1169 }
1170 
1171 template <bool tAlphaAtFront>
1172 template <bool tSourceHasAlpha>
1173 constexpr inline unsigned int FrameBlender::SourceOffset<tAlphaAtFront>::data()
1174 {
1175  return tSourceHasAlpha ? 1u : 0u;
1176 }
1177 
1178 template <>
1179 template <>
1180 constexpr inline unsigned int FrameBlender::SourceOffset<false>::data<true>()
1181 {
1182  return 0u;
1183 }
1184 
1185 template <>
1186 template <>
1187 constexpr inline unsigned int FrameBlender::SourceOffset<false>::data<false>()
1188 {
1189  return 0u;
1190 }
1191 
1192 template <bool tTargetHasAlpha>
1193 template <unsigned int tChannelsWithAlpha>
1195 {
1196  static_assert(tChannelsWithAlpha >= 2u, "Invalid channel input!");
1197 
1198  return tChannelsWithAlpha;
1199 }
1200 
1201 template <>
1202 template <unsigned int tChannelsWithAlpha>
1203 constexpr inline unsigned int FrameBlender::TargetOffset<false>::channels()
1204 {
1205  static_assert(tChannelsWithAlpha >= 2u, "Invalid channel number!");
1206 
1207  return tChannelsWithAlpha - 1u;
1208 }
1209 
1210 template <bool tTargetHasAlpha>
1211 template <bool tAlphaAtFront>
1213 {
1214  return 0u;
1215 }
1216 
1217 template <>
1218 template <>
1219 constexpr inline unsigned int FrameBlender::TargetOffset<true>::data<true>()
1220 {
1221  return 1u;
1222 }
1223 
1224 template <bool tHasAlpha>
1225 template <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 
1234 template <>
1235 template <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 
1244 template <bool tHasAlpha>
1245 template <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 
1254 template <>
1255 template <unsigned int tChannelsWithAlpha>
1256 constexpr inline unsigned int FrameBlender::FrameChannels<false>::channels()
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:1760
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:4136
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition: Frame.h:4127
bool isValid() const
Returns whether this frame is valid.
Definition: Frame.h:4416
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:4010
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:3111
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition: Frame.h:3156
uint32_t numberPlanes() const
Returns the number of planes of the pixel format of this frame.
Definition: Frame.h:3151
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:3121
@ 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:3116
unsigned int channels() const
Returns the number of individual channels the frame has.
Definition: Frame.h:3141
DataType dataType() const
Returns the data type of the pixel format of this frame.
Definition: Frame.h:3131
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