8 #ifndef META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_ALPHA_H
9 #define META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_ALPHA_H
32 template <
bool tAlphaAtFront,
bool tTransparentIs0xFF>
60 template <
typename TScalar = Scalar>
79 template <
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar>
95 template <
unsigned int tChannels>
105 template <
unsigned int tChannelsWithAlpha>
115 template <
bool tAlphaAtFront,
bool tTransparentIs0xFF>
116 template <
typename TScalar>
119 ocean_assert(frame !=
nullptr);
120 ocean_assert(channels >= 1u && channels <= 8u);
199 ocean_assert(
false &&
"Invalid channel number");
203 template <
bool tAlphaAtFront,
bool tTransparentIs0xFF>
204 template <
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar>
207 static_assert(tChannels != 0u,
"Invalid channel number!");
209 ocean_assert(frame !=
nullptr && result !=
nullptr);
210 ocean_assert(width > 0u && height > 0u);
212 ocean_assert(position.
x() >= TScalar(0));
213 ocean_assert(position.
y() >= TScalar(0));
217 ocean_assert(position.
x() <= TScalar(width - 1u));
218 ocean_assert(position.
y() <= TScalar(height - 1u));
224 ocean_assert(position.
x() <= TScalar(width));
225 ocean_assert(position.
y() <= TScalar(height));
228 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
230 const TScalar xShifted = tPixelCenter ==
PC_TOP_LEFT ? position.
x() : std::max(TScalar(0.0), position.
x() - TScalar(0.5));
231 const TScalar yShifted = tPixelCenter ==
PC_TOP_LEFT ? position.
y() : std::max(TScalar(0.0), position.
y() - TScalar(0.5));
233 const unsigned int left = (
unsigned int)(xShifted);
234 const unsigned int top = (
unsigned int)(yShifted);
236 ocean_assert(left < width);
237 ocean_assert(top < height);
239 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
240 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
242 const uint8_t* topLeft = frame + top * frameStrideElements + left * tChannels;
244 const TScalar sFactorRight = xShifted - TScalar(left);
245 const TScalar sFactorBottom = yShifted - TScalar(top);
247 const unsigned int factorRight = (
unsigned int)(sFactorRight * TScalar(128) + TScalar(0.5));
248 const unsigned int factorBottom = (
unsigned int)(sFactorBottom * TScalar(128) + TScalar(0.5));
250 const unsigned int factorLeft = 128u - factorRight;
251 const unsigned int factorTop = 128u - factorBottom;
253 const unsigned int factorTopLeft = factorTop * factorLeft;
254 const unsigned int factorTopRight = factorTop * factorRight;
255 const unsigned int factorBottomLeft = factorBottom * factorLeft;
256 const unsigned int factorBottomRight = factorBottom * factorRight;
258 const unsigned int factorTopLeftAlpha = factorTopLeft * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[alphaOffset<tChannels>()]);
259 const unsigned int factorTopRightAlpha = factorTopRight * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[rightOffset + alphaOffset<tChannels>()]);
260 const unsigned int factorBottomLeftAlpha = factorBottomLeft * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[bottomOffset + alphaOffset<tChannels>()]);
261 const unsigned int factorBottomRightAlpha = factorBottomRight * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[bottomOffset + rightOffset + alphaOffset<tChannels>()]);
263 const unsigned int sumFactorsAlpha = factorTopLeftAlpha + factorTopRightAlpha + factorBottomLeftAlpha + factorBottomRightAlpha;
265 const uint8_t*
const pixelTopLeft = topLeft;
266 const uint8_t*
const pixelTopRight = topLeft + rightOffset;
267 const uint8_t*
const pixelBottomLeft = topLeft + bottomOffset;
268 const uint8_t*
const pixelBottomRight = topLeft + bottomOffset + rightOffset;
271 if (sumFactorsAlpha != 0u)
273 const unsigned int sumFactorsAlpha_2 = sumFactorsAlpha / 2u;
277 result[n] = uint8_t((pixelTopLeft[n] * factorTopLeftAlpha + pixelTopRight[n] * factorTopRightAlpha + pixelBottomLeft[n] * factorBottomLeftAlpha + pixelBottomRight[n] * factorBottomRightAlpha + sumFactorsAlpha_2) / sumFactorsAlpha);
284 result[n] = uint8_t((pixelTopLeft[n] * factorTopLeft + pixelTopRight[n] * factorTopRight + pixelBottomLeft[n] * factorBottomLeft + pixelBottomRight[n] * factorBottomRight + 8192u) / 16384u);
289 if constexpr (tTransparentIs0xFF)
291 result[alphaOffset<tChannels>()] = uint8_t((factorTopLeft * pixelTopLeft[alphaOffset<tChannels>()]
292 + factorTopRight * pixelTopRight[alphaOffset<tChannels>()]
293 + factorBottomLeft * pixelBottomLeft[alphaOffset<tChannels>()]
294 + factorBottomRight * pixelBottomRight[alphaOffset<tChannels>()] + 8192u) / 16384u);
298 result[alphaOffset<tChannels>()] = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(uint8_t((sumFactorsAlpha + 8192u) / 16384u));
302 template <
bool tAlphaAtFront,
bool tTransparentIs0xFF>
303 template <
unsigned int tChannels>
306 static_assert(tChannels != 0u,
"Invalid channel number!");
308 ocean_assert(frame && result);
315 for (
unsigned int n = 0u; n < tChannels - 1u; ++n)
324 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
329 ocean_assert(left >= -1 && left <
int(width));
330 ocean_assert(top >= -1 && top <
int(height));
332 if ((
unsigned int)left < width - 1u && (
unsigned int)top < height - 1u)
336 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
337 const unsigned int txi_ = 128u - txi;
339 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
340 const unsigned int tyi_ = 128u - tyi;
342 const uint8_t* topLeft = frame + top * frameStrideElements + left * tChannels;
344 const unsigned int txty = txi * tyi * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[frameStrideElements + tChannels + alphaOffset<tChannels>()]);
345 const unsigned int txty_ = txi * tyi_ * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[tChannels + alphaOffset<tChannels>()]);
346 const unsigned int tx_ty = txi_ * tyi * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[frameStrideElements + alphaOffset<tChannels>()]);
347 const unsigned int tx_ty_ = txi_ * tyi_ * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(topLeft[alphaOffset<tChannels>()]);
349 const unsigned int denominator = tx_ty_ + txty_ + tx_ty + txty;
352 if (denominator != 0u)
354 const unsigned int denominator_2 = denominator / 2u;
358 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[tChannels + n] * txty_ + topLeft[frameStrideElements + n] * tx_ty + topLeft[frameStrideElements + tChannels + n] * txty + denominator_2) / denominator);
365 result[n] = uint8_t((topLeft[n] * txi_ * tyi_ + topLeft[tChannels + n] * txi * tyi_ + topLeft[frameStrideElements + n] * txi_ * tyi + topLeft[frameStrideElements + tChannels + n] * txi * tyi + 8192u) >> 14u);
370 if constexpr (tTransparentIs0xFF)
373 result[alphaOffset<tChannels>()] = uint8_t((txi_ * tyi_ * topLeft[alphaOffset<tChannels>()]
374 + txi * tyi_ * topLeft[tChannels + alphaOffset<tChannels>()]
375 + txi_ * tyi * topLeft[frameStrideElements + alphaOffset<tChannels>()]
376 + txi * tyi * topLeft[frameStrideElements + tChannels + alphaOffset<tChannels>()] + 8192u) >> 14u);
380 result[alphaOffset<tChannels>()] = FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(uint8_t((denominator + 8192u) >> 14u));
387 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
388 const unsigned int txi_ = 128u - txi;
390 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
391 const unsigned int tyi_ = 128u - tyi;
393 const unsigned int rightOffset = (left >= 0 && left + 1u < width) ? tChannels : 0u;
394 const unsigned int bottomOffset = (top >= 0 && top + 1u < height) ? frameStrideElements : 0u;
396 ocean_assert(left <
int(width) && top <
int(height));
397 const uint8_t* topLeft = frame + max(0, top) * frameStrideElements + max(0, left) * tChannels;
400 : FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>());
403 : FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>());
406 : FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>());
409 : FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(FrameBlender::fullTransparent8Bit<tTransparentIs0xFF>());
411 const unsigned int txty = txi * tyi * alphaBottomRight;
412 const unsigned int txty_ = txi * tyi_ * alphaTopRight;
413 const unsigned int tx_ty = txi_ * tyi * alphaBottomLeft;
414 const unsigned int tx_ty_ = txi_ * tyi_ * alphaTopLeft;
416 const unsigned int denominator = tx_ty_ + txty_ + tx_ty + txty;
419 if (denominator != 0u)
421 const unsigned int denominator_2 = denominator / 2u;
425 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + denominator_2) / denominator);
432 result[n] = uint8_t((topLeft[n] * txi_ * tyi_ + topLeft[rightOffset + n] * txi * tyi_ + topLeft[bottomOffset + n] * txi_ * tyi + topLeft[bottomOffset + rightOffset + n] * txi * tyi + 8192u) >> 14u);
436 if constexpr (tTransparentIs0xFF)
440 + txi * tyi_ * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(alphaTopRight)
441 + txi_ * tyi * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(alphaBottomLeft)
442 + txi * tyi * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(alphaBottomRight) + 8192u) >> 14u);
451 template <
bool tAlphaAtFront,
bool tTransparentIs0xFF>
452 template <
unsigned int tChannelsWithAlpha>
458 template <
bool tAlphaAtFront,
bool tTransparentIs0xFF>
Helper class allowing to determine the offset that is necessary to access the alpha channel.
Definition: FrameBlender.h:60
static constexpr unsigned int data()
Returns the offset that is applied to access the first data channel.
Definition: FrameBlender.h:1160
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition: FrameInterpolatorBilinearAlpha.h:43
static bool interpolatePixel8BitPerChannel(const uint8_t *frame, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const PixelCenter pixelCenter, const VectorT2< TScalar > &position, uint8_t *result)
Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame.
Definition: FrameInterpolatorBilinearAlpha.h:117
This class implements bilinear frame interpolator functions for frames holding an alpha channel.
Definition: FrameInterpolatorBilinearAlpha.h:34
static void interpolatePixel8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const VectorT2< TScalar > &position, uint8_t *result)
Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame.
Definition: FrameInterpolatorBilinearAlpha.h:205
static void interpolateInfiniteBorder8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const Vector2 &position, uint8_t *result)
Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame wit...
Definition: FrameInterpolatorBilinearAlpha.h:304
static unsigned int dataOffset()
Returns the offset that is applied to access the first data channel.
Definition: FrameInterpolatorBilinearAlpha.h:459
static unsigned int alphaOffset()
Returns the offset that is applied to access the alpha channel.
Definition: FrameInterpolatorBilinearAlpha.h:453
static T floor(const T value)
Returns the largest integer value that is not greater than the given value.
Definition: Numeric.h:2026
This class implements a vector with two elements.
Definition: Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
PixelCenter
Definition of individual centers of pixels.
Definition: CV.h:117
@ PC_TOP_LEFT
The center of a pixel is in the upper-left corner of each pixel's square.
Definition: CV.h:133
@ PC_CENTER
The center of a pixel is located in the center of each pixel's square (with an offset of 0....
Definition: CV.h:150
float Scalar
Definition of a scalar type.
Definition: Math.h:128
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15