8#ifndef META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_H
9#define META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_H
81 static inline bool resize(
Frame& frame,
const unsigned int width,
const unsigned int height,
Worker* worker =
nullptr);
279 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);
312 template <
typename TScalar = Scalar>
313 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);
333 template <
typename TSource,
typename TTarget,
typename TScalar = Scalar,
typename TIntermediate = TScalar>
334 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));
384 template <
typename T,
unsigned int tChannels>
385 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);
406 template <
typename T,
unsigned int tChannels>
407 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);
425 template <
unsigned int tChannels>
426 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);
455 template <
unsigned int tChannels>
456 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);
479 template <
typename T,
unsigned int tChannels>
480 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);
504 template <
unsigned int tChannels>
505 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);
529 template <
unsigned int tChannels>
530 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);
556 template <
unsigned int tChannels>
557 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);
577 template <
unsigned int tChannels>
578 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);
599 template <
unsigned int tChannels>
600 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);
619 template <
typename T,
unsigned int tChannels>
620 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);
641 template <
unsigned int tChannels>
642 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);
662 template <
typename T,
unsigned int tChannels>
663 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);
679 template <
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar>
680 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);
700 template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar,
typename TIntermediate = TScalar>
701 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));
718 template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
719 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);
733 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);
746 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);
770 template <
unsigned int tChannels>
771 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);
790 template <
unsigned int tChannels>
791 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);
809 template <
unsigned int tChannels>
810 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);
836 template <
typename T>
837 static void interpolateRowVertical(
const T* sourceRowTop,
const T* sourceRowBottom, T* targetRow,
const unsigned int elements,
const float factorBottom);
852 template <
typename T,
unsigned int tChannels>
853 static void interpolateRowHorizontal(
const T* extendedSourceRow, T* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight);
855#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
880 template <
typename T>
881 static void interpolateRowVerticalNEON(
const T* sourceRowTop,
const T* sourceRowBottom, T* targetRow,
const unsigned int elements,
const float factorBottom);
895 template <
unsigned int tChannels>
911 template <
typename T,
unsigned int tChannels>
912 static void interpolateRowHorizontalNEON(
const T* extendedSourceRow, T* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight);
932 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);
954 template <
typename T,
typename TScale,
unsigned int tChannels>
955 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);
973 template <
unsigned int tChannels>
974 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);
1002 template <
unsigned int tChannels>
1003 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);
1024 template <
unsigned int tChannels>
1025 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);
1046 template <
typename T,
unsigned int tChannels>
1047 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);
1049#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1078 template <
unsigned int tChannels>
1079 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);
1100 template <
unsigned int tChannels>
1101 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);
1118 template <
unsigned int tChannels>
1119 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);
1135 template <
unsigned int tChannels>
1136 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);
1140#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1169 template <
unsigned int tChannels>
1170 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);
1191 template <
unsigned int tChannels>
1192 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);
1209 template <
unsigned int tChannels>
1210 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);
1221 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);
1245 template <
unsigned int tChannels>
1246 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);
1266 template <
unsigned int tChannels>
1267 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);
1291 template <
unsigned int tChannels>
1292 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);
1310 template <
unsigned int tChannels>
1311 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);
1330 template <
unsigned int tChannels>
1331 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);
1349 template <
unsigned int tChannels>
1350 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);
1369 template <
typename T,
unsigned int tChannels>
1370 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);
1372#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1390 template <
unsigned int tChannels>
1391 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);
1414 template <
unsigned int tChannels>
1415 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);
1420 ocean_assert(frame.
isValid());
1421 ocean_assert(width >= 1u && height >= 1u);
1425 if (!
resize(frame, target, worker))
1433 frame = std::move(target);
1437template <
typename TScalar>
1440 ocean_assert(frame !=
nullptr);
1441 ocean_assert(channels >= 1u && channels <= 8u);
1448 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1452 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1456 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1460 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1464 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1468 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1472 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1476 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1490 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1494 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1498 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1502 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1506 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1510 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1514 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1518 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1526 ocean_assert(
false &&
"Invalid channel number");
1530template <
typename TSource,
typename TTarget,
typename TScalar,
typename TIntermediate>
1533 ocean_assert(frame !=
nullptr);
1534 ocean_assert(channels >= 1u && channels <= 8u);
1541 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1545 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1549 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1553 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1557 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1561 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1565 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1569 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1583 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1587 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1591 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1595 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1599 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1603 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1607 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1611 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1619 ocean_assert(
false &&
"Invalid channel number");
1623template <
typename T,
unsigned int tChannels>
1624inline 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)
1626 ocean_assert(source !=
nullptr && target !=
nullptr);
1627 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1628 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1630 const double sourceX_s_targetX = double(sourceWidth) / double(targetWidth);
1631 const double sourceY_s_targetY = double(sourceHeight) / double(targetHeight);
1633 scale<T, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1636template <
typename T,
unsigned int tChannels>
1637inline 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)
1639 ocean_assert(source !=
nullptr && target !=
nullptr);
1640 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1641 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1642 ocean_assert(sourceX_s_targetX > 0.0);
1643 ocean_assert(sourceY_s_targetY > 0.0);
1645 if (sourceWidth == targetWidth && sourceHeight == targetHeight)
1647 FrameConverter::subFrame<T>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
1651 if (std::is_same<T, uint8_t>::value)
1655 scale8BitPerChannel<tChannels>((
const uint8_t*)source, (uint8_t*)target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1663 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);
1667 scaleSubset<T, TScale, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
1672template <
unsigned int tChannels>
1673inline 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)
1680 if (targetWidth >= 4u)
1682#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1683 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);
1685#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1686 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);
1691 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);
1695 if (targetWidth >= 4u)
1697#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1698 affine8BitPerChannelSSESubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1700#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1701 affine8BitPerChannelNEONSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1706 affine8BitPerChannelSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1710template <
unsigned int tChannels>
1711inline 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)
1718 if (outputWidth >= 4u)
1720#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1721 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);
1723#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1724 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);
1729 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);
1733 if (outputWidth >= 4u)
1735#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1736 homography8BitPerChannelSSESubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1738#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1739 homography8BitPerChannelNEONSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1744 homography8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1748template <
typename T,
unsigned int tChannels>
1749inline 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)
1751 if (std::is_same<T, uint8_t>::value)
1753 homography8BitPerChannel<tChannels>((
const uint8_t*)input, inputWidth, inputHeight, input_H_output, (
const uint8_t*)borderColor, (uint8_t*)output, outputOrigin, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, worker);
1763 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);
1767 homographySubset<T, tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1772template <
unsigned int tChannels>
1773inline 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)
1777 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);
1781 homographies8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, borderColor, output, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1785template <
unsigned int tChannels>
1786inline 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)
1793 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);
1797 homographyMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, output, outputMask, maskValue, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1801template <
unsigned int tChannels>
1802inline 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)
1806 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);
1810 homographiesMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, output, outputMask, maskValue, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1814template <
unsigned int tChannels>
1819 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1823 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographyWithCamera8BitPerChannelSubset<tChannels>, &inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputCamera.
height());
1827 homographyWithCamera8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, outputCamera.
height());
1831template <
unsigned int tChannels>
1832inline 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)
1836 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1840 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);
1844 homographyWithCameraMask8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, inputPaddingElements, &normalizedHomography, output, outputMask, outputPaddingElements, outputMaskPaddingElements, maskValue, 0u, outputCamera.
height());
1848template <
typename T,
unsigned int tChannels>
1849inline 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)
1851 if constexpr (std::is_same<T, uint8_t>::value)
1853#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1854 if ((tChannels >= 1u && input_LT_output.
sizeX() >= 8) || (tChannels >= 2u && input_LT_output.
sizeX() >= 4))
1860 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::lookup8BitPerChannelSubsetNEON<tChannels>, input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0u, (
unsigned int)(input_LT_output.
sizeY()), 9u, 10u, 20u);
1864 lookup8BitPerChannelSubsetNEON<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1873 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);
1877 lookup8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1882 ocean_assert((!std::is_same<T, uint8_t>::value));
1886 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);
1890 lookupSubset<T, tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1895template <
unsigned int tChannels>
1896inline 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)
1900 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);
1904 lookupMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, output, outputMask, maskValue, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1908template <
typename T,
unsigned int tChannels>
1909void 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)
1911 static_assert(tChannels >= 1u,
"Invalid channel number!");
1913 ocean_assert(sourceFrame !=
nullptr);
1914 ocean_assert(sourceCamera.
isValid());
1916 ocean_assert(targetCamera.
isValid());
1917 ocean_assert(targetFrame !=
nullptr);
1918 ocean_assert(binSizeInPixel >= 1u);
1920 const size_t binsX = std::max(1u, targetCamera.
width() / binSizeInPixel);
1921 const size_t binsY = std::max(1u, targetCamera.
height() / binSizeInPixel);
1924 for (
size_t yBin = 0; yBin <= lookupTable.
binsY(); ++yBin)
1926 for (
size_t xBin = 0; xBin <= lookupTable.
binsX(); ++xBin)
1930 constexpr bool makeUnitVector =
false;
1932 const Vector3 rayI = source_R_target * targetCamera.
vector(cornerPosition, makeUnitVector);
1949 lookup<T, tChannels>(sourceFrame, sourceCamera.
width(), sourceCamera.
height(), lookupTable,
true , borderColor, targetFrame, sourceFramePaddingElements, targetFramePaddingElements, worker);
1951 if (source_OLT_target)
1953 *source_OLT_target = std::move(lookupTable);
1957template <
unsigned int tChannels>
1958void 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)
1960 static_assert(tChannels != 0u,
"Invalid channel number!");
1962 ocean_assert(source !=
nullptr && target !=
nullptr);
1963 ocean_assert(width >= 1u && height >= 1u);
1967 worker->
executeFunction(
Worker::Function::createStatic(&rotate8BitPerChannelSubset<tChannels>, source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height);
1971 rotate8BitPerChannelSubset<tChannels>(source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, height);
1975template <
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar>
1978 static_assert(tChannels != 0u,
"Invalid channel number!");
1979 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
1981 ocean_assert(frame !=
nullptr && result !=
nullptr);
1982 ocean_assert(width != 0u && height != 0u);
1984 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
1986 ocean_assert(position.
x() >= TScalar(0));
1987 ocean_assert(position.
y() >= TScalar(0));
1991 ocean_assert(position.
x() <= TScalar(width - 1u));
1992 ocean_assert(position.
y() <= TScalar(height - 1u));
1994 const unsigned int left = (
unsigned int)(position.
x());
1995 const unsigned int top = (
unsigned int)(position.
y());
1996 ocean_assert(left < width && top < height);
1998 const TScalar tx = position.
x() - TScalar(left);
1999 ocean_assert(tx >= 0 && tx <= 1);
2000 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
2001 const unsigned int txi_ = 128u - txi;
2003 const TScalar ty = position.
y() - TScalar(top);
2004 ocean_assert(ty >= 0 && ty <= 1);
2005 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
2006 const unsigned int tyi_ = 128u - tyi;
2008 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2009 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2011 const uint8_t*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2013 const unsigned int txty = txi * tyi;
2014 const unsigned int txty_ = txi * tyi_;
2015 const unsigned int tx_ty = txi_ * tyi;
2016 const unsigned int tx_ty_ = txi_ * tyi_;
2018 for (
unsigned int n = 0u; n < tChannels; ++n)
2020 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2025 ocean_assert(tPixelCenter ==
PC_CENTER);
2027 ocean_assert(position.
x() <= TScalar(width));
2028 ocean_assert(position.
y() <= TScalar(height));
2030 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2031 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2033 const unsigned int left = (
unsigned int)(xShifted);
2034 const unsigned int top = (
unsigned int)(yShifted);
2036 ocean_assert(left < width);
2037 ocean_assert(top < height);
2039 const TScalar tx = xShifted - TScalar(left);
2040 const TScalar ty = yShifted - TScalar(top);
2042 ocean_assert(tx >= 0 && tx <= 1);
2043 ocean_assert(ty >= 0 && ty <= 1);
2045 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
2046 const unsigned int txi_ = 128u - txi;
2048 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
2049 const unsigned int tyi_ = 128u - tyi;
2051 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2052 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2054 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2056 const unsigned int txty = txi * tyi;
2057 const unsigned int txty_ = txi * tyi_;
2058 const unsigned int tx_ty = txi_ * tyi;
2059 const unsigned int tx_ty_ = txi_ * tyi_;
2061 for (
unsigned int n = 0u; n < tChannels; ++n)
2063 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2068template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar,
typename TIntermediate>
2071 static_assert(tChannels != 0u,
"Invalid channel number!");
2072 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
2074 ocean_assert(frame !=
nullptr && result !=
nullptr);
2075 ocean_assert(width != 0u && height != 0u);
2077 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2079 ocean_assert(position.
x() >= TScalar(0));
2080 ocean_assert(position.
y() >= TScalar(0));
2084 ocean_assert(position.
x() <= TScalar(width - 1u));
2085 ocean_assert(position.
y() <= TScalar(height - 1u));
2087 const unsigned int left = (
unsigned int)(position.
x());
2088 const unsigned int top = (
unsigned int)(position.
y());
2090 const TScalar tx = position.
x() - TScalar(left);
2091 ocean_assert(tx >= 0 && tx <= 1);
2093 const TScalar ty = position.
y() - TScalar(top);
2094 ocean_assert(ty >= 0 && ty <= 1);
2096 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2097 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2099 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2101 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2102 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2103 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2104 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2108 for (
unsigned int n = 0u; n < tChannels; ++n)
2110 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);
2115 ocean_assert(tPixelCenter ==
PC_CENTER);
2117 ocean_assert(position.
x() <= TScalar(width));
2118 ocean_assert(position.
y() <= TScalar(height));
2120 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2121 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2123 const unsigned int left = (
unsigned int)(xShifted);
2124 const unsigned int top = (
unsigned int)(yShifted);
2126 ocean_assert(left < width);
2127 ocean_assert(top < height);
2129 const TScalar tx = xShifted - TScalar(left);
2130 const TScalar ty = yShifted - TScalar(top);
2132 ocean_assert(tx >= 0 && tx <= 1);
2133 ocean_assert(ty >= 0 && ty <= 1);
2135 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2136 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2138 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2140 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2141 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2142 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2143 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2147 for (
unsigned int n = 0u; n < tChannels; ++n)
2149 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);
2154template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
2157 static_assert(tChannels != 0u,
"Invalid channel number!");
2159 ocean_assert(frame && result);
2166 for (
unsigned int n = 0u; n < tChannels - 1u; ++n)
2176 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2181 ocean_assert(left >= -1 && left <
int(width));
2182 ocean_assert(top >= -1 && top <
int(height));
2184 if ((
unsigned int)left < width - 1u && (
unsigned int)top < height - 1u)
2188 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2189 const unsigned int txi_ = 128u - txi;
2191 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2192 const unsigned int tyi_ = 128u - tyi;
2194 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2196 const unsigned int txty = txi * tyi;
2197 const unsigned int txty_ = txi * tyi_;
2198 const unsigned int tx_ty = txi_ * tyi;
2199 const unsigned int tx_ty_ = txi_ * tyi_;
2201 for (
unsigned int n = 0u; n < tChannels; ++n)
2203 result[n] = (topLeft[n] * tx_ty_ + topLeft[tChannels + n] * txty_
2204 + topLeft[frameStrideElements + n] * tx_ty + topLeft[frameStrideElements + tChannels + n] * txty + 8192u) >> 14u;
2211 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2212 const unsigned int txi_ = 128u - txi;
2214 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2215 const unsigned int tyi_ = 128u - tyi;
2217 const unsigned int rightOffset = (left >= 0 && left + 1u < width) ? tChannels : 0u;
2218 const unsigned int bottomOffset = (top >= 0 && top + 1u < height) ? frameStrideElements : 0u;
2220 ocean_assert(left <
int(width) && top <
int(height));
2221 const uint8_t*
const topLeft = frame + max(0, top) * frameStrideElements + max(0, left) * tChannels;
2223 const unsigned int txty = txi * tyi;
2224 const unsigned int txty_ = txi * tyi_;
2225 const unsigned int tx_ty = txi_ * tyi;
2226 const unsigned int tx_ty_ = txi_ * tyi_;
2230 result[n] = (topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_
2231 + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u;
2243template <
unsigned int tChannels>
2244void 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)
2246 static_assert(tChannels >= 1u,
"Invalid channel number!");
2248 ocean_assert(source !=
nullptr && target !=
nullptr);
2249 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2250 ocean_assert_and_suppress_unused(targetWidth > 0u && targetHeight > 0u, targetHeight);
2251 ocean_assert(source_A_target);
2254 ocean_assert(firstTargetRow + numberOutputRows <= targetHeight);
2256 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2258 const Scalar scalarSourceWidth_1 =
Scalar(sourceWidth - 1u);
2259 const Scalar scalarSourceHeight_1 =
Scalar(sourceHeight - 1u);
2263 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2264 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2266 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberOutputRows; ++y)
2268 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2294 for (
unsigned int x = 0u; x < targetWidth; ++x)
2299 const Scalar debugSourceX = (*source_A_target)[0] *
Scalar(x) + (*source_A_target)[3] *
Scalar(y) + (*source_A_target)[6];
2300 const Scalar debugSourceY = (*source_A_target)[1] *
Scalar(x) + (*source_A_target)[4] *
Scalar(y) + (*source_A_target)[7];
2304 if (sourcePosition.
x() <
Scalar(0) || sourcePosition.
x() > scalarSourceWidth_1 || sourcePosition.
y() <
Scalar(0) || sourcePosition.
y() > scalarSourceHeight_1)
2306 *targetRow = *bColor;
2310 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, sourceWidth, sourceHeight, sourcePaddingElements, sourcePosition, (uint8_t*)(targetRow));
2318template <
unsigned int tChannels>
2319void 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)
2321 static_assert(tChannels >= 1u,
"Invalid channel number!");
2323 ocean_assert(input !=
nullptr && output !=
nullptr);
2324 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2325 ocean_assert(outputWidth > 0u && outputHeight > 0u);
2326 ocean_assert(input_H_output !=
nullptr);
2328 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2330 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2332 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
2333 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
2337 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2338 const PixelType bColor = borderColor ? *(PixelType*)borderColor : *(PixelType*)zeroColor;
2340 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2366 const Scalar X2 = (*input_H_output)(2, 0);
2367 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2369 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2371 for (
unsigned int x = 0u; x < outputWidth; ++x)
2378 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2381 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
2383 *outputRowPixel = bColor;
2387 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputRowPixel));
2395template <
typename T,
unsigned int tChannels>
2396void 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)
2398 static_assert(tChannels >= 1u,
"Invalid channel number!");
2400 ocean_assert(input !=
nullptr && output !=
nullptr);
2401 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2402 ocean_assert_and_suppress_unused(outputWidth > 0u && outputHeight > 0u, outputHeight);
2403 ocean_assert(input_H_output !=
nullptr);
2405 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
2407 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2409 const Scalar scalarInputWidth1 =
Scalar(inputWidth - 1u);
2410 const Scalar scalarInputHeight1 =
Scalar(inputHeight - 1u);
2417 constexpr T zeroColor[tChannels] = {T(0)};
2418 const PixelType*
const bColor = borderColor ? (PixelType*)(borderColor) : (PixelType*)(zeroColor);
2420 constexpr TIntermediate bias = TIntermediate(0);
2422 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2448 const Scalar X2 = (*input_H_output)(2, 0);
2449 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2451 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2453 for (
unsigned int x = 0u; x < outputWidth; ++x)
2460 ocean_assert((std::is_same<float, Scalar>::value) || inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2463 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
x() <= scalarInputWidth1 && inputPosition.
y() >=
Scalar(0) && inputPosition.
y() <= scalarInputHeight1)
2465 interpolatePixel<T, T, tChannels, CV::PC_TOP_LEFT, Scalar, TIntermediate>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputRowPixel), bias);
2469 *outputRowPixel = *bColor;
2477#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
2479template <
unsigned int tChannels>
2480inline 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)
2482 static_assert(tChannels >= 1u,
"Invalid channel number!");
2484 ocean_assert(source && target);
2485 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2486 ocean_assert(targetWidth >= 4u && targetHeight > 0u);
2487 ocean_assert(source_A_target);
2490 ocean_assert_and_suppress_unused(firstTargetRow + numberTargetRows <= targetHeight, targetHeight);
2492 const unsigned int sourceStrideElements = tChannels * sourceWidth + sourcePaddingElements;
2493 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2497 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2498 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2500 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2502 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2503 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2504 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2505 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2508 const __m128 m128_f_X0 = _mm_set_ps1(
float((*source_A_target)(0, 0)));
2509 const __m128 m128_f_X1 = _mm_set_ps1(
float((*source_A_target)(1, 0)));
2511 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
2513 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2537 const __m128 m128_f_C0 = _mm_set_ps1(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
2538 const __m128 m128_f_C1 = _mm_set_ps1(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
2541 const __m128 m128_f_zero = _mm_setzero_ps();
2544 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2547 const __m128i m128_i_sourceStrideElements = _mm_set1_epi32(sourceStrideElements);
2550 const __m128i m128_i_sourceWidth_1 = _mm_set1_epi32(
int(sourceWidth) - 1);
2551 const __m128i m128_i_sourceHeight_1 = _mm_set1_epi32(
int(sourceHeight) - 1);
2554 const __m128 m128_f_sourceWidth_1 = _mm_set_ps1(
float(sourceWidth - 1u));
2555 const __m128 m128_f_sourceHeight_1 = _mm_set_ps1(
float(sourceHeight - 1u));
2557 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
2559 if (x + 4u > targetWidth)
2564 ocean_assert(x >= 4u && targetWidth > 4u);
2565 const unsigned int newX = targetWidth - 4u;
2567 ocean_assert(x > newX);
2568 targetRow -= x - newX;
2573 ocean_assert(!(x + 4u < targetWidth));
2579 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2582 const __m128 m128_f_sourceX = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2583 const __m128 m128_f_sourceY = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2586 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));
2587 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));
2589 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2592 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2595 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2596 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2597 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2600 targetRow[0] = *bColor;
2601 targetRow[1] = *bColor;
2602 targetRow[2] = *bColor;
2603 targetRow[3] = *bColor;
2611 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2612 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2616 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_sourceX);
2617 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_sourceY);
2620 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2621 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2624 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_sourceWidth_1);
2625 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_sourceHeight_1);
2628 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));
2629 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));
2630 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));
2631 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));
2634 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2635 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2636 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2637 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2645 __m128 m128_f_tx = _mm_sub_ps(m128_f_sourceX, m128_f_tx_floor);
2646 __m128 m128_f_ty = _mm_sub_ps(m128_f_sourceY, m128_f_ty_floor);
2649 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2650 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2652 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2653 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2655 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2656 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2658 interpolate4Pixels8BitPerChannelSSE<tChannels>(source, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, targetRow);
2664template <
unsigned int tChannels>
2665inline 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)
2667 static_assert(tChannels >= 1u,
"Invalid channel number!");
2669 ocean_assert(input !=
nullptr && output !=
nullptr);
2670 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2671 ocean_assert(outputWidth >= 4u && outputHeight > 0u);
2672 ocean_assert(input_H_output !=
nullptr);
2674 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2676 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
2677 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2681 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2682 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2684 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2686 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2687 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2688 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2689 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2692 const __m128 m128_f_X0 = _mm_set_ps1(
float((*input_H_output)(0, 0)));
2693 const __m128 m128_f_X1 = _mm_set_ps1(
float((*input_H_output)(1, 0)));
2694 const __m128 m128_f_X2 = _mm_set_ps1(
float((*input_H_output)(2, 0)));
2697 const __m128 m128_f_zero = _mm_setzero_ps();
2700 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2703 const __m128i m128_i_inputStrideElements = _mm_set1_epi32(inputStrideElements);
2706 const __m128i m128_i_inputWidth_1 = _mm_set1_epi32(
int(inputWidth) - 1);
2707 const __m128i m128_i_inputHeight_1 = _mm_set1_epi32(
int(inputHeight) - 1);
2710 const __m128 m128_f_inputWidth_1 = _mm_set_ps1(
float(inputWidth - 1u));
2711 const __m128 m128_f_inputHeight_1 = _mm_set_ps1(
float(inputHeight - 1u));
2713 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2715 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
2739 const __m128 m128_f_C0 = _mm_set_ps1(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
2740 const __m128 m128_f_C1 = _mm_set_ps1(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
2741 const __m128 m128_f_C2 = _mm_set_ps1(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
2743 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
2745 if (x + 4u > outputWidth)
2750 ocean_assert(x >= 4u && outputWidth > 4u);
2751 const unsigned int newX = outputWidth - 4u;
2753 ocean_assert(x > newX);
2754 outputPixelData -= x - newX;
2759 ocean_assert(!(x + 4u < outputWidth));
2765 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2768 const __m128 m128_f_xx = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2769 const __m128 m128_f_yy = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2770 const __m128 m128_f_zz = _mm_add_ps(_mm_mul_ps(m128_f_X2, m128_f_x_0123), m128_f_C2);
2772#ifdef USE_APPROXIMATED_INVERSE_OF_ZZ
2777 const __m128 inv_zz_128 = _mm_rcp_ps(m128_f_zz);
2780 const __m128 m128_f_inputX = _mm_mul_ps(m128_f_xx, inv_zz_128);
2781 const __m128 m128_f_inputY = _mm_mul_ps(m128_f_yy, inv_zz_128);
2786 const __m128 m128_f_inputX = _mm_div_ps(m128_f_xx, m128_f_zz);
2787 const __m128 m128_f_inputY = _mm_div_ps(m128_f_yy, m128_f_zz);
2793 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));
2794 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));
2796 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2799 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2802 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2803 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2804 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2807 outputPixelData[0] = *bColor;
2808 outputPixelData[1] = *bColor;
2809 outputPixelData[2] = *bColor;
2810 outputPixelData[3] = *bColor;
2812 outputPixelData += 4;
2818 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2819 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2823 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_inputX);
2824 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_inputY);
2827 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2828 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2831 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_inputWidth_1);
2832 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_inputHeight_1);
2835 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));
2836 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));
2837 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));
2838 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));
2841 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2842 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2843 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2844 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2852 __m128 m128_f_tx = _mm_sub_ps(m128_f_inputX, m128_f_tx_floor);
2853 __m128 m128_f_ty = _mm_sub_ps(m128_f_inputY, m128_f_ty_floor);
2856 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2857 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2859 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2860 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2862 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2863 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2865 interpolate4Pixels8BitPerChannelSSE<tChannels>(input, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, outputPixelData);
2866 outputPixelData += 4;
2872OCEAN_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)
2889 const __m128i mask32_Channel0 =
SSE::set128i(0xFFFFFF09FFFFFF06ull, 0xFFFFFF03FFFFFF00ull);
2890 const __m128i mask32_Channel1 =
SSE::set128i(0xFFFFFF0AFFFFFF07ull, 0xFFFFFF04FFFFFF01ull);
2891 const __m128i mask32_Channel2 =
SSE::set128i(0xFFFFFF0BFFFFFF08ull, 0xFFFFFF05FFFFFF02ull);
2899 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2902 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2905 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2909 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2910 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2911 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
2915 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
2916 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
2917 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
2921 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
2922 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
2923 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
2926 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
2935 __m128i interpolation_channel0 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFF0CFFull, 0xFF08FFFF04FFFF00ull));
2941 __m128i interpolation_channel1 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFF0CFFFFull, 0x08FFFF04FFFF00FFull));
2947 __m128i interpolation_channel2 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFF0CFFFF08ull, 0xFFFF04FFFF00FFFFull));
2952 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), interpolation_channel2);
2956OCEAN_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)
2973 const __m128i mask32_Channel0 =
SSE::set128i(0xA0A0A00CA0A0A008ull, 0xA0A0A004A0A0A000ull);
2974 const __m128i mask32_Channel1 =
SSE::set128i(0xA0A0A00DA0A0A009ull, 0xA0A0A005A0A0A001ull);
2975 const __m128i mask32_Channel2 =
SSE::set128i(0xA0A0A00EA0A0A00Aull, 0xA0A0A006A0A0A002ull);
2976 const __m128i mask32_Channel3 =
SSE::set128i(0xA0A0A00FA0A0A00Bull, 0xA0A0A007A0A0A003ull);
2984 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2987 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2990 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2993 __m128i multiplication_channel3 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel3));
2997 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2998 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2999 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
3000 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel3)));
3004 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
3005 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
3006 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
3007 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel3)));
3011 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
3012 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
3013 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
3014 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel3)));
3017 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3024 __m128i interpolation_channel0 = _mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14);
3029 __m128i interpolation_channel1 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14), 8);
3033 __m128i interpolation_channel2 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14), 16);
3037 __m128i interpolation_channel3 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel3, m128_i_8192), 14), 24);
3042 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), _mm_or_si128(interpolation_channel2, interpolation_channel3));
3045#ifdef OCEAN_COMPILER_MSC
3051OCEAN_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)
3053 ocean_assert(source !=
nullptr);
3054 ocean_assert(targetPositionPixels !=
nullptr);
3060 OCEAN_ALIGN_DATA(16) PixelType pixels[16];
3064 for (
unsigned int i = 0u; i < 4u; ++i)
3068 pixels[i * 4u + 0u] = *((PixelType*)(source + offsetsTopLeft[i]));
3069 pixels[i * 4u + 1u] = *((PixelType*)(source + offsetsTopRight[i]));
3070 pixels[i * 4u + 2u] = *((PixelType*)(source + offsetsBottomLeft[i]));
3071 pixels[i * 4u + 3u] = *((PixelType*)(source + offsetsBottomRight[i]));
3075 pixels[i * 4u + 0u] = borderColor;
3076 pixels[i * 4u + 1u] = borderColor;
3077 pixels[i * 4u + 2u] = borderColor;
3078 pixels[i * 4u + 3u] = borderColor;
3082 static_assert(
sizeof(__m128i) ==
sizeof(pixels),
"Invalid data type!");
3084 const __m128i m128_pixels = _mm_load_si128((
const __m128i*)pixels);
3090 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3091 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3096 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3097 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3098 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3099 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3115 const __m128i mask32_topLeft =
SSE::set128i(0xFFFFFF0CFFFFFF08ull, 0xFFFFFF04FFFFFF00ull);
3116 const __m128i mask32_topRight =
SSE::set128i(0xFFFFFF0DFFFFFF09ull, 0xFFFFFF05FFFFFF01ull);
3117 const __m128i mask32_bottomLeft =
SSE::set128i(0xFFFFFF0EFFFFFF0Aull, 0xFFFFFF06FFFFFF02ull);
3118 const __m128i mask32_bottomRight =
SSE::set128i(0xFFFFFF0FFFFFFF0Bull, 0xFFFFFF07FFFFFF03ull);
3126 __m128i multiplicationA = _mm_mullo_epi32(m128_factorsTopLeft, _mm_shuffle_epi8(m128_pixels, mask32_topLeft));
3127 __m128i multiplicationB = _mm_mullo_epi32(m128_factorsTopRight, _mm_shuffle_epi8(m128_pixels, mask32_topRight));
3129 multiplicationA = _mm_add_epi32(multiplicationA, _mm_mullo_epi32(m128_factorsBottomLeft, _mm_shuffle_epi8(m128_pixels, mask32_bottomLeft)));
3130 multiplicationB = _mm_add_epi32(multiplicationB, _mm_mullo_epi32(m128_factorsBottomRight, _mm_shuffle_epi8(m128_pixels, mask32_bottomRight)));
3132 __m128i multiplication = _mm_add_epi32(multiplicationA, multiplicationB);
3134 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3139 const __m128i result = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF0C080400ull));
3141 *((
unsigned int*)targetPositionPixels) = _mm_extract_epi32(result, 0);
3145OCEAN_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)
3147 ocean_assert(source !=
nullptr);
3148 ocean_assert(targetPositionPixels !=
nullptr);
3154 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[6];
3155 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[6];
3156 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[6];
3157 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[6];
3161 for (
unsigned int i = 0u; i < 4u; ++i)
3165 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3166 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3167 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3168 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3172 topLeftPixels[i] = borderColor;
3173 topRightPixels[i] = borderColor;
3174 bottomLeftPixels[i] = borderColor;
3175 bottomRightPixels[i] = borderColor;
3179 static_assert(
sizeof(__m128i) <=
sizeof(topLeftPixels),
"Invalid data type!");
3181 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3182 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3183 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3184 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3190 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3191 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3196 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3197 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3198 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3199 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3202 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<3u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3205 memcpy(targetPositionPixels, &m128_interpolationResult, 12u);
3211OCEAN_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)
3213 ocean_assert(source !=
nullptr);
3214 ocean_assert(targetPositionPixels !=
nullptr);
3220 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[4];
3221 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[4];
3222 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[4];
3223 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[4];
3228 for (
unsigned int i = 0u; i < 4u; ++i)
3232 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3233 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3234 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3235 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3239 topLeftPixels[i] = borderColor;
3240 topRightPixels[i] = borderColor;
3241 bottomLeftPixels[i] = borderColor;
3242 bottomRightPixels[i] = borderColor;
3246 static_assert(
sizeof(__m128i) ==
sizeof(topLeftPixels),
"Invalid data type!");
3248 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3249 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3250 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3251 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3257 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3258 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3263 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3264 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3265 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3266 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3269 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<4u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3271 _mm_storeu_si128((__m128i*)targetPositionPixels, m128_interpolationResult);
3274template <
unsigned int tChannels>
3275OCEAN_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)
3277 ocean_assert(source !=
nullptr);
3278 ocean_assert(targetPositionPixels !=
nullptr);
3282 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopLeft[4];
3283 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopRight[4];
3284 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomLeft[4];
3285 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomRight[4];
3291 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3292 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3297 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3298 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3299 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3300 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3304 _mm_store_si128((__m128i*)factorsTopLeft, m128_factorsTopLeft);
3305 _mm_store_si128((__m128i*)factorsTopRight, m128_factorsTopRight);
3306 _mm_store_si128((__m128i*)factorsBottomLeft, m128_factorsBottomLeft);
3307 _mm_store_si128((__m128i*)factorsBottomRight, m128_factorsBottomRight);
3309 for (
unsigned int i = 0u; i < 4u; ++i)
3313 const uint8_t* topLeft = source + offsetsTopLeft[i];
3314 const uint8_t* topRight = source + offsetsTopRight[i];
3316 const uint8_t* bottomLeft = source + offsetsBottomLeft[i];
3317 const uint8_t* bottomRight = source + offsetsBottomRight[i];
3319 const unsigned int& factorTopLeft = factorsTopLeft[i];
3320 const unsigned int& factorTopRight = factorsTopRight[i];
3321 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
3322 const unsigned int& factorBottomRight = factorsBottomRight[i];
3324 for (
unsigned int n = 0u; n < tChannels; ++n)
3326 ((uint8_t*)targetPositionPixels)[n] = (uint8_t)((topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u);
3331 *targetPositionPixels = borderColor;
3334 targetPositionPixels++;
3340#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
3342template <
unsigned int tChannels>
3343void 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)
3345 static_assert(tChannels >= 1u,
"Invalid channel number!");
3347 ocean_assert(source && target);
3348 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
3349 ocean_assert_and_suppress_unused(targetWidth >= 4u && targetHeight > 0u, targetHeight);
3350 ocean_assert(source_A_target);
3353 ocean_assert(firstTargetRow + numberTargetRows <= targetHeight);
3355 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
3356 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
3360 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3361 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3363 unsigned int validPixels[4];
3365 unsigned int topLeftOffsetsElements[4];
3366 unsigned int topRightOffsetsElements[4];
3367 unsigned int bottomLeftOffsetsElements[4];
3368 unsigned int bottomRightOffsetsElements[4];
3370 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3373 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*source_A_target)(0, 0)));
3374 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*source_A_target)(1, 0)));
3376 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
3378 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
3402 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
3403 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
3406 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3409 const uint32x4_t m128_u_sourceStrideElements = vdupq_n_u32(sourceStrideElements);
3412 const uint32x4_t m128_u_sourceWidth_1 = vdupq_n_u32(sourceWidth - 1u);
3413 const uint32x4_t m128_u_sourceHeight_1 = vdupq_n_u32(sourceHeight - 1u);
3416 const float32x4_t m128_f_sourceWidth_1 = vdupq_n_f32(
float(sourceWidth - 1u));
3417 const float32x4_t m128_f_sourceHeight_1 = vdupq_n_f32(
float(sourceHeight - 1u));
3419 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
3421 if (x + 4u > targetWidth)
3426 ocean_assert(x >= 4u && targetWidth > 4u);
3427 const unsigned int newX = targetWidth - 4u;
3429 ocean_assert(x > newX);
3430 targetRow -= x - newX;
3435 ocean_assert(!(x + 4u < targetWidth));
3441 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3442 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3445 const float32x4_t m128_f_sourceX = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3446 const float32x4_t m128_f_sourceY = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3450 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));
3451 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));
3453 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3457 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3458 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3461 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3462 vst1q_u32(debugValidPixels, m128_u_validPixel);
3463 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3466 targetRow[0] = *bColor;
3467 targetRow[1] = *bColor;
3468 targetRow[2] = *bColor;
3469 targetRow[3] = *bColor;
3478 vst1q_u32(validPixels, m128_u_validPixel);
3479 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3484 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_sourceX);
3485 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_sourceY);
3488 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_sourceWidth_1);
3489 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_sourceHeight_1);
3492 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3493 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3494 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3495 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3498 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3499 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3500 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3501 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3507 float32x4_t m128_f_tx = vsubq_f32(m128_f_sourceX, vcvtq_f32_u32(m128_u_left));
3508 float32x4_t m128_f_ty = vsubq_f32(m128_f_sourceY, vcvtq_f32_u32(m128_u_top));
3511 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3512 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3514 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3515 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3517 if constexpr (tChannels > 4u)
3527 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3528 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3532 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3533 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3534 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3535 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3537 unsigned int tx_ty_s[4];
3538 unsigned int txty_s[4];
3539 unsigned int tx_tys[4];
3540 unsigned int txtys[4];
3543 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3544 vst1q_u32(txty_s, m128_u_txty_);
3545 vst1q_u32(tx_tys, m128_u_tx_ty);
3546 vst1q_u32(txtys, m128_u_txty);
3548 for (
unsigned int i = 0u; i < 4u; ++i)
3552 ocean_assert(topLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3553 ocean_assert(topRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3554 ocean_assert(bottomLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3555 ocean_assert(bottomRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3557 const uint8_t* topLeft = source + topLeftOffsetsElements[i];
3558 const uint8_t* topRight = source + topRightOffsetsElements[i];
3560 const uint8_t* bottomLeft = source + bottomLeftOffsetsElements[i];
3561 const uint8_t* bottomRight = source + bottomRightOffsetsElements[i];
3563 const unsigned int tx_ty_ = tx_ty_s[i];
3564 const unsigned int txty_ = txty_s[i];
3565 const unsigned int tx_ty = tx_tys[i];
3566 const unsigned int txty = txtys[i];
3568 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3570 for (
unsigned int n = 0u; n < tChannels; ++n)
3572 ((uint8_t*)targetRow)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3577 *targetRow = *bColor;
3585 interpolate4Pixels8BitPerChannelNEON<tChannels>(source, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, targetRow);
3592template <
unsigned int tChannels>
3593void 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)
3595 static_assert(tChannels >= 1u,
"Invalid channel number!");
3597 ocean_assert(input !=
nullptr && output !=
nullptr);
3598 ocean_assert(inputWidth > 0u && inputHeight > 0u);
3599 ocean_assert_and_suppress_unused(outputWidth >= 4u && outputHeight > 0u, outputHeight);
3600 ocean_assert(input_H_output !=
nullptr);
3602 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
3604 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
3605 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
3609 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3610 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3612 unsigned int validPixels[4];
3614 unsigned int topLeftOffsetsElements[4];
3615 unsigned int topRightOffsetsElements[4];
3616 unsigned int bottomLeftOffsetsElements[4];
3617 unsigned int bottomRightOffsetsElements[4];
3619 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3622 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*input_H_output)(0, 0)));
3623 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*input_H_output)(1, 0)));
3624 const float32x4_t m128_f_X2 = vdupq_n_f32(
float((*input_H_output)(2, 0)));
3626 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
3628 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
3652 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
3653 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
3654 const float32x4_t m128_f_C2 = vdupq_n_f32(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
3657 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3660 const uint32x4_t m128_u_inputStrideElements = vdupq_n_u32(inputStrideElements);
3663 const uint32x4_t m128_u_inputWidth_1 = vdupq_n_u32(inputWidth - 1u);
3664 const uint32x4_t m128_u_inputHeight_1 = vdupq_n_u32(inputHeight - 1u);
3667 const float32x4_t m128_f_inputWidth_1 = vdupq_n_f32(
float(inputWidth - 1u));
3668 const float32x4_t m128_f_inputHeight_1 = vdupq_n_f32(
float(inputHeight - 1u));
3670 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
3672 if (x + 4u > outputWidth)
3677 ocean_assert(x >= 4u && outputWidth > 4u);
3678 const unsigned int newX = outputWidth - 4u;
3680 ocean_assert(x > newX);
3681 outputPixelData -= x - newX;
3686 ocean_assert(!(x + 4u < outputWidth));
3692 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3693 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3696 const float32x4_t m128_f_xx = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3697 const float32x4_t m128_f_yy = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3698 const float32x4_t m128_f_zz = vmlaq_f32(m128_f_C2, m128_f_X2, m128_f_x_0123);
3700#ifdef USE_DIVISION_ARM64_ARCHITECTURE
3703 const float32x4_t m128_f_inputX = vdivq_f32(m128_f_xx, m128_f_zz);
3704 const float32x4_t m128_f_inputY = vdivq_f32(m128_f_yy, m128_f_zz);
3710 float32x4_t inv_zz_128 = vrecpeq_f32(m128_f_zz);
3711 inv_zz_128 = vmulq_f32(vrecpsq_f32(m128_f_zz, inv_zz_128), inv_zz_128);
3714 const float32x4_t m128_f_inputX = vmulq_f32(m128_f_xx, inv_zz_128);
3715 const float32x4_t m128_f_inputY = vmulq_f32(m128_f_yy, inv_zz_128);
3721 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));
3722 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));
3724 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3728 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3729 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3732 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3733 vst1q_u32(debugValidPixels, m128_u_validPixel);
3734 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3737 outputPixelData[0] = *bColor;
3738 outputPixelData[1] = *bColor;
3739 outputPixelData[2] = *bColor;
3740 outputPixelData[3] = *bColor;
3742 outputPixelData += 4;
3749 vst1q_u32(validPixels, m128_u_validPixel);
3750 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3755 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_inputX);
3756 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_inputY);
3759 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_inputWidth_1);
3760 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_inputHeight_1);
3763 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3764 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3765 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3766 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3769 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3770 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3771 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3772 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3778 float32x4_t m128_f_tx = vsubq_f32(m128_f_inputX, vcvtq_f32_u32(m128_u_left));
3779 float32x4_t m128_f_ty = vsubq_f32(m128_f_inputY, vcvtq_f32_u32(m128_u_top));
3782 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3783 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3785 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3786 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3788 if constexpr (tChannels > 4u)
3798 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3799 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3803 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3804 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3805 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3806 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3808 unsigned int tx_ty_s[4];
3809 unsigned int txty_s[4];
3810 unsigned int tx_tys[4];
3811 unsigned int txtys[4];
3814 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3815 vst1q_u32(txty_s, m128_u_txty_);
3816 vst1q_u32(tx_tys, m128_u_tx_ty);
3817 vst1q_u32(txtys, m128_u_txty);
3819 for (
unsigned int i = 0u; i < 4u; ++i)
3823 ocean_assert(topLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3824 ocean_assert(topRightOffsetsElements[i] < inputStrideElements * inputHeight);
3825 ocean_assert(bottomLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3826 ocean_assert(bottomRightOffsetsElements[i] < inputStrideElements * inputHeight);
3828 const uint8_t* topLeft = input + topLeftOffsetsElements[i];
3829 const uint8_t* topRight = input + topRightOffsetsElements[i];
3831 const uint8_t* bottomLeft = input + bottomLeftOffsetsElements[i];
3832 const uint8_t* bottomRight = input + bottomRightOffsetsElements[i];
3834 const unsigned int tx_ty_ = tx_ty_s[i];
3835 const unsigned int txty_ = txty_s[i];
3836 const unsigned int tx_ty = tx_tys[i];
3837 const unsigned int txty = txtys[i];
3839 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3841 for (
unsigned int n = 0u; n < tChannels; ++n)
3843 ((uint8_t*)outputPixelData)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3848 *outputPixelData = *bColor;
3856 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, outputPixelData);
3857 outputPixelData += 4;
3864OCEAN_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)
3866 ocean_assert(source !=
nullptr);
3867 ocean_assert(targetPositionPixels !=
nullptr);
3879 for (
unsigned int i = 0u; i < 4u; ++i)
3890 pixels[i * 4u + 0u] = borderColor;
3891 pixels[i * 4u + 1u] = borderColor;
3892 pixels[i * 4u + 2u] = borderColor;
3893 pixels[i * 4u + 3u] = borderColor;
3897 static_assert(
sizeof(uint8x16_t) ==
sizeof(pixels),
"Invalid data type!");
3899 const uint8x16_t m128_pixels = vld1q_u8((
const uint8_t*)pixels);
3905 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
3906 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
3911 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
3912 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
3913 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
3914 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
3929 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
3931 const uint32x4_t m128_muliplicationA = vmulq_u32(vandq_u32(vreinterpretq_u32_u8(m128_pixels), m128_maskFirstByte), m128_factorsTopLeft);
3932 const uint32x4_t m128_muliplicationB = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 8), m128_maskFirstByte), m128_factorsTopRight);
3933 const uint32x4_t m128_muliplicationC = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 16), m128_maskFirstByte), m128_factorsBottomLeft);
3934 const uint32x4_t m128_muliplicationD = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 24), m128_maskFirstByte), m128_factorsBottomRight);
3936 const uint32x4_t m128_multiplication = vaddq_u32(vaddq_u32(m128_muliplicationA, m128_muliplicationB), vaddq_u32(m128_muliplicationC, m128_muliplicationD));
3940 const uint8x16_t m128_interpolation = vreinterpretq_u8_u32(vshrq_n_u32(vaddq_u32(m128_multiplication, vdupq_n_u32(8192u)), 14));
3950#if defined(__aarch64__)
3955 const uint8x8_t m64_interpolation01 = vtbl1_u8(vget_low_u8(m128_interpolation), m64_mask0);
3956 const uint8x8_t m64_interpolation23 = vtbl1_u8(vget_high_u8(m128_interpolation), m64_mask1);
3958 const uint8x8_t m64_interpolation0123 = vorr_u8(m64_interpolation01, m64_interpolation23);
3960 const uint32_t result = vget_lane_u32(vreinterpret_u32_u8(m64_interpolation0123), 0);
3961 memcpy(targetPositionPixels, &result,
sizeof(uint32_t));
3965 *((uint8_t*)targetPositionPixels + 0) = vgetq_lane_u8(m128_interpolation, 0);
3966 *((uint8_t*)targetPositionPixels + 1) = vgetq_lane_u8(m128_interpolation, 4);
3967 *((uint8_t*)targetPositionPixels + 2) = vgetq_lane_u8(m128_interpolation, 8);
3968 *((uint8_t*)targetPositionPixels + 3) = vgetq_lane_u8(m128_interpolation, 12);
3975 const uint8x16_t factorsLeft_factorsTop_128_u_8x16 = vsubq_u8(vdupq_n_u8(128u), factorsRight_factorsBottom_128_u_8x16);
3977 const uint8x8_t factorsRight_u_8x8 = vget_low_u8(factorsRight_factorsBottom_128_u_8x16);
3978 const uint16x8_t factorsBottom_u_16x8 = vmovl_u8(vget_high_u8(factorsRight_factorsBottom_128_u_8x16));
3980 const uint8x8_t factorsLeft_u_8x8 = vget_low_u8(factorsLeft_factorsTop_128_u_8x16);
3981 const uint16x8_t factorsTop_u_16x8 = vmovl_u8(vget_high_u8(factorsLeft_factorsTop_128_u_8x16));
3983 const uint16x8_t intermediateTop_u_16x8 = vmlal_u8(vmull_u8(topLeft_u_8x8, factorsLeft_u_8x8), topRight_u_8x8, factorsRight_u_8x8);
3984 const uint16x8_t intermediateBottom_u_16x8 = vmlal_u8(vmull_u8(bottomLeft_u_8x8, factorsLeft_u_8x8), bottomRight_u_8x8, factorsRight_u_8x8);
3986 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));
3987 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));
3989 const uint16x8_t result_16x8 = vcombine_u16(vrshrn_n_u32(resultA_32x4, 14), vrshrn_n_u32(resultB_32x4, 14));
3991 const uint8x8_t result_8x8 = vmovn_u16(result_16x8);
3993 vst1_u8(targetPositionPixels, result_8x8);
3997OCEAN_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)
3999 ocean_assert(source !=
nullptr);
4000 ocean_assert(targetPositionPixels !=
nullptr);
4006 PixelType topPixels[8];
4007 PixelType bottomPixels[8];
4016 for (
unsigned int i = 0u; i < 4u; ++i)
4020 *(topPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4021 *(topPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4022 *(bottomPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4023 *(bottomPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4027 *(topPixels + i * 2u + 0u) = borderColor;
4028 *(topPixels + i * 2u + 1u) = borderColor;
4029 *(bottomPixels + i * 2u + 0u) = borderColor;
4030 *(bottomPixels + i * 2u + 1u) = borderColor;
4034 static_assert(
sizeof(uint32x4_t) ==
sizeof(topPixels),
"Invalid data type!");
4036 const uint32x4_t m128_topPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topPixels));
4037 const uint32x4_t m128_bottomPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomPixels));
4043 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4044 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4049 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4050 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4051 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4052 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4055 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4057 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topPixels, m128_maskFirstByte), m128_factorsTopLeft);
4058 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4060 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4061 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4063 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4064 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4066 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4067 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4072 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4073 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4079 const uint32x4_t m128_interpolation = vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8));
4086 const uint8x8_t m64_interpolation_low = vtbl1_u8(vget_low_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask0);
4087 const uint8x8_t m64_interpolation_high = vtbl1_u8(vget_high_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask1);
4089 const uint8x8_t m64_interpolation = vorr_u8(m64_interpolation_low, m64_interpolation_high);
4096 vst1_u8((uint8_t*)targetPositionPixels, m64_interpolation);
4100OCEAN_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)
4102 ocean_assert(source !=
nullptr);
4103 ocean_assert(targetPositionPixels !=
nullptr);
4107 uint32_t topLeftPixels[4];
4108 uint32_t topRightPixels[4];
4109 uint32_t bottomLeftPixels[4];
4110 uint32_t bottomRightPixels[4];
4118 for (
unsigned int i = 0u; i < 4u; ++i)
4122 memcpy(topLeftPixels + i, source + offsetsTopLeftElements[i],
sizeof(uint8_t) * 3);
4123 memcpy(topRightPixels + i, source + offsetsTopRightElements[i],
sizeof(uint8_t) * 3);
4124 memcpy(bottomLeftPixels + i, source + offsetsBottomLeftElements[i],
sizeof(uint8_t) * 3);
4125 memcpy(bottomRightPixels + i, source + offsetsBottomRightElements[i],
sizeof(uint8_t) * 3);
4129 memcpy(topLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4130 memcpy(topRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4131 memcpy(bottomLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4132 memcpy(bottomRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4136 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4138 const uint32x4_t m128_topLeftPixels = vld1q_u32(topLeftPixels);
4139 const uint32x4_t m128_topRightPixels = vld1q_u32(topRightPixels);
4140 const uint32x4_t m128_bottomLeftPixels = vld1q_u32(bottomLeftPixels);
4141 const uint32x4_t m128_bottomRightPixels = vld1q_u32(bottomRightPixels);
4147 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4148 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4153 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4154 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4155 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4156 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4159 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4161 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4162 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4163 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4165 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4166 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4167 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4169 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4170 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4171 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4173 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4174 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4175 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4180 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4181 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4182 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4186 const uint32x4_t m128_interpolation = vorrq_u32(vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8)), vshlq_n_u32(m128_interpolation2, 16));
4192 uint32_t intermediateBuffer[4];
4193 vst1q_u32(intermediateBuffer, m128_interpolation);
4195 for (
unsigned int i = 0u; i < 4u; ++i)
4197 memcpy(targetPositionPixels + i, intermediateBuffer + i,
sizeof(uint8_t) * 3);
4202OCEAN_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)
4204 ocean_assert(source !=
nullptr);
4205 ocean_assert(targetPositionPixels !=
nullptr);
4211 PixelType topLeftPixels[4];
4212 PixelType topRightPixels[4];
4213 PixelType bottomLeftPixels[4];
4214 PixelType bottomRightPixels[4];
4222 for (
unsigned int i = 0u; i < 4u; ++i)
4226 *(topLeftPixels + i) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4227 *(topRightPixels + i) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4228 *(bottomLeftPixels + i) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4229 *(bottomRightPixels + i) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4233 *(topLeftPixels + i) = borderColor;
4234 *(topRightPixels + i) = borderColor;
4235 *(bottomLeftPixels + i) = borderColor;
4236 *(bottomRightPixels + i) = borderColor;
4240 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4242 const uint32x4_t m128_topLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topLeftPixels));
4243 const uint32x4_t m128_topRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topRightPixels));
4244 const uint32x4_t m128_bottomLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomLeftPixels));
4245 const uint32x4_t m128_bottomRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomRightPixels));
4251 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4252 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4257 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4258 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4259 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4260 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4263 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4265 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4266 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4267 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4268 uint32x4_t m128_muliplicationChannel3 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 24), m128_maskFirstByte), m128_factorsTopLeft);
4270 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4271 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4272 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4273 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4275 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4276 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4277 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4278 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 24), m128_maskFirstByte), m128_factorsBottomLeft));
4280 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4281 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4282 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4283 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4288 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4289 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4290 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4291 const uint32x4_t m128_interpolation3 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel3, vdupq_n_u32(8192u)), 14);
4295 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)));
4297 vst1q_u8((uint8_t*)targetPositionPixels, vreinterpretq_u8_u32(m128_interpolation));
4300template <
unsigned int tChannels>
4301OCEAN_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)
4303 ocean_assert(source !=
nullptr);
4304 ocean_assert(targetPositionPixels !=
nullptr);
4308 unsigned int factorsTopLeft[4];
4309 unsigned int factorsTopRight[4];
4310 unsigned int factorsBottomLeft[4];
4311 unsigned int factorsBottomRight[4];
4317 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4318 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4323 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4324 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4325 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4326 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4330 vst1q_u32(factorsTopLeft, m128_factorsTopLeft);
4331 vst1q_u32(factorsTopRight, m128_factorsTopRight);
4332 vst1q_u32(factorsBottomLeft, m128_factorsBottomLeft);
4333 vst1q_u32(factorsBottomRight, m128_factorsBottomRight);
4335 for (
unsigned int i = 0u; i < 4u; ++i)
4339 const uint8_t* topLeft = source + offsetsTopLeftElements[i];
4340 const uint8_t* topRight = source + offsetsTopRightElements[i];
4342 const uint8_t* bottomLeft = source + offsetsBottomLeftElements[i];
4343 const uint8_t* bottomRight = source + offsetsBottomRightElements[i];
4345 const unsigned int& factorTopLeft = factorsTopLeft[i];
4346 const unsigned int& factorTopRight = factorsTopRight[i];
4347 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
4348 const unsigned int& factorBottomRight = factorsBottomRight[i];
4350 for (
unsigned int n = 0u; n < tChannels; ++n)
4352 ((uint8_t*)targetPositionPixels)[n] = (topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u;
4357 *targetPositionPixels = borderColor;
4360 targetPositionPixels++;
4366template <
unsigned int tChannels>
4367inline 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)
4369 static_assert(tChannels >= 1u,
"Invalid channel number!");
4371 ocean_assert(input && output);
4372 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4373 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4375 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4376 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4377 ocean_assert(homographies);
4379 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4381 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4382 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4384 constexpr uint8_t zeroColor[tChannels] = {uint8_t(0)};
4385 const uint8_t*
const bColor = borderColor ? borderColor : zeroColor;
4387 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4401 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4403 for (
unsigned int x = 0; x < outputWidth; ++x)
4407 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4408 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4412 const Scalar tx = 1 - _tx;
4413 const Scalar ty = 1 - _ty;
4415 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4416 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4417 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4418 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4420 const Scalar tTopLeft = tx * ty;
4421 const Scalar tTopRight = _tx * ty;
4422 const Scalar tBottomLeft = tx * _ty;
4423 const Scalar tBottomRight = _tx * _ty;
4425 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4426 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4428 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4430 for (
unsigned int c = 0u; c < tChannels; ++c)
4432 outputData[c] = bColor[c];
4437 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4440 outputData += tChannels;
4443 outputData += outputPaddingElements;
4447template <
unsigned int tChannels>
4448void 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)
4450 static_assert(tChannels >= 1u,
"Invalid channel number!");
4452 ocean_assert(input !=
nullptr && output !=
nullptr);
4453 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4454 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4455 ocean_assert(input_H_output !=
nullptr);
4457 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
4459 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4460 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4462 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4463 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4467 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4469 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4470 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
4494 const Scalar X2 = (*input_H_output)(2, 0);
4495 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
4497 for (
unsigned int x = 0; x < outputWidth; ++x)
4503 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
4506 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4508 *outputMaskData = 0xFF - maskValue;
4512 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4513 *outputMaskData = maskValue;
4522template <
unsigned int tChannels>
4523inline 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)
4525 static_assert(tChannels >= 1u,
"Invalid channel number!");
4527 ocean_assert(input && output);
4528 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4529 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4531 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4532 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4533 ocean_assert(homographies);
4535 const unsigned int outputStrideElements = tChannels * outputWidth + outputPaddingElements;
4536 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4538 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4539 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4541 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4542 outputMask += firstOutputRow * outputMaskStrideElements;
4556 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4558 for (
unsigned int x = 0u; x < outputWidth; ++x)
4562 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4563 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4567 const Scalar tx = 1 - _tx;
4568 const Scalar ty = 1 - _ty;
4570 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4571 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4572 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4573 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4575 const Scalar tTopLeft = tx * ty;
4576 const Scalar tTopRight = _tx * ty;
4577 const Scalar tBottomLeft = tx * _ty;
4578 const Scalar tBottomRight = _tx * _ty;
4580 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4581 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4583 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4585 *outputMask = 0xFFu - maskValue;
4589 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4590 *outputMask = maskValue;
4593 outputData += tChannels;
4597 outputData += outputPaddingElements;
4598 outputMask += outputMaskPaddingElements;
4602template <
unsigned int tChannels>
4603void 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)
4605 static_assert(tChannels >= 1u,
"Invalid channel number!");
4607 ocean_assert(inputCamera && outputCamera && normalizedHomography);
4608 ocean_assert(input && output);
4610 ocean_assert(firstRow + numberRows <= outputCamera->height());
4612 const unsigned int outputStrideElements = tChannels * outputCamera->
width() + outputPaddingElements;
4621 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4622 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4624 uint8_t* outputData = output + firstRow * outputStrideElements;
4626 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4628 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4632 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4634 *((PixelType*)outputData) = *bColor;
4638 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4641 outputData += tChannels;
4644 outputData += outputPaddingElements;
4648template <
unsigned int tChannels>
4649void 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)
4651 static_assert(tChannels >= 1u,
"Invalid channel number!");
4653 ocean_assert(inputCamera !=
nullptr && outputCamera !=
nullptr && normalizedHomography !=
nullptr);
4654 ocean_assert(input !=
nullptr && output !=
nullptr);
4656 ocean_assert(firstRow + numberRows <= outputCamera->height());
4658 const unsigned int outputStrideElements = outputCamera->
width() * tChannels + outputPaddingElements;
4659 const unsigned int outputMaskStrideElements = outputCamera->
width() + outputMaskPaddingElements;
4666 uint8_t* outputData = output + firstRow * outputStrideElements;
4667 outputMask += firstRow * outputMaskStrideElements;
4669 constexpr bool useDistortionParameters =
true;
4671 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4673 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4677 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4679 *outputMask = 0xFF - maskValue;
4683 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4684 *outputMask = maskValue;
4687 outputData += tChannels;
4691 outputData += outputPaddingElements;
4692 outputMask += outputMaskPaddingElements;
4696template <
unsigned int tChannels>
4697void 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)
4699 static_assert(tChannels >= 1u,
"Invalid channel number!");
4701 ocean_assert(input_LT_output !=
nullptr);
4702 ocean_assert(input !=
nullptr && output !=
nullptr);
4704 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4705 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4709 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4710 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4712 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4714 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4716 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4721 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4724 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4728 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4730 for (
unsigned int x = 0u; x < columns; ++x)
4732 const Vector2& lookupValue = rowLookupData[x];
4736 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4738 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4742 *outputData = *bColor;
4750template <
typename T,
unsigned int tChannels>
4751void 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)
4753 static_assert(tChannels >= 1u,
"Invalid channel number!");
4755 ocean_assert((!std::is_same<uint8_t, T>::value));
4757 ocean_assert(input_LT_output !=
nullptr);
4758 ocean_assert(input !=
nullptr && output !=
nullptr);
4760 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4761 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4765 const T zeroColor[tChannels] = {T(0)};
4766 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4768 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4770 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4772 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4777 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4780 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4784 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4786 for (
unsigned int x = 0u; x < columns; ++x)
4788 const Vector2& lookupValue = rowLookupData[x];
4792 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4794 interpolatePixel<T, T, tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputData));
4798 *outputData = *bColor;
4806#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
4809inline 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)
4811 ocean_assert(input_LT_output !=
nullptr);
4812 ocean_assert(input !=
nullptr && output !=
nullptr);
4814 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4815 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4817 using PixelType = uint8_t;
4819 const uint8x16_t constantBorderColor_u_8x16 = vdupq_n_u8(borderColor ? *borderColor : 0u);
4821 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
4822 ocean_assert(outputWidth >= 8u);
4824 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4826 const unsigned int inputStrideElements = inputWidth + inputPaddingElements;
4827 const unsigned int outputStrideElements = outputWidth + outputPaddingElements;
4829 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
4832 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
4833 const float32x4_t constantEight_f_32x4 = vdupq_n_f32(8.0f);
4836 const float f_01234567[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
4837 const float32x4_t conststant0123_f_32x4 = vld1q_f32(f_01234567 + 0);
4838 const float32x4_t conststant4567_f_32x4 = vld1q_f32(f_01234567 + 4);
4840 const float32x4_t constant128_f_32x4 = vdupq_n_f32(128.0f);
4842 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
4844 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(1u);
4846 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
4847 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
4849 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
4850 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
4852 unsigned int validPixels[8];
4854 unsigned int topLeftOffsetsElements[8];
4855 unsigned int bottomLeftOffsetsElements[8];
4859 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4861 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
4865 float32x4_t additionalInputOffsetX0123_f_32x4 = conststant0123_f_32x4;
4866 float32x4_t additionalInputOffsetX4567_f_32x4 = conststant4567_f_32x4;
4868 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
4870 for (
unsigned int x = 0u; x < outputWidth; x += 8u)
4872 if (x + 8u > outputWidth)
4877 ocean_assert(x >= 8u && outputWidth > 8u);
4878 const unsigned int newX = outputWidth - 8u;
4880 ocean_assert(x > newX);
4881 const unsigned int xOffset = x - newX;
4883 outputPixelData -= xOffset;
4887 additionalInputOffsetX0123_f_32x4 = vsubq_f32(additionalInputOffsetX0123_f_32x4, vdupq_n_f32(
float(xOffset)));
4888 additionalInputOffsetX4567_f_32x4 = vsubq_f32(additionalInputOffsetX4567_f_32x4, vdupq_n_f32(
float(xOffset)));
4894 ocean_assert(!(x + 8u < outputWidth));
4897 const float32x4x2_t inputPositions0123_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 0u));
4898 const float32x4x2_t inputPositions4567_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 4u));
4900 float32x4_t inputPositionsX0123_f_32x4 = inputPositions0123_f_32x4x2.val[0];
4901 float32x4_t inputPositionsY0123_f_32x4 = inputPositions0123_f_32x4x2.val[1];
4903 float32x4_t inputPositionsX4567_f_32x4 = inputPositions4567_f_32x4x2.val[0];
4904 float32x4_t inputPositionsY4567_f_32x4 = inputPositions4567_f_32x4x2.val[1];
4908 inputPositionsX0123_f_32x4 = vaddq_f32(inputPositionsX0123_f_32x4, additionalInputOffsetX0123_f_32x4);
4909 inputPositionsY0123_f_32x4 = vaddq_f32(inputPositionsY0123_f_32x4, additionalInputOffsetY_f_32x4);
4911 inputPositionsX4567_f_32x4 = vaddq_f32(inputPositionsX4567_f_32x4, additionalInputOffsetX4567_f_32x4);
4912 inputPositionsY4567_f_32x4 = vaddq_f32(inputPositionsY4567_f_32x4, additionalInputOffsetY_f_32x4);
4914 additionalInputOffsetX0123_f_32x4 = vaddq_f32(additionalInputOffsetX0123_f_32x4, constantEight_f_32x4);
4915 additionalInputOffsetX4567_f_32x4 = vaddq_f32(additionalInputOffsetX4567_f_32x4, constantEight_f_32x4);
4919 const uint32x4_t validPixelsX0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX0123_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX0123_f_32x4, constantZero_f_32x4));
4920 const uint32x4_t validPixelsX4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX4567_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX4567_f_32x4, constantZero_f_32x4));
4922 const uint32x4_t validPixelsY0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY0123_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY0123_f_32x4, constantZero_f_32x4));
4923 const uint32x4_t validPixelsY4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY4567_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY4567_f_32x4, constantZero_f_32x4));
4925 const uint32x4_t validPixels0123_u_32x4 = vandq_u32(validPixelsX0123_u_32x4, validPixelsY0123_u_32x4);
4926 const uint32x4_t validPixels4567_u_32x4 = vandq_u32(validPixelsX4567_u_32x4, validPixelsY4567_u_32x4);
4928 vst1q_u32(validPixels + 0, validPixels0123_u_32x4);
4929 vst1q_u32(validPixels + 4, validPixels4567_u_32x4);
4932 const uint32x4_t inputPositionsLeft0123_u_32x4 = vcvtq_u32_f32(inputPositionsX0123_f_32x4);
4933 const uint32x4_t inputPositionsLeft4567_u_32x4 = vcvtq_u32_f32(inputPositionsX4567_f_32x4);
4935 const uint32x4_t inputPositionsTop0123_u_32x4 = vcvtq_u32_f32(inputPositionsY0123_f_32x4);
4936 const uint32x4_t inputPositionsTop4567_u_32x4 = vcvtq_u32_f32(inputPositionsY4567_f_32x4);
4938 const uint32x4_t inputPositionsBottom0123_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop0123_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
4939 const uint32x4_t inputPositionsBottom4567_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop4567_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
4942 const uint32x4_t topLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsTop0123_u_32x4, constantInputStrideElements_u_32x4);
4943 vst1q_u32(topLeftOffsetsElements + 0, topLeftOffsetsElements0123_u_32x4);
4944 const uint32x4_t topLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsTop4567_u_32x4, constantInputStrideElements_u_32x4);
4945 vst1q_u32(topLeftOffsetsElements + 4, topLeftOffsetsElements4567_u_32x4);
4947 const uint32x4_t bottomLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsBottom0123_u_32x4, constantInputStrideElements_u_32x4);
4948 vst1q_u32(bottomLeftOffsetsElements + 0, bottomLeftOffsetsElements0123_u_32x4);
4949 const uint32x4_t bottomLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsBottom4567_u_32x4, constantInputStrideElements_u_32x4);
4950 vst1q_u32(bottomLeftOffsetsElements + 4, bottomLeftOffsetsElements4567_u_32x4);
4954 float32x4_t tx0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX0123_f_32x4, vcvtq_f32_u32(inputPositionsLeft0123_u_32x4)), constant128_f_32x4);
4955 float32x4_t tx4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX4567_f_32x4, vcvtq_f32_u32(inputPositionsLeft4567_u_32x4)), constant128_f_32x4);
4957 float32x4_t ty0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY0123_f_32x4, vcvtq_f32_u32(inputPositionsTop0123_u_32x4)), constant128_f_32x4);
4958 float32x4_t ty4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY4567_f_32x4, vcvtq_f32_u32(inputPositionsTop4567_u_32x4)), constant128_f_32x4);
4960 const uint32x4_t tx0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx0123_f_32x4, vdupq_n_f32(0.5)));
4961 const uint32x4_t tx4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx4567_f_32x4, vdupq_n_f32(0.5)));
4963 const uint32x4_t ty0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty0123_f_32x4, vdupq_n_f32(0.5)));
4964 const uint32x4_t ty4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty4567_f_32x4, vdupq_n_f32(0.5)));
4966 const uint16x8_t tx01234567_128_u_16x8 = vcombine_u16(vmovn_u32(tx0123_128_u_32x4), vmovn_u32(tx4567_128_u_32x4));
4967 const uint16x8_t ty01234567_128_u_16x8 = vcombine_u16(vmovn_u32(ty0123_128_u_32x4), vmovn_u32(ty4567_128_u_32x4));
4969 const uint8x16_t tx_ty_128_u_8x16 = vcombine_u8(vmovn_u16(tx01234567_128_u_16x8), vmovn_u16(ty01234567_128_u_16x8));
4972 vst1q_u8(pixels + 0, constantBorderColor_u_8x16);
4973 vst1q_u8(pixels + 16, constantBorderColor_u_8x16);
4975 struct LeftRightPixel
4981 static_assert(
sizeof(LeftRightPixel) == 2,
"Invalid data type!");
4985 for (
unsigned int i = 0u; i < 8u; ++i)
4989 ocean_assert((topLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
4990 ocean_assert((bottomLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
4992 ((LeftRightPixel*)pixels)[0u + i] = *(LeftRightPixel*)(input + topLeftOffsetsElements[i]);
4993 ((LeftRightPixel*)pixels)[8u + i] = *(LeftRightPixel*)(input + bottomLeftOffsetsElements[i]);
4997 const uint8x8x2_t topLeft_topRight_u_8x8x2 = vld2_u8(pixels);
4998 const uint8x8x2_t bottomLeft_bottomRight_u_8x8x2 = vld2_u8(pixels + 16);
5000 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);
5002 outputPixelData += 8;
5007template <
unsigned int tChannels>
5008void 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)
5010 ocean_assert(input_LT_output !=
nullptr);
5011 ocean_assert(input !=
nullptr && output !=
nullptr);
5013 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5014 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5018 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
5019 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
5021 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
5022 ocean_assert(outputWidth >= 4u);
5024 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5026 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
5027 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
5029 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
5032 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
5033 const float32x4_t constantFour_f_32x4 = vdupq_n_f32(4.0f);
5036 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
5037 float32x4_t conststant0123_f_32x4 = vld1q_f32(f_0123);
5039 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
5041 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
5043 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
5044 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
5046 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
5047 const uint32x4_t constantInputWidth1_u_32x4 = vdupq_n_u32(inputWidth - 1u);
5048 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
5050 unsigned int validPixels[4];
5052 unsigned int topLeftOffsetsElements[4];
5053 unsigned int topRightOffsetsElements[4];
5054 unsigned int bottomLeftOffsetsElements[4];
5055 unsigned int bottomRightOffsetsElements[4];
5057 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5059 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
5063 float32x4_t additionalInputOffsetX_f_32x4 = conststant0123_f_32x4;
5064 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
5066 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
5068 if (x + 4u > outputWidth)
5073 ocean_assert(x >= 4u && outputWidth > 4u);
5074 const unsigned int newX = outputWidth - 4u;
5076 ocean_assert(x > newX);
5077 const unsigned int xOffset = x - newX;
5079 outputPixelData -= xOffset;
5083 additionalInputOffsetX_f_32x4 = vsubq_f32(additionalInputOffsetX_f_32x4, vdupq_n_f32(
float(xOffset)));
5089 ocean_assert(!(x + 4u < outputWidth));
5092 const float32x4x2_t inputPositions_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x));
5094 float32x4_t inputPositionsX_f_32x4 = inputPositions_f_32x4x2.val[0];
5095 float32x4_t inputPositionsY_f_32x4 = inputPositions_f_32x4x2.val[1];
5099 inputPositionsX_f_32x4 = vaddq_f32(inputPositionsX_f_32x4, additionalInputOffsetX_f_32x4);
5100 inputPositionsY_f_32x4 = vaddq_f32(inputPositionsY_f_32x4, additionalInputOffsetY_f_32x4);
5102 additionalInputOffsetX_f_32x4 = vaddq_f32(additionalInputOffsetX_f_32x4, constantFour_f_32x4);
5106 const uint32x4_t validPixelsX_u_32x4 = vandq_u32(vcleq_f32(inputPositionsX_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX_f_32x4, constantZero_f_32x4));
5107 const uint32x4_t validPixelsY_u_32x4 = vandq_u32(vcleq_f32(inputPositionsY_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY_f_32x4, constantZero_f_32x4));
5109 const uint32x4_t validPixels_u_32x4 = vandq_u32(validPixelsX_u_32x4, validPixelsY_u_32x4);
5111 vst1q_u32(validPixels, validPixels_u_32x4);
5113 const uint32x4_t inputPositionsLeft_u_32x4 = vcvtq_u32_f32(inputPositionsX_f_32x4);
5114 const uint32x4_t inputPositionsTop_u_32x4 = vcvtq_u32_f32(inputPositionsY_f_32x4);
5116 const uint32x4_t inputPositionsRight_u_32x4 = vminq_u32(vaddq_u32(inputPositionsLeft_u_32x4, constantOne_u_32x4), constantInputWidth1_u_32x4);
5117 const uint32x4_t inputPositionsBottom_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
5119 const uint32x4_t topLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5120 const uint32x4_t topRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5121 const uint32x4_t bottomLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5122 const uint32x4_t bottomRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5124 vst1q_u32(topLeftOffsetsElements, topLeftOffsetsElements_u_32x4);
5125 vst1q_u32(topRightOffsetsElements, topRightOffsetsElements_u_32x4);
5126 vst1q_u32(bottomLeftOffsetsElements, bottomLeftOffsetsElements_u_32x4);
5127 vst1q_u32(bottomRightOffsetsElements, bottomRightOffsetsElements_u_32x4);
5130 float32x4_t tx_f_32x4 = vsubq_f32(inputPositionsX_f_32x4, vcvtq_f32_u32(inputPositionsLeft_u_32x4));
5131 float32x4_t ty_f_32x4 = vsubq_f32(inputPositionsY_f_32x4, vcvtq_f32_u32(inputPositionsTop_u_32x4));
5134 tx_f_32x4 = vmulq_f32(tx_f_32x4, vdupq_n_f32(128.0f));
5135 ty_f_32x4 = vmulq_f32(ty_f_32x4, vdupq_n_f32(128.0f));
5137 const uint32x4_t tx_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx_f_32x4, vdupq_n_f32(0.5)));
5138 const uint32x4_t ty_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty_f_32x4, vdupq_n_f32(0.5)));
5140 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, tx_128_u_32x4, ty_128_u_32x4, outputPixelData);
5142 outputPixelData += 4;
5149template <
unsigned int tChannels>
5150void 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)
5152 ocean_assert(input_LT_output !=
nullptr);
5153 ocean_assert(input !=
nullptr && output !=
nullptr);
5155 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5156 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5160 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
5162 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
5163 const unsigned int outputMaskStrideElements = columns + outputMaskPaddingElements;
5165 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5170 Memory rowLookupMemory = Memory::create<Vector2>(columns);
5173 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5177 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
5178 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
5180 for (
unsigned int x = 0u; x < columns; ++x)
5182 const Vector2& lookupValue = rowLookupData[x];
5186 if (inputPosition.
x() >= 0 && inputPosition.
y() >= 0 && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
5188 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
5189 *outputMaskData = maskValue;
5193 *outputMaskData = 0xFFu - maskValue;
5202template <
unsigned int tChannels>
5203void 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)
5205 ocean_assert(source !=
nullptr && target !=
nullptr);
5206 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
5207 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
5208 ocean_assert(sourceX_s_targetX > 0.0);
5209 ocean_assert(sourceY_s_targetY > 0.0);
5211 if (sourceWidth == targetWidth && sourceHeight == targetHeight)
5213 FrameConverter::subFrame<uint8_t>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
5217 if (worker && sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5219#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5220 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5222 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);
5226 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);
5231 if (sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5233#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5234 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5236 scale8BitPerChannelSubset7BitPrecisionNEON(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5242 scale8BitPerChannelSubset<tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5246template <
unsigned int tChannels>
5247void 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)
5249 ocean_assert(source !=
nullptr && target !=
nullptr);
5250 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
5251 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
5252 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5254 const Scalar sourceX_T_targetX =
Scalar(sourceX_s_targetX);
5255 const Scalar sourceY_T_targetY =
Scalar(sourceY_s_targetY);
5303 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
5305 const Scalar sourceX_T_targetXOffset = sourceX_T_targetX *
Scalar(0.5) -
Scalar(0.5);
5306 const Scalar sourceY_T_targetYOffset = sourceY_T_targetY *
Scalar(0.5) -
Scalar(0.5);
5309 const Scalar sourceHeight_1 =
Scalar(sourceHeight - 1u);
5311 target += (targetWidth * tChannels + targetPaddingElements) * firstTargetRow;
5313 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5316 ocean_assert(sy >=
Scalar(0) && sy <
Scalar(sourceHeight));
5318 const unsigned int sTop = (
unsigned int)sy;
5319 ocean_assert(sy >=
Scalar(sTop));
5322 ocean_assert(ty >= 0 && ty <= 1);
5324 const unsigned int factorBottom = (
unsigned int)(ty *
Scalar(128) +
Scalar(0.5));
5325 const unsigned int factorTop = 128u - factorBottom;
5327 const uint8_t*
const sourceTop = source + sourceStrideElements * sTop;
5328 const uint8_t*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
5330 for (
unsigned int x = 0; x < targetWidth; ++x)
5333 ocean_assert(sx >=
Scalar(0) && sx <
Scalar(sourceWidth));
5335 const unsigned int sLeft = (
unsigned int)sx;
5336 ocean_assert(sx >=
Scalar(sLeft));
5339 ocean_assert(tx >= 0 && tx <= 1);
5341 const unsigned int factorRight = (
unsigned int)(tx *
Scalar(128) +
Scalar(0.5));
5342 const unsigned int factorLeft = 128u - factorRight;
5344 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
5346 const uint8_t*
const sourceTopLeft = sourceTop + sLeft * tChannels;
5347 const uint8_t*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
5349 const unsigned int factorTopLeft = factorTop * factorLeft;
5350 const unsigned int factorTopRight = factorTop * factorRight;
5351 const unsigned int factorBottomLeft = factorBottom * factorLeft;
5352 const unsigned int factorBottomRight = factorBottom * factorRight;
5354 for (
unsigned int n = 0u; n < tChannels; ++n)
5356 target[n] = (uint8_t)((sourceTopLeft[n] * factorTopLeft + sourceTopLeft[sourceRightOffset + n] * factorTopRight
5357 + sourceBottomLeft[n] * factorBottomLeft + sourceBottomLeft[sourceRightOffset + n] * factorBottomRight + 8192u) >> 14u);
5360 target += tChannels;
5363 target += targetPaddingElements;
5367template <
typename T>
5370 ocean_assert(sourceRowTop !=
nullptr);
5371 ocean_assert(sourceRowBottom !=
nullptr);
5372 ocean_assert(targetRow !=
nullptr);
5373 ocean_assert(elements >= 1u);
5374 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
5378 const FloatType internalFactorBottom = FloatType(factorBottom);
5379 const FloatType internalFactorTop = FloatType(1.0f - factorBottom);
5381 for (
unsigned int n = 0u; n < elements; ++n)
5383 targetRow[n] = T(FloatType(sourceRowTop[n]) * internalFactorTop + FloatType(sourceRowBottom[n]) * internalFactorBottom);
5387template <
typename T,
unsigned int tChannels>
5390 static_assert(tChannels != 0u,
"Invalid channel number!");
5392 ocean_assert(extendedSourceRow !=
nullptr);
5393 ocean_assert(targetRow !=
nullptr);
5394 ocean_assert(targetWidth >= 1u);
5395 ocean_assert(interpolationLocations !=
nullptr);
5396 ocean_assert(interpolationFactorsRight !=
nullptr);
5397 ocean_assert_and_suppress_unused(channels == tChannels, channels);
5401 for (
unsigned int x = 0u; x < targetWidth; ++x)
5403 const FloatType internalFactorRight = FloatType(interpolationFactorsRight[x]);
5404 ocean_assert(internalFactorRight >= FloatType(0) && internalFactorRight <= FloatType(1));
5406 const FloatType internalFactorLeft = FloatType(1.0f - interpolationFactorsRight[x]);
5408 const unsigned int& leftLocation = interpolationLocations[x];
5409 const unsigned int rightLocation = leftLocation + tChannels;
5411 for (
unsigned int n = 0u; n < tChannels; ++n)
5413 targetRow[x * tChannels + n] = T(FloatType(extendedSourceRow[leftLocation + n]) * internalFactorLeft + FloatType(extendedSourceRow[rightLocation + n]) * internalFactorRight);
5418#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5420#ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5423inline 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)
5425 ocean_assert(source !=
nullptr && target !=
nullptr);
5426 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5427 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5428 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5429 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5430 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5432 ocean_assert(sourcePaddingElements == 0u);
5433 ocean_assert(targetPaddingElements == 0u);
5437 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5438 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5441 unsigned int leftOffsets[8];
5454 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5455 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5457 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5458 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5461 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5464 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5467 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5470 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5472 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5473 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5475 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5477 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5479 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5480 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5481 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5483 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5485 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5487 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5489 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5490 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5492 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5494 if (x + 8u > targetWidth)
5499 ocean_assert(x >= 8u && targetWidth > 8u);
5500 const unsigned int newX = targetWidth - 8u;
5502 ocean_assert(x > newX);
5503 targetPixelData -= x - newX;
5508 ocean_assert(!(x + 8u < targetWidth));
5514 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5515 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5518 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))));
5519 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5521 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))));
5522 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5526 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5527 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5530 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5531 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5538 uint8x8x2_t topLeftPixels;
5539 uint8x8x2_t topRightPixels;
5541 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
5542 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
5544 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
5545 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
5547 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
5548 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
5550 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
5551 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
5553 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
5554 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
5556 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
5557 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
5559 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
5560 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
5562 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
5563 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
5568 uint8x8x2_t bottomLeftPixels;
5569 uint8x8x2_t bottomRightPixels;
5571 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
5572 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
5574 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
5575 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
5577 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
5578 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
5580 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
5581 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
5583 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
5584 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
5586 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
5587 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
5589 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
5590 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
5592 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
5593 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
5601 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5602 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5605 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5606 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5607 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5612 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
5613 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
5615 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
5616 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
5618 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5619 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5624 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
5625 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
5627 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
5628 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
5630 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5631 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5636 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
5637 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
5639 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
5640 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
5645 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5646 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5649 vst2_u8((uint8_t*)targetPixelData, result);
5651 targetPixelData += 8;
5657 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5659 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5661 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5663 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5664 ocean_assert(lastSourcePixelLeft < sourceWidth);
5665 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5667 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5669 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5670 const unsigned int factorLeft = 128u - factorRight;
5672 for (
unsigned int c = 0u; c < 2u; ++c)
5674 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5675 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5683#ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_SLIGHTLY_DIFFERENT_APPROACH
5686inline 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)
5688 ocean_assert(source !=
nullptr && target !=
nullptr);
5689 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5690 ocean_assert(sourceHeight >= 0u && sourceHeight <= 65535u);
5691 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u)
5692 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5693 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5695 ocean_assert(sourcePaddingElements == 0u);
5696 ocean_assert(targetPaddingElements == 0u);
5698 using PixelType = typename
DataType<uint8_t, 2u>::Type;
5700 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5701 const PixelType* const sourcePixelData = (const PixelType*)source;
5704 unsigned int leftOffsets[8];
5707 unsigned int topPixels[8];
5708 unsigned int bottomPixels[8];
5721 const
unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5722 const
unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5724 const
int targetOffsetX_fixed16 = (
int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5725 const
int targetOffsetY_fixed16 = (
int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5728 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5731 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5734 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5737 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5739 const
unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5740 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5742 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5744 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5746 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5747 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5748 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5750 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5752 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5754 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5756 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5757 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5759 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5761 if (x + 8u > targetWidth)
5766 ocean_assert(x >= 8u && targetWidth > 8u);
5767 const unsigned int newX = targetWidth - 8u;
5769 ocean_assert(x > newX);
5770 targetPixelData -= x - newX;
5775 ocean_assert(!(x + 8u < targetWidth));
5781 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5782 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5785 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))));
5786 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5788 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))));
5789 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5793 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5794 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5797 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5798 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5808 for (
unsigned int n = 0u; n < 8u; ++n)
5810 topPixels[n] = *(
unsigned int*)(sourceTopRowPixelData + leftOffsets[n]);
5813 const uint16x8_t m128_topPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 0));
5814 const uint16x8_t m128_topPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 4));
5816 for (
unsigned int n = 0u; n < 8u; ++n)
5818 bottomPixels[n] = *(
unsigned int*)(sourceBottomRowPixelData + leftOffsets[n]);
5821 const uint16x8_t m128_bottomPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 0));
5822 const uint16x8_t m128_bottomPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 4));
5829 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5830 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5833 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5834 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5839 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5846 const uint16x8x2_t m2_128_topPixelsLeftRight = vuzpq_u16(m128_topPixels_0123, m128_topPixels_4567);
5852 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])));
5853 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])));
5855 const uint8x8_t& m64_topPixelsLeft_channel_0 = m2_64_topPixelsLeft_channels_01.val[0];
5856 const uint8x8_t& m64_topPixelsLeft_channel_1 = m2_64_topPixelsLeft_channels_01.val[1];
5858 const uint8x8_t& m64_topPixelsRight_channel_0 = m2_64_topPixelsRight_channels_01.val[0];
5859 const uint8x8_t& m64_topPixelsRight_channel_1 = m2_64_topPixelsRight_channels_01.val[1];
5863 uint16x8_t m128_muliplication_channel_0 = vmull_u8(m64_topPixelsLeft_channel_0, m64_u_factorsLeft);
5864 uint16x8_t m128_muliplication_channel_1 = vmull_u8(m64_topPixelsLeft_channel_1, m64_u_factorsLeft);
5866 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_topPixelsRight_channel_0, m64_u_factorsRight);
5867 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_topPixelsRight_channel_1, m64_u_factorsRight);
5869 const uint8x8_t m64_topRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5870 const uint8x8_t m64_topRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5874 const uint16x8x2_t m2_128_bottomPixelsLeftRight = vuzpq_u16(m128_bottomPixels_0123, m128_bottomPixels_4567);
5876 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])));
5877 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])));
5879 const uint8x8_t& m64_bottomPixelsLeft_channel_0 = m2_64_bottomPixelsLeft_channels_01.val[0];
5880 const uint8x8_t& m64_bottomPixelsLeft_channel_1 = m2_64_bottomPixelsLeft_channels_01.val[1];
5882 const uint8x8_t& m64_bottomPixelsRight_channel_0 = m2_64_bottomPixelsRight_channels_01.val[0];
5883 const uint8x8_t& m64_bottomPixelsRight_channel_1 = m2_64_bottomPixelsRight_channels_01.val[1];
5887 m128_muliplication_channel_0 = vmull_u8(m64_bottomPixelsLeft_channel_0, m64_u_factorsLeft);
5888 m128_muliplication_channel_1 = vmull_u8(m64_bottomPixelsLeft_channel_1, m64_u_factorsLeft);
5890 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomPixelsRight_channel_0, m64_u_factorsRight);
5891 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomPixelsRight_channel_1, m64_u_factorsRight);
5893 const uint8x8_t m64_bottomRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5894 const uint8x8_t m64_bottomRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5898 m128_muliplication_channel_0 = vmull_u8(m64_topRow_channel_0, m64_u_factorsTop);
5899 m128_muliplication_channel_1 = vmull_u8(m64_topRow_channel_1, m64_u_factorsTop);
5901 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomRow_channel_0, m64_u_factorsBottom);
5902 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomRow_channel_1, m64_u_factorsBottom);
5906 uint8x8x2_t m2_64_result;
5907 m2_64_result.val[0] = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5908 m2_64_result.val[1] = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5911 vst2_u8((uint8_t*)targetPixelData, m2_64_result);
5913 targetPixelData += 8;
5919 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5921 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5923 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5925 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5926 ocean_assert(lastSourcePixelLeft < sourceWidth);
5927 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5929 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5931 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5932 const unsigned int factorLeft = 128u - factorRight;
5934 for (
unsigned int c = 0u; c < 2u; ++c)
5936 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5937 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5945#ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5948inline 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)
5950 ocean_assert(source !=
nullptr && target !=
nullptr);
5951 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5952 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5953 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5954 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5955 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5957 ocean_assert(sourcePaddingElements == 0u);
5958 ocean_assert(targetPaddingElements == 0u);
5960 using PixelType =
typename DataType<uint8_t, 3u>::Type;
5962 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5963 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5966 unsigned int leftOffsets[8];
5979 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5980 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5982 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5983 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5986 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5989 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5992 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5995 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5997 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5998 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6000 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6002 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6004 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6005 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6006 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6008 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6010 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6012 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6014 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6015 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6017 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6019 if (x + 8u > targetWidth)
6024 ocean_assert(x >= 8u && targetWidth > 8u);
6025 const unsigned int newX = targetWidth - 8u;
6027 ocean_assert(x > newX);
6028 targetPixelData -= x - newX;
6033 ocean_assert(!(x + 8u < targetWidth));
6039 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6040 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6043 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))));
6044 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6046 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))));
6047 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6051 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6052 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6055 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6056 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6063 uint8x8x3_t topLeftPixels;
6064 uint8x8x3_t topRightPixels;
6066 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6067 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6069 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6070 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6072 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6073 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6075 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6076 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6078 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6079 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6081 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6082 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6084 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6085 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6087 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6088 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6093 uint8x8x3_t bottomLeftPixels;
6094 uint8x8x3_t bottomRightPixels;
6096 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6097 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6099 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6100 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6102 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6103 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6105 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6106 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6108 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6109 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6111 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6112 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6114 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6115 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6117 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6118 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6126 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6127 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6130 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6131 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6132 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6137 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6138 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6139 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6141 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6142 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6143 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6145 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6146 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6147 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6152 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6153 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6154 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6156 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6157 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6158 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6160 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6161 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6162 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6167 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6168 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6169 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6171 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6172 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6173 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6178 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6179 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6180 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6183 vst3_u8((uint8_t*)targetPixelData, result);
6185 targetPixelData += 8;
6191 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6193 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6195 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6197 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6198 ocean_assert(lastSourcePixelLeft < sourceWidth);
6199 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6201 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6203 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6204 const unsigned int factorLeft = 128u - factorRight;
6206 for (
unsigned int c = 0u; c < 3u; ++c)
6208 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
6209 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6217#ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_MORE_GENERIC_APPROACH
6222inline 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)
6224 ocean_assert(source !=
nullptr && target !=
nullptr);
6225 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
6226 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
6227 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
6228 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
6229 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6231 ocean_assert(sourcePaddingElements == 0u);
6232 ocean_assert(targetPaddingElements == 0u);
6234 using PixelType =
typename DataType<uint8_t, 4u>::Type;
6236 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
6237 const PixelType*
const sourcePixelData = (
const PixelType*)source;
6240 unsigned int leftOffsets[8];
6243 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6256 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
6257 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6259 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
6260 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
6263 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
6266 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
6269 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
6272 const int32x4_t m128_s_zero = vdupq_n_s32(0);
6274 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
6275 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6277 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6279 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6281 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6282 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6283 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6285 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6287 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6289 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6291 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6292 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6294 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6296 if (x + 8u > targetWidth)
6301 ocean_assert(x >= 8u && targetWidth > 8u);
6302 const unsigned int newX = targetWidth - 8u;
6304 ocean_assert(x > newX);
6305 targetPixelData -= x - newX;
6310 ocean_assert(!(x + 8u < targetWidth));
6316 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6317 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6320 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))));
6321 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6323 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))));
6324 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6328 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6329 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6332 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6333 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6340 uint8x8x4_t topLeftPixels;
6341 uint8x8x4_t topRightPixels;
6343 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6344 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6346 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6347 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6349 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6350 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6352 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6353 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6355 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6356 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6358 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6359 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6361 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6362 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6364 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6365 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6370 uint8x8x4_t bottomLeftPixels;
6371 uint8x8x4_t bottomRightPixels;
6373 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6374 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6376 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6377 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6379 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6380 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6382 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6383 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6385 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6386 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6388 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6389 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6391 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6392 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6394 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6395 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6403 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6404 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6407 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6408 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6409 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6414 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6415 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6416 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6417 uint16x8_t m128_muliplicationChannel_3 = vmull_u8(topLeftPixels.val[3], m64_u_factorsLeft);
6419 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6420 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6421 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6422 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, topRightPixels.val[3], m64_u_factorsRight);
6424 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6425 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6426 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6427 uint8x8_t m64_topRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6432 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6433 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6434 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6435 m128_muliplicationChannel_3 = vmull_u8(bottomLeftPixels.val[3], m64_u_factorsLeft);
6437 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6438 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6439 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6440 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, bottomRightPixels.val[3], m64_u_factorsRight);
6442 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6443 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6444 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6445 uint8x8_t m64_bottomRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6450 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6451 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6452 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6453 m128_muliplicationChannel_3 = vmull_u8(m64_topRowChannel_3, m64_u_factorsTop);
6455 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6456 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6457 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6458 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, m64_bottomRowChannel_3, m64_u_factorsBottom);
6463 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6464 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6465 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6466 result.val[3] = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6469 vst4_u8((uint8_t*)targetPixelData, result);
6471 targetPixelData += 8;
6477 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6479 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6481 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6483 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6484 ocean_assert(lastSourcePixelLeft < sourceWidth);
6485 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6487 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6489 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6490 const unsigned int factorLeft = 128u - factorRight;
6492 for (
unsigned int c = 0u; c < 4u; ++c)
6494 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorTop
6495 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6506inline void FrameInterpolatorBilinear::interpolateRowVerticalNEON<float>(
const float* sourceRowTop,
const float* sourceRowBottom,
float* targetRow,
const unsigned int elements,
const float factorBottom)
6508 ocean_assert(sourceRowTop !=
nullptr);
6509 ocean_assert(sourceRowBottom !=
nullptr);
6510 ocean_assert(targetRow !=
nullptr);
6511 ocean_assert(elements >= 16u);
6512 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6515 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6517 const float32x4_t factorsBottom_f_32x4 = vdupq_n_f32(factorBottom);
6518 const float32x4_t factorsTop_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsBottom_f_32x4);
6520 for (
unsigned int n = 0u; n < elements; n += 16u)
6522 if (n + 16u > elements)
6527 ocean_assert(n >= 16u && elements > 16u);
6528 const unsigned int offset = n - (elements - 16u);
6529 ocean_assert(offset < 16u);
6531 sourceRowTop -= offset;
6532 sourceRowBottom -= offset;
6533 targetRow -= offset;
6536 ocean_assert(!(n + 16u < elements));
6540 const float32x4_t top_03_32x4 = vld1q_f32(sourceRowTop + 0);
6541 const float32x4_t top_47_32x4 = vld1q_f32(sourceRowTop + 4);
6542 const float32x4_t top_8B_32x4 = vld1q_f32(sourceRowTop + 8);
6543 const float32x4_t top_CF_32x4 = vld1q_f32(sourceRowTop + 12);
6545 const float32x4_t bottom_03_32x4 = vld1q_f32(sourceRowBottom + 0);
6546 const float32x4_t bottom_47_32x4 = vld1q_f32(sourceRowBottom + 4);
6547 const float32x4_t bottom_8B_32x4 = vld1q_f32(sourceRowBottom + 8);
6548 const float32x4_t bottom_CF_32x4 = vld1q_f32(sourceRowBottom + 12);
6551 float32x4_t interpolatedRow_03_32x4 = vmulq_f32(top_03_32x4, factorsTop_f_32x4);
6552 float32x4_t interpolatedRow_47_32x4 = vmulq_f32(top_47_32x4, factorsTop_f_32x4);
6553 float32x4_t interpolatedRow_8B_32x4 = vmulq_f32(top_8B_32x4, factorsTop_f_32x4);
6554 float32x4_t interpolatedRow_CF_32x4 = vmulq_f32(top_CF_32x4, factorsTop_f_32x4);
6556 interpolatedRow_03_32x4 = vmlaq_f32(interpolatedRow_03_32x4, bottom_03_32x4, factorsBottom_f_32x4);
6557 interpolatedRow_47_32x4 = vmlaq_f32(interpolatedRow_47_32x4, bottom_47_32x4, factorsBottom_f_32x4);
6558 interpolatedRow_8B_32x4 = vmlaq_f32(interpolatedRow_8B_32x4, bottom_8B_32x4, factorsBottom_f_32x4);
6559 interpolatedRow_CF_32x4 = vmlaq_f32(interpolatedRow_CF_32x4, bottom_CF_32x4, factorsBottom_f_32x4);
6562 vst1q_f32(targetRow + 0, interpolatedRow_03_32x4);
6563 vst1q_f32(targetRow + 4, interpolatedRow_47_32x4);
6564 vst1q_f32(targetRow + 8, interpolatedRow_8B_32x4);
6565 vst1q_f32(targetRow + 12, interpolatedRow_CF_32x4);
6568 sourceRowBottom += 16;
6574inline 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)
6576 ocean_assert(extendedSourceRow !=
nullptr);
6577 ocean_assert(targetRow !=
nullptr);
6578 ocean_assert(targetWidth >= 8u);
6579 ocean_assert(interpolationLocations !=
nullptr);
6580 ocean_assert(interpolationFactorsRight !=
nullptr);
6582 ocean_assert_and_suppress_unused(channels == 1u, channels);
6585 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6587 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6589 if (x + 8u > targetWidth)
6594 ocean_assert(x >= 8u && targetWidth > 8u);
6595 const unsigned int newX = targetWidth - 8u;
6597 ocean_assert(x > newX);
6598 const unsigned int offset = x - newX;
6600 targetRow -= offset;
6601 interpolationLocations -= offset;
6602 interpolationFactorsRight -= offset;
6607 ocean_assert(!(x + 8u < targetWidth));
6612 const float32x2_t pixel_0_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[0]);
6613 const float32x2_t pixel_1_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[1]);
6614 const float32x4_t pixel_01_f_32x4 = vcombine_f32(pixel_0_f_32x2, pixel_1_f_32x2);
6616 const float32x2_t pixel_2_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[2]);
6617 const float32x2_t pixel_3_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[3]);
6618 const float32x4_t pixel_23_f_32x4 = vcombine_f32(pixel_2_f_32x2, pixel_3_f_32x2);
6620 const float32x2_t pixel_4_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[4]);
6621 const float32x2_t pixel_5_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[5]);
6622 const float32x4_t pixel_45_f_32x4 = vcombine_f32(pixel_4_f_32x2, pixel_5_f_32x2);
6624 const float32x2_t pixel_6_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[6]);
6625 const float32x2_t pixel_7_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[7]);
6626 const float32x4_t pixel_67_f_32x4 = vcombine_f32(pixel_6_f_32x2, pixel_7_f_32x2);
6628 const float32x4_t factorsRight_0123_f_32x4 = vld1q_f32(interpolationFactorsRight + 0);
6629 const float32x4_t factorsLeft_0123_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_0123_f_32x4);
6630 const float32x4x2_t factorsLeftRight_0123_f_32x4_2 = vzipq_f32(factorsLeft_0123_f_32x4, factorsRight_0123_f_32x4);
6632 const float32x4_t factorsRight_4567_f_32x4 = vld1q_f32(interpolationFactorsRight + 4);
6633 const float32x4_t factorsLeft_4567_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_4567_f_32x4);
6634 const float32x4x2_t factorsLeftRight_4567_f_32x4_2 = vzipq_f32(factorsLeft_4567_f_32x4, factorsRight_4567_f_32x4);
6636 const float32x4_t multiplied_01_f_32x4 = vmulq_f32(pixel_01_f_32x4, factorsLeftRight_0123_f_32x4_2.val[0]);
6637 const float32x4_t multiplied_23_f_32x4 = vmulq_f32(pixel_23_f_32x4, factorsLeftRight_0123_f_32x4_2.val[1]);
6639 const float32x4_t multiplied_45_f_32x4 = vmulq_f32(pixel_45_f_32x4, factorsLeftRight_4567_f_32x4_2.val[0]);
6640 const float32x4_t multiplied_67_f_32x4 = vmulq_f32(pixel_67_f_32x4, factorsLeftRight_4567_f_32x4_2.val[1]);
6642 const float32x2_t result_01_f_32x2 = vpadd_f32(vget_low_f32(multiplied_01_f_32x4), vget_high_f32(multiplied_01_f_32x4));
6643 const float32x2_t result_23_f_32x2 = vpadd_f32(vget_low_f32(multiplied_23_f_32x4), vget_high_f32(multiplied_23_f_32x4));
6645 const float32x2_t result_45_f_32x2 = vpadd_f32(vget_low_f32(multiplied_45_f_32x4), vget_high_f32(multiplied_45_f_32x4));
6646 const float32x2_t result_67_f_32x2 = vpadd_f32(vget_low_f32(multiplied_67_f_32x4), vget_high_f32(multiplied_67_f_32x4));
6648 const float32x4_t result_0123_f_32x4 = vcombine_f32(result_01_f_32x2, result_23_f_32x2);
6649 const float32x4_t result_4567_f_32x4 = vcombine_f32(result_45_f_32x2, result_67_f_32x2);
6651 vst1q_f32(targetRow + 0, result_0123_f_32x4);
6652 vst1q_f32(targetRow + 4, result_4567_f_32x4);
6655 interpolationLocations += 8;
6656 interpolationFactorsRight += 8;
6661inline 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)
6663 ocean_assert(source !=
nullptr && target !=
nullptr);
6664 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
6665 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
6666 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6668 ocean_assert(sourceWidth != targetWidth || sourceHeight != targetHeight);
6670 const unsigned int sourceStrideElements = sourceWidth * 1u + sourcePaddingElements;
6671 const unsigned int targetStrideElements = targetWidth * 1u + targetPaddingElements;
6673 using InterpolateRowVerticalFunction = void (*)(
const float*,
const float*,
float*,
const unsigned int,
const float);
6674 using InterpolateRowHorizontalFunction = void (*)(
const float*,
float*,
const unsigned int,
const unsigned int,
const unsigned int*,
const float*);
6676 InterpolateRowVerticalFunction interpolateRowVerticalFunction = interpolateRowVertical<float>;
6677 InterpolateRowHorizontalFunction interpolateRowHorizontalFunction = interpolateRowHorizontal<float, 1u>;
6679 if (sourceWidth * 1u >= 16u)
6681 interpolateRowVerticalFunction = interpolateRowVerticalNEON<float>;
6684 if (targetWidth >= 8u)
6686 interpolateRowHorizontalFunction = interpolateRowHorizontalNEON<float, 1u>;
6689 target += targetStrideElements * firstTargetRow;
6691 const float sourceX_T_targetX = float(sourceX_s_targetX);
6692 const float sourceY_T_targetY = float(sourceY_s_targetY);
6696 Memory memoryIntermediateExtendedRow;
6697 Memory memoryHorizontalInterpolationLocations;
6698 Memory memoryHorizontalInterpolationFactorsRight;
6700 if (sourceWidth != targetWidth)
6704 memoryIntermediateExtendedRow = Memory::create<float>(sourceWidth + 1u);
6706 memoryHorizontalInterpolationLocations = Memory::create<unsigned int>(targetWidth);
6708 memoryHorizontalInterpolationFactorsRight = Memory::create<float>(targetWidth);
6711 if (memoryHorizontalInterpolationLocations)
6713 ocean_assert(memoryHorizontalInterpolationFactorsRight);
6715 if (targetWidth >= 4u)
6717 const float32x4_t sourceX_T_targetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX);
6718 const float32x4_t targetOffsetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX * 0.5f - 0.5f);
6721 const float32x4_t constant_0_f_32x4 = vdupq_n_f32(0);
6724 const float32x4_t constant_4_f_32x4 = vdupq_n_f32(4.0f);
6727 const uint32x4_t sourceWidth_1_u_32x4 = vdupq_n_u32(sourceWidth - 1u);
6730 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
6731 float32x4_t x_0123_f_32x4 = vld1q_f32(f_0123);
6735 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
6737 if (x + 4u > targetWidth)
6742 ocean_assert(x >= 4u && targetWidth > 4u);
6743 const unsigned int newX = targetWidth - 4u;
6745 ocean_assert(x > newX);
6746 const unsigned int offset = x - newX;
6750 x_0123_f_32x4 = vsubq_f32(x_0123_f_32x4, vdupq_n_f32(
float(offset)));
6753 ocean_assert(!(x + 4u < targetWidth));
6757 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)));
6761 uint32x4_t left_0123_u_32x4 = vminq_u32(vcvtq_u32_f32(sourceX_0123_f_32x4), sourceWidth_1_u_32x4);
6764 vst1q_u32(memoryHorizontalInterpolationLocations.
data<
unsigned int>() + x, left_0123_u_32x4);
6767 const float32x4_t factorsRight_f_32x4 = vsubq_f32(sourceX_0123_f_32x4, vcvtq_f32_u32(left_0123_u_32x4));
6769 vst1q_f32(memoryHorizontalInterpolationFactorsRight.
data<
float>() + x, factorsRight_f_32x4);
6772 x_0123_f_32x4 = vaddq_f32(x_0123_f_32x4, constant_4_f_32x4);
6777 const float targetOffsetX = sourceX_T_targetX * 0.5f - 0.5f;
6781 for (
unsigned int x = 0u; x < targetWidth; ++x)
6783 const float sourceX = max(0.0f, targetOffsetX +
float(x) * sourceX_T_targetX);
6785 const unsigned int left = min((
unsigned int)sourceX, sourceWidth - 1u);
6787 memoryHorizontalInterpolationLocations.
data<
unsigned int>()[x] = left;
6789 const float factorRight = sourceX - float(left);
6790 ocean_assert(factorRight >= 0.0f && factorRight <= 1.0f);
6792 memoryHorizontalInterpolationFactorsRight.
data<
float>()[x] = factorRight;
6797 const float targetOffsetY = sourceY_T_targetY * 0.5f - 0.5f;
6799 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6801 const float sourceY = minmax<float>(0.0f, targetOffsetY + sourceY_T_targetY *
float(y),
float(sourceHeight) - 1.0f);
6803 const unsigned int sourceRowTop = (
unsigned int)sourceY;
6804 const float factorBottom = sourceY - float(sourceRowTop);
6805 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6807 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6809 const float*
const sourceTopRow = source + sourceStrideElements * sourceRowTop;
6810 const float*
const sourceBottomRow = source + sourceStrideElements * sourceRowBottom;
6812 float* targetRow =
nullptr;
6814 if (sourceHeight == targetHeight)
6816 ocean_assert(sourceWidth != targetWidth);
6817 ocean_assert(memoryIntermediateExtendedRow);
6820 memcpy(memoryIntermediateExtendedRow.
data<
float>(), sourceTopRow, sourceWidth *
sizeof(
float));
6825 targetRow = memoryIntermediateExtendedRow.
isNull() ? target : memoryIntermediateExtendedRow.
data<
float>();
6827 ocean_assert(targetRow !=
nullptr);
6828 ocean_assert(interpolateRowVerticalFunction !=
nullptr);
6829 interpolateRowVerticalFunction(sourceTopRow, sourceBottomRow, targetRow, sourceWidth * 1u, factorBottom);
6832 if (memoryIntermediateExtendedRow)
6836 memoryIntermediateExtendedRow.
data<
float>()[sourceWidth] = memoryIntermediateExtendedRow.
data<
float>()[sourceWidth - 1u];
6838 interpolateRowHorizontalFunction(memoryIntermediateExtendedRow.
data<
float>(), target, targetWidth, 1u, memoryHorizontalInterpolationLocations.
data<
unsigned int>(), memoryHorizontalInterpolationFactorsRight.
data<
float>());
6841 target += targetStrideElements;
6847template <
typename T,
typename TScale,
unsigned int tChannels>
6848void 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)
6850 static_assert((std::is_same<float, TScale>::value || std::is_same<double, TScale>::value),
"Invalid TScale type");
6852 ocean_assert(source !=
nullptr && target !=
nullptr);
6853 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
6854 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
6855 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6857 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
6858 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
6860 const TScale sourceX_T_targetX = TScale(sourceX_s_targetX);
6861 const TScale sourceY_T_targetY = TScale(sourceY_s_targetY);
6909 const TScale sourceX_T_targetXOffset = sourceX_T_targetX * TScale(0.5) - TScale(0.5);
6910 const TScale sourceY_T_targetYOffset = sourceY_T_targetY * TScale(0.5) - TScale(0.5);
6912 const TScale sourceWidth_1 = TScale(sourceWidth - 1u);
6913 const TScale sourceHeight_1 = TScale(sourceHeight - 1u);
6915 target += targetStrideElements * firstTargetRow;
6917 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6919 const TScale sy =
minmax(TScale(0), sourceY_T_targetYOffset + sourceY_T_targetY * TScale(y), sourceHeight_1);
6920 ocean_assert(sy >= TScale(0) && sy < TScale(sourceHeight));
6922 const unsigned int sTop = (
unsigned int)sy;
6923 ocean_assert(sy >= TScale(sTop));
6925 const TScale factorBottom = sy - TScale(sTop);
6926 ocean_assert(factorBottom >= TScale(0) && factorBottom <= TScale(1));
6928 const TScale factorTop = TScale(1) - factorBottom;
6929 ocean_assert(factorTop >= TScale(0) && factorTop <= TScale(1));
6931 const T*
const sourceTop = source + sTop * sourceStrideElements;
6932 const T*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
6934 for (
unsigned int x = 0; x < targetWidth; ++x)
6936 const TScale sx =
minmax(TScale(0), sourceX_T_targetXOffset + sourceX_T_targetX * TScale(x), sourceWidth_1);
6937 ocean_assert(sx >= TScale(0) && sx < TScale(sourceWidth));
6939 const unsigned int sLeft = (
unsigned int)sx;
6940 ocean_assert(sx >= TScale(sLeft));
6942 const TScale factorRight = sx - TScale(sLeft);
6943 ocean_assert(factorRight >= TScale(0) && factorRight <= TScale(1));
6945 const TScale factorLeft = TScale(1) - factorRight;
6946 ocean_assert(factorLeft >= TScale(0) && factorLeft <= TScale(1));
6948 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
6950 const T*
const sourceTopLeft = sourceTop + sLeft * tChannels;
6951 const T*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
6953 const TScale factorTopLeft = factorTop * factorLeft;
6954 const TScale factorTopRight = factorTop * factorRight;
6955 const TScale factorBottomLeft = factorBottom * factorLeft;
6956 const TScale factorBottomRight = factorBottom * factorRight;
6958 for (
unsigned int n = 0u; n < tChannels; ++n)
6960 target[n] = T(TScale(sourceTopLeft[n]) * factorTopLeft + TScale(sourceTopLeft[sourceRightOffset + n]) * factorTopRight
6961 + TScale(sourceBottomLeft[n]) * factorBottomLeft + TScale(sourceBottomLeft[sourceRightOffset + n]) * factorBottomRight);
6964 target += tChannels;
6967 target += targetPaddingElements;
6971template <
unsigned int tChannels>
6972void 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)
6974 static_assert(tChannels != 0u,
"Invalid channel number!");
6976 ocean_assert(firstTargetRow + numberTargetRows <= height);
6980 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
6982 uint8_t zeroColor[tChannels] = {uint8_t(0)};
6983 const PixelType bColor = borderColor ? *(
const PixelType*)borderColor : *(
const PixelType*)zeroColor;
6986 const SquareMatrix2 rotationMatrix2(rotationMatrix3(0, 0), rotationMatrix3(1, 0), rotationMatrix3(0, 1), rotationMatrix3(1, 1));
6990 const Vector2 anchorPosition(horizontalAnchorPosition, verticalAnchorPosition);
6992 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6994 PixelType* targetPixel = (PixelType*)(target + y * targetStrideElements);
6998 for (
unsigned int x = 0; x < width; ++x)
7000 const Vector2 sourceLocation(anchorPosition + rotationMatrix2 * (
Vector2(
Scalar(x), floatY) - anchorPosition));
7002 if (sourceLocation.
x() >= 0 && sourceLocation.
y() >= 0 && sourceLocation.
x() <= width_1 && sourceLocation.
y() <= height_1)
7004 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, width, height, sourcePaddingElements, sourceLocation, (uint8_t*)(targetPixel));
7008 *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:61
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:1531
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:1438
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:342
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:45
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:4301
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:1749
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:1909
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:1815
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)
Transforms a given input frame into an output frame by application of an interpolation lookup table.
Definition FrameInterpolatorBilinear.h:1849
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:1976
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:2480
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:1832
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:4523
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:1802
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:3593
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:2396
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:1786
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:3973
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:4367
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:4603
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:1673
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:4649
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:3343
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)
Transforms a subset of a given input frame into an output frame by application of an interpolation lo...
Definition FrameInterpolatorBilinear.h:5008
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:5423
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:5388
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:6972
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:1896
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:3275
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:1773
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:4697
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:1624
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:1637
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:4751
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:5247
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:1958
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:5368
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:1711
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:2155
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:5150
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:2244
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:2665
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:5203
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:4448
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:6848
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:2319
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:2069
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:3875
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:1879
void setRelativeTimestamp(const Timestamp &relative)
Sets the relative timestamp of this frame.
Definition Frame.h:4317
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4612
void setTimestamp(const Timestamp ×tamp)
Sets the timestamp of this frame.
Definition Frame.h:4312
const Timestamp & timestamp() const
Returns the timestamp of this frame.
Definition Frame.h:4302
const Timestamp & relativeTimestamp() const
Returns the relative timestamp of this frame.
Definition Frame.h:4307
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:947
size_t sizeX() const
Returns the horizontal dimension of this lookup object.
Definition Lookup2.h:941
size_t binsY() const
Returns the number of vertical bins of this lookup object.
Definition Lookup2.h:959
size_t binsX() const
Returns the number of horizontal bins of this lookup object.
Definition Lookup2.h:953
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:1786
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:2128
void bilinearValues(const size_t y, TTarget *values) const
Applies a lookup for an entire row in this lookup object.
Definition Lookup2.h:1864
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
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
bool isEqual(const VectorT2< T > &vector, const T eps) const
Returns whether two vectors are equal up to a specified epsilon.
Definition Vector2.h:758
const T & y() const noexcept
Returns the y value.
Definition Vector3.h:824
const T & x() const noexcept
Returns the x value.
Definition Vector3.h:812
const T & z() const noexcept
Returns the z value.
Definition Vector3.h:836
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