8#ifndef META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_H
9#define META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_H
37namespace Test {
namespace TestCV {
class TestFrameInterpolatorBilinearNEON; } }
85 static inline bool resize(
Frame& frame,
const unsigned int width,
const unsigned int height,
Worker* worker =
nullptr);
283 static bool rotate(
const Frame& source,
Frame& target,
const Scalar horizontalAnchorPosition,
const Scalar verticalAnchorPosition,
const Scalar angle,
Worker* worker =
nullptr,
const uint8_t* borderColor =
nullptr);
316 template <
typename TScalar = Scalar>
317 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);
337 template <
typename TSource,
typename TTarget,
typename TScalar = Scalar,
typename TIntermediate = TScalar>
338 static bool interpolatePixel(
const TSource* frame,
const unsigned int channels,
const unsigned int width,
const unsigned int height,
const unsigned int framePaddingElements,
const PixelCenter pixelCenter,
const VectorT2<TScalar>& position, TTarget* result,
const TIntermediate& resultBias = TIntermediate(0));
388 template <
typename T,
unsigned int tChannels>
389 static inline void resize(
const T* source, T* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
410 template <
typename T,
unsigned int tChannels>
411 static inline void scale(
const T* source, T* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
429 template <
unsigned int tChannels>
430 static inline void rotate8BitPerChannel(
const uint8_t* source, uint8_t* target,
const unsigned int width,
const unsigned int height,
const Scalar horizontalAnchorPosition,
const Scalar verticalAnchorPosition,
const Scalar angle,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr,
const uint8_t* borderColor =
nullptr);
459 template <
unsigned int tChannels>
460 static inline void affine8BitPerChannel(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3& source_A_target,
const uint8_t* borderColor, uint8_t* target,
const PixelPositionI& targetOrigin,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
483 template <
typename T,
unsigned int tChannels>
484 static inline void homography(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3& input_H_output,
const T* borderColor, T* output,
const PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker =
nullptr);
508 template <
unsigned int tChannels>
509 static inline void homographies8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3 homographies[4],
const uint8_t* borderColor, uint8_t* output,
const Vector2& outputQuadrantCenter,
const PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker =
nullptr);
533 template <
unsigned int tChannels>
534 static inline void homographyMask8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3& input_H_output, uint8_t* output, uint8_t* outputMask,
const PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const uint8_t maskValue ,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker =
nullptr);
560 template <
unsigned int tChannels>
561 static inline void homographiesMask8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3 homographies[4], uint8_t* output, uint8_t* outputMask,
const Vector2& outputQuadrantCenter,
const PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker =
nullptr,
const uint8_t maskValue = 0xFF);
581 template <
unsigned int tChannels>
582 static inline void homographyWithCamera8BitPerChannel(
const PinholeCamera& inputCamera,
const PinholeCamera& outputCamera,
const uint8_t* input,
const SquareMatrix3& homography,
const bool useDistortionParameters,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker =
nullptr);
603 template <
unsigned int tChannels>
604 static inline void homographyWithCameraMask8BitPerChannel(
const PinholeCamera& inputCamera,
const PinholeCamera& outputCamera,
const uint8_t* input,
const unsigned int inputPaddingElements,
const SquareMatrix3& homography, uint8_t* output, uint8_t* outputMask,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker =
nullptr,
const uint8_t maskValue = 0xFF);
623 template <
typename T,
unsigned int tChannels>
624 static inline void lookup(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable& input_LT_output,
const bool offset,
const T* borderColor, T* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker =
nullptr,
const bool useOptimizedNEON =
false,
const bool useOptimizedBilinearValuesAndFactorCalculation =
false,
const bool useOptimizedNEONFactorReplication =
false);
645 template <
unsigned int tChannels>
646 static inline void lookupMask8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable& input_LT_output,
const bool offset, uint8_t* output, uint8_t* outputMask,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker =
nullptr,
const uint8_t maskValue = 0xFF);
666 template <
typename T,
unsigned int tChannels>
667 static void resampleCameraImage(
const T* sourceFrame,
const AnyCamera& sourceCamera,
const SquareMatrix3& source_R_target,
const AnyCamera& targetCamera, T* targetFrame,
const unsigned int sourceFramePaddingElements,
const unsigned int targetFramePaddingElements,
LookupCorner2<Vector2>* source_OLT_target =
nullptr,
Worker* worker =
nullptr,
const unsigned int binSizeInPixel = 8u,
const T* borderColor =
nullptr);
683 template <
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar>
684 static inline 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);
704 template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar,
typename TIntermediate = TScalar>
705 static inline void interpolatePixel(
const TSource* frame,
const unsigned int width,
const unsigned int height,
const unsigned int framePaddingElements,
const VectorT2<TScalar>& position, TTarget* result,
const TIntermediate& resultBias = TIntermediate(0));
722 template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
723 static inline void interpolate1PixelFullAlphaBorder8BitPerChannel(
const uint8_t* frame,
const unsigned int width,
const unsigned int height,
const Vector2& position, uint8_t* result,
const unsigned int framePaddingElements);
737 static Scalar patchIntensitySum1Channel(
const uint32_t* linedIntegralFrame,
const unsigned int frameWidth,
const unsigned int frameHeight,
const unsigned int lineIntegralFramePaddingElements,
const Vector2& center,
const CV::PixelCenter pixelCenter,
const unsigned int patchWidth,
const unsigned int patchHeight);
750 static bool coversHomographyInputFrame(
const unsigned int inputWidth,
const unsigned int inputHeight,
const unsigned int outputWidth,
const unsigned int outputHeight,
const SquareMatrix3& input_H_output,
const int outputOriginX = 0,
const int outputOriginY = 0);
774 template <
unsigned int tChannels>
775 static inline void homography8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3& input_H_output,
const uint8_t* borderColor, uint8_t* output,
const PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker =
nullptr);
794 template <
unsigned int tChannels>
795 static inline void scale8BitPerChannel(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
813 template <
unsigned int tChannels>
814 static void scale8BitPerChannelSubset(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows);
840 template <
typename T>
841 static void interpolateRowVertical(
const T* sourceRowTop,
const T* sourceRowBottom, T* targetRow,
const unsigned int elements,
const float factorBottom);
856 template <
typename T,
unsigned int tChannels>
857 static void interpolateRowHorizontal(
const T* extendedSourceRow, T* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight);
859#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
884 template <
typename T>
885 static void interpolateRowVerticalNEON(
const T* sourceRowTop,
const T* sourceRowBottom, T* targetRow,
const unsigned int elements,
const float factorBottom);
899 template <
unsigned int tChannels>
915 template <
typename T,
unsigned int tChannels>
916 static void interpolateRowHorizontalNEON(
const T* extendedSourceRow, T* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight);
936 static void scale8BitPerChannelSubset7BitPrecisionNEON(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int channels,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows);
958 template <
typename T,
typename TScale,
unsigned int tChannels>
959 static void scaleSubset(
const T* source, T* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows);
977 template <
unsigned int tChannels>
978 static void rotate8BitPerChannelSubset(
const uint8_t* source, uint8_t* target,
const unsigned int width,
const unsigned int height,
const Scalar horizontalAnchorPosition,
const Scalar verticalAnchorPosition,
const Scalar angle,
const uint8_t* borderColor,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows);
1006 template <
unsigned int tChannels>
1007 static inline void affine8BitPerChannelSubset(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3* source_A_target,
const uint8_t* borderColor, uint8_t* target,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements);
1028 template <
unsigned int tChannels>
1029 static inline void homography8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const uint8_t* borderColor, uint8_t* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1050 template <
typename T,
unsigned int tChannels>
1051 static inline void homographySubset(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const T* borderColor, T* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1053#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1082 template <
unsigned int tChannels>
1083 static inline void affine8BitPerChannelSSESubset(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3* source_A_target,
const uint8_t* borderColor, uint8_t* target,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements);
1104 template <
unsigned int tChannels>
1105 static inline void homography8BitPerChannelSSESubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const uint8_t* borderColor, uint8_t* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1122 template <
unsigned int tChannels>
1123 static OCEAN_FORCE_INLINE
void interpolate4Pixels8BitPerChannelSSE(
const uint8_t* source,
const unsigned int offsetsTopLeft[4],
const unsigned int offsetsTopRight[4],
const unsigned int offsetsBottomLeft[4],
const unsigned int offsetsBottomRight[4],
const unsigned int validPixels[4],
const typename DataType<uint8_t, tChannels>::Type& borderColor,
const __m128i& m128_factorsRight,
const __m128i& m128_factorsBottom,
typename DataType<uint8_t, tChannels>::Type* targetPositionPixels);
1139 template <
unsigned int tChannels>
1140 static OCEAN_FORCE_INLINE __m128i
interpolate4Pixels8BitPerChannelSSE(
const __m128i& m128_sourcesTopLeft,
const __m128i& m128_sourcesTopRight,
const __m128i& m128_sourcesBottomLeft,
const __m128i& m128_sourcesBottomRight,
const __m128i& m128_factorsTopLeft,
const __m128i& m128_factorsTopRight,
const __m128i& m128_factorsBottomLeft,
const __m128i& m128_factorsBottomRight);
1144#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1173 template <
unsigned int tChannels>
1174 static inline void affine8BitPerChannelNEONSubset(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3* source_A_target,
const uint8_t* borderColor, uint8_t* target,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements);
1195 template <
unsigned int tChannels>
1196 static inline void homography8BitPerChannelNEONSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const uint8_t* borderColor, uint8_t* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1213 template <
unsigned int tChannels>
1214 static OCEAN_FORCE_INLINE
void interpolate4Pixels8BitPerChannelNEON(
const uint8_t* source,
const unsigned int offsetsTopLeftElements[4],
const unsigned int offsetsTopRightElements[4],
const unsigned int offsetsBottomLeftElements[4],
const unsigned int offsetsBottomRightElements[4],
const unsigned int validPixels[4],
const typename DataType<uint8_t, tChannels>::Type& borderColor,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, tChannels>::Type* targetPositionPixels);
1225 static OCEAN_FORCE_INLINE
void interpolate8Pixels1Channel8BitNEON(
const uint8x8_t& topLeft_u_8x8,
const uint8x8_t& topRight_u_8x8,
const uint8x8_t& bottomLeft_u_8x8,
const uint8x8_t& bottomRight_u_8x8,
const uint8x16_t& factorsRight_factorsBottom_128_u_8x16, uint8_t* targetPositionPixels);
1241 static OCEAN_FORCE_INLINE
void interpolate4Pixels4Channel8BitPerChannelNEON(
const uint8x16_t& topLeftPixels_u8x16,
const uint8x16_t& topRightPixels_u8x16,
const uint8x16_t& bottomLeftPixels_u8x16,
const uint8x16_t& bottomRightPixels_u8x16,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, 4u>::Type* targetPositionPixels,
const bool useOptimizedNEONFactorReplication =
false);
1265 template <
unsigned int tChannels>
1266 static inline void homographies8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* homographies,
const uint8_t* borderColor, uint8_t* output,
const Scalar outputQuadrantCenterX,
const Scalar outputQuadrantCenterY,
const int outputOriginX,
const int outputOriginY,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1286 template <
unsigned int tChannels>
1287 static inline void homographyMask8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output, uint8_t* output, uint8_t* outputMask,
const uint8_t maskValue,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1311 template <
unsigned int tChannels>
1312 static inline void homographiesMask8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* homographies, uint8_t* output, uint8_t* outputMask,
const uint8_t maskValue,
const Scalar outputQuadrantCenterX,
const Scalar outputQuadrantCenterY,
const int outputOriginX,
const int outputOriginY,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows);
1330 template <
unsigned int tChannels>
1331 static void homographyWithCamera8BitPerChannelSubset(
const PinholeCamera* inputCamera,
const PinholeCamera* outputCamera,
const PinholeCamera::DistortionLookup* outputCameraDistortionLookup,
const uint8_t* input,
const SquareMatrix3* normalizedHomography,
const bool useDistortionParameters,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows);
1350 template <
unsigned int tChannels>
1351 static void homographyWithCameraMask8BitPerChannelSubset(
const PinholeCamera* inputCamera,
const PinholeCamera* outputCamera,
const PinholeCamera::DistortionLookup* outputCameraDistortionLookup,
const uint8_t* input,
const unsigned int inputPaddingElements,
const SquareMatrix3* normalizedHomography, uint8_t* output, uint8_t* outputMask,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const uint8_t maskValue,
const unsigned int firstRow,
const unsigned int numberRows);
1369 template <
unsigned int tChannels>
1370 static void lookup8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows);
1389 template <
typename T,
unsigned int tChannels>
1390 static void lookupSubset(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const T* borderColor, T* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows);
1392#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1410 template <
unsigned int tChannels>
1411 static void lookup8BitPerChannelSubsetNEON(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows,
const bool useOptimizedNEON =
false,
const bool useOptimizedBilinearValuesAndFactorCalculation =
false,
const bool useOptimizedNEONFactorReplication =
false);
1434 template <
unsigned int tChannels>
1435 static void lookupMask8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset, uint8_t* output, uint8_t* outputMask,
const uint8_t maskValue,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows);
1440 ocean_assert(frame.
isValid());
1441 ocean_assert(width >= 1u && height >= 1u);
1445 if (!
resize(frame, target, worker))
1453 frame = std::move(target);
1457template <
typename TScalar>
1460 ocean_assert(frame !=
nullptr);
1461 ocean_assert(channels >= 1u && channels <= 8u);
1468 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1472 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1476 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1480 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1484 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1488 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1492 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1496 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1510 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1514 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1518 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1522 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1526 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1530 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1534 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1538 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1546 ocean_assert(
false &&
"Invalid channel number");
1550template <
typename TSource,
typename TTarget,
typename TScalar,
typename TIntermediate>
1553 ocean_assert(frame !=
nullptr);
1554 ocean_assert(channels >= 1u && channels <= 8u);
1561 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1565 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1569 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1573 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1577 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1581 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1585 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1589 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1603 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1607 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1611 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1615 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1619 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1623 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1627 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1631 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1639 ocean_assert(
false &&
"Invalid channel number");
1643template <
typename T,
unsigned int tChannels>
1644inline void FrameInterpolatorBilinear::resize(
const T* source, T* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker)
1646 ocean_assert(source !=
nullptr && target !=
nullptr);
1647 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1648 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1650 const double sourceX_s_targetX = double(sourceWidth) / double(targetWidth);
1651 const double sourceY_s_targetY = double(sourceHeight) / double(targetHeight);
1653 scale<T, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1656template <
typename T,
unsigned int tChannels>
1657inline void FrameInterpolatorBilinear::scale(
const T* source, T* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker)
1659 ocean_assert(source !=
nullptr && target !=
nullptr);
1660 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1661 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1662 ocean_assert(sourceX_s_targetX > 0.0);
1663 ocean_assert(sourceY_s_targetY > 0.0);
1665 if (sourceWidth == targetWidth && sourceHeight == targetHeight && sourceX_s_targetX == 1.0 && sourceY_s_targetY == 1.0)
1667 FrameConverter::subFrame<T>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
1671 if (std::is_same<T, uint8_t>::value)
1675 scale8BitPerChannel<tChannels>((
const uint8_t*)source, (uint8_t*)target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1683 worker->
executeFunction(
Worker::Function::createStatic(&scaleSubset<T, TScale, tChannels>, source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, targetHeight);
1687 scaleSubset<T, TScale, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
1692template <
unsigned int tChannels>
1693inline void FrameInterpolatorBilinear::affine8BitPerChannel(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3& source_A_target,
const uint8_t* borderColor, uint8_t* target,
const CV::PixelPositionI& targetOrigin,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker)
1700 if (targetWidth >= 4u)
1702#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1703 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::affine8BitPerChannelSSESubset<tChannels>, source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, 0u, sourcePaddingElements, targetPaddingElements), 0, targetHeight, 8u, 9u, 20u);
1705#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1706 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::affine8BitPerChannelNEONSubset<tChannels>, source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, 0u, sourcePaddingElements, targetPaddingElements), 0, targetHeight, 8u, 9u, 20u);
1711 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::affine8BitPerChannelSubset<tChannels>, source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, 0u, sourcePaddingElements, targetPaddingElements), 0, targetHeight, 8u, 9u, 20u);
1715 if (targetWidth >= 4u)
1717#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1718 affine8BitPerChannelSSESubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1720#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1721 affine8BitPerChannelNEONSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1726 affine8BitPerChannelSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1730template <
unsigned int tChannels>
1731inline void FrameInterpolatorBilinear::homography8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3& input_H_output,
const uint8_t* borderColor, uint8_t* output,
const CV::PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker)
1738 if (outputWidth >= 4u)
1740#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1741 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homography8BitPerChannelSSESubset<tChannels>, input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputHeight, 10u, 11u, 20u);
1743#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1744 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homography8BitPerChannelNEONSubset<tChannels>, input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputHeight, 10u, 11u, 20u);
1749 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homography8BitPerChannelSubset<tChannels>, input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputHeight, 10u, 11u, 20u);
1753 if (outputWidth >= 4u)
1755#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1756 homography8BitPerChannelSSESubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1758#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1759 homography8BitPerChannelNEONSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1764 homography8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1768template <
typename T,
unsigned int tChannels>
1769inline void FrameInterpolatorBilinear::homography(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3& input_H_output,
const T* borderColor, T* output,
const CV::PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker)
1771 if (std::is_same<T, uint8_t>::value)
1773 homography8BitPerChannel<tChannels>((
const uint8_t*)input, inputWidth, inputHeight, input_H_output, (
const uint8_t*)borderColor, (uint8_t*)output, outputOrigin, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, worker);
1783 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographySubset<T, tChannels>, input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputHeight, 10u, 11u, 20u);
1787 homographySubset<T, tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1792template <
unsigned int tChannels>
1793inline void FrameInterpolatorBilinear::homographies8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3 homographies[4],
const uint8_t* borderColor, uint8_t* output,
const Vector2& outputQuadrantCenter,
const PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker)
1797 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographies8BitPerChannelSubset<tChannels>, input, inputWidth, inputHeight, homographies, borderColor, output, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputHeight, 14u, 15u, 20u);
1801 homographies8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, borderColor, output, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1805template <
unsigned int tChannels>
1806inline void FrameInterpolatorBilinear::homographyMask8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3& input_H_output, uint8_t* output, uint8_t* outputMask,
const CV::PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const uint8_t maskValue,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker)
1813 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographyMask8BitPerChannelSubset<tChannels>, input, inputWidth, inputHeight, &input_H_shiftedOutput, output, outputMask, maskValue, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, 0u), 0, outputHeight, 12u, 13u, 20u);
1817 homographyMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, output, outputMask, maskValue, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1821template <
unsigned int tChannels>
1822inline void FrameInterpolatorBilinear::homographiesMask8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3 homographies[4], uint8_t* output, uint8_t* outputMask,
const Vector2& outputQuadrantCenter,
const CV::PixelPositionI& outputOrigin,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker,
const uint8_t maskValue)
1826 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographiesMask8BitPerChannelSubset<tChannels>, input, inputWidth, inputHeight, homographies, output, outputMask, maskValue, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, 0u), 0, outputHeight);
1830 homographiesMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, output, outputMask, maskValue, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1834template <
unsigned int tChannels>
1839 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1843 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographyWithCamera8BitPerChannelSubset<tChannels>, &inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputCamera.
height());
1847 homographyWithCamera8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, outputCamera.
height());
1851template <
unsigned int tChannels>
1852inline void FrameInterpolatorBilinear::homographyWithCameraMask8BitPerChannel(
const PinholeCamera& inputCamera,
const PinholeCamera& outputCamera,
const uint8_t* input,
const unsigned int inputPaddingElements,
const SquareMatrix3&
homography, uint8_t* output, uint8_t* outputMask,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker,
const uint8_t maskValue)
1856 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1860 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographyWithCameraMask8BitPerChannelSubset<tChannels>, &inputCamera, &outputCamera, &outputCameraDistortionLookup, input, inputPaddingElements, &normalizedHomography, output, outputMask, outputPaddingElements, outputMaskPaddingElements, maskValue, 0u, 0u), 0, outputCamera.
height(), 11u, 12u, 10u);
1864 homographyWithCameraMask8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, inputPaddingElements, &normalizedHomography, output, outputMask, outputPaddingElements, outputMaskPaddingElements, maskValue, 0u, outputCamera.
height());
1868template <
typename T,
unsigned int tChannels>
1869inline void FrameInterpolatorBilinear::lookup(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable& input_LT_output,
const bool offset,
const T* borderColor, T* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
Worker* worker,
const bool useOptimizedNEON,
const bool useOptimizedBilinearValuesAndFactorCalculation, [[maybe_unused]]
const bool useOptimizedNEONFactorReplication)
1871 if constexpr (std::is_same<T, uint8_t>::value)
1873#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1874 if ((tChannels >= 1u && input_LT_output.
sizeX() >= 8) || (tChannels >= 2u && input_LT_output.
sizeX() >= 4))
1880 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::lookup8BitPerChannelSubsetNEON<tChannels>, input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u, useOptimizedNEON, useOptimizedBilinearValuesAndFactorCalculation, useOptimizedNEONFactorReplication), 0u, (
unsigned int)(input_LT_output.
sizeY()), 9u, 10u, 20u);
1884 lookup8BitPerChannelSubsetNEON<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()), useOptimizedNEON, useOptimizedBilinearValuesAndFactorCalculation, useOptimizedNEONFactorReplication);
1893 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::lookup8BitPerChannelSubset<tChannels>, input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0u, (
unsigned int)input_LT_output.
sizeY(), 9u, 10u, 20u);
1897 lookup8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1902 ocean_assert((!std::is_same<T, uint8_t>::value));
1906 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::lookupSubset<T, tChannels>, input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0u, (
unsigned int)(input_LT_output.
sizeY()), 9u, 10u, 20u);
1910 lookupSubset<T, tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1915template <
unsigned int tChannels>
1916inline void FrameInterpolatorBilinear::lookupMask8BitPerChannel(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable& input_LT_output,
const bool offset, uint8_t* output, uint8_t* outputMask,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
Worker* worker,
const uint8_t maskValue)
1920 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::lookupMask8BitPerChannelSubset<tChannels>, input, inputWidth, inputHeight, &input_LT_output, offset, output, outputMask, maskValue, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, 0u), 0u, (
unsigned int)(input_LT_output.
sizeY()), 11u, 12u, 20u);
1924 lookupMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, output, outputMask, maskValue, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1928template <
typename T,
unsigned int tChannels>
1929void FrameInterpolatorBilinear::resampleCameraImage(
const T* sourceFrame,
const AnyCamera& sourceCamera,
const SquareMatrix3& source_R_target,
const AnyCamera& targetCamera, T* targetFrame,
const unsigned int sourceFramePaddingElements,
const unsigned int targetFramePaddingElements,
LookupCorner2<Vector2>* source_OLT_target,
Worker* worker,
const unsigned int binSizeInPixel,
const T* borderColor)
1931 static_assert(tChannels >= 1u,
"Invalid channel number!");
1933 ocean_assert(sourceFrame !=
nullptr);
1934 ocean_assert(sourceCamera.
isValid());
1936 ocean_assert(targetCamera.
isValid());
1937 ocean_assert(targetFrame !=
nullptr);
1938 ocean_assert(binSizeInPixel >= 1u);
1940 const size_t binsX = std::max(1u, targetCamera.
width() / binSizeInPixel);
1941 const size_t binsY = std::max(1u, targetCamera.
height() / binSizeInPixel);
1944 for (
size_t yBin = 0; yBin <= lookupTable.
binsY(); ++yBin)
1946 for (
size_t xBin = 0; xBin <= lookupTable.
binsX(); ++xBin)
1950 constexpr bool makeUnitVector =
false;
1952 const Vector3 rayI = source_R_target * targetCamera.
vector(cornerPosition, makeUnitVector);
1969 lookup<T, tChannels>(sourceFrame, sourceCamera.
width(), sourceCamera.
height(), lookupTable,
true , borderColor, targetFrame, sourceFramePaddingElements, targetFramePaddingElements, worker);
1971 if (source_OLT_target)
1973 *source_OLT_target = std::move(lookupTable);
1977template <
unsigned int tChannels>
1978void FrameInterpolatorBilinear::rotate8BitPerChannel(
const uint8_t* source, uint8_t* target,
const unsigned int width,
const unsigned int height,
const Scalar horizontalAnchorPosition,
const Scalar verticalAnchorPosition,
const Scalar angle,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker,
const uint8_t* borderColor)
1980 static_assert(tChannels != 0u,
"Invalid channel number!");
1982 ocean_assert(source !=
nullptr && target !=
nullptr);
1983 ocean_assert(width >= 1u && height >= 1u);
1987 worker->
executeFunction(
Worker::Function::createStatic(&rotate8BitPerChannelSubset<tChannels>, source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height);
1991 rotate8BitPerChannelSubset<tChannels>(source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, height);
1995template <
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar>
1998 static_assert(tChannels != 0u,
"Invalid channel number!");
1999 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
2001 ocean_assert(frame !=
nullptr && result !=
nullptr);
2002 ocean_assert(width != 0u && height != 0u);
2004 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2006 ocean_assert(position.
x() >= TScalar(0));
2007 ocean_assert(position.
y() >= TScalar(0));
2011 ocean_assert(position.
x() <= TScalar(width - 1u));
2012 ocean_assert(position.
y() <= TScalar(height - 1u));
2014 const unsigned int left = (
unsigned int)(position.
x());
2015 const unsigned int top = (
unsigned int)(position.
y());
2016 ocean_assert(left < width && top < height);
2018 const TScalar tx = position.
x() - TScalar(left);
2019 ocean_assert(tx >= 0 && tx <= 1);
2020 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
2021 const unsigned int txi_ = 128u - txi;
2023 const TScalar ty = position.
y() - TScalar(top);
2024 ocean_assert(ty >= 0 && ty <= 1);
2025 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
2026 const unsigned int tyi_ = 128u - tyi;
2028 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2029 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2031 const uint8_t*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2033 const unsigned int txty = txi * tyi;
2034 const unsigned int txty_ = txi * tyi_;
2035 const unsigned int tx_ty = txi_ * tyi;
2036 const unsigned int tx_ty_ = txi_ * tyi_;
2038 for (
unsigned int n = 0u; n < tChannels; ++n)
2040 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2045 ocean_assert(tPixelCenter ==
PC_CENTER);
2047 ocean_assert(position.
x() <= TScalar(width));
2048 ocean_assert(position.
y() <= TScalar(height));
2050 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2051 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2053 const unsigned int left = (
unsigned int)(xShifted);
2054 const unsigned int top = (
unsigned int)(yShifted);
2056 ocean_assert(left < width);
2057 ocean_assert(top < height);
2059 const TScalar tx = xShifted - TScalar(left);
2060 const TScalar ty = yShifted - TScalar(top);
2062 ocean_assert(tx >= 0 && tx <= 1);
2063 ocean_assert(ty >= 0 && ty <= 1);
2065 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
2066 const unsigned int txi_ = 128u - txi;
2068 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
2069 const unsigned int tyi_ = 128u - tyi;
2071 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2072 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2074 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2076 const unsigned int txty = txi * tyi;
2077 const unsigned int txty_ = txi * tyi_;
2078 const unsigned int tx_ty = txi_ * tyi;
2079 const unsigned int tx_ty_ = txi_ * tyi_;
2081 for (
unsigned int n = 0u; n < tChannels; ++n)
2083 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2088template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar,
typename TIntermediate>
2091 static_assert(tChannels != 0u,
"Invalid channel number!");
2092 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
2094 ocean_assert(frame !=
nullptr && result !=
nullptr);
2095 ocean_assert(width != 0u && height != 0u);
2097 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2099 ocean_assert(position.
x() >= TScalar(0));
2100 ocean_assert(position.
y() >= TScalar(0));
2104 ocean_assert(position.
x() <= TScalar(width - 1u));
2105 ocean_assert(position.
y() <= TScalar(height - 1u));
2107 const unsigned int left = (
unsigned int)(position.
x());
2108 const unsigned int top = (
unsigned int)(position.
y());
2110 const TScalar tx = position.
x() - TScalar(left);
2111 ocean_assert(tx >= 0 && tx <= 1);
2113 const TScalar ty = position.
y() - TScalar(top);
2114 ocean_assert(ty >= 0 && ty <= 1);
2116 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2117 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2119 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2121 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2122 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2123 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2124 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2128 for (
unsigned int n = 0u; n < tChannels; ++n)
2130 result[n] = TTarget(TIntermediate(topLeft[n]) * tx_ty_ + TIntermediate(topLeft[rightOffset + n]) * txty_ + TIntermediate(topLeft[bottomOffset + n]) * tx_ty + TIntermediate(topLeft[bottomOffset + rightOffset + n]) * txty + resultBias);
2135 ocean_assert(tPixelCenter ==
PC_CENTER);
2137 ocean_assert(position.
x() <= TScalar(width));
2138 ocean_assert(position.
y() <= TScalar(height));
2140 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2141 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2143 const unsigned int left = (
unsigned int)(xShifted);
2144 const unsigned int top = (
unsigned int)(yShifted);
2146 ocean_assert(left < width);
2147 ocean_assert(top < height);
2149 const TScalar tx = xShifted - TScalar(left);
2150 const TScalar ty = yShifted - TScalar(top);
2152 ocean_assert(tx >= 0 && tx <= 1);
2153 ocean_assert(ty >= 0 && ty <= 1);
2155 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2156 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2158 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2160 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2161 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2162 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2163 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2167 for (
unsigned int n = 0u; n < tChannels; ++n)
2169 result[n] = TTarget(TIntermediate(topLeft[n]) * tx_ty_ + TIntermediate(topLeft[rightOffset + n]) * txty_ + TIntermediate(topLeft[bottomOffset + n]) * tx_ty + TIntermediate(topLeft[bottomOffset + rightOffset + n]) * txty + resultBias);
2174template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
2177 static_assert(tChannels != 0u,
"Invalid channel number!");
2179 ocean_assert(frame && result);
2186 for (
unsigned int n = 0u; n < tChannels - 1u; ++n)
2196 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2201 ocean_assert(left >= -1 && left <
int(width));
2202 ocean_assert(top >= -1 && top <
int(height));
2204 if ((
unsigned int)left < width - 1u && (
unsigned int)top < height - 1u)
2208 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2209 const unsigned int txi_ = 128u - txi;
2211 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2212 const unsigned int tyi_ = 128u - tyi;
2214 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2216 const unsigned int txty = txi * tyi;
2217 const unsigned int txty_ = txi * tyi_;
2218 const unsigned int tx_ty = txi_ * tyi;
2219 const unsigned int tx_ty_ = txi_ * tyi_;
2221 for (
unsigned int n = 0u; n < tChannels; ++n)
2223 result[n] = (topLeft[n] * tx_ty_ + topLeft[tChannels + n] * txty_
2224 + topLeft[frameStrideElements + n] * tx_ty + topLeft[frameStrideElements + tChannels + n] * txty + 8192u) >> 14u;
2231 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2232 const unsigned int txi_ = 128u - txi;
2234 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2235 const unsigned int tyi_ = 128u - tyi;
2237 const unsigned int rightOffset = (left >= 0 && left + 1u < width) ? tChannels : 0u;
2238 const unsigned int bottomOffset = (top >= 0 && top + 1u < height) ? frameStrideElements : 0u;
2240 ocean_assert(left <
int(width) && top <
int(height));
2241 const uint8_t*
const topLeft = frame + max(0, top) * frameStrideElements + max(0, left) * tChannels;
2243 const unsigned int txty = txi * tyi;
2244 const unsigned int txty_ = txi * tyi_;
2245 const unsigned int tx_ty = txi_ * tyi;
2246 const unsigned int tx_ty_ = txi_ * tyi_;
2250 result[n] = (topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_
2251 + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u;
2263template <
unsigned int tChannels>
2264void FrameInterpolatorBilinear::affine8BitPerChannelSubset(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3* source_A_target,
const uint8_t* borderColor, uint8_t* target,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberOutputRows,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements)
2266 static_assert(tChannels >= 1u,
"Invalid channel number!");
2268 ocean_assert(source !=
nullptr && target !=
nullptr);
2269 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2270 ocean_assert_and_suppress_unused(targetWidth > 0u && targetHeight > 0u, targetHeight);
2271 ocean_assert(source_A_target);
2274 ocean_assert(firstTargetRow + numberOutputRows <= targetHeight);
2276 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2278 const Scalar scalarSourceWidth_1 =
Scalar(sourceWidth - 1u);
2279 const Scalar scalarSourceHeight_1 =
Scalar(sourceHeight - 1u);
2283 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2284 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2286 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberOutputRows; ++y)
2288 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2314 for (
unsigned int x = 0u; x < targetWidth; ++x)
2319 const Scalar debugSourceX = (*source_A_target)[0] *
Scalar(x) + (*source_A_target)[3] *
Scalar(y) + (*source_A_target)[6];
2320 const Scalar debugSourceY = (*source_A_target)[1] *
Scalar(x) + (*source_A_target)[4] *
Scalar(y) + (*source_A_target)[7];
2324 if (sourcePosition.
x() <
Scalar(0) || sourcePosition.
x() > scalarSourceWidth_1 || sourcePosition.
y() <
Scalar(0) || sourcePosition.
y() > scalarSourceHeight_1)
2326 *targetRow = *bColor;
2330 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, sourceWidth, sourceHeight, sourcePaddingElements, sourcePosition, (uint8_t*)(targetRow));
2338template <
unsigned int tChannels>
2339void FrameInterpolatorBilinear::homography8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const uint8_t* borderColor, uint8_t* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows)
2341 static_assert(tChannels >= 1u,
"Invalid channel number!");
2343 ocean_assert(input !=
nullptr && output !=
nullptr);
2344 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2345 ocean_assert(outputWidth > 0u && outputHeight > 0u);
2346 ocean_assert(input_H_output !=
nullptr);
2348 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2350 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2352 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
2353 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
2357 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2358 const PixelType bColor = borderColor ? *(PixelType*)borderColor : *(PixelType*)zeroColor;
2360 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2386 const Scalar X2 = (*input_H_output)(2, 0);
2387 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2389 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2391 for (
unsigned int x = 0u; x < outputWidth; ++x)
2398 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2401 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
2403 *outputRowPixel = bColor;
2407 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputRowPixel));
2415template <
typename T,
unsigned int tChannels>
2416void FrameInterpolatorBilinear::homographySubset(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const T* borderColor, T* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows)
2418 static_assert(tChannels >= 1u,
"Invalid channel number!");
2420 ocean_assert(input !=
nullptr && output !=
nullptr);
2421 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2422 ocean_assert_and_suppress_unused(outputWidth > 0u && outputHeight > 0u, outputHeight);
2423 ocean_assert(input_H_output !=
nullptr);
2425 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
2427 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2429 const Scalar scalarInputWidth1 =
Scalar(inputWidth - 1u);
2430 const Scalar scalarInputHeight1 =
Scalar(inputHeight - 1u);
2437 constexpr T zeroColor[tChannels] = {T(0)};
2438 const PixelType*
const bColor = borderColor ? (PixelType*)(borderColor) : (PixelType*)(zeroColor);
2440 constexpr TIntermediate bias = TIntermediate(0);
2442 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2468 const Scalar X2 = (*input_H_output)(2, 0);
2469 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2471 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2473 for (
unsigned int x = 0u; x < outputWidth; ++x)
2480 ocean_assert((std::is_same<float, Scalar>::value) || inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2483 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
x() <= scalarInputWidth1 && inputPosition.
y() >=
Scalar(0) && inputPosition.
y() <= scalarInputHeight1)
2485 interpolatePixel<T, T, tChannels, CV::PC_TOP_LEFT, Scalar, TIntermediate>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputRowPixel), bias);
2489 *outputRowPixel = *bColor;
2497#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
2499template <
unsigned int tChannels>
2500inline void FrameInterpolatorBilinear::affine8BitPerChannelSSESubset(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3* source_A_target,
const uint8_t* borderColor, uint8_t* target,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements)
2502 static_assert(tChannels >= 1u,
"Invalid channel number!");
2504 ocean_assert(source && target);
2505 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2506 ocean_assert(targetWidth >= 4u && targetHeight > 0u);
2507 ocean_assert(source_A_target);
2510 ocean_assert_and_suppress_unused(firstTargetRow + numberTargetRows <= targetHeight, targetHeight);
2512 const unsigned int sourceStrideElements = tChannels * sourceWidth + sourcePaddingElements;
2513 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2517 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2518 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2520 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2522 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2523 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2524 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2525 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2528 const __m128 m128_f_X0 = _mm_set_ps1(
float((*source_A_target)(0, 0)));
2529 const __m128 m128_f_X1 = _mm_set_ps1(
float((*source_A_target)(1, 0)));
2531 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
2533 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2557 const __m128 m128_f_C0 = _mm_set_ps1(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
2558 const __m128 m128_f_C1 = _mm_set_ps1(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
2561 const __m128 m128_f_zero = _mm_setzero_ps();
2564 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2567 const __m128i m128_i_sourceStrideElements = _mm_set1_epi32(sourceStrideElements);
2570 const __m128i m128_i_sourceWidth_1 = _mm_set1_epi32(
int(sourceWidth) - 1);
2571 const __m128i m128_i_sourceHeight_1 = _mm_set1_epi32(
int(sourceHeight) - 1);
2574 const __m128 m128_f_sourceWidth_1 = _mm_set_ps1(
float(sourceWidth - 1u));
2575 const __m128 m128_f_sourceHeight_1 = _mm_set_ps1(
float(sourceHeight - 1u));
2577 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
2579 if (x + 4u > targetWidth)
2584 ocean_assert(x >= 4u && targetWidth > 4u);
2585 const unsigned int newX = targetWidth - 4u;
2587 ocean_assert(x > newX);
2588 targetRow -= x - newX;
2593 ocean_assert(!(x + 4u < targetWidth));
2599 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2602 const __m128 m128_f_sourceX = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2603 const __m128 m128_f_sourceY = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2606 const __m128 m128_f_validPixelX = _mm_and_ps(_mm_cmple_ps(m128_f_sourceX, m128_f_sourceWidth_1), _mm_cmpge_ps(m128_f_sourceX, m128_f_zero));
2607 const __m128 m128_f_validPixelY = _mm_and_ps(_mm_cmple_ps(m128_f_sourceY, m128_f_sourceHeight_1), _mm_cmpge_ps(m128_f_sourceY, m128_f_zero));
2609 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2612 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2615 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2616 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2617 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2620 targetRow[0] = *bColor;
2621 targetRow[1] = *bColor;
2622 targetRow[2] = *bColor;
2623 targetRow[3] = *bColor;
2631 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2632 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2636 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_sourceX);
2637 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_sourceY);
2640 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2641 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2644 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_sourceWidth_1);
2645 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_sourceHeight_1);
2648 const __m128i m128_i_topLeftOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_top, m128_i_sourceStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_left));
2649 const __m128i m128_i_topRightOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_top, m128_i_sourceStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_right));
2650 const __m128i m128_i_bottomLeftOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_bottom, m128_i_sourceStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_left));
2651 const __m128i m128_i_bottomRightOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_bottom, m128_i_sourceStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_right));
2654 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2655 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2656 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2657 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2665 __m128 m128_f_tx = _mm_sub_ps(m128_f_sourceX, m128_f_tx_floor);
2666 __m128 m128_f_ty = _mm_sub_ps(m128_f_sourceY, m128_f_ty_floor);
2669 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2670 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2672 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2673 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2675 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2676 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2678 interpolate4Pixels8BitPerChannelSSE<tChannels>(source, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, targetRow);
2684template <
unsigned int tChannels>
2685inline void FrameInterpolatorBilinear::homography8BitPerChannelSSESubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const uint8_t* borderColor, uint8_t* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows)
2687 static_assert(tChannels >= 1u,
"Invalid channel number!");
2689 ocean_assert(input !=
nullptr && output !=
nullptr);
2690 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2691 ocean_assert(outputWidth >= 4u && outputHeight > 0u);
2692 ocean_assert(input_H_output !=
nullptr);
2694 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2696 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
2697 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2701 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2702 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2704 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2706 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2707 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2708 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2709 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2712 const __m128 m128_f_X0 = _mm_set_ps1(
float((*input_H_output)(0, 0)));
2713 const __m128 m128_f_X1 = _mm_set_ps1(
float((*input_H_output)(1, 0)));
2714 const __m128 m128_f_X2 = _mm_set_ps1(
float((*input_H_output)(2, 0)));
2717 const __m128 m128_f_zero = _mm_setzero_ps();
2720 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2723 const __m128i m128_i_inputStrideElements = _mm_set1_epi32(inputStrideElements);
2726 const __m128i m128_i_inputWidth_1 = _mm_set1_epi32(
int(inputWidth) - 1);
2727 const __m128i m128_i_inputHeight_1 = _mm_set1_epi32(
int(inputHeight) - 1);
2730 const __m128 m128_f_inputWidth_1 = _mm_set_ps1(
float(inputWidth - 1u));
2731 const __m128 m128_f_inputHeight_1 = _mm_set_ps1(
float(inputHeight - 1u));
2733 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2735 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
2759 const __m128 m128_f_C0 = _mm_set_ps1(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
2760 const __m128 m128_f_C1 = _mm_set_ps1(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
2761 const __m128 m128_f_C2 = _mm_set_ps1(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
2763 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
2765 if (x + 4u > outputWidth)
2770 ocean_assert(x >= 4u && outputWidth > 4u);
2771 const unsigned int newX = outputWidth - 4u;
2773 ocean_assert(x > newX);
2774 outputPixelData -= x - newX;
2779 ocean_assert(!(x + 4u < outputWidth));
2785 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2788 const __m128 m128_f_xx = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2789 const __m128 m128_f_yy = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2790 const __m128 m128_f_zz = _mm_add_ps(_mm_mul_ps(m128_f_X2, m128_f_x_0123), m128_f_C2);
2792#ifdef USE_APPROXIMATED_INVERSE_OF_ZZ
2797 const __m128 inv_zz_128 = _mm_rcp_ps(m128_f_zz);
2800 const __m128 m128_f_inputX = _mm_mul_ps(m128_f_xx, inv_zz_128);
2801 const __m128 m128_f_inputY = _mm_mul_ps(m128_f_yy, inv_zz_128);
2806 const __m128 m128_f_inputX = _mm_div_ps(m128_f_xx, m128_f_zz);
2807 const __m128 m128_f_inputY = _mm_div_ps(m128_f_yy, m128_f_zz);
2813 const __m128 m128_f_validPixelX = _mm_and_ps(_mm_cmple_ps (m128_f_inputX, m128_f_inputWidth_1), _mm_cmpge_ps(m128_f_inputX, m128_f_zero));
2814 const __m128 m128_f_validPixelY = _mm_and_ps(_mm_cmple_ps (m128_f_inputY, m128_f_inputHeight_1), _mm_cmpge_ps(m128_f_inputY, m128_f_zero));
2816 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2819 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2822 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2823 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2824 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2827 outputPixelData[0] = *bColor;
2828 outputPixelData[1] = *bColor;
2829 outputPixelData[2] = *bColor;
2830 outputPixelData[3] = *bColor;
2832 outputPixelData += 4;
2838 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2839 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2843 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_inputX);
2844 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_inputY);
2847 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2848 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2851 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_inputWidth_1);
2852 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_inputHeight_1);
2855 const __m128i m128_i_topLeftOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_top, m128_i_inputStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_left));
2856 const __m128i m128_i_topRightOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_top, m128_i_inputStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_right));
2857 const __m128i m128_i_bottomLeftOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_bottom, m128_i_inputStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_left));
2858 const __m128i m128_i_bottomRightOffset = _mm_add_epi32(_mm_mullo_epi32(m128_i_bottom, m128_i_inputStrideElements), _mm_mullo_epi32(m128_i_channels, m128_i_right));
2861 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2862 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2863 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2864 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2872 __m128 m128_f_tx = _mm_sub_ps(m128_f_inputX, m128_f_tx_floor);
2873 __m128 m128_f_ty = _mm_sub_ps(m128_f_inputY, m128_f_ty_floor);
2876 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2877 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2879 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2880 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2882 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2883 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2885 interpolate4Pixels8BitPerChannelSSE<tChannels>(input, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, outputPixelData);
2886 outputPixelData += 4;
2892OCEAN_FORCE_INLINE __m128i FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelSSE<3u>(
const __m128i& sourcesTopLeft,
const __m128i& sourcesTopRight,
const __m128i& sourcesBottomLeft,
const __m128i& sourcesBottomRight,
const __m128i& factorsTopLeft,
const __m128i& factorsTopRight,
const __m128i& factorsBottomLeft,
const __m128i& factorsBottomRight)
2909 const __m128i mask32_Channel0 =
SSE::set128i(0xFFFFFF09FFFFFF06ull, 0xFFFFFF03FFFFFF00ull);
2910 const __m128i mask32_Channel1 =
SSE::set128i(0xFFFFFF0AFFFFFF07ull, 0xFFFFFF04FFFFFF01ull);
2911 const __m128i mask32_Channel2 =
SSE::set128i(0xFFFFFF0BFFFFFF08ull, 0xFFFFFF05FFFFFF02ull);
2919 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2922 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2925 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2929 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2930 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2931 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
2935 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
2936 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
2937 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
2941 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
2942 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
2943 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
2946 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
2955 __m128i interpolation_channel0 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFF0CFFull, 0xFF08FFFF04FFFF00ull));
2961 __m128i interpolation_channel1 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFF0CFFFFull, 0x08FFFF04FFFF00FFull));
2967 __m128i interpolation_channel2 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFF0CFFFF08ull, 0xFFFF04FFFF00FFFFull));
2972 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), interpolation_channel2);
2976OCEAN_FORCE_INLINE __m128i FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelSSE<4u>(
const __m128i& sourcesTopLeft,
const __m128i& sourcesTopRight,
const __m128i& sourcesBottomLeft,
const __m128i& sourcesBottomRight,
const __m128i& factorsTopLeft,
const __m128i& factorsTopRight,
const __m128i& factorsBottomLeft,
const __m128i& factorsBottomRight)
2993 const __m128i mask32_Channel0 =
SSE::set128i(0xA0A0A00CA0A0A008ull, 0xA0A0A004A0A0A000ull);
2994 const __m128i mask32_Channel1 =
SSE::set128i(0xA0A0A00DA0A0A009ull, 0xA0A0A005A0A0A001ull);
2995 const __m128i mask32_Channel2 =
SSE::set128i(0xA0A0A00EA0A0A00Aull, 0xA0A0A006A0A0A002ull);
2996 const __m128i mask32_Channel3 =
SSE::set128i(0xA0A0A00FA0A0A00Bull, 0xA0A0A007A0A0A003ull);
3004 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
3007 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
3010 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
3013 __m128i multiplication_channel3 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel3));
3017 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
3018 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
3019 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
3020 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel3)));
3024 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
3025 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
3026 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
3027 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel3)));
3031 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
3032 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
3033 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
3034 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel3)));
3037 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3044 __m128i interpolation_channel0 = _mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14);
3049 __m128i interpolation_channel1 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14), 8);
3053 __m128i interpolation_channel2 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14), 16);
3057 __m128i interpolation_channel3 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel3, m128_i_8192), 14), 24);
3062 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), _mm_or_si128(interpolation_channel2, interpolation_channel3));
3065#ifdef OCEAN_COMPILER_MSC
3071OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelSSE<1u>(
const uint8_t* source,
const unsigned int offsetsTopLeft[4],
const unsigned int offsetsTopRight[4],
const unsigned int offsetsBottomLeft[4],
const unsigned int offsetsBottomRight[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 1u>::Type& borderColor,
const __m128i& m128_factorsRight,
const __m128i& m128_factorsBottom,
typename DataType<uint8_t, 1u>::Type* targetPositionPixels)
3073 ocean_assert(source !=
nullptr);
3074 ocean_assert(targetPositionPixels !=
nullptr);
3080 OCEAN_ALIGN_DATA(16) PixelType pixels[16];
3084 for (
unsigned int i = 0u; i < 4u; ++i)
3088 pixels[i * 4u + 0u] = *((PixelType*)(source + offsetsTopLeft[i]));
3089 pixels[i * 4u + 1u] = *((PixelType*)(source + offsetsTopRight[i]));
3090 pixels[i * 4u + 2u] = *((PixelType*)(source + offsetsBottomLeft[i]));
3091 pixels[i * 4u + 3u] = *((PixelType*)(source + offsetsBottomRight[i]));
3095 pixels[i * 4u + 0u] = borderColor;
3096 pixels[i * 4u + 1u] = borderColor;
3097 pixels[i * 4u + 2u] = borderColor;
3098 pixels[i * 4u + 3u] = borderColor;
3102 static_assert(
sizeof(__m128i) ==
sizeof(pixels),
"Invalid data type!");
3104 const __m128i m128_pixels = _mm_load_si128((
const __m128i*)pixels);
3110 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3111 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3116 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3117 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3118 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3119 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3135 const __m128i mask32_topLeft =
SSE::set128i(0xFFFFFF0CFFFFFF08ull, 0xFFFFFF04FFFFFF00ull);
3136 const __m128i mask32_topRight =
SSE::set128i(0xFFFFFF0DFFFFFF09ull, 0xFFFFFF05FFFFFF01ull);
3137 const __m128i mask32_bottomLeft =
SSE::set128i(0xFFFFFF0EFFFFFF0Aull, 0xFFFFFF06FFFFFF02ull);
3138 const __m128i mask32_bottomRight =
SSE::set128i(0xFFFFFF0FFFFFFF0Bull, 0xFFFFFF07FFFFFF03ull);
3146 __m128i multiplicationA = _mm_mullo_epi32(m128_factorsTopLeft, _mm_shuffle_epi8(m128_pixels, mask32_topLeft));
3147 __m128i multiplicationB = _mm_mullo_epi32(m128_factorsTopRight, _mm_shuffle_epi8(m128_pixels, mask32_topRight));
3149 multiplicationA = _mm_add_epi32(multiplicationA, _mm_mullo_epi32(m128_factorsBottomLeft, _mm_shuffle_epi8(m128_pixels, mask32_bottomLeft)));
3150 multiplicationB = _mm_add_epi32(multiplicationB, _mm_mullo_epi32(m128_factorsBottomRight, _mm_shuffle_epi8(m128_pixels, mask32_bottomRight)));
3152 __m128i multiplication = _mm_add_epi32(multiplicationA, multiplicationB);
3154 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3159 const __m128i result = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF0C080400ull));
3161 *((
unsigned int*)targetPositionPixels) = _mm_extract_epi32(result, 0);
3165OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelSSE<3u>(
const uint8_t* source,
const unsigned int offsetsTopLeft[4],
const unsigned int offsetsTopRight[4],
const unsigned int offsetsBottomLeft[4],
const unsigned int offsetsBottomRight[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 3u>::Type& borderColor,
const __m128i& m128_factorsRight,
const __m128i& m128_factorsBottom,
typename DataType<uint8_t, 3u>::Type* targetPositionPixels)
3167 ocean_assert(source !=
nullptr);
3168 ocean_assert(targetPositionPixels !=
nullptr);
3174 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[6];
3175 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[6];
3176 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[6];
3177 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[6];
3181 for (
unsigned int i = 0u; i < 4u; ++i)
3185 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3186 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3187 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3188 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3192 topLeftPixels[i] = borderColor;
3193 topRightPixels[i] = borderColor;
3194 bottomLeftPixels[i] = borderColor;
3195 bottomRightPixels[i] = borderColor;
3199 static_assert(
sizeof(__m128i) <=
sizeof(topLeftPixels),
"Invalid data type!");
3201 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3202 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3203 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3204 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3210 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3211 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3216 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3217 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3218 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3219 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3222 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<3u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3225 memcpy(targetPositionPixels, &m128_interpolationResult, 12u);
3231OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelSSE<4u>(
const uint8_t* source,
const unsigned int offsetsTopLeft[4],
const unsigned int offsetsTopRight[4],
const unsigned int offsetsBottomLeft[4],
const unsigned int offsetsBottomRight[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 4u>::Type& borderColor,
const __m128i& m128_factorsRight,
const __m128i& m128_factorsBottom,
typename DataType<uint8_t, 4u>::Type* targetPositionPixels)
3233 ocean_assert(source !=
nullptr);
3234 ocean_assert(targetPositionPixels !=
nullptr);
3240 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[4];
3241 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[4];
3242 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[4];
3243 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[4];
3248 for (
unsigned int i = 0u; i < 4u; ++i)
3252 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3253 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3254 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3255 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3259 topLeftPixels[i] = borderColor;
3260 topRightPixels[i] = borderColor;
3261 bottomLeftPixels[i] = borderColor;
3262 bottomRightPixels[i] = borderColor;
3266 static_assert(
sizeof(__m128i) ==
sizeof(topLeftPixels),
"Invalid data type!");
3268 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3269 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3270 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3271 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3277 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3278 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3283 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3284 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3285 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3286 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3289 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<4u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3291 _mm_storeu_si128((__m128i*)targetPositionPixels, m128_interpolationResult);
3294template <
unsigned int tChannels>
3295OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelSSE(
const uint8_t* source,
const unsigned int offsetsTopLeft[4],
const unsigned int offsetsTopRight[4],
const unsigned int offsetsBottomLeft[4],
const unsigned int offsetsBottomRight[4],
const unsigned int validPixels[4],
const typename DataType<uint8_t, tChannels>::Type& borderColor,
const __m128i& m128_factorsRight,
const __m128i& m128_factorsBottom,
typename DataType<uint8_t, tChannels>::Type* targetPositionPixels)
3297 ocean_assert(source !=
nullptr);
3298 ocean_assert(targetPositionPixels !=
nullptr);
3302 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopLeft[4];
3303 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopRight[4];
3304 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomLeft[4];
3305 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomRight[4];
3311 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3312 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3317 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3318 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3319 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3320 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3324 _mm_store_si128((__m128i*)factorsTopLeft, m128_factorsTopLeft);
3325 _mm_store_si128((__m128i*)factorsTopRight, m128_factorsTopRight);
3326 _mm_store_si128((__m128i*)factorsBottomLeft, m128_factorsBottomLeft);
3327 _mm_store_si128((__m128i*)factorsBottomRight, m128_factorsBottomRight);
3329 for (
unsigned int i = 0u; i < 4u; ++i)
3333 const uint8_t* topLeft = source + offsetsTopLeft[i];
3334 const uint8_t* topRight = source + offsetsTopRight[i];
3336 const uint8_t* bottomLeft = source + offsetsBottomLeft[i];
3337 const uint8_t* bottomRight = source + offsetsBottomRight[i];
3339 const unsigned int& factorTopLeft = factorsTopLeft[i];
3340 const unsigned int& factorTopRight = factorsTopRight[i];
3341 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
3342 const unsigned int& factorBottomRight = factorsBottomRight[i];
3344 for (
unsigned int n = 0u; n < tChannels; ++n)
3346 ((uint8_t*)targetPositionPixels)[n] = (uint8_t)((topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u);
3351 *targetPositionPixels = borderColor;
3354 targetPositionPixels++;
3360#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
3362template <
unsigned int tChannels>
3363void FrameInterpolatorBilinear::affine8BitPerChannelNEONSubset(
const uint8_t* source,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const SquareMatrix3* source_A_target,
const uint8_t* borderColor, uint8_t* target,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements)
3365 static_assert(tChannels >= 1u,
"Invalid channel number!");
3367 ocean_assert(source && target);
3368 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
3369 ocean_assert_and_suppress_unused(targetWidth >= 4u && targetHeight > 0u, targetHeight);
3370 ocean_assert(source_A_target);
3373 ocean_assert(firstTargetRow + numberTargetRows <= targetHeight);
3375 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
3376 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
3380 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3381 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3383 unsigned int validPixels[4];
3385 unsigned int topLeftOffsetsElements[4];
3386 unsigned int topRightOffsetsElements[4];
3387 unsigned int bottomLeftOffsetsElements[4];
3388 unsigned int bottomRightOffsetsElements[4];
3390 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3393 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*source_A_target)(0, 0)));
3394 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*source_A_target)(1, 0)));
3396 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
3398 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
3422 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
3423 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
3426 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3429 const uint32x4_t m128_u_sourceStrideElements = vdupq_n_u32(sourceStrideElements);
3432 const uint32x4_t m128_u_sourceWidth_1 = vdupq_n_u32(sourceWidth - 1u);
3433 const uint32x4_t m128_u_sourceHeight_1 = vdupq_n_u32(sourceHeight - 1u);
3436 const float32x4_t m128_f_sourceWidth_1 = vdupq_n_f32(
float(sourceWidth - 1u));
3437 const float32x4_t m128_f_sourceHeight_1 = vdupq_n_f32(
float(sourceHeight - 1u));
3439 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
3441 if (x + 4u > targetWidth)
3446 ocean_assert(x >= 4u && targetWidth > 4u);
3447 const unsigned int newX = targetWidth - 4u;
3449 ocean_assert(x > newX);
3450 targetRow -= x - newX;
3455 ocean_assert(!(x + 4u < targetWidth));
3461 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3462 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3465 const float32x4_t m128_f_sourceX = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3466 const float32x4_t m128_f_sourceY = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3470 const uint32x4_t m128_u_validPixelX = vandq_u32(vcleq_f32(m128_f_sourceX, m128_f_sourceWidth_1), vcgeq_f32(m128_f_sourceX, m128_f_zero));
3471 const uint32x4_t m128_u_validPixelY = vandq_u32(vcleq_f32(m128_f_sourceY, m128_f_sourceHeight_1), vcgeq_f32(m128_f_sourceY, m128_f_zero));
3473 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3477 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3478 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3481 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3482 vst1q_u32(debugValidPixels, m128_u_validPixel);
3483 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3486 targetRow[0] = *bColor;
3487 targetRow[1] = *bColor;
3488 targetRow[2] = *bColor;
3489 targetRow[3] = *bColor;
3498 vst1q_u32(validPixels, m128_u_validPixel);
3499 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3504 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_sourceX);
3505 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_sourceY);
3508 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_sourceWidth_1);
3509 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_sourceHeight_1);
3512 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3513 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3514 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3515 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3518 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3519 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3520 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3521 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3527 float32x4_t m128_f_tx = vsubq_f32(m128_f_sourceX, vcvtq_f32_u32(m128_u_left));
3528 float32x4_t m128_f_ty = vsubq_f32(m128_f_sourceY, vcvtq_f32_u32(m128_u_top));
3531 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3532 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3534 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3535 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3537 if constexpr (tChannels > 4u)
3547 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3548 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3552 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3553 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3554 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3555 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3557 unsigned int tx_ty_s[4];
3558 unsigned int txty_s[4];
3559 unsigned int tx_tys[4];
3560 unsigned int txtys[4];
3563 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3564 vst1q_u32(txty_s, m128_u_txty_);
3565 vst1q_u32(tx_tys, m128_u_tx_ty);
3566 vst1q_u32(txtys, m128_u_txty);
3568 for (
unsigned int i = 0u; i < 4u; ++i)
3572 ocean_assert(topLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3573 ocean_assert(topRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3574 ocean_assert(bottomLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3575 ocean_assert(bottomRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3577 const uint8_t* topLeft = source + topLeftOffsetsElements[i];
3578 const uint8_t* topRight = source + topRightOffsetsElements[i];
3580 const uint8_t* bottomLeft = source + bottomLeftOffsetsElements[i];
3581 const uint8_t* bottomRight = source + bottomRightOffsetsElements[i];
3583 const unsigned int tx_ty_ = tx_ty_s[i];
3584 const unsigned int txty_ = txty_s[i];
3585 const unsigned int tx_ty = tx_tys[i];
3586 const unsigned int txty = txtys[i];
3588 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3590 for (
unsigned int n = 0u; n < tChannels; ++n)
3592 ((uint8_t*)targetRow)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3597 *targetRow = *bColor;
3605 interpolate4Pixels8BitPerChannelNEON<tChannels>(source, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, targetRow);
3612template <
unsigned int tChannels>
3613void FrameInterpolatorBilinear::homography8BitPerChannelNEONSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output,
const uint8_t* borderColor, uint8_t* output,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows)
3615 static_assert(tChannels >= 1u,
"Invalid channel number!");
3617 ocean_assert(input !=
nullptr && output !=
nullptr);
3618 ocean_assert(inputWidth > 0u && inputHeight > 0u);
3619 ocean_assert_and_suppress_unused(outputWidth >= 4u && outputHeight > 0u, outputHeight);
3620 ocean_assert(input_H_output !=
nullptr);
3622 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
3624 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
3625 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
3629 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3630 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3632 unsigned int validPixels[4];
3634 unsigned int topLeftOffsetsElements[4];
3635 unsigned int topRightOffsetsElements[4];
3636 unsigned int bottomLeftOffsetsElements[4];
3637 unsigned int bottomRightOffsetsElements[4];
3639 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3642 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*input_H_output)(0, 0)));
3643 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*input_H_output)(1, 0)));
3644 const float32x4_t m128_f_X2 = vdupq_n_f32(
float((*input_H_output)(2, 0)));
3646 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
3648 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
3672 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
3673 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
3674 const float32x4_t m128_f_C2 = vdupq_n_f32(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
3677 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3680 const uint32x4_t m128_u_inputStrideElements = vdupq_n_u32(inputStrideElements);
3683 const uint32x4_t m128_u_inputWidth_1 = vdupq_n_u32(inputWidth - 1u);
3684 const uint32x4_t m128_u_inputHeight_1 = vdupq_n_u32(inputHeight - 1u);
3687 const float32x4_t m128_f_inputWidth_1 = vdupq_n_f32(
float(inputWidth - 1u));
3688 const float32x4_t m128_f_inputHeight_1 = vdupq_n_f32(
float(inputHeight - 1u));
3690 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
3692 if (x + 4u > outputWidth)
3697 ocean_assert(x >= 4u && outputWidth > 4u);
3698 const unsigned int newX = outputWidth - 4u;
3700 ocean_assert(x > newX);
3701 outputPixelData -= x - newX;
3706 ocean_assert(!(x + 4u < outputWidth));
3712 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3713 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3716 const float32x4_t m128_f_xx = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3717 const float32x4_t m128_f_yy = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3718 const float32x4_t m128_f_zz = vmlaq_f32(m128_f_C2, m128_f_X2, m128_f_x_0123);
3720#ifdef USE_DIVISION_ARM64_ARCHITECTURE
3723 const float32x4_t m128_f_inputX = vdivq_f32(m128_f_xx, m128_f_zz);
3724 const float32x4_t m128_f_inputY = vdivq_f32(m128_f_yy, m128_f_zz);
3730 float32x4_t inv_zz_128 = vrecpeq_f32(m128_f_zz);
3731 inv_zz_128 = vmulq_f32(vrecpsq_f32(m128_f_zz, inv_zz_128), inv_zz_128);
3734 const float32x4_t m128_f_inputX = vmulq_f32(m128_f_xx, inv_zz_128);
3735 const float32x4_t m128_f_inputY = vmulq_f32(m128_f_yy, inv_zz_128);
3741 const uint32x4_t m128_u_validPixelX = vandq_u32(vcleq_f32(m128_f_inputX, m128_f_inputWidth_1), vcgeq_f32(m128_f_inputX, m128_f_zero));
3742 const uint32x4_t m128_u_validPixelY = vandq_u32(vcleq_f32(m128_f_inputY, m128_f_inputHeight_1), vcgeq_f32(m128_f_inputY, m128_f_zero));
3744 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3748 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3749 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3752 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3753 vst1q_u32(debugValidPixels, m128_u_validPixel);
3754 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3757 outputPixelData[0] = *bColor;
3758 outputPixelData[1] = *bColor;
3759 outputPixelData[2] = *bColor;
3760 outputPixelData[3] = *bColor;
3762 outputPixelData += 4;
3769 vst1q_u32(validPixels, m128_u_validPixel);
3770 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3775 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_inputX);
3776 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_inputY);
3779 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_inputWidth_1);
3780 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_inputHeight_1);
3783 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3784 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3785 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3786 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3789 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3790 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3791 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3792 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3798 float32x4_t m128_f_tx = vsubq_f32(m128_f_inputX, vcvtq_f32_u32(m128_u_left));
3799 float32x4_t m128_f_ty = vsubq_f32(m128_f_inputY, vcvtq_f32_u32(m128_u_top));
3802 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3803 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3805 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3806 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3808 if constexpr (tChannels > 4u)
3818 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3819 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3823 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3824 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3825 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3826 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3828 unsigned int tx_ty_s[4];
3829 unsigned int txty_s[4];
3830 unsigned int tx_tys[4];
3831 unsigned int txtys[4];
3834 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3835 vst1q_u32(txty_s, m128_u_txty_);
3836 vst1q_u32(tx_tys, m128_u_tx_ty);
3837 vst1q_u32(txtys, m128_u_txty);
3839 for (
unsigned int i = 0u; i < 4u; ++i)
3843 ocean_assert(topLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3844 ocean_assert(topRightOffsetsElements[i] < inputStrideElements * inputHeight);
3845 ocean_assert(bottomLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3846 ocean_assert(bottomRightOffsetsElements[i] < inputStrideElements * inputHeight);
3848 const uint8_t* topLeft = input + topLeftOffsetsElements[i];
3849 const uint8_t* topRight = input + topRightOffsetsElements[i];
3851 const uint8_t* bottomLeft = input + bottomLeftOffsetsElements[i];
3852 const uint8_t* bottomRight = input + bottomRightOffsetsElements[i];
3854 const unsigned int tx_ty_ = tx_ty_s[i];
3855 const unsigned int txty_ = txty_s[i];
3856 const unsigned int tx_ty = tx_tys[i];
3857 const unsigned int txty = txtys[i];
3859 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3861 for (
unsigned int n = 0u; n < tChannels; ++n)
3863 ((uint8_t*)outputPixelData)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3868 *outputPixelData = *bColor;
3876 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, outputPixelData);
3877 outputPixelData += 4;
3884OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelNEON<1u>(
const uint8_t* source,
const unsigned int offsetsTopLeftElements[4],
const unsigned int offsetsTopRightElements[4],
const unsigned int offsetsBottomLeftElements[4],
const unsigned int offsetsBottomRightElements[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 1u>::Type& borderColor,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, 1u>::Type* targetPositionPixels)
3886 ocean_assert(source !=
nullptr);
3887 ocean_assert(targetPositionPixels !=
nullptr);
3899 for (
unsigned int i = 0u; i < 4u; ++i)
3910 pixels[i * 4u + 0u] = borderColor;
3911 pixels[i * 4u + 1u] = borderColor;
3912 pixels[i * 4u + 2u] = borderColor;
3913 pixels[i * 4u + 3u] = borderColor;
3917 static_assert(
sizeof(uint8x16_t) ==
sizeof(pixels),
"Invalid data type!");
3919 const uint8x16_t m128_pixels = vld1q_u8((
const uint8_t*)pixels);
3925 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
3926 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
3931 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
3932 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
3933 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
3934 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
3949 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
3951 const uint32x4_t m128_muliplicationA = vmulq_u32(vandq_u32(vreinterpretq_u32_u8(m128_pixels), m128_maskFirstByte), m128_factorsTopLeft);
3952 const uint32x4_t m128_muliplicationB = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 8), m128_maskFirstByte), m128_factorsTopRight);
3953 const uint32x4_t m128_muliplicationC = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 16), m128_maskFirstByte), m128_factorsBottomLeft);
3954 const uint32x4_t m128_muliplicationD = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 24), m128_maskFirstByte), m128_factorsBottomRight);
3956 const uint32x4_t m128_multiplication = vaddq_u32(vaddq_u32(m128_muliplicationA, m128_muliplicationB), vaddq_u32(m128_muliplicationC, m128_muliplicationD));
3960 const uint8x16_t m128_interpolation = vreinterpretq_u8_u32(vshrq_n_u32(vaddq_u32(m128_multiplication, vdupq_n_u32(8192u)), 14));
3970#if defined(__aarch64__)
3975 const uint8x8_t m64_interpolation01 = vtbl1_u8(vget_low_u8(m128_interpolation), m64_mask0);
3976 const uint8x8_t m64_interpolation23 = vtbl1_u8(vget_high_u8(m128_interpolation), m64_mask1);
3978 const uint8x8_t m64_interpolation0123 = vorr_u8(m64_interpolation01, m64_interpolation23);
3980 const uint32_t result = vget_lane_u32(vreinterpret_u32_u8(m64_interpolation0123), 0);
3981 memcpy(targetPositionPixels, &result,
sizeof(uint32_t));
3985 *((uint8_t*)targetPositionPixels + 0) = vgetq_lane_u8(m128_interpolation, 0);
3986 *((uint8_t*)targetPositionPixels + 1) = vgetq_lane_u8(m128_interpolation, 4);
3987 *((uint8_t*)targetPositionPixels + 2) = vgetq_lane_u8(m128_interpolation, 8);
3988 *((uint8_t*)targetPositionPixels + 3) = vgetq_lane_u8(m128_interpolation, 12);
3995 const uint8x16_t factorsLeft_factorsTop_128_u_8x16 = vsubq_u8(vdupq_n_u8(128u), factorsRight_factorsBottom_128_u_8x16);
3997 const uint8x8_t factorsRight_u_8x8 = vget_low_u8(factorsRight_factorsBottom_128_u_8x16);
3998 const uint16x8_t factorsBottom_u_16x8 = vmovl_u8(vget_high_u8(factorsRight_factorsBottom_128_u_8x16));
4000 const uint8x8_t factorsLeft_u_8x8 = vget_low_u8(factorsLeft_factorsTop_128_u_8x16);
4001 const uint16x8_t factorsTop_u_16x8 = vmovl_u8(vget_high_u8(factorsLeft_factorsTop_128_u_8x16));
4003 const uint16x8_t intermediateTop_u_16x8 = vmlal_u8(vmull_u8(topLeft_u_8x8, factorsLeft_u_8x8), topRight_u_8x8, factorsRight_u_8x8);
4004 const uint16x8_t intermediateBottom_u_16x8 = vmlal_u8(vmull_u8(bottomLeft_u_8x8, factorsLeft_u_8x8), bottomRight_u_8x8, factorsRight_u_8x8);
4006 const uint32x4_t resultA_32x4 = vmlal_u16(vmull_u16(vget_low_u16(intermediateTop_u_16x8), vget_low_u16(factorsTop_u_16x8)), vget_low_u16(intermediateBottom_u_16x8), vget_low_u16(factorsBottom_u_16x8));
4007 const uint32x4_t resultB_32x4 = vmlal_u16(vmull_u16(vget_high_u16(intermediateTop_u_16x8), vget_high_u16(factorsTop_u_16x8)), vget_high_u16(intermediateBottom_u_16x8), vget_high_u16(factorsBottom_u_16x8));
4009 const uint16x8_t result_16x8 = vcombine_u16(vrshrn_n_u32(resultA_32x4, 14), vrshrn_n_u32(resultB_32x4, 14));
4011 const uint8x8_t result_8x8 = vmovn_u16(result_16x8);
4013 vst1_u8(targetPositionPixels, result_8x8);
4017OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelNEON<2u>(
const uint8_t* source,
const unsigned int offsetsTopLeftElements[4],
const unsigned int offsetsTopRightElements[4],
const unsigned int offsetsBottomLeftElements[4],
const unsigned int offsetsBottomRightElements[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 2u>::Type& borderColor,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, 2u>::Type* targetPositionPixels)
4019 ocean_assert(source !=
nullptr);
4020 ocean_assert(targetPositionPixels !=
nullptr);
4026 PixelType topPixels[8];
4027 PixelType bottomPixels[8];
4036 for (
unsigned int i = 0u; i < 4u; ++i)
4040 *(topPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4041 *(topPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4042 *(bottomPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4043 *(bottomPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4047 *(topPixels + i * 2u + 0u) = borderColor;
4048 *(topPixels + i * 2u + 1u) = borderColor;
4049 *(bottomPixels + i * 2u + 0u) = borderColor;
4050 *(bottomPixels + i * 2u + 1u) = borderColor;
4054 static_assert(
sizeof(uint32x4_t) ==
sizeof(topPixels),
"Invalid data type!");
4056 const uint32x4_t m128_topPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topPixels));
4057 const uint32x4_t m128_bottomPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomPixels));
4063 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4064 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4069 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4070 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4071 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4072 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4075 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4077 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topPixels, m128_maskFirstByte), m128_factorsTopLeft);
4078 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4080 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4081 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4083 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4084 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4086 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4087 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4092 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4093 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4099 const uint32x4_t m128_interpolation = vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8));
4106 const uint8x8_t m64_interpolation_low = vtbl1_u8(vget_low_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask0);
4107 const uint8x8_t m64_interpolation_high = vtbl1_u8(vget_high_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask1);
4109 const uint8x8_t m64_interpolation = vorr_u8(m64_interpolation_low, m64_interpolation_high);
4116 vst1_u8((uint8_t*)targetPositionPixels, m64_interpolation);
4120OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelNEON<3u>(
const uint8_t* source,
const unsigned int offsetsTopLeftElements[4],
const unsigned int offsetsTopRightElements[4],
const unsigned int offsetsBottomLeftElements[4],
const unsigned int offsetsBottomRightElements[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 3u>::Type& borderColor,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, 3u>::Type* targetPositionPixels)
4122 ocean_assert(source !=
nullptr);
4123 ocean_assert(targetPositionPixels !=
nullptr);
4127 uint32_t topLeftPixels[4];
4128 uint32_t topRightPixels[4];
4129 uint32_t bottomLeftPixels[4];
4130 uint32_t bottomRightPixels[4];
4138 for (
unsigned int i = 0u; i < 4u; ++i)
4142 memcpy(topLeftPixels + i, source + offsetsTopLeftElements[i],
sizeof(uint8_t) * 3);
4143 memcpy(topRightPixels + i, source + offsetsTopRightElements[i],
sizeof(uint8_t) * 3);
4144 memcpy(bottomLeftPixels + i, source + offsetsBottomLeftElements[i],
sizeof(uint8_t) * 3);
4145 memcpy(bottomRightPixels + i, source + offsetsBottomRightElements[i],
sizeof(uint8_t) * 3);
4149 memcpy(topLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4150 memcpy(topRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4151 memcpy(bottomLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4152 memcpy(bottomRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4156 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4158 const uint32x4_t m128_topLeftPixels = vld1q_u32(topLeftPixels);
4159 const uint32x4_t m128_topRightPixels = vld1q_u32(topRightPixels);
4160 const uint32x4_t m128_bottomLeftPixels = vld1q_u32(bottomLeftPixels);
4161 const uint32x4_t m128_bottomRightPixels = vld1q_u32(bottomRightPixels);
4167 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4168 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4173 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4174 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4175 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4176 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4179 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4181 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4182 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4183 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4185 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4186 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4187 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4189 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4190 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4191 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4193 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4194 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4195 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4200 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4201 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4202 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4206 const uint32x4_t m128_interpolation = vorrq_u32(vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8)), vshlq_n_u32(m128_interpolation2, 16));
4212 uint32_t intermediateBuffer[4];
4213 vst1q_u32(intermediateBuffer, m128_interpolation);
4215 for (
unsigned int i = 0u; i < 4u; ++i)
4217 memcpy(targetPositionPixels + i, intermediateBuffer + i,
sizeof(uint8_t) * 3);
4222OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelNEON<4u>(
const uint8_t* source,
const unsigned int offsetsTopLeftElements[4],
const unsigned int offsetsTopRightElements[4],
const unsigned int offsetsBottomLeftElements[4],
const unsigned int offsetsBottomRightElements[4],
const unsigned int validPixels[4],
const DataType<uint8_t, 4u>::Type& borderColor,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, 4u>::Type* targetPositionPixels)
4224 ocean_assert(source !=
nullptr);
4225 ocean_assert(targetPositionPixels !=
nullptr);
4231 PixelType topLeftPixels[4];
4232 PixelType topRightPixels[4];
4233 PixelType bottomLeftPixels[4];
4234 PixelType bottomRightPixels[4];
4242 for (
unsigned int i = 0u; i < 4u; ++i)
4246 *(topLeftPixels + i) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4247 *(topRightPixels + i) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4248 *(bottomLeftPixels + i) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4249 *(bottomRightPixels + i) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4253 *(topLeftPixels + i) = borderColor;
4254 *(topRightPixels + i) = borderColor;
4255 *(bottomLeftPixels + i) = borderColor;
4256 *(bottomRightPixels + i) = borderColor;
4260 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4262 const uint32x4_t m128_topLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topLeftPixels));
4263 const uint32x4_t m128_topRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topRightPixels));
4264 const uint32x4_t m128_bottomLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomLeftPixels));
4265 const uint32x4_t m128_bottomRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomRightPixels));
4271 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4272 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4277 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4278 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4279 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4280 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4283 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4285 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4286 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4287 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4288 uint32x4_t m128_muliplicationChannel3 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 24), m128_maskFirstByte), m128_factorsTopLeft);
4290 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4291 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4292 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4293 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4295 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4296 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4297 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4298 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 24), m128_maskFirstByte), m128_factorsBottomLeft));
4300 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4301 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4302 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4303 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4308 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4309 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4310 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4311 const uint32x4_t m128_interpolation3 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel3, vdupq_n_u32(8192u)), 14);
4315 const uint32x4_t m128_interpolation = vorrq_u32(vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8)), vorrq_u32(vshlq_n_u32(m128_interpolation2, 16), vshlq_n_u32(m128_interpolation3, 24)));
4317 vst1q_u8((uint8_t*)targetPositionPixels, vreinterpretq_u8_u32(m128_interpolation));
4322 ocean_assert(targetPositionPixels !=
nullptr);
4327 uint8x8_t factorsRight_lo;
4328 uint8x8_t factorsRight_hi;
4329 uint8x8_t factorsLeft_lo;
4330 uint8x8_t factorsLeft_hi;
4331 uint8x8_t factorsBottom_lo;
4332 uint8x8_t factorsBottom_hi;
4333 uint8x8_t factorsTop_lo;
4334 uint8x8_t factorsTop_hi;
4336#if defined(__aarch64__)
4338 if (!useOptimizedNEONFactorReplication)
4340 (void)useOptimizedNEONFactorReplication;
4343 const uint8x8_t factorsRight_u8x8 = vmovn_u16(vcombine_u16(vmovn_u32(m128_factorsRight), vmovn_u32(m128_factorsRight)));
4344 const uint8x8x2_t factorsRight_zip1 = vzip_u8(factorsRight_u8x8, factorsRight_u8x8);
4345 const uint8x8x2_t factorsRight_zip2 = vzip_u8(factorsRight_zip1.val[0], factorsRight_zip1.val[0]);
4347 factorsRight_lo = factorsRight_zip2.val[0];
4348 factorsRight_hi = factorsRight_zip2.val[1];
4349 factorsLeft_lo = vsub_u8(vdup_n_u8(128u), factorsRight_lo);
4350 factorsLeft_hi = vsub_u8(vdup_n_u8(128u), factorsRight_hi);
4352 const uint8x8_t factorsBottom_u8x8 = vmovn_u16(vcombine_u16(vmovn_u32(m128_factorsBottom), vmovn_u32(m128_factorsBottom)));
4353 const uint8x8x2_t factorsBottom_zip1 = vzip_u8(factorsBottom_u8x8, factorsBottom_u8x8);
4354 const uint8x8x2_t factorsBottom_zip2 = vzip_u8(factorsBottom_zip1.val[0], factorsBottom_zip1.val[0]);
4356 factorsBottom_lo = factorsBottom_zip2.val[0];
4357 factorsBottom_hi = factorsBottom_zip2.val[1];
4358 factorsTop_lo = vsub_u8(vdup_n_u8(128u), factorsBottom_lo);
4359 factorsTop_hi = vsub_u8(vdup_n_u8(128u), factorsBottom_hi);
4361#if defined(__aarch64__)
4367 static const uint8x16_t replicateU32Idx = {0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12};
4369 const uint8x16_t factorsRight_rep = vqtbl1q_u8(vreinterpretq_u8_u32(m128_factorsRight), replicateU32Idx);
4370 const uint8x16_t factorsLeft_rep = vsubq_u8(vdupq_n_u8(128u), factorsRight_rep);
4372 factorsRight_lo = vget_low_u8(factorsRight_rep);
4373 factorsRight_hi = vget_high_u8(factorsRight_rep);
4374 factorsLeft_lo = vget_low_u8(factorsLeft_rep);
4375 factorsLeft_hi = vget_high_u8(factorsLeft_rep);
4377 const uint8x16_t factorsBottom_rep = vqtbl1q_u8(vreinterpretq_u8_u32(m128_factorsBottom), replicateU32Idx);
4378 const uint8x16_t factorsTop_rep = vsubq_u8(vdupq_n_u8(128u), factorsBottom_rep);
4380 factorsBottom_lo = vget_low_u8(factorsBottom_rep);
4381 factorsBottom_hi = vget_high_u8(factorsBottom_rep);
4382 factorsTop_lo = vget_low_u8(factorsTop_rep);
4383 factorsTop_hi = vget_high_u8(factorsTop_rep);
4388 const uint8x8_t topLeft_lo = vget_low_u8(topLeftPixels_u8x16);
4389 const uint8x8_t topLeft_hi = vget_high_u8(topLeftPixels_u8x16);
4390 const uint8x8_t topRight_lo = vget_low_u8(topRightPixels_u8x16);
4391 const uint8x8_t topRight_hi = vget_high_u8(topRightPixels_u8x16);
4392 const uint8x8_t bottomLeft_lo = vget_low_u8(bottomLeftPixels_u8x16);
4393 const uint8x8_t bottomLeft_hi = vget_high_u8(bottomLeftPixels_u8x16);
4394 const uint8x8_t bottomRight_lo = vget_low_u8(bottomRightPixels_u8x16);
4395 const uint8x8_t bottomRight_hi = vget_high_u8(bottomRightPixels_u8x16);
4399 const uint16x8_t topInterp_lo = vmlal_u8(vmull_u8(topLeft_lo, factorsLeft_lo), topRight_lo, factorsRight_lo);
4400 const uint16x8_t botInterp_lo = vmlal_u8(vmull_u8(bottomLeft_lo, factorsLeft_lo), bottomRight_lo, factorsRight_lo);
4403 const uint16x8_t factorsTop_lo_u16 = vmovl_u8(factorsTop_lo);
4404 const uint16x8_t factorsBottom_lo_u16 = vmovl_u8(factorsBottom_lo);
4406 const uint32x4_t result_lo_A = vmlal_u16(vmull_u16(vget_low_u16(topInterp_lo), vget_low_u16(factorsTop_lo_u16)), vget_low_u16(botInterp_lo), vget_low_u16(factorsBottom_lo_u16));
4407 const uint32x4_t result_lo_B = vmlal_u16(vmull_u16(vget_high_u16(topInterp_lo), vget_high_u16(factorsTop_lo_u16)), vget_high_u16(botInterp_lo), vget_high_u16(factorsBottom_lo_u16));
4410 const uint16x8_t topInterp_hi = vmlal_u8(vmull_u8(topLeft_hi, factorsLeft_hi), topRight_hi, factorsRight_hi);
4411 const uint16x8_t botInterp_hi = vmlal_u8(vmull_u8(bottomLeft_hi, factorsLeft_hi), bottomRight_hi, factorsRight_hi);
4413 const uint16x8_t factorsTop_hi_u16 = vmovl_u8(factorsTop_hi);
4414 const uint16x8_t factorsBottom_hi_u16 = vmovl_u8(factorsBottom_hi);
4416 const uint32x4_t result_hi_A = vmlal_u16(vmull_u16(vget_low_u16(topInterp_hi), vget_low_u16(factorsTop_hi_u16)), vget_low_u16(botInterp_hi), vget_low_u16(factorsBottom_hi_u16));
4417 const uint32x4_t result_hi_B = vmlal_u16(vmull_u16(vget_high_u16(topInterp_hi), vget_high_u16(factorsTop_hi_u16)), vget_high_u16(botInterp_hi), vget_high_u16(factorsBottom_hi_u16));
4420 const uint16x4_t narrow_lo_A = vrshrn_n_u32(result_lo_A, 14);
4421 const uint16x4_t narrow_lo_B = vrshrn_n_u32(result_lo_B, 14);
4422 const uint16x4_t narrow_hi_A = vrshrn_n_u32(result_hi_A, 14);
4423 const uint16x4_t narrow_hi_B = vrshrn_n_u32(result_hi_B, 14);
4425 const uint8x8_t result_lo = vmovn_u16(vcombine_u16(narrow_lo_A, narrow_lo_B));
4426 const uint8x8_t result_hi = vmovn_u16(vcombine_u16(narrow_hi_A, narrow_hi_B));
4428 vst1q_u8((uint8_t*)targetPositionPixels, vcombine_u8(result_lo, result_hi));
4431template <
unsigned int tChannels>
4432OCEAN_FORCE_INLINE
void FrameInterpolatorBilinear::interpolate4Pixels8BitPerChannelNEON(
const uint8_t* source,
const unsigned int offsetsTopLeftElements[4],
const unsigned int offsetsTopRightElements[4],
const unsigned int offsetsBottomLeftElements[4],
const unsigned int offsetsBottomRightElements[4],
const unsigned int validPixels[4],
const typename DataType<uint8_t, tChannels>::Type& borderColor,
const uint32x4_t& m128_factorsRight,
const uint32x4_t& m128_factorsBottom,
typename DataType<uint8_t, tChannels>::Type* targetPositionPixels)
4434 ocean_assert(source !=
nullptr);
4435 ocean_assert(targetPositionPixels !=
nullptr);
4439 unsigned int factorsTopLeft[4];
4440 unsigned int factorsTopRight[4];
4441 unsigned int factorsBottomLeft[4];
4442 unsigned int factorsBottomRight[4];
4448 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4449 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4454 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4455 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4456 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4457 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4461 vst1q_u32(factorsTopLeft, m128_factorsTopLeft);
4462 vst1q_u32(factorsTopRight, m128_factorsTopRight);
4463 vst1q_u32(factorsBottomLeft, m128_factorsBottomLeft);
4464 vst1q_u32(factorsBottomRight, m128_factorsBottomRight);
4466 for (
unsigned int i = 0u; i < 4u; ++i)
4470 const uint8_t* topLeft = source + offsetsTopLeftElements[i];
4471 const uint8_t* topRight = source + offsetsTopRightElements[i];
4473 const uint8_t* bottomLeft = source + offsetsBottomLeftElements[i];
4474 const uint8_t* bottomRight = source + offsetsBottomRightElements[i];
4476 const unsigned int& factorTopLeft = factorsTopLeft[i];
4477 const unsigned int& factorTopRight = factorsTopRight[i];
4478 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
4479 const unsigned int& factorBottomRight = factorsBottomRight[i];
4481 for (
unsigned int n = 0u; n < tChannels; ++n)
4483 ((uint8_t*)targetPositionPixels)[n] = (topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u;
4488 *targetPositionPixels = borderColor;
4491 targetPositionPixels++;
4497template <
unsigned int tChannels>
4498inline void FrameInterpolatorBilinear::homographies8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* homographies,
const uint8_t* borderColor, uint8_t* output,
const Scalar outputQuadrantCenterX,
const Scalar outputQuadrantCenterY,
const int outputOriginX,
const int outputOriginY,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows)
4500 static_assert(tChannels >= 1u,
"Invalid channel number!");
4502 ocean_assert(input && output);
4503 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4504 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4506 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4507 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4508 ocean_assert(homographies);
4510 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4512 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4513 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4515 constexpr uint8_t zeroColor[tChannels] = {uint8_t(0)};
4516 const uint8_t*
const bColor = borderColor ? borderColor : zeroColor;
4518 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4532 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4534 for (
unsigned int x = 0; x < outputWidth; ++x)
4538 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4539 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4543 const Scalar tx = 1 - _tx;
4544 const Scalar ty = 1 - _ty;
4546 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4547 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4548 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4549 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4551 const Scalar tTopLeft = tx * ty;
4552 const Scalar tTopRight = _tx * ty;
4553 const Scalar tBottomLeft = tx * _ty;
4554 const Scalar tBottomRight = _tx * _ty;
4556 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4557 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4559 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4561 for (
unsigned int c = 0u; c < tChannels; ++c)
4563 outputData[c] = bColor[c];
4568 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4571 outputData += tChannels;
4574 outputData += outputPaddingElements;
4578template <
unsigned int tChannels>
4579void FrameInterpolatorBilinear::homographyMask8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* input_H_output, uint8_t* output, uint8_t* outputMask,
const uint8_t maskValue,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
unsigned int firstOutputRow,
const unsigned int numberOutputRows)
4581 static_assert(tChannels >= 1u,
"Invalid channel number!");
4583 ocean_assert(input !=
nullptr && output !=
nullptr);
4584 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4585 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4586 ocean_assert(input_H_output !=
nullptr);
4588 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
4590 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4591 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4593 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4594 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4598 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4600 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4601 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
4625 const Scalar X2 = (*input_H_output)(2, 0);
4626 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
4628 for (
unsigned int x = 0; x < outputWidth; ++x)
4634 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
4637 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4639 *outputMaskData = 0xFF - maskValue;
4643 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4644 *outputMaskData = maskValue;
4653template <
unsigned int tChannels>
4654inline void FrameInterpolatorBilinear::homographiesMask8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const SquareMatrix3* homographies, uint8_t* output, uint8_t* outputMask,
const uint8_t maskValue,
const Scalar outputQuadrantCenterX,
const Scalar outputQuadrantCenterY,
const int outputOriginX,
const int outputOriginY,
const unsigned int outputWidth,
const unsigned int outputHeight,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const unsigned int firstOutputRow,
const unsigned int numberOutputRows)
4656 static_assert(tChannels >= 1u,
"Invalid channel number!");
4658 ocean_assert(input && output);
4659 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4660 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4662 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4663 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4664 ocean_assert(homographies);
4666 const unsigned int outputStrideElements = tChannels * outputWidth + outputPaddingElements;
4667 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4669 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4670 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4672 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4673 outputMask += firstOutputRow * outputMaskStrideElements;
4687 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4689 for (
unsigned int x = 0u; x < outputWidth; ++x)
4693 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4694 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4698 const Scalar tx = 1 - _tx;
4699 const Scalar ty = 1 - _ty;
4701 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4702 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4703 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4704 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4706 const Scalar tTopLeft = tx * ty;
4707 const Scalar tTopRight = _tx * ty;
4708 const Scalar tBottomLeft = tx * _ty;
4709 const Scalar tBottomRight = _tx * _ty;
4711 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4712 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4714 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4716 *outputMask = 0xFFu - maskValue;
4720 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4721 *outputMask = maskValue;
4724 outputData += tChannels;
4728 outputData += outputPaddingElements;
4729 outputMask += outputMaskPaddingElements;
4733template <
unsigned int tChannels>
4734void FrameInterpolatorBilinear::homographyWithCamera8BitPerChannelSubset(
const PinholeCamera* inputCamera,
const PinholeCamera* outputCamera,
const PinholeCamera::DistortionLookup* outputCameraDistortionLookup,
const uint8_t* input,
const SquareMatrix3* normalizedHomography,
const bool useDistortionParameters,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows)
4736 static_assert(tChannels >= 1u,
"Invalid channel number!");
4738 ocean_assert(inputCamera && outputCamera && normalizedHomography);
4739 ocean_assert(input && output);
4741 ocean_assert(firstRow + numberRows <= outputCamera->height());
4743 const unsigned int outputStrideElements = tChannels * outputCamera->
width() + outputPaddingElements;
4752 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4753 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4755 uint8_t* outputData = output + firstRow * outputStrideElements;
4757 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4759 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4763 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4765 *((PixelType*)outputData) = *bColor;
4769 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4772 outputData += tChannels;
4775 outputData += outputPaddingElements;
4779template <
unsigned int tChannels>
4780void FrameInterpolatorBilinear::homographyWithCameraMask8BitPerChannelSubset(
const PinholeCamera* inputCamera,
const PinholeCamera* outputCamera,
const PinholeCamera::DistortionLookup* outputCameraDistortionLookup,
const uint8_t* input,
const unsigned int inputPaddingElements,
const SquareMatrix3* normalizedHomography, uint8_t* output, uint8_t* outputMask,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const uint8_t maskValue,
const unsigned int firstRow,
const unsigned int numberRows)
4782 static_assert(tChannels >= 1u,
"Invalid channel number!");
4784 ocean_assert(inputCamera !=
nullptr && outputCamera !=
nullptr && normalizedHomography !=
nullptr);
4785 ocean_assert(input !=
nullptr && output !=
nullptr);
4787 ocean_assert(firstRow + numberRows <= outputCamera->height());
4789 const unsigned int outputStrideElements = outputCamera->
width() * tChannels + outputPaddingElements;
4790 const unsigned int outputMaskStrideElements = outputCamera->
width() + outputMaskPaddingElements;
4797 uint8_t* outputData = output + firstRow * outputStrideElements;
4798 outputMask += firstRow * outputMaskStrideElements;
4800 constexpr bool useDistortionParameters =
true;
4802 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4804 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4808 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4810 *outputMask = 0xFF - maskValue;
4814 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4815 *outputMask = maskValue;
4818 outputData += tChannels;
4822 outputData += outputPaddingElements;
4823 outputMask += outputMaskPaddingElements;
4827template <
unsigned int tChannels>
4828void FrameInterpolatorBilinear::lookup8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows)
4830 static_assert(tChannels >= 1u,
"Invalid channel number!");
4832 ocean_assert(input_LT_output !=
nullptr);
4833 ocean_assert(input !=
nullptr && output !=
nullptr);
4835 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4836 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4840 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4841 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4847 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4849 if (
size_t(columns) != input_LT_output->
sizeX())
4851 ocean_assert(
false &&
"Lookup table is wider than 32 bits!");
4855 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4857 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4862 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4865 if (rowLookupData ==
nullptr)
4869 ocean_assert(
false &&
"Failed to allocate the row lookup buffer!");
4873 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4877 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4879 for (
unsigned int x = 0u; x < columns; ++x)
4881 const Vector2& lookupValue = rowLookupData[x];
4885 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4887 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4891 *outputData = *bColor;
4899template <
typename T,
unsigned int tChannels>
4900void FrameInterpolatorBilinear::lookupSubset(
const T* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const T* borderColor, T* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows)
4902 static_assert(tChannels >= 1u,
"Invalid channel number!");
4904 ocean_assert((!std::is_same<uint8_t, T>::value));
4906 ocean_assert(input_LT_output !=
nullptr);
4907 ocean_assert(input !=
nullptr && output !=
nullptr);
4909 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4910 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4914 const T zeroColor[tChannels] = {T(0)};
4915 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4921 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4923 if (
size_t(columns) != input_LT_output->
sizeX())
4925 ocean_assert(
false &&
"Lookup table is wider than 32 bits!");
4929 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4931 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4936 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4939 if (rowLookupData ==
nullptr)
4943 ocean_assert(
false &&
"Failed to allocate the row lookup buffer!");
4947 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4951 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4953 for (
unsigned int x = 0u; x < columns; ++x)
4955 const Vector2& lookupValue = rowLookupData[x];
4959 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4961 interpolatePixel<T, T, tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputData));
4965 *outputData = *bColor;
4973#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
4976inline void FrameInterpolatorBilinear::lookup8BitPerChannelSubsetNEON<1u>(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows,
const bool useOptimizedNEON,
const bool useOptimizedBilinearValuesAndFactorCalculation,
const bool )
4978 ocean_assert(input_LT_output !=
nullptr);
4979 ocean_assert(input !=
nullptr && output !=
nullptr);
4981 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4982 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4984 using PixelType = uint8_t;
4986 const uint8x16_t constantBorderColor_u_8x16 = vdupq_n_u8(borderColor ? *borderColor : 0u);
4992 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
4994 if (
size_t(outputWidth) != input_LT_output->
sizeX())
4996 ocean_assert(
false &&
"Lookup table is wider than 32 bits!");
5000 ocean_assert(outputWidth >= 8u);
5002 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5004 const unsigned int inputStrideElements = inputWidth + inputPaddingElements;
5005 const unsigned int outputStrideElements = outputWidth + outputPaddingElements;
5007 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
5010 if (rowLookupData ==
nullptr)
5014 ocean_assert(
false &&
"Failed to allocate the row lookup buffer!");
5018 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
5019 const float32x4_t constantEight_f_32x4 = vdupq_n_f32(8.0f);
5022 const float f_01234567[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
5023 const float32x4_t conststant0123_f_32x4 = vld1q_f32(f_01234567 + 0);
5024 const float32x4_t conststant4567_f_32x4 = vld1q_f32(f_01234567 + 4);
5026 const float32x4_t constant128_f_32x4 = vdupq_n_f32(128.0f);
5028 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
5030 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(1u);
5032 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
5033 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
5035 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
5036 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
5038 unsigned int validPixels[8];
5040 unsigned int topLeftOffsetsElements[8];
5041 unsigned int bottomLeftOffsetsElements[8];
5045 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5047 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
5051 float32x4_t additionalInputOffsetX0123_f_32x4 = conststant0123_f_32x4;
5052 float32x4_t additionalInputOffsetX4567_f_32x4 = conststant4567_f_32x4;
5054 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
5056 for (
unsigned int x = 0u; x < outputWidth; x += 8u)
5058 if (x + 8u > outputWidth)
5063 ocean_assert(x >= 8u && outputWidth > 8u);
5064 const unsigned int newX = outputWidth - 8u;
5066 ocean_assert(x > newX);
5067 const unsigned int xOffset = x - newX;
5069 outputPixelData -= xOffset;
5073 additionalInputOffsetX0123_f_32x4 = vsubq_f32(additionalInputOffsetX0123_f_32x4, vdupq_n_f32(
float(xOffset)));
5074 additionalInputOffsetX4567_f_32x4 = vsubq_f32(additionalInputOffsetX4567_f_32x4, vdupq_n_f32(
float(xOffset)));
5080 ocean_assert(!(x + 8u < outputWidth));
5083 const float32x4x2_t inputPositions0123_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 0u));
5084 const float32x4x2_t inputPositions4567_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 4u));
5086 float32x4_t inputPositionsX0123_f_32x4 = inputPositions0123_f_32x4x2.val[0];
5087 float32x4_t inputPositionsY0123_f_32x4 = inputPositions0123_f_32x4x2.val[1];
5089 float32x4_t inputPositionsX4567_f_32x4 = inputPositions4567_f_32x4x2.val[0];
5090 float32x4_t inputPositionsY4567_f_32x4 = inputPositions4567_f_32x4x2.val[1];
5094 inputPositionsX0123_f_32x4 = vaddq_f32(inputPositionsX0123_f_32x4, additionalInputOffsetX0123_f_32x4);
5095 inputPositionsY0123_f_32x4 = vaddq_f32(inputPositionsY0123_f_32x4, additionalInputOffsetY_f_32x4);
5097 inputPositionsX4567_f_32x4 = vaddq_f32(inputPositionsX4567_f_32x4, additionalInputOffsetX4567_f_32x4);
5098 inputPositionsY4567_f_32x4 = vaddq_f32(inputPositionsY4567_f_32x4, additionalInputOffsetY_f_32x4);
5100 additionalInputOffsetX0123_f_32x4 = vaddq_f32(additionalInputOffsetX0123_f_32x4, constantEight_f_32x4);
5101 additionalInputOffsetX4567_f_32x4 = vaddq_f32(additionalInputOffsetX4567_f_32x4, constantEight_f_32x4);
5105 const uint32x4_t validPixelsX0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX0123_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX0123_f_32x4, constantZero_f_32x4));
5106 const uint32x4_t validPixelsX4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX4567_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX4567_f_32x4, constantZero_f_32x4));
5108 const uint32x4_t validPixelsY0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY0123_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY0123_f_32x4, constantZero_f_32x4));
5109 const uint32x4_t validPixelsY4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY4567_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY4567_f_32x4, constantZero_f_32x4));
5111 const uint32x4_t validPixels0123_u_32x4 = vandq_u32(validPixelsX0123_u_32x4, validPixelsY0123_u_32x4);
5112 const uint32x4_t validPixels4567_u_32x4 = vandq_u32(validPixelsX4567_u_32x4, validPixelsY4567_u_32x4);
5114 vst1q_u32(validPixels + 0, validPixels0123_u_32x4);
5115 vst1q_u32(validPixels + 4, validPixels4567_u_32x4);
5118 const uint32x4_t inputPositionsLeft0123_u_32x4 = vcvtq_u32_f32(inputPositionsX0123_f_32x4);
5119 const uint32x4_t inputPositionsLeft4567_u_32x4 = vcvtq_u32_f32(inputPositionsX4567_f_32x4);
5121 const uint32x4_t inputPositionsTop0123_u_32x4 = vcvtq_u32_f32(inputPositionsY0123_f_32x4);
5122 const uint32x4_t inputPositionsTop4567_u_32x4 = vcvtq_u32_f32(inputPositionsY4567_f_32x4);
5124 const uint32x4_t inputPositionsBottom0123_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop0123_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
5125 const uint32x4_t inputPositionsBottom4567_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop4567_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
5128 const uint32x4_t topLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsTop0123_u_32x4, constantInputStrideElements_u_32x4);
5129 vst1q_u32(topLeftOffsetsElements + 0, topLeftOffsetsElements0123_u_32x4);
5130 const uint32x4_t topLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsTop4567_u_32x4, constantInputStrideElements_u_32x4);
5131 vst1q_u32(topLeftOffsetsElements + 4, topLeftOffsetsElements4567_u_32x4);
5133 const uint32x4_t bottomLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsBottom0123_u_32x4, constantInputStrideElements_u_32x4);
5134 vst1q_u32(bottomLeftOffsetsElements + 0, bottomLeftOffsetsElements0123_u_32x4);
5135 const uint32x4_t bottomLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsBottom4567_u_32x4, constantInputStrideElements_u_32x4);
5136 vst1q_u32(bottomLeftOffsetsElements + 4, bottomLeftOffsetsElements4567_u_32x4);
5140 float32x4_t tx0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX0123_f_32x4, vcvtq_f32_u32(inputPositionsLeft0123_u_32x4)), constant128_f_32x4);
5141 float32x4_t tx4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX4567_f_32x4, vcvtq_f32_u32(inputPositionsLeft4567_u_32x4)), constant128_f_32x4);
5143 float32x4_t ty0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY0123_f_32x4, vcvtq_f32_u32(inputPositionsTop0123_u_32x4)), constant128_f_32x4);
5144 float32x4_t ty4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY4567_f_32x4, vcvtq_f32_u32(inputPositionsTop4567_u_32x4)), constant128_f_32x4);
5146 const uint32x4_t tx0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx0123_f_32x4, vdupq_n_f32(0.5)));
5147 const uint32x4_t tx4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx4567_f_32x4, vdupq_n_f32(0.5)));
5149 const uint32x4_t ty0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty0123_f_32x4, vdupq_n_f32(0.5)));
5150 const uint32x4_t ty4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty4567_f_32x4, vdupq_n_f32(0.5)));
5152 const uint16x8_t tx01234567_128_u_16x8 = vcombine_u16(vmovn_u32(tx0123_128_u_32x4), vmovn_u32(tx4567_128_u_32x4));
5153 const uint16x8_t ty01234567_128_u_16x8 = vcombine_u16(vmovn_u32(ty0123_128_u_32x4), vmovn_u32(ty4567_128_u_32x4));
5155 const uint8x16_t tx_ty_128_u_8x16 = vcombine_u8(vmovn_u16(tx01234567_128_u_16x8), vmovn_u16(ty01234567_128_u_16x8));
5158 vst1q_u8(pixels + 0, constantBorderColor_u_8x16);
5159 vst1q_u8(pixels + 16, constantBorderColor_u_8x16);
5161 struct LeftRightPixel
5167 static_assert(
sizeof(LeftRightPixel) == 2,
"Invalid data type!");
5171 for (
unsigned int i = 0u; i < 8u; ++i)
5175 ocean_assert((topLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
5176 ocean_assert((bottomLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
5178 ((LeftRightPixel*)pixels)[0u + i] = *(LeftRightPixel*)(input + topLeftOffsetsElements[i]);
5179 ((LeftRightPixel*)pixels)[8u + i] = *(LeftRightPixel*)(input + bottomLeftOffsetsElements[i]);
5183 const uint8x8x2_t topLeft_topRight_u_8x8x2 = vld2_u8(pixels);
5184 const uint8x8x2_t bottomLeft_bottomRight_u_8x8x2 = vld2_u8(pixels + 16);
5186 interpolate8Pixels1Channel8BitNEON(topLeft_topRight_u_8x8x2.val[0], topLeft_topRight_u_8x8x2.val[1], bottomLeft_bottomRight_u_8x8x2.val[0], bottomLeft_bottomRight_u_8x8x2.val[1], tx_ty_128_u_8x16, outputPixelData);
5188 outputPixelData += 8;
5193template <
unsigned int tChannels>
5194void FrameInterpolatorBilinear::lookup8BitPerChannelSubsetNEON(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset,
const uint8_t* borderColor, uint8_t* output,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows,
const bool useOptimizedNEON,
const bool useOptimizedBilinearValuesAndFactorCalculation,
const bool useOptimizedNEONFactorReplication)
5196 ocean_assert(input_LT_output !=
nullptr);
5197 ocean_assert(input !=
nullptr && output !=
nullptr);
5199 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5200 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5204 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
5205 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
5211 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
5213 if (
size_t(outputWidth) != input_LT_output->
sizeX())
5215 ocean_assert(
false &&
"Lookup table is wider than 32 bits!");
5219 ocean_assert(outputWidth >= 4u);
5221 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5223 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
5224 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
5226 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
5229 if (rowLookupData ==
nullptr)
5233 ocean_assert(
false &&
"Failed to allocate the row lookup buffer!");
5237 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
5238 const float32x4_t constantFour_f_32x4 = vdupq_n_f32(4.0f);
5241 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
5242 float32x4_t conststant0123_f_32x4 = vld1q_f32(f_0123);
5244 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
5246 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
5248 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
5249 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
5251#if defined(__aarch64__)
5252 const float32x4_t constant128_f_32x4 = vdupq_n_f32(128.0f);
5255 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
5256 const uint32x4_t constantInputWidth1_u_32x4 = vdupq_n_u32(inputWidth - 1u);
5257 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
5259 unsigned int validPixels[4];
5261 unsigned int topLeftOffsetsElements[4];
5262 unsigned int topRightOffsetsElements[4];
5263 unsigned int bottomLeftOffsetsElements[4];
5264 unsigned int bottomRightOffsetsElements[4];
5266 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5268 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
5270 input_LT_output->
bilinearValues<
VectorF2>(y, rowLookupData, useOptimizedBilinearValuesAndFactorCalculation);
5272 float32x4_t additionalInputOffsetX_f_32x4 = conststant0123_f_32x4;
5273 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
5275 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
5277 if (x + 4u > outputWidth)
5282 ocean_assert(x >= 4u && outputWidth > 4u);
5283 const unsigned int newX = outputWidth - 4u;
5285 ocean_assert(x > newX);
5286 const unsigned int xOffset = x - newX;
5288 outputPixelData -= xOffset;
5292 additionalInputOffsetX_f_32x4 = vsubq_f32(additionalInputOffsetX_f_32x4, vdupq_n_f32(
float(xOffset)));
5298 ocean_assert(!(x + 4u < outputWidth));
5301 const float32x4x2_t inputPositions_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x));
5303 float32x4_t inputPositionsX_f_32x4 = inputPositions_f_32x4x2.val[0];
5304 float32x4_t inputPositionsY_f_32x4 = inputPositions_f_32x4x2.val[1];
5308 inputPositionsX_f_32x4 = vaddq_f32(inputPositionsX_f_32x4, additionalInputOffsetX_f_32x4);
5309 inputPositionsY_f_32x4 = vaddq_f32(inputPositionsY_f_32x4, additionalInputOffsetY_f_32x4);
5311 additionalInputOffsetX_f_32x4 = vaddq_f32(additionalInputOffsetX_f_32x4, constantFour_f_32x4);
5315 const uint32x4_t validPixelsX_u_32x4 = vandq_u32(vcleq_f32(inputPositionsX_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX_f_32x4, constantZero_f_32x4));
5316 const uint32x4_t validPixelsY_u_32x4 = vandq_u32(vcleq_f32(inputPositionsY_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY_f_32x4, constantZero_f_32x4));
5318 const uint32x4_t validPixels_u_32x4 = vandq_u32(validPixelsX_u_32x4, validPixelsY_u_32x4);
5320 vst1q_u32(validPixels, validPixels_u_32x4);
5322 const uint32x4_t inputPositionsLeft_u_32x4 = vcvtq_u32_f32(inputPositionsX_f_32x4);
5323 const uint32x4_t inputPositionsTop_u_32x4 = vcvtq_u32_f32(inputPositionsY_f_32x4);
5325 const uint32x4_t inputPositionsRight_u_32x4 = vminq_u32(vaddq_u32(inputPositionsLeft_u_32x4, constantOne_u_32x4), constantInputWidth1_u_32x4);
5326 const uint32x4_t inputPositionsBottom_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
5328 const uint32x4_t topLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5329 const uint32x4_t topRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5330 const uint32x4_t bottomLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5331 const uint32x4_t bottomRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5334 uint32x4_t tx_128_u_32x4;
5335 uint32x4_t ty_128_u_32x4;
5337#if defined(__aarch64__)
5339 if (useOptimizedBilinearValuesAndFactorCalculation)
5342 const float32x4_t tx_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX_f_32x4, vrndmq_f32(inputPositionsX_f_32x4)), constant128_f_32x4);
5343 const float32x4_t ty_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY_f_32x4, vrndmq_f32(inputPositionsY_f_32x4)), constant128_f_32x4);
5345 tx_128_u_32x4 = vcvtaq_u32_f32(tx_f_32x4);
5346 ty_128_u_32x4 = vcvtaq_u32_f32(ty_f_32x4);
5352 float32x4_t tx_f_32x4 = vsubq_f32(inputPositionsX_f_32x4, vcvtq_f32_u32(inputPositionsLeft_u_32x4));
5353 float32x4_t ty_f_32x4 = vsubq_f32(inputPositionsY_f_32x4, vcvtq_f32_u32(inputPositionsTop_u_32x4));
5356 tx_f_32x4 = vmulq_f32(tx_f_32x4, vdupq_n_f32(128.0f));
5357 ty_f_32x4 = vmulq_f32(ty_f_32x4, vdupq_n_f32(128.0f));
5359 tx_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx_f_32x4, vdupq_n_f32(0.5)));
5360 ty_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty_f_32x4, vdupq_n_f32(0.5)));
5363 if constexpr (tChannels == 4u)
5365 if (useOptimizedNEON)
5371 PixelType topLeftPixels[4];
5372 PixelType topRightPixels[4];
5373 PixelType bottomLeftPixels[4];
5374 PixelType bottomRightPixels[4];
5376 topLeftPixels[0] = validPixels[0] ? *((
const PixelType*)(input + vgetq_lane_u32(topLeftOffsetsElements_u_32x4, 0))) : *bColor;
5377 topLeftPixels[1] = validPixels[1] ? *((
const PixelType*)(input + vgetq_lane_u32(topLeftOffsetsElements_u_32x4, 1))) : *bColor;
5378 topLeftPixels[2] = validPixels[2] ? *((
const PixelType*)(input + vgetq_lane_u32(topLeftOffsetsElements_u_32x4, 2))) : *bColor;
5379 topLeftPixels[3] = validPixels[3] ? *((
const PixelType*)(input + vgetq_lane_u32(topLeftOffsetsElements_u_32x4, 3))) : *bColor;
5381 topRightPixels[0] = validPixels[0] ? *((
const PixelType*)(input + vgetq_lane_u32(topRightOffsetsElements_u_32x4, 0))) : *bColor;
5382 topRightPixels[1] = validPixels[1] ? *((
const PixelType*)(input + vgetq_lane_u32(topRightOffsetsElements_u_32x4, 1))) : *bColor;
5383 topRightPixels[2] = validPixels[2] ? *((
const PixelType*)(input + vgetq_lane_u32(topRightOffsetsElements_u_32x4, 2))) : *bColor;
5384 topRightPixels[3] = validPixels[3] ? *((
const PixelType*)(input + vgetq_lane_u32(topRightOffsetsElements_u_32x4, 3))) : *bColor;
5386 bottomLeftPixels[0] = validPixels[0] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomLeftOffsetsElements_u_32x4, 0))) : *bColor;
5387 bottomLeftPixels[1] = validPixels[1] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomLeftOffsetsElements_u_32x4, 1))) : *bColor;
5388 bottomLeftPixels[2] = validPixels[2] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomLeftOffsetsElements_u_32x4, 2))) : *bColor;
5389 bottomLeftPixels[3] = validPixels[3] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomLeftOffsetsElements_u_32x4, 3))) : *bColor;
5391 bottomRightPixels[0] = validPixels[0] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomRightOffsetsElements_u_32x4, 0))) : *bColor;
5392 bottomRightPixels[1] = validPixels[1] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomRightOffsetsElements_u_32x4, 1))) : *bColor;
5393 bottomRightPixels[2] = validPixels[2] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomRightOffsetsElements_u_32x4, 2))) : *bColor;
5394 bottomRightPixels[3] = validPixels[3] ? *((
const PixelType*)(input + vgetq_lane_u32(bottomRightOffsetsElements_u_32x4, 3))) : *bColor;
5396 const uint8x16_t topLeftPixels_u8x16 = vld1q_u8((
const uint8_t*)topLeftPixels);
5397 const uint8x16_t topRightPixels_u8x16 = vld1q_u8((
const uint8_t*)topRightPixels);
5398 const uint8x16_t bottomLeftPixels_u8x16 = vld1q_u8((
const uint8_t*)bottomLeftPixels);
5399 const uint8x16_t bottomRightPixels_u8x16 = vld1q_u8((
const uint8_t*)bottomRightPixels);
5401 interpolate4Pixels4Channel8BitPerChannelNEON(topLeftPixels_u8x16, topRightPixels_u8x16, bottomLeftPixels_u8x16, bottomRightPixels_u8x16, tx_128_u_32x4, ty_128_u_32x4, outputPixelData, useOptimizedNEONFactorReplication);
5405 vst1q_u32(topLeftOffsetsElements, topLeftOffsetsElements_u_32x4);
5406 vst1q_u32(topRightOffsetsElements, topRightOffsetsElements_u_32x4);
5407 vst1q_u32(bottomLeftOffsetsElements, bottomLeftOffsetsElements_u_32x4);
5408 vst1q_u32(bottomRightOffsetsElements, bottomRightOffsetsElements_u_32x4);
5410 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, tx_128_u_32x4, ty_128_u_32x4, outputPixelData);
5415 vst1q_u32(topLeftOffsetsElements, topLeftOffsetsElements_u_32x4);
5416 vst1q_u32(topRightOffsetsElements, topRightOffsetsElements_u_32x4);
5417 vst1q_u32(bottomLeftOffsetsElements, bottomLeftOffsetsElements_u_32x4);
5418 vst1q_u32(bottomRightOffsetsElements, bottomRightOffsetsElements_u_32x4);
5420 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, tx_128_u_32x4, ty_128_u_32x4, outputPixelData);
5423 outputPixelData += 4;
5430template <
unsigned int tChannels>
5431void FrameInterpolatorBilinear::lookupMask8BitPerChannelSubset(
const uint8_t* input,
const unsigned int inputWidth,
const unsigned int inputHeight,
const LookupTable* input_LT_output,
const bool offset, uint8_t* output, uint8_t* outputMask,
const uint8_t maskValue,
const unsigned int inputPaddingElements,
const unsigned int outputPaddingElements,
const unsigned int outputMaskPaddingElements,
const unsigned int firstRow,
const unsigned int numberRows)
5433 ocean_assert(input_LT_output !=
nullptr);
5434 ocean_assert(input !=
nullptr && output !=
nullptr);
5436 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5437 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5445 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
5447 if (
size_t(columns) != input_LT_output->
sizeX())
5449 ocean_assert(
false &&
"Lookup table is wider than 32 bits!");
5453 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
5454 const unsigned int outputMaskStrideElements = columns + outputMaskPaddingElements;
5456 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5461 Memory rowLookupMemory = Memory::create<Vector2>(columns);
5464 if (rowLookupData ==
nullptr)
5468 ocean_assert(
false &&
"Failed to allocate the row lookup buffer!");
5472 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5476 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
5477 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
5479 for (
unsigned int x = 0u; x < columns; ++x)
5481 const Vector2& lookupValue = rowLookupData[x];
5485 if (inputPosition.
x() >= 0 && inputPosition.
y() >= 0 && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
5487 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
5488 *outputMaskData = maskValue;
5492 *outputMaskData = 0xFFu - maskValue;
5501template <
unsigned int tChannels>
5502void FrameInterpolatorBilinear::scale8BitPerChannel(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker)
5504 ocean_assert(source !=
nullptr && target !=
nullptr);
5505 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
5506 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
5507 ocean_assert(sourceX_s_targetX > 0.0);
5508 ocean_assert(sourceY_s_targetY > 0.0);
5510 if (sourceWidth == targetWidth && sourceHeight == targetHeight && sourceX_s_targetX == 1.0 && sourceY_s_targetY == 1.0)
5512 FrameConverter::subFrame<uint8_t>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
5516 if (worker && sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5518#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5519 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5521 worker->
executeFunction(
Worker::Function::createStatic(&
scale8BitPerChannelSubset7BitPrecisionNEON, source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, targetHeight);
5525 worker->
executeFunction(
Worker::Function::createStatic(&scale8BitPerChannelSubset<tChannels>, source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, targetHeight);
5530 if (sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5532#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5533 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5535 scale8BitPerChannelSubset7BitPrecisionNEON(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5541 scale8BitPerChannelSubset<tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5545template <
unsigned int tChannels>
5546void FrameInterpolatorBilinear::scale8BitPerChannelSubset(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
5548 ocean_assert(source !=
nullptr && target !=
nullptr);
5549 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
5550 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
5551 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5553 const Scalar sourceX_T_targetX =
Scalar(sourceX_s_targetX);
5554 const Scalar sourceY_T_targetY =
Scalar(sourceY_s_targetY);
5602 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
5604 const Scalar sourceX_T_targetXOffset = sourceX_T_targetX *
Scalar(0.5) -
Scalar(0.5);
5605 const Scalar sourceY_T_targetYOffset = sourceY_T_targetY *
Scalar(0.5) -
Scalar(0.5);
5608 const Scalar sourceHeight_1 =
Scalar(sourceHeight - 1u);
5610 target += (targetWidth * tChannels + targetPaddingElements) * firstTargetRow;
5612 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5615 ocean_assert(sy >=
Scalar(0) && sy <
Scalar(sourceHeight));
5617 const unsigned int sTop = (
unsigned int)sy;
5618 ocean_assert(sy >=
Scalar(sTop));
5621 ocean_assert(ty >= 0 && ty <= 1);
5623 const unsigned int factorBottom = (
unsigned int)(ty *
Scalar(128) +
Scalar(0.5));
5624 const unsigned int factorTop = 128u - factorBottom;
5626 const uint8_t*
const sourceTop = source + sourceStrideElements * sTop;
5627 const uint8_t*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
5629 for (
unsigned int x = 0; x < targetWidth; ++x)
5632 ocean_assert(sx >=
Scalar(0) && sx <
Scalar(sourceWidth));
5634 const unsigned int sLeft = (
unsigned int)sx;
5635 ocean_assert(sx >=
Scalar(sLeft));
5638 ocean_assert(tx >= 0 && tx <= 1);
5640 const unsigned int factorRight = (
unsigned int)(tx *
Scalar(128) +
Scalar(0.5));
5641 const unsigned int factorLeft = 128u - factorRight;
5643 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
5645 const uint8_t*
const sourceTopLeft = sourceTop + sLeft * tChannels;
5646 const uint8_t*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
5648 const unsigned int factorTopLeft = factorTop * factorLeft;
5649 const unsigned int factorTopRight = factorTop * factorRight;
5650 const unsigned int factorBottomLeft = factorBottom * factorLeft;
5651 const unsigned int factorBottomRight = factorBottom * factorRight;
5653 for (
unsigned int n = 0u; n < tChannels; ++n)
5655 target[n] = (uint8_t)((sourceTopLeft[n] * factorTopLeft + sourceTopLeft[sourceRightOffset + n] * factorTopRight
5656 + sourceBottomLeft[n] * factorBottomLeft + sourceBottomLeft[sourceRightOffset + n] * factorBottomRight + 8192u) >> 14u);
5659 target += tChannels;
5662 target += targetPaddingElements;
5666template <
typename T>
5669 ocean_assert(sourceRowTop !=
nullptr);
5670 ocean_assert(sourceRowBottom !=
nullptr);
5671 ocean_assert(targetRow !=
nullptr);
5672 ocean_assert(elements >= 1u);
5673 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
5677 const FloatType internalFactorBottom = FloatType(factorBottom);
5678 const FloatType internalFactorTop = FloatType(1.0f - factorBottom);
5680 for (
unsigned int n = 0u; n < elements; ++n)
5682 targetRow[n] = T(FloatType(sourceRowTop[n]) * internalFactorTop + FloatType(sourceRowBottom[n]) * internalFactorBottom);
5686template <
typename T,
unsigned int tChannels>
5689 static_assert(tChannels != 0u,
"Invalid channel number!");
5691 ocean_assert(extendedSourceRow !=
nullptr);
5692 ocean_assert(targetRow !=
nullptr);
5693 ocean_assert(targetWidth >= 1u);
5694 ocean_assert(interpolationLocations !=
nullptr);
5695 ocean_assert(interpolationFactorsRight !=
nullptr);
5696 ocean_assert_and_suppress_unused(channels == tChannels, channels);
5700 for (
unsigned int x = 0u; x < targetWidth; ++x)
5702 const FloatType internalFactorRight = FloatType(interpolationFactorsRight[x]);
5703 ocean_assert(internalFactorRight >= FloatType(0) && internalFactorRight <= FloatType(1));
5705 const FloatType internalFactorLeft = FloatType(1.0f - interpolationFactorsRight[x]);
5707 const unsigned int& leftLocation = interpolationLocations[x];
5708 const unsigned int rightLocation = leftLocation + tChannels;
5710 for (
unsigned int n = 0u; n < tChannels; ++n)
5712 targetRow[x * tChannels + n] = T(FloatType(extendedSourceRow[leftLocation + n]) * internalFactorLeft + FloatType(extendedSourceRow[rightLocation + n]) * internalFactorRight);
5717#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5719#ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5722inline void FrameInterpolatorBilinear::scale8BitPerChannelSubset7BitPrecisionNEON<2u, 8u>(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
5724 ocean_assert(source !=
nullptr && target !=
nullptr);
5725 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5726 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5727 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5728 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5729 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5731 ocean_assert(sourcePaddingElements == 0u);
5732 ocean_assert(targetPaddingElements == 0u);
5736 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5737 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5740 unsigned int leftOffsets[8];
5753 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5754 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5756 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5757 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5760 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5763 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5766 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5769 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5771 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5772 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5774 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5776 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5778 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5779 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5780 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5782 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5784 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5786 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5788 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5789 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5791 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5793 if (x + 8u > targetWidth)
5798 ocean_assert(x >= 8u && targetWidth > 8u);
5799 const unsigned int newX = targetWidth - 8u;
5801 ocean_assert(x > newX);
5802 targetPixelData -= x - newX;
5807 ocean_assert(!(x + 8u < targetWidth));
5813 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5814 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5817 const int32x4_t m128_s_sourceX_0123_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_0123))));
5818 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5820 const int32x4_t m128_s_sourceX_4567_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_4567))));
5821 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5825 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5826 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5829 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5830 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5837 uint8x8x2_t topLeftPixels;
5838 uint8x8x2_t topRightPixels;
5840 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
5841 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
5843 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
5844 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
5846 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
5847 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
5849 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
5850 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
5852 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
5853 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
5855 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
5856 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
5858 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
5859 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
5861 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
5862 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
5867 uint8x8x2_t bottomLeftPixels;
5868 uint8x8x2_t bottomRightPixels;
5870 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
5871 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
5873 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
5874 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
5876 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
5877 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
5879 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
5880 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
5882 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
5883 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
5885 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
5886 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
5888 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
5889 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
5891 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
5892 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
5900 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5901 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5904 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5905 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5906 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5911 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
5912 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
5914 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
5915 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
5917 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5918 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5923 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
5924 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
5926 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
5927 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
5929 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5930 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5935 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
5936 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
5938 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
5939 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
5944 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5945 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5948 vst2_u8((uint8_t*)targetPixelData, result);
5950 targetPixelData += 8;
5956 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5958 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5960 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5962 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5963 ocean_assert(lastSourcePixelLeft < sourceWidth);
5964 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5966 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5968 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5969 const unsigned int factorLeft = 128u - factorRight;
5971 for (
unsigned int c = 0u; c < 2u; ++c)
5973 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5974 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5982#ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_SLIGHTLY_DIFFERENT_APPROACH
5985inline void FrameInterpolatorBilinear::scale8BitPerChannelSubset7BitPrecisionNEON<2u, 8u>(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
5987 ocean_assert(source !=
nullptr && target !=
nullptr);
5988 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5989 ocean_assert(sourceHeight >= 0u && sourceHeight <= 65535u);
5990 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u)
5991 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5992 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5994 ocean_assert(sourcePaddingElements == 0u);
5995 ocean_assert(targetPaddingElements == 0u);
5997 using PixelType = typename
DataType<uint8_t, 2u>::Type;
5999 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
6000 const PixelType* const sourcePixelData = (const PixelType*)source;
6003 unsigned int leftOffsets[8];
6006 unsigned int topPixels[8];
6007 unsigned int bottomPixels[8];
6020 const
unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
6021 const
unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6023 const
int targetOffsetX_fixed16 = (
int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
6024 const
int targetOffsetY_fixed16 = (
int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
6027 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
6030 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
6033 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
6036 const int32x4_t m128_s_zero = vdupq_n_s32(0);
6038 const
unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
6039 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6041 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6043 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6045 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6046 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6047 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6049 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6051 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6053 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6055 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6056 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6058 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6060 if (x + 8u > targetWidth)
6065 ocean_assert(x >= 8u && targetWidth > 8u);
6066 const unsigned int newX = targetWidth - 8u;
6068 ocean_assert(x > newX);
6069 targetPixelData -= x - newX;
6074 ocean_assert(!(x + 8u < targetWidth));
6080 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6081 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6084 const int32x4_t m128_s_sourceX_0123_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_0123))));
6085 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6087 const int32x4_t m128_s_sourceX_4567_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_4567))));
6088 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6092 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6093 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6096 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6097 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6107 for (
unsigned int n = 0u; n < 8u; ++n)
6109 topPixels[n] = *(
unsigned int*)(sourceTopRowPixelData + leftOffsets[n]);
6112 const uint16x8_t m128_topPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 0));
6113 const uint16x8_t m128_topPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 4));
6115 for (
unsigned int n = 0u; n < 8u; ++n)
6117 bottomPixels[n] = *(
unsigned int*)(sourceBottomRowPixelData + leftOffsets[n]);
6120 const uint16x8_t m128_bottomPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 0));
6121 const uint16x8_t m128_bottomPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 4));
6128 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6129 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6132 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6133 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6138 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6145 const uint16x8x2_t m2_128_topPixelsLeftRight = vuzpq_u16(m128_topPixels_0123, m128_topPixels_4567);
6151 const uint8x8x2_t m2_64_topPixelsLeft_channels_01 = vuzp_u8(vget_low_u8(vreinterpretq_u8_u16(m2_128_topPixelsLeftRight.val[0])), vget_high_u8(vreinterpretq_u8_u16(m2_128_topPixelsLeftRight.val[0])));
6152 const uint8x8x2_t m2_64_topPixelsRight_channels_01 = vuzp_u8(vget_low_u8(vreinterpretq_u8_u16(m2_128_topPixelsLeftRight.val[1])), vget_high_u8(vreinterpretq_u8_u16(m2_128_topPixelsLeftRight.val[1])));
6154 const uint8x8_t& m64_topPixelsLeft_channel_0 = m2_64_topPixelsLeft_channels_01.val[0];
6155 const uint8x8_t& m64_topPixelsLeft_channel_1 = m2_64_topPixelsLeft_channels_01.val[1];
6157 const uint8x8_t& m64_topPixelsRight_channel_0 = m2_64_topPixelsRight_channels_01.val[0];
6158 const uint8x8_t& m64_topPixelsRight_channel_1 = m2_64_topPixelsRight_channels_01.val[1];
6162 uint16x8_t m128_muliplication_channel_0 = vmull_u8(m64_topPixelsLeft_channel_0, m64_u_factorsLeft);
6163 uint16x8_t m128_muliplication_channel_1 = vmull_u8(m64_topPixelsLeft_channel_1, m64_u_factorsLeft);
6165 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_topPixelsRight_channel_0, m64_u_factorsRight);
6166 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_topPixelsRight_channel_1, m64_u_factorsRight);
6168 const uint8x8_t m64_topRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
6169 const uint8x8_t m64_topRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
6173 const uint16x8x2_t m2_128_bottomPixelsLeftRight = vuzpq_u16(m128_bottomPixels_0123, m128_bottomPixels_4567);
6175 const uint8x8x2_t m2_64_bottomPixelsLeft_channels_01 = vuzp_u8(vget_low_u8(vreinterpretq_u8_u16(m2_128_bottomPixelsLeftRight.val[0])), vget_high_u8(vreinterpretq_u8_u16(m2_128_bottomPixelsLeftRight.val[0])));
6176 const uint8x8x2_t m2_64_bottomPixelsRight_channels_01 = vuzp_u8(vget_low_u8(vreinterpretq_u8_u16(m2_128_bottomPixelsLeftRight.val[1])), vget_high_u8(vreinterpretq_u8_u16(m2_128_bottomPixelsLeftRight.val[1])));
6178 const uint8x8_t& m64_bottomPixelsLeft_channel_0 = m2_64_bottomPixelsLeft_channels_01.val[0];
6179 const uint8x8_t& m64_bottomPixelsLeft_channel_1 = m2_64_bottomPixelsLeft_channels_01.val[1];
6181 const uint8x8_t& m64_bottomPixelsRight_channel_0 = m2_64_bottomPixelsRight_channels_01.val[0];
6182 const uint8x8_t& m64_bottomPixelsRight_channel_1 = m2_64_bottomPixelsRight_channels_01.val[1];
6186 m128_muliplication_channel_0 = vmull_u8(m64_bottomPixelsLeft_channel_0, m64_u_factorsLeft);
6187 m128_muliplication_channel_1 = vmull_u8(m64_bottomPixelsLeft_channel_1, m64_u_factorsLeft);
6189 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomPixelsRight_channel_0, m64_u_factorsRight);
6190 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomPixelsRight_channel_1, m64_u_factorsRight);
6192 const uint8x8_t m64_bottomRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
6193 const uint8x8_t m64_bottomRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
6197 m128_muliplication_channel_0 = vmull_u8(m64_topRow_channel_0, m64_u_factorsTop);
6198 m128_muliplication_channel_1 = vmull_u8(m64_topRow_channel_1, m64_u_factorsTop);
6200 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomRow_channel_0, m64_u_factorsBottom);
6201 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomRow_channel_1, m64_u_factorsBottom);
6205 uint8x8x2_t m2_64_result;
6206 m2_64_result.val[0] = vrshrn_n_u16(m128_muliplication_channel_0, 7);
6207 m2_64_result.val[1] = vrshrn_n_u16(m128_muliplication_channel_1, 7);
6210 vst2_u8((uint8_t*)targetPixelData, m2_64_result);
6212 targetPixelData += 8;
6218 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6220 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6222 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6224 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6225 ocean_assert(lastSourcePixelLeft < sourceWidth);
6226 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6228 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6230 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6231 const unsigned int factorLeft = 128u - factorRight;
6233 for (
unsigned int c = 0u; c < 2u; ++c)
6235 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
6236 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6244#ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
6247inline void FrameInterpolatorBilinear::scale8BitPerChannelSubset7BitPrecisionNEON<3u, 8u>(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
6249 ocean_assert(source !=
nullptr && target !=
nullptr);
6250 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
6251 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
6252 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
6253 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
6254 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6256 ocean_assert(sourcePaddingElements == 0u);
6257 ocean_assert(targetPaddingElements == 0u);
6259 using PixelType =
typename DataType<uint8_t, 3u>::Type;
6261 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
6262 const PixelType*
const sourcePixelData = (
const PixelType*)source;
6265 unsigned int leftOffsets[8];
6278 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
6279 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6281 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
6282 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
6285 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
6288 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
6291 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
6294 const int32x4_t m128_s_zero = vdupq_n_s32(0);
6296 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
6297 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6299 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6301 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6303 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6304 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6305 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6307 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6309 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6311 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6313 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6314 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6316 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6318 if (x + 8u > targetWidth)
6323 ocean_assert(x >= 8u && targetWidth > 8u);
6324 const unsigned int newX = targetWidth - 8u;
6326 ocean_assert(x > newX);
6327 targetPixelData -= x - newX;
6332 ocean_assert(!(x + 8u < targetWidth));
6338 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6339 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6342 const int32x4_t m128_s_sourceX_0123_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_0123))));
6343 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6345 const int32x4_t m128_s_sourceX_4567_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_4567))));
6346 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6350 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6351 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6354 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6355 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6362 uint8x8x3_t topLeftPixels;
6363 uint8x8x3_t topRightPixels;
6365 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6366 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6368 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6369 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6371 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6372 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6374 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6375 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6377 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6378 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6380 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6381 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6383 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6384 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6386 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6387 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6392 uint8x8x3_t bottomLeftPixels;
6393 uint8x8x3_t bottomRightPixels;
6395 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6396 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6398 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6399 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6401 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6402 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6404 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6405 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6407 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6408 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6410 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6411 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6413 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6414 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6416 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6417 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6425 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6426 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6429 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6430 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6431 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6436 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6437 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6438 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6440 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6441 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6442 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6444 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6445 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6446 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6451 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6452 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6453 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6455 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6456 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6457 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6459 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6460 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6461 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6466 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6467 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6468 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6470 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6471 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6472 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6477 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6478 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6479 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6482 vst3_u8((uint8_t*)targetPixelData, result);
6484 targetPixelData += 8;
6490 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6492 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6494 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6496 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6497 ocean_assert(lastSourcePixelLeft < sourceWidth);
6498 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6500 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6502 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6503 const unsigned int factorLeft = 128u - factorRight;
6505 for (
unsigned int c = 0u; c < 3u; ++c)
6507 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
6508 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6516#ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_MORE_GENERIC_APPROACH
6521inline void FrameInterpolatorBilinear::resize8BitPerChannelSubset7BitPrecisionNEON<4u, 8u>(
const uint8_t* source, uint8_t* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
6523 ocean_assert(source !=
nullptr && target !=
nullptr);
6524 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
6525 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
6526 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
6527 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
6528 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6530 ocean_assert(sourcePaddingElements == 0u);
6531 ocean_assert(targetPaddingElements == 0u);
6533 using PixelType =
typename DataType<uint8_t, 4u>::Type;
6535 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
6536 const PixelType*
const sourcePixelData = (
const PixelType*)source;
6539 unsigned int leftOffsets[8];
6542 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6555 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
6556 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6558 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
6559 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
6562 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
6565 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
6568 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
6571 const int32x4_t m128_s_zero = vdupq_n_s32(0);
6573 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
6574 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6576 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6578 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6580 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6581 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6582 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6584 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6586 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6588 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6590 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6591 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6593 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6595 if (x + 8u > targetWidth)
6600 ocean_assert(x >= 8u && targetWidth > 8u);
6601 const unsigned int newX = targetWidth - 8u;
6603 ocean_assert(x > newX);
6604 targetPixelData -= x - newX;
6609 ocean_assert(!(x + 8u < targetWidth));
6615 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6616 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6619 const int32x4_t m128_s_sourceX_0123_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_0123))));
6620 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6622 const int32x4_t m128_s_sourceX_4567_fixed16 = vmaxq_s32(m128_s_zero, vaddq_s32(m128_s_targetOffsetX_fixed16, vreinterpretq_s32_u32(vmulq_u32(m128_u_sourceX_T_targetX_fixed16, m128_u_x_4567))));
6623 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6627 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6628 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6631 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6632 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6639 uint8x8x4_t topLeftPixels;
6640 uint8x8x4_t topRightPixels;
6642 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6643 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6645 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6646 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6648 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6649 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6651 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6652 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6654 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6655 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6657 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6658 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6660 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6661 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6663 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6664 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6669 uint8x8x4_t bottomLeftPixels;
6670 uint8x8x4_t bottomRightPixels;
6672 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6673 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6675 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6676 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6678 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6679 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6681 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6682 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6684 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6685 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6687 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6688 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6690 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6691 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6693 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6694 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6702 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6703 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6706 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6707 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6708 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6713 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6714 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6715 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6716 uint16x8_t m128_muliplicationChannel_3 = vmull_u8(topLeftPixels.val[3], m64_u_factorsLeft);
6718 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6719 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6720 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6721 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, topRightPixels.val[3], m64_u_factorsRight);
6723 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6724 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6725 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6726 uint8x8_t m64_topRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6731 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6732 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6733 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6734 m128_muliplicationChannel_3 = vmull_u8(bottomLeftPixels.val[3], m64_u_factorsLeft);
6736 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6737 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6738 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6739 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, bottomRightPixels.val[3], m64_u_factorsRight);
6741 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6742 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6743 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6744 uint8x8_t m64_bottomRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6749 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6750 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6751 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6752 m128_muliplicationChannel_3 = vmull_u8(m64_topRowChannel_3, m64_u_factorsTop);
6754 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6755 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6756 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6757 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, m64_bottomRowChannel_3, m64_u_factorsBottom);
6762 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6763 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6764 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6765 result.val[3] = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6768 vst4_u8((uint8_t*)targetPixelData, result);
6770 targetPixelData += 8;
6776 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6778 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6780 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6782 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6783 ocean_assert(lastSourcePixelLeft < sourceWidth);
6784 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6786 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6788 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6789 const unsigned int factorLeft = 128u - factorRight;
6791 for (
unsigned int c = 0u; c < 4u; ++c)
6793 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorTop
6794 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6805inline void FrameInterpolatorBilinear::interpolateRowVerticalNEON<float>(
const float* sourceRowTop,
const float* sourceRowBottom,
float* targetRow,
const unsigned int elements,
const float factorBottom)
6807 ocean_assert(sourceRowTop !=
nullptr);
6808 ocean_assert(sourceRowBottom !=
nullptr);
6809 ocean_assert(targetRow !=
nullptr);
6810 ocean_assert(elements >= 16u);
6811 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6814 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6816 const float32x4_t factorsBottom_f_32x4 = vdupq_n_f32(factorBottom);
6817 const float32x4_t factorsTop_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsBottom_f_32x4);
6819 for (
unsigned int n = 0u; n < elements; n += 16u)
6821 if (n + 16u > elements)
6826 ocean_assert(n >= 16u && elements > 16u);
6827 const unsigned int offset = n - (elements - 16u);
6828 ocean_assert(offset < 16u);
6830 sourceRowTop -= offset;
6831 sourceRowBottom -= offset;
6832 targetRow -= offset;
6835 ocean_assert(!(n + 16u < elements));
6839 const float32x4_t top_03_32x4 = vld1q_f32(sourceRowTop + 0);
6840 const float32x4_t top_47_32x4 = vld1q_f32(sourceRowTop + 4);
6841 const float32x4_t top_8B_32x4 = vld1q_f32(sourceRowTop + 8);
6842 const float32x4_t top_CF_32x4 = vld1q_f32(sourceRowTop + 12);
6844 const float32x4_t bottom_03_32x4 = vld1q_f32(sourceRowBottom + 0);
6845 const float32x4_t bottom_47_32x4 = vld1q_f32(sourceRowBottom + 4);
6846 const float32x4_t bottom_8B_32x4 = vld1q_f32(sourceRowBottom + 8);
6847 const float32x4_t bottom_CF_32x4 = vld1q_f32(sourceRowBottom + 12);
6850 float32x4_t interpolatedRow_03_32x4 = vmulq_f32(top_03_32x4, factorsTop_f_32x4);
6851 float32x4_t interpolatedRow_47_32x4 = vmulq_f32(top_47_32x4, factorsTop_f_32x4);
6852 float32x4_t interpolatedRow_8B_32x4 = vmulq_f32(top_8B_32x4, factorsTop_f_32x4);
6853 float32x4_t interpolatedRow_CF_32x4 = vmulq_f32(top_CF_32x4, factorsTop_f_32x4);
6855 interpolatedRow_03_32x4 = vmlaq_f32(interpolatedRow_03_32x4, bottom_03_32x4, factorsBottom_f_32x4);
6856 interpolatedRow_47_32x4 = vmlaq_f32(interpolatedRow_47_32x4, bottom_47_32x4, factorsBottom_f_32x4);
6857 interpolatedRow_8B_32x4 = vmlaq_f32(interpolatedRow_8B_32x4, bottom_8B_32x4, factorsBottom_f_32x4);
6858 interpolatedRow_CF_32x4 = vmlaq_f32(interpolatedRow_CF_32x4, bottom_CF_32x4, factorsBottom_f_32x4);
6861 vst1q_f32(targetRow + 0, interpolatedRow_03_32x4);
6862 vst1q_f32(targetRow + 4, interpolatedRow_47_32x4);
6863 vst1q_f32(targetRow + 8, interpolatedRow_8B_32x4);
6864 vst1q_f32(targetRow + 12, interpolatedRow_CF_32x4);
6867 sourceRowBottom += 16;
6873inline void FrameInterpolatorBilinear::interpolateRowHorizontalNEON<float, 1u>(
const float* extendedSourceRow,
float* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight)
6875 ocean_assert(extendedSourceRow !=
nullptr);
6876 ocean_assert(targetRow !=
nullptr);
6877 ocean_assert(targetWidth >= 8u);
6878 ocean_assert(interpolationLocations !=
nullptr);
6879 ocean_assert(interpolationFactorsRight !=
nullptr);
6881 ocean_assert_and_suppress_unused(channels == 1u, channels);
6884 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6886 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6888 if (x + 8u > targetWidth)
6893 ocean_assert(x >= 8u && targetWidth > 8u);
6894 const unsigned int newX = targetWidth - 8u;
6896 ocean_assert(x > newX);
6897 const unsigned int offset = x - newX;
6899 targetRow -= offset;
6900 interpolationLocations -= offset;
6901 interpolationFactorsRight -= offset;
6906 ocean_assert(!(x + 8u < targetWidth));
6911 const float32x2_t pixel_0_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[0]);
6912 const float32x2_t pixel_1_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[1]);
6913 const float32x4_t pixel_01_f_32x4 = vcombine_f32(pixel_0_f_32x2, pixel_1_f_32x2);
6915 const float32x2_t pixel_2_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[2]);
6916 const float32x2_t pixel_3_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[3]);
6917 const float32x4_t pixel_23_f_32x4 = vcombine_f32(pixel_2_f_32x2, pixel_3_f_32x2);
6919 const float32x2_t pixel_4_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[4]);
6920 const float32x2_t pixel_5_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[5]);
6921 const float32x4_t pixel_45_f_32x4 = vcombine_f32(pixel_4_f_32x2, pixel_5_f_32x2);
6923 const float32x2_t pixel_6_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[6]);
6924 const float32x2_t pixel_7_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[7]);
6925 const float32x4_t pixel_67_f_32x4 = vcombine_f32(pixel_6_f_32x2, pixel_7_f_32x2);
6927 const float32x4_t factorsRight_0123_f_32x4 = vld1q_f32(interpolationFactorsRight + 0);
6928 const float32x4_t factorsLeft_0123_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_0123_f_32x4);
6929 const float32x4x2_t factorsLeftRight_0123_f_32x4_2 = vzipq_f32(factorsLeft_0123_f_32x4, factorsRight_0123_f_32x4);
6931 const float32x4_t factorsRight_4567_f_32x4 = vld1q_f32(interpolationFactorsRight + 4);
6932 const float32x4_t factorsLeft_4567_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_4567_f_32x4);
6933 const float32x4x2_t factorsLeftRight_4567_f_32x4_2 = vzipq_f32(factorsLeft_4567_f_32x4, factorsRight_4567_f_32x4);
6935 const float32x4_t multiplied_01_f_32x4 = vmulq_f32(pixel_01_f_32x4, factorsLeftRight_0123_f_32x4_2.val[0]);
6936 const float32x4_t multiplied_23_f_32x4 = vmulq_f32(pixel_23_f_32x4, factorsLeftRight_0123_f_32x4_2.val[1]);
6938 const float32x4_t multiplied_45_f_32x4 = vmulq_f32(pixel_45_f_32x4, factorsLeftRight_4567_f_32x4_2.val[0]);
6939 const float32x4_t multiplied_67_f_32x4 = vmulq_f32(pixel_67_f_32x4, factorsLeftRight_4567_f_32x4_2.val[1]);
6941 const float32x2_t result_01_f_32x2 = vpadd_f32(vget_low_f32(multiplied_01_f_32x4), vget_high_f32(multiplied_01_f_32x4));
6942 const float32x2_t result_23_f_32x2 = vpadd_f32(vget_low_f32(multiplied_23_f_32x4), vget_high_f32(multiplied_23_f_32x4));
6944 const float32x2_t result_45_f_32x2 = vpadd_f32(vget_low_f32(multiplied_45_f_32x4), vget_high_f32(multiplied_45_f_32x4));
6945 const float32x2_t result_67_f_32x2 = vpadd_f32(vget_low_f32(multiplied_67_f_32x4), vget_high_f32(multiplied_67_f_32x4));
6947 const float32x4_t result_0123_f_32x4 = vcombine_f32(result_01_f_32x2, result_23_f_32x2);
6948 const float32x4_t result_4567_f_32x4 = vcombine_f32(result_45_f_32x2, result_67_f_32x2);
6950 vst1q_f32(targetRow + 0, result_0123_f_32x4);
6951 vst1q_f32(targetRow + 4, result_4567_f_32x4);
6954 interpolationLocations += 8;
6955 interpolationFactorsRight += 8;
6960inline void FrameInterpolatorBilinear::scaleSubset<float, float, 1u>(
const float* source,
float* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
6962 ocean_assert(source !=
nullptr && target !=
nullptr);
6963 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
6964 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
6965 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6967 ocean_assert(sourceWidth != targetWidth || sourceHeight != targetHeight || sourceX_s_targetX != 1.0 || sourceY_s_targetY != 1.0);
6969 const unsigned int sourceStrideElements = sourceWidth * 1u + sourcePaddingElements;
6970 const unsigned int targetStrideElements = targetWidth * 1u + targetPaddingElements;
6972 using InterpolateRowVerticalFunction = void (*)(
const float*,
const float*,
float*,
const unsigned int,
const float);
6973 using InterpolateRowHorizontalFunction = void (*)(
const float*,
float*,
const unsigned int,
const unsigned int,
const unsigned int*,
const float*);
6975 InterpolateRowVerticalFunction interpolateRowVerticalFunction = interpolateRowVertical<float>;
6976 InterpolateRowHorizontalFunction interpolateRowHorizontalFunction = interpolateRowHorizontal<float, 1u>;
6978 if (sourceWidth * 1u >= 16u)
6980 interpolateRowVerticalFunction = interpolateRowVerticalNEON<float>;
6983 if (targetWidth >= 8u)
6985 interpolateRowHorizontalFunction = interpolateRowHorizontalNEON<float, 1u>;
6988 target += targetStrideElements * firstTargetRow;
6990 const float sourceX_T_targetX = float(sourceX_s_targetX);
6991 const float sourceY_T_targetY = float(sourceY_s_targetY);
6995 Memory memoryIntermediateExtendedRow;
6996 Memory memoryHorizontalInterpolationLocations;
6997 Memory memoryHorizontalInterpolationFactorsRight;
6999 if (sourceWidth != targetWidth || sourceX_T_targetX != 1.0f)
7003 memoryIntermediateExtendedRow = Memory::create<float>(sourceWidth + 1u);
7005 memoryHorizontalInterpolationLocations = Memory::create<unsigned int>(targetWidth);
7007 memoryHorizontalInterpolationFactorsRight = Memory::create<float>(targetWidth);
7010 if (memoryHorizontalInterpolationLocations)
7012 ocean_assert(memoryHorizontalInterpolationFactorsRight);
7014 if (targetWidth >= 4u)
7016 const float32x4_t sourceX_T_targetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX);
7017 const float32x4_t targetOffsetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX * 0.5f - 0.5f);
7020 const float32x4_t constant_0_f_32x4 = vdupq_n_f32(0);
7023 const float32x4_t constant_4_f_32x4 = vdupq_n_f32(4.0f);
7026 const uint32x4_t sourceWidth_1_u_32x4 = vdupq_n_u32(sourceWidth - 1u);
7029 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
7030 float32x4_t x_0123_f_32x4 = vld1q_f32(f_0123);
7034 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
7036 if (x + 4u > targetWidth)
7041 ocean_assert(x >= 4u && targetWidth > 4u);
7042 const unsigned int newX = targetWidth - 4u;
7044 ocean_assert(x > newX);
7045 const unsigned int offset = x - newX;
7049 x_0123_f_32x4 = vsubq_f32(x_0123_f_32x4, vdupq_n_f32(
float(offset)));
7052 ocean_assert(!(x + 4u < targetWidth));
7056 const float32x4_t sourceX_0123_f_32x4 = vmaxq_f32(constant_0_f_32x4, vaddq_f32(targetOffsetX_f_32x4, vmulq_f32(sourceX_T_targetX_f_32x4, x_0123_f_32x4)));
7060 uint32x4_t left_0123_u_32x4 = vminq_u32(vcvtq_u32_f32(sourceX_0123_f_32x4), sourceWidth_1_u_32x4);
7063 vst1q_u32(memoryHorizontalInterpolationLocations.
data<
unsigned int>() + x, left_0123_u_32x4);
7066 const float32x4_t factorsRight_f_32x4 = vsubq_f32(sourceX_0123_f_32x4, vcvtq_f32_u32(left_0123_u_32x4));
7068 vst1q_f32(memoryHorizontalInterpolationFactorsRight.
data<
float>() + x, factorsRight_f_32x4);
7071 x_0123_f_32x4 = vaddq_f32(x_0123_f_32x4, constant_4_f_32x4);
7076 const float targetOffsetX = sourceX_T_targetX * 0.5f - 0.5f;
7080 for (
unsigned int x = 0u; x < targetWidth; ++x)
7082 const float sourceX = max(0.0f, targetOffsetX +
float(x) * sourceX_T_targetX);
7084 const unsigned int left = min((
unsigned int)sourceX, sourceWidth - 1u);
7086 memoryHorizontalInterpolationLocations.
data<
unsigned int>()[x] = left;
7088 const float factorRight = sourceX - float(left);
7089 ocean_assert(factorRight >= 0.0f && factorRight <= 1.0f);
7091 memoryHorizontalInterpolationFactorsRight.
data<
float>()[x] = factorRight;
7096 const float targetOffsetY = sourceY_T_targetY * 0.5f - 0.5f;
7098 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
7100 const float sourceY = minmax<float>(0.0f, targetOffsetY + sourceY_T_targetY *
float(y),
float(sourceHeight) - 1.0f);
7102 const unsigned int sourceRowTop = (
unsigned int)sourceY;
7103 const float factorBottom = sourceY - float(sourceRowTop);
7104 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
7106 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
7108 const float*
const sourceTopRow = source + sourceStrideElements * sourceRowTop;
7109 const float*
const sourceBottomRow = source + sourceStrideElements * sourceRowBottom;
7111 float* targetRow =
nullptr;
7113 if (memoryIntermediateExtendedRow && factorBottom == 0.0f)
7115 ocean_assert(sourceWidth != targetWidth);
7118 memcpy(memoryIntermediateExtendedRow.
data<
float>(), sourceTopRow, sourceWidth *
sizeof(
float));
7123 targetRow = memoryIntermediateExtendedRow.
isNull() ? target : memoryIntermediateExtendedRow.
data<
float>();
7125 ocean_assert(targetRow !=
nullptr);
7126 ocean_assert(interpolateRowVerticalFunction !=
nullptr);
7127 interpolateRowVerticalFunction(sourceTopRow, sourceBottomRow, targetRow, sourceWidth * 1u, factorBottom);
7130 if (memoryIntermediateExtendedRow)
7134 memoryIntermediateExtendedRow.
data<
float>()[sourceWidth] = memoryIntermediateExtendedRow.
data<
float>()[sourceWidth - 1u];
7136 interpolateRowHorizontalFunction(memoryIntermediateExtendedRow.
data<
float>(), target, targetWidth, 1u, memoryHorizontalInterpolationLocations.
data<
unsigned int>(), memoryHorizontalInterpolationFactorsRight.
data<
float>());
7139 target += targetStrideElements;
7145template <
typename T,
typename TScale,
unsigned int tChannels>
7146void FrameInterpolatorBilinear::scaleSubset(
const T* source, T* target,
const unsigned int sourceWidth,
const unsigned int sourceHeight,
const unsigned int targetWidth,
const unsigned int targetHeight,
const double sourceX_s_targetX,
const double sourceY_s_targetY,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
7148 static_assert((std::is_same<float, TScale>::value || std::is_same<double, TScale>::value),
"Invalid TScale type");
7150 ocean_assert(source !=
nullptr && target !=
nullptr);
7151 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
7152 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
7153 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
7155 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
7156 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
7158 const TScale sourceX_T_targetX = TScale(sourceX_s_targetX);
7159 const TScale sourceY_T_targetY = TScale(sourceY_s_targetY);
7207 const TScale sourceX_T_targetXOffset = sourceX_T_targetX * TScale(0.5) - TScale(0.5);
7208 const TScale sourceY_T_targetYOffset = sourceY_T_targetY * TScale(0.5) - TScale(0.5);
7210 const TScale sourceWidth_1 = TScale(sourceWidth - 1u);
7211 const TScale sourceHeight_1 = TScale(sourceHeight - 1u);
7213 target += targetStrideElements * firstTargetRow;
7215 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
7217 const TScale sy =
minmax(TScale(0), sourceY_T_targetYOffset + sourceY_T_targetY * TScale(y), sourceHeight_1);
7218 ocean_assert(sy >= TScale(0) && sy < TScale(sourceHeight));
7220 const unsigned int sTop = (
unsigned int)sy;
7221 ocean_assert(sy >= TScale(sTop));
7223 const TScale factorBottom = sy - TScale(sTop);
7224 ocean_assert(factorBottom >= TScale(0) && factorBottom <= TScale(1));
7226 const TScale factorTop = TScale(1) - factorBottom;
7227 ocean_assert(factorTop >= TScale(0) && factorTop <= TScale(1));
7229 const T*
const sourceTop = source + sTop * sourceStrideElements;
7230 const T*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
7232 for (
unsigned int x = 0; x < targetWidth; ++x)
7234 const TScale sx =
minmax(TScale(0), sourceX_T_targetXOffset + sourceX_T_targetX * TScale(x), sourceWidth_1);
7235 ocean_assert(sx >= TScale(0) && sx < TScale(sourceWidth));
7237 const unsigned int sLeft = (
unsigned int)sx;
7238 ocean_assert(sx >= TScale(sLeft));
7240 const TScale factorRight = sx - TScale(sLeft);
7241 ocean_assert(factorRight >= TScale(0) && factorRight <= TScale(1));
7243 const TScale factorLeft = TScale(1) - factorRight;
7244 ocean_assert(factorLeft >= TScale(0) && factorLeft <= TScale(1));
7246 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
7248 const T*
const sourceTopLeft = sourceTop + sLeft * tChannels;
7249 const T*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
7251 const TScale factorTopLeft = factorTop * factorLeft;
7252 const TScale factorTopRight = factorTop * factorRight;
7253 const TScale factorBottomLeft = factorBottom * factorLeft;
7254 const TScale factorBottomRight = factorBottom * factorRight;
7256 for (
unsigned int n = 0u; n < tChannels; ++n)
7258 target[n] = T(TScale(sourceTopLeft[n]) * factorTopLeft + TScale(sourceTopLeft[sourceRightOffset + n]) * factorTopRight
7259 + TScale(sourceBottomLeft[n]) * factorBottomLeft + TScale(sourceBottomLeft[sourceRightOffset + n]) * factorBottomRight);
7262 target += tChannels;
7265 target += targetPaddingElements;
7269template <
unsigned int tChannels>
7270void FrameInterpolatorBilinear::rotate8BitPerChannelSubset(
const uint8_t* source, uint8_t* target,
const unsigned int width,
const unsigned int height,
const Scalar horizontalAnchorPosition,
const Scalar verticalAnchorPosition,
const Scalar angle,
const uint8_t* borderColor,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
const unsigned int firstTargetRow,
const unsigned int numberTargetRows)
7272 static_assert(tChannels != 0u,
"Invalid channel number!");
7274 ocean_assert(firstTargetRow + numberTargetRows <= height);
7278 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
7280 uint8_t zeroColor[tChannels] = {uint8_t(0)};
7281 const PixelType bColor = borderColor ? *(
const PixelType*)borderColor : *(
const PixelType*)zeroColor;
7284 const SquareMatrix2 rotationMatrix2(rotationMatrix3(0, 0), rotationMatrix3(1, 0), rotationMatrix3(0, 1), rotationMatrix3(1, 1));
7288 const Vector2 anchorPosition(horizontalAnchorPosition, verticalAnchorPosition);
7290 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
7292 PixelType* targetPixel = (PixelType*)(target + y * targetStrideElements);
7296 for (
unsigned int x = 0; x < width; ++x)
7298 const Vector2 sourceLocation(anchorPosition + rotationMatrix2 * (
Vector2(
Scalar(x), floatY) - anchorPosition));
7300 if (sourceLocation.
x() >= 0 && sourceLocation.
y() >= 0 && sourceLocation.
x() <= width_1 && sourceLocation.
y() <= height_1)
7302 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, width, height, sourcePaddingElements, sourceLocation, (uint8_t*)(targetPixel));
7306 *targetPixel = bColor;
This class implements the abstract base class for all AnyCamera objects.
Definition AnyCamera.h:131
virtual VectorT3< T > vector(const VectorT2< T > &distortedImagePoint, const bool makeUnitVector=true) const =0
Returns a vector starting at the camera's center and intersecting a given 2D point in the image.
virtual unsigned int width() const =0
Returns the width of the camera image.
virtual unsigned int height() const =0
Returns the height of the camera image.
virtual VectorT2< T > projectToImageIF(const VectorT3< T > &objectPoint) const =0
Projects a 3D object point into the camera frame.
virtual bool isValid() const =0
Returns whether this camera is valid.
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:1171
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition FrameInterpolatorBilinear.h:65
static bool homographies(const Frame &input, Frame &output, const SquareMatrix3 homographies[4], const Vector2 &outputQuadrantCenter, const uint8_t *borderColor=nullptr, Worker *worker=nullptr, const PixelPositionI &outputOrigin=PixelPositionI(0, 0))
Transforms a given input frame into an output frame (with arbitrary frame dimension) by application o...
static bool zoom(const Frame &source, Frame &target, const Scalar zoomFactor, Worker *worker=nullptr)
Zooms into a given input frame (or zooms out) and stores the zoomed image content in an output frame.
static bool homographyMask(const Frame &input, Frame &output, Frame &outputMask, const SquareMatrix3 &input_H_output, Worker *worker=nullptr, const uint8_t maskValue=0xFF, const PixelPositionI &outputOrigin=PixelPositionI(0, 0))
Transforms a given input frame into an output frame (with arbitrary frame dimension) by application o...
static bool lookupMask(const Frame &input, Frame &output, Frame &outputMask, const LookupTable &input_LT_output, const bool offset, Worker *worker=nullptr, const uint8_t maskValue=0xFF)
Transforms a given input frame into an output frame by application of an interpolation lookup table a...
static bool homographyWithCameraMask(const AnyCamera &inputCamera, const AnyCamera &outputCamera, const Frame &input, Frame &output, Frame &outputMask, const SquareMatrix3 &homography, Worker *worker=nullptr, const uint8_t maskValue=0xFFu)
Transforms a given input frame into an output frame by application of a homography.
static bool rotate(const Frame &source, Frame &target, const Scalar horizontalAnchorPosition, const Scalar verticalAnchorPosition, const Scalar angle, Worker *worker=nullptr, const uint8_t *borderColor=nullptr)
Rotates a given frame by a bilinear interpolation.
static bool resize(const Frame &source, Frame &target, Worker *worker=nullptr)
Resizes/rescales a given frame by application of a bilinear interpolation.
static bool homographiesMask(const Frame &input, Frame &output, Frame &outputMask, const SquareMatrix3 *homographies, const Vector2 &outputQuadrantCenter, Worker *worker=nullptr, const uint8_t maskValue=0xFF, const PixelPositionI &outputOrigin=PixelPositionI(0, 0))
Transforms a given input frame into an output frame (with arbitrary frame dimension) by application o...
static bool interpolatePixel(const TSource *frame, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const PixelCenter pixelCenter, const VectorT2< TScalar > &position, TTarget *result, const TIntermediate &resultBias=TIntermediate(0))
Determines the interpolated pixel values for a given pixel position in a frame with arbitrary data ty...
Definition FrameInterpolatorBilinear.h:1551
static bool resampleCameraImage(const Frame &sourceFrame, const AnyCamera &sourceCamera, const SquareMatrix3 &source_R_target, const AnyCamera &targetCamera, Frame &targetFrame, LookupCorner2< Vector2 > *source_OLT_target=nullptr, Worker *worker=nullptr, const unsigned int binSizeInPixel=8u, const void *borderColor=nullptr)
Re-samples a camera image which has been captured with a camera profile as if the image would have be...
static bool homographyWithCamera(const PinholeCamera &inputCamera, const PinholeCamera &outputCamera, const Frame &input, Frame &output, const SquareMatrix3 &homography, const bool useDistortionParameters, const uint8_t *borderColor=nullptr, Worker *worker=nullptr)
Transforms a given input frame into an output frame by application of a homography.
static bool lookup(const Frame &input, Frame &output, const LookupTable &input_LT_output, const bool offset, const void *borderColor, Worker *worker=nullptr)
Transforms a given input frame into an output frame by application of an interpolation lookup table.
static bool affine(const Frame &source, Frame &target, const SquareMatrix3 &source_A_target, const uint8_t *borderColor=nullptr, Worker *worker=nullptr, const PixelPositionI &targetOrigin=PixelPositionI(0, 0))
Applies an affine transformation to an image.
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 FrameInterpolatorBilinear.h:1458
static bool homography(const Frame &input, Frame &output, const SquareMatrix3 &input_H_output, const void *borderColor=nullptr, Worker *worker=nullptr, const PixelPositionI &outputOrigin=PixelPositionI(0, 0))
Transforms a given input frame into an output frame (with arbitrary frame dimension) by application o...
This class implements highly optimized interpolation functions with fixed properties.
Definition FrameInterpolatorBilinear.h:346
static void resize400x400To256x256_8BitPerChannel(const uint8_t *const source, uint8_t *const target, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Resizes a given FORMAT_Y8 frame with resolution 400x400 to a FORMAT_Y8 frame with resolution 256x256 ...
static void resize400x400To224x224_8BitPerChannel(const uint8_t *const source, uint8_t *const target, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Resizes a given FORMAT_Y8 frame with resolution 400x400 to a FORMAT_Y8 frame with resolution 224x224 ...
This class implements bilinear frame interpolator functions.
Definition FrameInterpolatorBilinear.h:47
static OCEAN_FORCE_INLINE void interpolate4Pixels8BitPerChannelNEON(const uint8_t *source, const unsigned int offsetsTopLeftElements[4], const unsigned int offsetsTopRightElements[4], const unsigned int offsetsBottomLeftElements[4], const unsigned int offsetsBottomRightElements[4], const unsigned int validPixels[4], const typename DataType< uint8_t, tChannels >::Type &borderColor, const uint32x4_t &m128_factorsRight, const uint32x4_t &m128_factorsBottom, typename DataType< uint8_t, tChannels >::Type *targetPositionPixels)
Interpolates 4 independent pixels concurrently based on already known locations (top-left,...
Definition FrameInterpolatorBilinear.h:4432
static void homography(const T *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 &input_H_output, const T *borderColor, T *output, const PixelPositionI &outputOrigin, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, Worker *worker=nullptr)
Transforms a input frame with (almost) arbitrary pixel format into an output frame by application of ...
Definition FrameInterpolatorBilinear.h:1769
static void resampleCameraImage(const T *sourceFrame, const AnyCamera &sourceCamera, const SquareMatrix3 &source_R_target, const AnyCamera &targetCamera, T *targetFrame, const unsigned int sourceFramePaddingElements, const unsigned int targetFramePaddingElements, LookupCorner2< Vector2 > *source_OLT_target=nullptr, Worker *worker=nullptr, const unsigned int binSizeInPixel=8u, const T *borderColor=nullptr)
Re-samples a camera image which has been captured with a camera profile as if the image would have be...
Definition FrameInterpolatorBilinear.h:1929
static void interpolateRowVerticalNEON(const T *sourceRowTop, const T *sourceRowBottom, T *targetRow, const unsigned int elements, const float factorBottom)
Applies a (vertical) linear interpolation between two rows with arbitrary data types.
static void homographyWithCamera8BitPerChannel(const PinholeCamera &inputCamera, const PinholeCamera &outputCamera, const uint8_t *input, const SquareMatrix3 &homography, const bool useDistortionParameters, const uint8_t *borderColor, uint8_t *output, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, Worker *worker=nullptr)
Transforms a given 8 bit per channel input frame into an output frame by application of a homography.
Definition FrameInterpolatorBilinear.h:1835
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 FrameInterpolatorBilinear.h:1996
static void affine8BitPerChannelSSESubset(const uint8_t *source, const unsigned int sourceWidth, const unsigned int sourceHeight, const SquareMatrix3 *source_A_target, const uint8_t *borderColor, uint8_t *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int firstTargetRow, const unsigned int numberTargetRows, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Subset function to apply an affine transform to an N-channel, 8-bit unsigned image (using SSE).
Definition FrameInterpolatorBilinear.h:2500
static Scalar patchIntensitySum1Channel(const uint32_t *linedIntegralFrame, const unsigned int frameWidth, const unsigned int frameHeight, const unsigned int lineIntegralFramePaddingElements, const Vector2 ¢er, const CV::PixelCenter pixelCenter, const unsigned int patchWidth, const unsigned int patchHeight)
Interpolate the sum of intensity values of an image patch in a frame, while the frame is provided as ...
static void homographyWithCameraMask8BitPerChannel(const PinholeCamera &inputCamera, const PinholeCamera &outputCamera, const uint8_t *input, const unsigned int inputPaddingElements, const SquareMatrix3 &homography, uint8_t *output, uint8_t *outputMask, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, Worker *worker=nullptr, const uint8_t maskValue=0xFF)
Transforms a given 8 bit per channel input frame into an output frame by application of a homography.
Definition FrameInterpolatorBilinear.h:1852
static void homographiesMask8BitPerChannelSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *homographies, uint8_t *output, uint8_t *outputMask, const uint8_t maskValue, const Scalar outputQuadrantCenterX, const Scalar outputQuadrantCenterY, const int outputOriginX, const int outputOriginY, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:4654
static void homographiesMask8BitPerChannel(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 homographies[4], uint8_t *output, uint8_t *outputMask, const Vector2 &outputQuadrantCenter, const PixelPositionI &outputOrigin, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, Worker *worker=nullptr, const uint8_t maskValue=0xFF)
Transforms a given 8 bit per channel input frame into an output frame by application of four homograp...
Definition FrameInterpolatorBilinear.h:1822
static void interpolateRowHorizontal8BitPerChannel7BitPrecision(const uint8_t *extendedSourceRow, uint8_t *targetRow, const unsigned int targetWidth, const unsigned int channels, const unsigned int *interpolationLocations, const uint8_t *interpolationFactors)
Applies a (horizontal) linear interpolation for one row with 8 bit per channel.
static void homography8BitPerChannelNEONSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *input_H_output, const uint8_t *borderColor, uint8_t *output, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:3613
static OCEAN_FORCE_INLINE void interpolate4Pixels4Channel8BitPerChannelNEON(const uint8x16_t &topLeftPixels_u8x16, const uint8x16_t &topRightPixels_u8x16, const uint8x16_t &bottomLeftPixels_u8x16, const uint8x16_t &bottomRightPixels_u8x16, const uint32x4_t &m128_factorsRight, const uint32x4_t &m128_factorsBottom, typename DataType< uint8_t, 4u >::Type *targetPositionPixels, const bool useOptimizedNEONFactorReplication=false)
Interpolates 4 independent 4-channel pixels using widening byte multiply.
Definition FrameInterpolatorBilinear.h:4320
static void interpolateRowVertical8BitPerChannel7BitPrecisionNEON(const uint8_t *sourceRowTop, const uint8_t *sourceRowBottom, uint8_t *targetRow, const unsigned int elements, const unsigned int factorBottom)
Applies a (vertical) linear interpolation between two rows with 8 bit per channel.
static void homographySubset(const T *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *input_H_output, const T *borderColor, T *output, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms a frame with (almost) arbitrary pixel format using the given homography.
Definition FrameInterpolatorBilinear.h:2416
static void homographyMask8BitPerChannel(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 &input_H_output, uint8_t *output, uint8_t *outputMask, const PixelPositionI &outputOrigin, const unsigned int outputWidth, const unsigned int outputHeight, const uint8_t maskValue, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, Worker *worker=nullptr)
Transforms a given 8 bit per channel input frame into an output frame by application of a homography.
Definition FrameInterpolatorBilinear.h:1806
static OCEAN_FORCE_INLINE void interpolate8Pixels1Channel8BitNEON(const uint8x8_t &topLeft_u_8x8, const uint8x8_t &topRight_u_8x8, const uint8x8_t &bottomLeft_u_8x8, const uint8x8_t &bottomRight_u_8x8, const uint8x16_t &factorsRight_factorsBottom_128_u_8x16, uint8_t *targetPositionPixels)
Interpolates 8 independent pixels concurrently of a 1 channel frame, the source pixel locations must ...
Definition FrameInterpolatorBilinear.h:3993
static void homographies8BitPerChannelSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *homographies, const uint8_t *borderColor, uint8_t *output, const Scalar outputQuadrantCenterX, const Scalar outputQuadrantCenterY, const int outputOriginX, const int outputOriginY, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms an 8 bit per channel frame using the given homographies.
Definition FrameInterpolatorBilinear.h:4498
static void homographyWithCamera8BitPerChannelSubset(const PinholeCamera *inputCamera, const PinholeCamera *outputCamera, const PinholeCamera::DistortionLookup *outputCameraDistortionLookup, const uint8_t *input, const SquareMatrix3 *normalizedHomography, const bool useDistortionParameters, const uint8_t *borderColor, uint8_t *output, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:4734
static void affine8BitPerChannel(const uint8_t *source, const unsigned int sourceWidth, const unsigned int sourceHeight, const SquareMatrix3 &source_A_target, const uint8_t *borderColor, uint8_t *target, const PixelPositionI &targetOrigin, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Apply an affine transforms to a N-channel, 8-bit frame The target frame must have the same pixel form...
Definition FrameInterpolatorBilinear.h:1693
static void lookup(const T *input, const unsigned int inputWidth, const unsigned int inputHeight, const LookupTable &input_LT_output, const bool offset, const T *borderColor, T *output, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, Worker *worker=nullptr, const bool useOptimizedNEON=false, const bool useOptimizedBilinearValuesAndFactorCalculation=false, const bool useOptimizedNEONFactorReplication=false)
Transforms a given input frame into an output frame by application of an interpolation lookup table.
Definition FrameInterpolatorBilinear.h:1869
static void homographyWithCameraMask8BitPerChannelSubset(const PinholeCamera *inputCamera, const PinholeCamera *outputCamera, const PinholeCamera::DistortionLookup *outputCameraDistortionLookup, const uint8_t *input, const unsigned int inputPaddingElements, const SquareMatrix3 *normalizedHomography, uint8_t *output, uint8_t *outputMask, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:4780
static void affine8BitPerChannelNEONSubset(const uint8_t *source, const unsigned int sourceWidth, const unsigned int sourceHeight, const SquareMatrix3 *source_A_target, const uint8_t *borderColor, uint8_t *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int firstTargetRow, const unsigned int numberTargetRows, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Subset function to apply an affine transform to an N-channel, 8-bit unsigned image (using NEON).
Definition FrameInterpolatorBilinear.h:3363
static void interpolateRowHorizontalNEON(const T *extendedSourceRow, T *targetRow, const unsigned int targetWidth, const unsigned int channels, const unsigned int *interpolationLocations, const float *interpolationFactorsRight)
Applies a (horizontal) linear interpolation for one row with arbitrary data type.
static void scale8BitPerChannelSubset7BitPrecisionNEON(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int channels, const double sourceX_s_targetX, const double sourceY_s_targetY, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Rescales a subset of a given frame with 8 bit per channel by a bilinear interpolation.
Definition FrameInterpolatorBilinear.h:5722
static OCEAN_FORCE_INLINE __m128i interpolate4Pixels8BitPerChannelSSE(const __m128i &m128_sourcesTopLeft, const __m128i &m128_sourcesTopRight, const __m128i &m128_sourcesBottomLeft, const __m128i &m128_sourcesBottomRight, const __m128i &m128_factorsTopLeft, const __m128i &m128_factorsTopRight, const __m128i &m128_factorsBottomLeft, const __m128i &m128_factorsBottomRight)
Interpolates 4 independent pixels concurrently based on already known locations (top-left,...
static void interpolateRowHorizontal(const T *extendedSourceRow, T *targetRow, const unsigned int targetWidth, const unsigned int channels, const unsigned int *interpolationLocations, const float *interpolationFactorsRight)
Applies a (horizontal) linear interpolation for one row with arbitrary data type.
Definition FrameInterpolatorBilinear.h:5687
static void rotate8BitPerChannelSubset(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const Scalar horizontalAnchorPosition, const Scalar verticalAnchorPosition, const Scalar angle, const uint8_t *borderColor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Rotates a subset of a given frame by a bilinear interpolation.
Definition FrameInterpolatorBilinear.h:7270
static void lookupMask8BitPerChannel(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const LookupTable &input_LT_output, const bool offset, uint8_t *output, uint8_t *outputMask, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, Worker *worker=nullptr, const uint8_t maskValue=0xFF)
Transforms a given input frame into an output frame by application of an interpolation lookup table.
Definition FrameInterpolatorBilinear.h:1916
static OCEAN_FORCE_INLINE void interpolate4Pixels8BitPerChannelSSE(const uint8_t *source, const unsigned int offsetsTopLeft[4], const unsigned int offsetsTopRight[4], const unsigned int offsetsBottomLeft[4], const unsigned int offsetsBottomRight[4], const unsigned int validPixels[4], const typename DataType< uint8_t, tChannels >::Type &borderColor, const __m128i &m128_factorsRight, const __m128i &m128_factorsBottom, typename DataType< uint8_t, tChannels >::Type *targetPositionPixels)
Interpolates 4 independent pixels concurrently based on already known locations (top-left,...
Definition FrameInterpolatorBilinear.h:3295
static void homographies8BitPerChannel(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 homographies[4], const uint8_t *borderColor, uint8_t *output, const Vector2 &outputQuadrantCenter, const PixelPositionI &outputOrigin, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, Worker *worker=nullptr)
Transforms a given 8 bit per channel input frame into an output frame by application of four homograp...
Definition FrameInterpolatorBilinear.h:1793
static void lookup8BitPerChannelSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const LookupTable *input_LT_output, const bool offset, const uint8_t *borderColor, uint8_t *output, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Transforms a subset of a given input frame with uint8_t as element type into an output frame by appli...
Definition FrameInterpolatorBilinear.h:4828
static void resize(const T *source, T *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Resizes a given frame with (almost) arbitrary data type (e.g., float, double, int) by using a bilinea...
Definition FrameInterpolatorBilinear.h:1644
static bool coversHomographyInputFrame(const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int outputWidth, const unsigned int outputHeight, const SquareMatrix3 &input_H_output, const int outputOriginX=0, const int outputOriginY=0)
Checks whether the application of a given homography for a specified input frame and output frame cov...
static void scale(const T *source, T *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const double sourceX_s_targetX, const double sourceY_s_targetY, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Rescales a given frame with arbitrary data type (e.g., float, double, int) by using a bilinear interp...
Definition FrameInterpolatorBilinear.h:1657
static void lookupSubset(const T *input, const unsigned int inputWidth, const unsigned int inputHeight, const LookupTable *input_LT_output, const bool offset, const T *borderColor, T *output, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Transforms a subset of a given input frame with arbitrary element type into an output frame by applic...
Definition FrameInterpolatorBilinear.h:4900
static void scale8BitPerChannelSubset(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const double sourceX_s_targetX, const double sourceY_s_targetY, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Resizes a subset of a given frame with 8 bit per channel by a bilinear interpolation.
Definition FrameInterpolatorBilinear.h:5546
static void rotate8BitPerChannel(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const Scalar horizontalAnchorPosition, const Scalar verticalAnchorPosition, const Scalar angle, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr, const uint8_t *borderColor=nullptr)
Rotates a given frame by a bilinear interpolation.
Definition FrameInterpolatorBilinear.h:1978
static void interpolateRowVertical(const T *sourceRowTop, const T *sourceRowBottom, T *targetRow, const unsigned int elements, const float factorBottom)
Applies a (vertical) linear interpolation between two rows with arbitrary data types.
Definition FrameInterpolatorBilinear.h:5667
static void homography8BitPerChannel(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 &input_H_output, const uint8_t *borderColor, uint8_t *output, const PixelPositionI &outputOrigin, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, Worker *worker=nullptr)
Transforms a given 8 bit per channel input frame into an output frame by application of a homography.
Definition FrameInterpolatorBilinear.h:1731
static void interpolate1PixelFullAlphaBorder8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const Vector2 &position, uint8_t *result, const unsigned int framePaddingElements)
Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame wit...
Definition FrameInterpolatorBilinear.h:2175
static void lookupMask8BitPerChannelSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const LookupTable *input_LT_output, const bool offset, uint8_t *output, uint8_t *outputMask, const uint8_t maskValue, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Transforms a given input frame into an output frame by application of an interpolation lookup table.
Definition FrameInterpolatorBilinear.h:5431
static void affine8BitPerChannelSubset(const uint8_t *source, const unsigned int sourceWidth, const unsigned int sourceHeight, const SquareMatrix3 *source_A_target, const uint8_t *borderColor, uint8_t *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int firstTargetRow, const unsigned int numberTargetRows, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements)
Subset function to apply an affine transform to an N-channel, 8-bit unsigned image.
Definition FrameInterpolatorBilinear.h:2264
static void homography8BitPerChannelSSESubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *input_H_output, const uint8_t *borderColor, uint8_t *output, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:2685
static void interpolateRowHorizontal8BitPerChannel7BitPrecisionNEON(const uint8_t *extendedSourceRow, uint8_t *targetRow, const unsigned int targetWidth, const unsigned int channels, const unsigned int *interpolationLocations, const uint8_t *interpolationFactors)
Applies a (horizontal) linear interpolation for one row with 8 bit per channel.
static void scale8BitPerChannel(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const double sourceX_s_targetX, const double sourceY_s_targetY, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Rescales a given frame with 8 bit per data channel by using a bilinear interpolation with user-define...
Definition FrameInterpolatorBilinear.h:5502
static void lookup8BitPerChannelSubsetNEON(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const LookupTable *input_LT_output, const bool offset, const uint8_t *borderColor, uint8_t *output, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstRow, const unsigned int numberRows, const bool useOptimizedNEON=false, const bool useOptimizedBilinearValuesAndFactorCalculation=false, const bool useOptimizedNEONFactorReplication=false)
Transforms a subset of a given input frame into an output frame by application of an interpolation lo...
Definition FrameInterpolatorBilinear.h:5194
static void homographyMask8BitPerChannelSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *input_H_output, uint8_t *output, uint8_t *outputMask, const uint8_t maskValue, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int outputMaskPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:4579
static void scaleSubset(const T *source, T *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const double sourceX_s_targetX, const double sourceY_s_targetY, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Resizes a subset of a given frame with arbitrary data type by a bilinear interpolation.
Definition FrameInterpolatorBilinear.h:7146
static void homography8BitPerChannelSubset(const uint8_t *input, const unsigned int inputWidth, const unsigned int inputHeight, const SquareMatrix3 *input_H_output, const uint8_t *borderColor, uint8_t *output, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputPaddingElements, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorBilinear.h:2339
static void interpolatePixel(const TSource *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const VectorT2< TScalar > &position, TTarget *result, const TIntermediate &resultBias=TIntermediate(0))
Determines the interpolated pixel values for a given pixel position in a frame with arbitrary data ty...
Definition FrameInterpolatorBilinear.h:2089
static constexpr uint8x8_t create_uint8x8(const uint8_t v0, const uint8_t v1, const uint8_t v2, const uint8_t v3, const uint8_t v4, const uint8_t v5, const uint8_t v6, const uint8_t v7)
Creates a uint8x8_t vector from 8 individual uint8_t values.
Definition NEON.h:591
This class implements a 2D pixel position with pixel precision.
Definition PixelPosition.h:63
T y() const
Returns the vertical coordinate position of this object.
Definition PixelPosition.h:468
T x() const
Returns the horizontal coordinate position of this object.
Definition PixelPosition.h:456
static __m128i set128i(const unsigned long long high64, const unsigned long long low64)
Sets a 128i value by two 64 bit values.
Definition SSE.h:3874
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
Template class allowing to define an array of data types.
Definition DataType.h:27
This class implements Ocean's image class.
Definition Frame.h:1969
void setRelativeTimestamp(const Timestamp &relative)
Sets the relative timestamp of this frame.
Definition Frame.h:4410
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4705
void setTimestamp(const Timestamp ×tamp)
Sets the timestamp of this frame.
Definition Frame.h:4405
const Timestamp & timestamp() const
Returns the timestamp of this frame.
Definition Frame.h:4395
const Timestamp & relativeTimestamp() const
Returns the relative timestamp of this frame.
Definition Frame.h:4400
Definition of a frame type composed by the frame dimension, pixel format and pixel origin.
Definition Frame.h:30
size_t sizeY() const
Returns the vertical dimension of this lookup object.
Definition Lookup2.h:960
size_t sizeX() const
Returns the horizontal dimension of this lookup object.
Definition Lookup2.h:954
size_t binsY() const
Returns the number of vertical bins of this lookup object.
Definition Lookup2.h:972
size_t binsX() const
Returns the number of horizontal bins of this lookup object.
Definition Lookup2.h:966
This class implements a 2D lookup object with values at the bins' corners defining the individual loo...
Definition Lookup2.h:636
Vector2 binTopLeftCornerPosition(const size_t binX, const size_t binY) const
Returns the corner position (the top left corner) of a specific bin in relation to the dimension of t...
Definition Lookup2.h:1799
void setBinTopLeftCornerValue(const size_t binX, const size_t binY, const T &value)
Sets the value of one specific lookup bin's top left corner.
Definition Lookup2.h:2215
void bilinearValues(const size_t y, TTarget *values) const
Applies a lookup for an entire row in this lookup object.
Definition Lookup2.h:1877
This class implements an object able to allocate memory.
Definition base/Memory.h:22
bool isNull() const
Returns whether this object holds any memory.
Definition base/Memory.h:401
void * data()
Returns the pointer to the writable memory which is allocated by this object.
Definition base/Memory.h:303
This class provides basic numeric functionalities.
Definition Numeric.h:57
static constexpr T eps()
Returns a small epsilon.
static T floor(const T value)
Returns the largest integer value that is not greater than the given value.
Definition Numeric.h:2035
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2096
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2246
unsigned int width() const
Returns the width of the camera image.
Definition PinholeCamera.h:1452
const SquareMatrixT3< T > & invertedIntrinsic() const
Returns the inverted intrinsic camera matrix.
Definition PinholeCamera.h:1333
const SquareMatrixT3< T > & intrinsic() const
Returns the intrinsic camera matrix.
Definition PinholeCamera.h:1327
unsigned int height() const
Returns the height of the camera image.
Definition PinholeCamera.h:1458
VectorT2< T > normalizedImagePoint2imagePoint(const VectorT2< T > &normalizedImagePoint, const bool distortImagePoint) const
Calculates the image point corresponding to a given normalized image point.
Definition PinholeCamera.h:1792
This class implements a 2x2 square matrix.
Definition SquareMatrix2.h:73
bool isNull() const
Returns whether this matrix is a zero matrix.
Definition SquareMatrix3.h:1334
const T * data() const
Returns a pointer to the internal values.
Definition SquareMatrix3.h:1047
bool isOrthonormal(const T epsilon=NumericT< T >::eps()) const
Returns whether this matrix is an orthonormal matrix.
Definition SquareMatrix3.h:1366
This class implements tests for the NEON-accelerated bilinear interpolation functions.
Definition TestFrameInterpolatorBilinearNEON.h:27
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:703
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:715
bool isEqual(const VectorT2< T > &vector, const T eps) const
Returns whether two vectors are equal up to a specified epsilon.
Definition Vector2.h:751
const T & y() const noexcept
Returns the y value.
Definition Vector3.h:816
const T & x() const noexcept
Returns the x value.
Definition Vector3.h:804
const T & z() const noexcept
Returns the z value.
Definition Vector3.h:828
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.
T minmax(const T &lowerBoundary, const T &value, const T &upperBoundary)
This function fits a given parameter into a specified value range.
Definition base/Utilities.h:973
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:129
SquareMatrixT3< Scalar > SquareMatrix3
Definition of the SquareMatrix3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with ...
Definition SquareMatrix3.h:43
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition Vector3.h:29
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition Vector2.h:28
RotationT< Scalar > Rotation
Definition of the Rotation object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION flag either with ...
Definition Rotation.h:32
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Default definition of a type with tBytes bytes.
Definition DataType.h:32
float Type
The 32 bit floating point data type for any data type T but 'double'.
Definition DataType.h:373