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