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 // 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: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