Ocean
FrameShrinkerAlpha.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_SHRINKER_ALPHA_H
9 #define META_OCEAN_CV_FRAME_SHRINKER_ALPHA_H
10 
11 #include "ocean/cv/CV.h"
12 #include "ocean/cv/FrameBlender.h"
13 
14 #include "ocean/base/Frame.h"
15 #include "ocean/base/Messenger.h"
16 #include "ocean/base/Worker.h"
17 
18 namespace Ocean
19 {
20 
21 namespace CV
22 {
23 
24 /**
25  * This class implements functions downsizing frames that hold alpha channels.
26  * @ingroup cv
27  */
29 {
30  public:
31 
32  /**
33  * The following comfort class provides comfortable functions simplifying prototyping applications but also increasing binary size of the resulting applications.
34  * Best practice is to avoid using these functions if binary size matters,<br>
35  * as for every comfort function a corresponding function exists with specialized functionality not increasing binary size significantly.<br>
36  */
37  class OCEAN_CV_EXPORT Comfort
38  {
39  public:
40 
41  /**
42  * Divides a given frame by two, taking four pixel values into account:<br>
43  * | 1 1 |<br>
44  * | 1 1 |<br>
45  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
46  * If the type of the target frame does not match to the input frame the target frame (and image buffer) will be replaced by a correct one.
47  * @param source The source frame to resize
48  * @param target The target frame receiving the smaller frame data
49  * @param worker Optional worker object to distribute the computational load to several CPU cores
50  * @return True, if succeeded
51  */
52  template <bool tTransparentIs0xFF>
53  static bool divideByTwo(const Frame& source, Frame& target, Worker* worker = nullptr);
54 
55  /**
56  * Divides a given frame by two, taking four pixel values into account:<br>
57  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
58  * @param frame The frame to resize
59  * @param worker Optional worker object to distribute the computational load to several CPU cores
60  * @return True, if succeeded
61  */
62  template <bool tTransparentIs0xFF>
63  static bool divideByTwo(Frame& frame, Worker* worker = nullptr);
64  };
65 
66  public:
67 
68  /**
69  * Divides a given 8 bit per channel frame by two, taking four pixel values into account:<br>
70  * | 1 1 |<br>
71  * | 1 1 |<br>
72  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
73  * @param source The source frame buffer to resize
74  * @param target The target frame buffer
75  * @param sourceWidth Width of the source frame in pixel, with range [2, infinity)
76  * @param sourceHeight Height of the source frame in pixel, with range [2, infinity)
77  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
78  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
79  * @param worker Optional worker object to distribute the computational load to several CPU cores
80  * @tparam tChannels Number of channels of the frame (including the alpha channel), with range [1, infinity)
81  * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
82  * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
83  */
84  template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
85  static void divideByTwo8BitPerChannel(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
86 
87  private:
88 
89  /**
90  * Divides a subset of a given 8 bit per channel frame by two, taking the average of four pixel values.
91  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
92  * @param source The source frame buffer to resize
93  * @param target The target frame buffer
94  * @param sourceWidth Width of the source frame in pixel, with range [2, infinity)
95  * @param sourceHeight Height of the source frame in pixel, with range [2, infinity)
96  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
97  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
98  * @param firstTargetRow First (including) row to halve
99  * @param numberTargetRows Number of rows to halve
100  * @tparam tChannels Number of channels of the frame (including the alpha channel), with range [1, infinity)
101  * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
102  * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
103  */
104  template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
105  static void divideByTwo8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
106 };
107 
108 template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
109 void FrameShrinkerAlpha::divideByTwo8BitPerChannel(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
110 {
111  static_assert(tChannels >= 1u, "Invalid channel number!");
112 
113  ocean_assert(source != nullptr && target != nullptr);
114  ocean_assert(sourceWidth >= 2u && sourceHeight >= 2u);
115 
116  const unsigned int targetHeight = sourceHeight / 2u;
117  ocean_assert(targetHeight > 0u);
118 
119  if (worker)
120  {
121  worker->executeFunction(Worker::Function::createStatic(&divideByTwo8BitPerChannelSubset<tChannels, tAlphaAtFront, tTransparentIs0xFF>, source, target, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, targetHeight, 6u, 7u, 20u);
122  }
123  else
124  {
125  divideByTwo8BitPerChannelSubset<tChannels, tAlphaAtFront, tTransparentIs0xFF>(source, target, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
126  }
127 }
128 
129 template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
130 void FrameShrinkerAlpha::divideByTwo8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
131 {
132  static_assert(tChannels >= 1u, "Invalid channel number!");
133 
134  ocean_assert(source != nullptr && target != nullptr);
135  ocean_assert(sourceWidth >= 2u && sourceHeight >= 2u);
136  ocean_assert(firstTargetRow + numberTargetRows <= sourceHeight / 2u);
137 
138  const unsigned int targetWidth = sourceWidth / 2u;
139 
140  const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
141  const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
142 
143  const bool xEven = sourceWidth % 2u == 0u;
144  const bool yEven = sourceHeight % 2u == 0u;
145 
146  const uint8_t* sourceFirst = source + firstTargetRow * 2u * sourceStrideElements;
147  const uint8_t* sourceSecond = sourceFirst + sourceStrideElements;
148 
149  target += firstTargetRow * targetStrideElements;
150 
151  const bool threeBottomRows = !yEven && firstTargetRow + numberTargetRows == sourceHeight / 2u;
152 
153  const unsigned int numberTwoTargetRows = threeBottomRows ? (unsigned int)(max(int(numberTargetRows) - 1, 0)) : numberTargetRows;
154  const unsigned int numberTwoTargetColumns = xEven ? targetWidth : (unsigned int)(max(int(targetWidth) - 1, 0));
155 
156  for (unsigned int y = 0u; y < numberTwoTargetRows; ++y)
157  {
158  for (unsigned int x = 0u; x < numberTwoTargetColumns; ++x)
159  {
160  // source0: | 1 1 |
161  // source1: | 1 1 | / 4
162 
163  const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
164  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
165  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
166  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]);
167 
168  if (denominator != 0u)
169  {
170  const unsigned int denominator_2 = denominator / 2u;
171 
172  // data channel
173  for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
174  target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
175  + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
176  + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
177  + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) + denominator_2) / denominator);
178 
179  // alpha channel
180  target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] = uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
181  + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
182  + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
183  + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 2u) / 4u);
184  }
185  else
186  {
187  for (unsigned int n = 0u; n < tChannels; ++n)
188  {
189  target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n] + sourceSecond[n] + sourceSecond[tChannels + n] + 2u) / 4u);
190  }
191  }
192 
193  target += tChannels;
194  sourceFirst += tChannels * 2u;
195  sourceSecond += tChannels * 2u;
196  }
197 
198  if (!xEven)
199  {
200  // three pixels left
201 
202  // source0: | 1 2 1 |
203  // source1: | 1 2 1 | / 8
204 
205  const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
206  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
207  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
208  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
209  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
210  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]);
211 
212  if (denominator != 0u)
213  {
214  const unsigned int denominator_2 = denominator / 2u;
215 
216  // data channel
217  for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
218  target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
219  + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
220  + sourceFirst[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
221  + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
222  + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
223  + sourceSecond[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) + denominator_2) / denominator);
224 
225  // alpha channel
226  target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] =
227  uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
228  + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
229  + sourceFirst[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
230  + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
231  + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
232  + sourceSecond[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 4u) / 8u);
233  }
234  else
235  {
236  for (unsigned int n = 0u; n < tChannels; ++n)
237  {
238  target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n] * 2u + sourceFirst[tChannels * 2u + n]
239  + sourceSecond[n] + sourceSecond[tChannels + n] * 2u + sourceSecond[tChannels * 2u + n] + 4u) / 8u);
240  }
241  }
242 
243  target += tChannels;
244  sourceFirst += tChannels * 3u;
245  sourceSecond += tChannels * 3u;
246  }
247 
248  target += targetPaddingElements;
249  sourceFirst += sourcePaddingElements + sourceStrideElements;
250  sourceSecond += sourcePaddingElements + sourceStrideElements;
251  }
252 
253  if (threeBottomRows)
254  {
255  const uint8_t* sourceThird = sourceSecond + sourceStrideElements;
256 
257  for (unsigned int x = 0u; x < numberTwoTargetColumns; ++x)
258  {
259  // source0: | 1 1 |
260  // source1: | 2 2 | / 8
261  // source2: | 1 1 |
262 
263  const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
264  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
265  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
266  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
267  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
268  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]);
269 
270  if (denominator != 0u)
271  {
272  const unsigned int denominator_2 = denominator / 2u;
273 
274  // data channel
275  for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
276  target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
277  + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
278  + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
279  + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
280  + sourceThird[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
281  + sourceThird[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) + denominator_2) / denominator);
282 
283  // alpha channel
284  target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] =
285  uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
286  + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
287  + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
288  + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
289  + sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
290  + sourceThird[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 4u) / 8u);
291  }
292  else
293  {
294  for (unsigned int n = 0u; n < tChannels; ++n)
295  {
296  target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n]
297  + sourceSecond[n] * 2u + sourceSecond[tChannels + n] * 2u
298  + sourceThird[n] + sourceThird[tChannels + n] + 4u) / 8u);
299  }
300  }
301 
302  target += tChannels;
303  sourceFirst += tChannels * 2u;
304  sourceSecond += tChannels * 2u;
305  sourceThird += tChannels * 2u;
306  }
307 
308  if (!xEven)
309  {
310  // three pixels left
311 
312  // source0: | 1 2 1 |
313  // source1: | 2 4 2 | / 16
314  // source2: | 1 2 1 |
315 
316 
317  const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
318  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
319  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
320  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
321  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 4u
322  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) * 2u
323  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
324  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
325  + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]);
326 
327  if (denominator != 0u)
328  {
329  const unsigned int denominator_2 = denominator / 2u;
330 
331  // data channel
332  for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
333  target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
334  + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
335  + sourceFirst[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
336  + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
337  + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 4u
338  + sourceSecond[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) * 2u
339  + sourceThird[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
340  + sourceThird[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
341  + sourceThird[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) + denominator_2) / denominator);
342 
343  // alpha channel
344  target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] =
345  uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
346  + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
347  + sourceFirst[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
348  + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
349  + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 4u
350  + sourceSecond[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
351  + sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
352  + sourceThird[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
353  + sourceThird[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 8u) / 16u);
354  }
355  else
356  {
357  for (unsigned int n = 0u; n < tChannels; ++n)
358  target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n] * 2u + sourceFirst[tChannels * 2u + n]
359  + sourceSecond[n] * 2u + sourceSecond[tChannels + n] * 4u + sourceSecond[tChannels * 2u + n] * 2u
360  + sourceThird[n] + sourceThird[tChannels + n] * 2u + sourceThird[tChannels * 2u + n] + 4u) / 8u);
361  }
362  }
363  }
364 }
365 
366 }
367 
368 }
369 
370 #endif // META_OCEAN_CV_FRAME_SHRINKER_ALPHA_H
Helper class allowing to determine the offset that is necessary to access the alpha channel.
Definition: FrameBlender.h:60
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition: FrameShrinkerAlpha.h:38
static bool divideByTwo(Frame &frame, Worker *worker=nullptr)
Divides a given frame by two, taking four pixel values into account: If the given source image has a...
static bool divideByTwo(const Frame &source, Frame &target, Worker *worker=nullptr)
Divides a given frame by two, taking four pixel values into account: | 1 1 | | 1 1 | If the given ...
This class implements functions downsizing frames that hold alpha channels.
Definition: FrameShrinkerAlpha.h:29
static void divideByTwo8BitPerChannelSubset(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Divides a subset of a given 8 bit per channel frame by two, taking the average of four pixel values.
Definition: FrameShrinkerAlpha.h:130
static void divideByTwo8BitPerChannel(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Divides a given 8 bit per channel frame by two, taking four pixel values into account: | 1 1 | | 1 ...
Definition: FrameShrinkerAlpha.h:109
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:1792
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