Ocean
Loading...
Searching...
No Matches
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"
13
14#include "ocean/base/Frame.h"
16#include "ocean/base/Worker.h"
17
18namespace Ocean
19{
20
21namespace 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
108template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
109void 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
129template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
130void 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 {
175 target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
176 + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
177 + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
178 + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) + denominator_2) / denominator);
179 }
180
181 // alpha channel
182 target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] = uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
183 + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
184 + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
185 + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 2u) / 4u);
186 }
187 else
188 {
189 for (unsigned int n = 0u; n < tChannels; ++n)
190 {
191 target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n] + sourceSecond[n] + sourceSecond[tChannels + n] + 2u) / 4u);
192 }
193 }
194
195 target += tChannels;
196 sourceFirst += tChannels * 2u;
197 sourceSecond += tChannels * 2u;
198 }
199
200 if (!xEven)
201 {
202 // three pixels left
203
204 // source0: | 1 2 1 |
205 // source1: | 1 2 1 | / 8
206
207 const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
208 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
209 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
210 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
211 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
212 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]);
213
214 if (denominator != 0u)
215 {
216 const unsigned int denominator_2 = denominator / 2u;
217
218 // data channel
219 for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
220 {
221 target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
222 + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
223 + sourceFirst[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
224 + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
225 + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
226 + sourceSecond[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) + denominator_2) / denominator);
227 }
228
229 // alpha channel
230 target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] =
231 uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
232 + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
233 + sourceFirst[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
234 + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
235 + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
236 + sourceSecond[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 4u) / 8u);
237 }
238 else
239 {
240 for (unsigned int n = 0u; n < tChannels; ++n)
241 {
242 target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n] * 2u + sourceFirst[tChannels * 2u + n]
243 + sourceSecond[n] + sourceSecond[tChannels + n] * 2u + sourceSecond[tChannels * 2u + n] + 4u) / 8u);
244 }
245 }
246
247 target += tChannels;
248 sourceFirst += tChannels * 3u;
249 sourceSecond += tChannels * 3u;
250 }
251
252 target += targetPaddingElements;
253 sourceFirst += sourcePaddingElements + sourceStrideElements;
254 sourceSecond += sourcePaddingElements + sourceStrideElements;
255 }
256
257 if (threeBottomRows)
258 {
259 const uint8_t* sourceThird = sourceSecond + sourceStrideElements;
260
261 for (unsigned int x = 0u; x < numberTwoTargetColumns; ++x)
262 {
263 // source0: | 1 1 |
264 // source1: | 2 2 | / 8
265 // source2: | 1 1 |
266
267 const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
268 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
269 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
270 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
271 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
272 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]);
273
274 if (denominator != 0u)
275 {
276 const unsigned int denominator_2 = denominator / 2u;
277
278 // data channel
279 for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
280 {
281 target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
282 + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels])
283 + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
284 + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
285 + sourceThird[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
286 + sourceThird[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) + denominator_2) / denominator);
287 }
288
289 // alpha channel
290 target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] =
291 uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
292 + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
293 + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
294 + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
295 + sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
296 + sourceThird[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 4u) / 8u);
297 }
298 else
299 {
300 for (unsigned int n = 0u; n < tChannels; ++n)
301 {
302 target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n]
303 + sourceSecond[n] * 2u + sourceSecond[tChannels + n] * 2u
304 + sourceThird[n] + sourceThird[tChannels + n] + 4u) / 8u);
305 }
306 }
307
308 target += tChannels;
309 sourceFirst += tChannels * 2u;
310 sourceSecond += tChannels * 2u;
311 sourceThird += tChannels * 2u;
312 }
313
314 if (!xEven)
315 {
316 // three pixels left
317
318 // source0: | 1 2 1 |
319 // source1: | 2 4 2 | / 16
320 // source2: | 1 2 1 |
321
322
323 const unsigned int denominator = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
324 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
325 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
326 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
327 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 4u
328 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) * 2u
329 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
330 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
331 + FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]);
332
333 if (denominator != 0u)
334 {
335 const unsigned int denominator_2 = denominator / 2u;
336
337 // data channel
338 for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
339 {
340 target[n] = uint8_t((sourceFirst[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
341 + sourceFirst[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
342 + sourceFirst[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u])
343 + sourceSecond[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]) * 2u
344 + sourceSecond[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 4u
345 + sourceSecond[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) * 2u
346 + sourceThird[n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()])
347 + sourceThird[tChannels + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels]) * 2u
348 + sourceThird[tChannels * 2u + n] * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>() + tChannels * 2u]) + denominator_2) / denominator);
349 }
350
351 // alpha channel
352 target[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] =
353 uint8_t((sourceFirst[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
354 + sourceFirst[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
355 + sourceFirst[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
356 + sourceSecond[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
357 + sourceSecond[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 4u
358 + sourceSecond[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
359 + sourceThird[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()]
360 + sourceThird[tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] * 2u
361 + sourceThird[tChannels * 2u + FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] + 8u) / 16u);
362 }
363 else
364 {
365 for (unsigned int n = 0u; n < tChannels; ++n)
366 {
367 target[n] = uint8_t((sourceFirst[n] + sourceFirst[tChannels + n] * 2u + sourceFirst[tChannels * 2u + n]
368 + sourceSecond[n] * 2u + sourceSecond[tChannels + n] * 4u + sourceSecond[tChannels * 2u + n] * 2u
369 + sourceThird[n] + sourceThird[tChannels + n] * 2u + sourceThird[tChannels * 2u + n] + 4u) / 8u);
370 }
371 }
372 }
373 }
374}
375
376}
377
378}
379
380#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:2877
This class implements Ocean's image class.
Definition Frame.h:1808
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